How-to implement "opening downloaded filelists of users" using the (RSN) patented "minimal impact" sarf patch method. --- NEW IDEA ADDED 2003-07-08 (European Time) --- NEW: I figured out that I should have made a WindowStuffListener or some such, something to make it possible to tell MainFrame what to do. That is too much like Real Work (pat. pending), however, so the faked downloaded thingy will have to do. Not that making a listener would be particularly hard, but... --- OLD TEXT BEGINS HERE --- Minimal impact my arse. Unfortunately, DC++ lacks some neat-o functions that are necessary for the deployment of this feature (existsFile). The most important thing is the inability to open a filelist (creating the window et cetera) from anywhere but in MainFrame. I solved it by using arnetheduck's code in ways never considered before (I hope), and by fiddling with it in ways best left unmentioned (specifically, by faking that the filelist had just been downloaded). The hubframe is patched, but you should be able to patch the SearchFrame using the same method. I'd really recommend moving some functions to WinUtil in that case, as copy'n'paste is Bad For the Health of Your Code, not to mention ugly. Err... not that any particular methods comes to mind. Hm. Sorry about that. Rambling on... Mayhap I have forgotten/overlooked something, but there really should be some way of communicating with the MainFrame object other than using sloppy workarounds. Perhaps targeted PostMessage calls would do the trick? In that case, the data structures used by the OnSpeaker method must be public. Oh! I know! A MainFrameEventHandler or somesuch! *G* Suggestions for improvements will be received with open hands and smiling mouths! The reason I do not use patch or diff is that it would put in my DC++k changes. This way, the patch should work. You are free to use this code in whatever way you like, except in ways that would make sarf sad. Making sarf sad is not illegal, however, so go ahead. Unmake my day. Should this code (in its current form) end up in DC++ I would be amazed and terrified (but silently thrilled). I want my 'net connection back! Waaaaaaaaaaaaah! Rambling terminated. Re-engage your brains before you leave the room, and don't forget to wipe the drool of your shoes. client/File.h : before static void deleteFile(const string& aFileName) throw() { ::DeleteFile(aFileName.c_str()); }; add static bool existsFile(const string& aFileName) { File* f = NULL; try { f = new File(aFileName, File::READ, File::OPEN); try { f->close(); } catch(const Exception&) { } delete f; return true; } catch(const FileException&) { } return false; }; client/QueueManager.h : below FLAG_BZLIST = 0x10, add /** The queue item downloaded was actually never downloaded, and should be deleted (internal, only available in FINISHED message) */ /** 0x80 is used to make this method forwards-compatible - feel free to change it when you feel the urge */ FLAG_TEMPORARY = 0x80, below void setPriority(const string& aTarget, QueueItem::Priority p) throw(); add void showFileList(string aFileName, User::Ptr aUser); client/QueueManager.cpp : before void QueueManager::onAction(TimerManagerListener::Types type, u_int32_t aTick) throw() { add void QueueManager::showFileList(string aFileName, User::Ptr aUser) { // try to emulate a real filelist download as much as possible QueueItem* qi = new QueueItem(aFileName, -1, QueueItem::Priority::HIGHEST, false); qi->setFlag(QueueItem::FLAG_CLIENT_VIEW); // not strictly necessary, but let's be nice about this, shall we? qi->setFlag(QueueItem::FLAG_USER_LIST); // wooohooo! new flags make GIR feel all warm and fuzzy inside! qi->setFlag(QueueItem::FLAG_TEMPORARY); // make sure that the MainFrame method does not crash when it tries to retrieve the user // the filename of the source is empty as it is not used by the destination method. QueueItem::Source* source = new QueueItem::Source(aUser, Util::emptyString); qi->setCurrent(source); fire(QueueManagerListener::FINISHED, qi); } windows/HubFrame.cpp : below if(showMenu) { add if(hasSomeSelectedUsersDownloadedLists()) { string s = "Open downloaded filelists"; opMenu.AppendMenu(MF_STRING, IDC_OPEN_USERS_FILELIST, s.c_str()); userMenu.AppendMenu(MF_STRING, IDC_OPEN_USERS_FILELIST, s.c_str()); } below while(added > 0) { userMenu.DeleteMenu(userMenu.GetMenuItemCount()-1, MF_BYPOSITION); added--; } } add if(hasSomeSelectedUsersDownloadedLists()) { opMenu.RemoveMenu(IDC_OPEN_USERS_FILELIST, MF_BYCOMMAND); userMenu.RemoveMenu(IDC_OPEN_USERS_FILELIST, MF_BYCOMMAND); } before void HubFrame::onAction(ClientListener::Types type, Client* /*client*/, const User::Ptr& user, const string& line) throw() { add void HubFrame::openUserList(string file, User::Ptr user) { QueueManager::getInstance()->showFileList(file, user); } void HubFrame::openUsersList(bool selected) { int i = -1; string file = Util::emptyString; string file2 = Util::emptyString; User::Ptr user = (User::Ptr)NULL; if(selected) { while( (i = ctrlUsers.GetNextItem(i, LVNI_SELECTED)) != -1) { user = ((UserInfo*)ctrlUsers.GetItemData(i))->user; file = Util::getAppPath() + "FileLists\\" + user->getNickAsFileName() + ".DcLst"; file2 = Util::getAppPath() + "FileLists\\" + user->getNickAsFileName() + ".bz2"; // I like bz2 files better than DcLst files if(File::existsFile(file2)) { openUserList(file2, user); } else if(File::existsFile(file)) { openUserList(file, user); } } } } bool HubFrame::hasSomeSelectedUsersDownloadedLists() { int i = -1; string file = Util::emptyString; string file2 = Util::emptyString; User::Ptr user = NULL; while( (i = ctrlUsers.GetNextItem(i, LVNI_SELECTED)) != -1) { user = ((UserInfo*)ctrlUsers.GetItemData(i))->user; file = Util::getAppPath() + "FileLists\\" + user->getNickAsFileName() + ".DcLst"; file2 = Util::getAppPath() + "FileLists\\" + user->getNickAsFileName() + ".bz2"; if((File::existsFile(file)) || (File::existsFile(file2))) { return true; } } return false; } LRESULT HubFrame::onOpenUsersList(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { openUsersList(true); return 0; } client/HubFrame.h : below COMMAND_ID_HANDLER(IDC_COPY_NICK, onCopyNick) add COMMAND_ID_HANDLER(IDC_CHECK_FILELIST, onCheckList) before LRESULT onKeyDownUsers(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/) { add bool hasSomeSelectedUsersDownloadedLists(); void openUserList(string file, User::Ptr user); void openUsersList(bool selected = true); LRESULT onOpenUsersList(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); windows/resource.h : before #define ID_FILE_CONNECT 32772 add #define IDC_CHECK_FILELIST 1632 (actually, 1632 should be replaced by the next free number in your resource.h, but nevermind) windows/MainFrame.cpp : below PostMessage(WM_SPEAKER, DOWNLOAD_LISTING, (LPARAM)i); add if(qi->isSet(QueueItem::FLAG_TEMPORARY)) { // make sure to clean up after we're done - the memory should be reclaimed delete qi->getCurrent(); delete qi; }