def __init__(self, frame): self.frame = frame self.searchid = int(random.random() * (2**31 - 1)) self.searches = {} self.usersearches = {} self.users = {} self.maxdisplayedresults = self.frame.np.config.sections['searches'][ "max_displayed_results"] self.maxstoredresults = self.frame.np.config.sections['searches'][ "max_stored_results"] ui = self.frame.np.config.sections["ui"] IconNotebook.__init__( self, self.frame.images, angle=ui["labelsearch"], tabclosers=ui["tabclosers"], show_hilite_image=self.frame.np.config.sections["notifications"] ["notification_tab_icons"], reorderable=ui["tab_reorderable"], notebookraw=self.frame.SearchNotebookRaw) self.popup_enable() self.load_config() self.wish_list = WishList(frame, self) self.update_visuals()
def __init__(self, frame): self.frame = frame self.searches = {} self.usersearches = {} IconNotebook.__init__( self, self.frame.images, tabclosers=config.sections["ui"]["tabclosers"], show_hilite_image=config.sections["notifications"] ["notification_tab_icons"], notebookraw=self.frame.SearchNotebookRaw) self.load_config() self.wish_list = WishList(frame, self) self.update_visuals()
class Searches(IconNotebook): def __init__(self, frame): self.frame = frame self.searchid = int(random.random() * (2**31 - 1)) self.searches = {} self.usersearches = {} self.users = {} self.maxdisplayedresults = self.frame.np.config.sections['searches'][ "max_displayed_results"] self.maxstoredresults = self.frame.np.config.sections['searches'][ "max_stored_results"] ui = self.frame.np.config.sections["ui"] IconNotebook.__init__( self, self.frame.images, angle=ui["labelsearch"], tabclosers=ui["tabclosers"], show_hilite_image=self.frame.np.config.sections["notifications"] ["notification_tab_icons"], reorderable=ui["tab_reorderable"], notebookraw=self.frame.SearchNotebookRaw) self.popup_enable() self.load_config() self.wish_list = WishList(frame, self) self.update_visuals() def load_config(self): """ Add search history to SearchEntryCombo later and connect Wishlist, after widgets have been created. """ items = self.frame.np.config.sections["searches"]["history"] templist = [] for i in items: if i not in templist: templist.append(i) for i in templist: self.frame.search_entry_combo_model.append([i]) def on_clear_search_history(self): self.frame.search_entry.set_text("") self.frame.np.config.sections["searches"]["history"] = [] self.frame.np.config.write_configuration() self.frame.SearchEntryCombo.get_model().clear() self.frame.search_entry_combo_model.append([""]) def on_search(self): self.save_columns() text = self.frame.search_entry.get_text().strip() if not text: return users = [] room = None search_mode = self.frame.SearchMethod.get_active_id() feedback = None if search_mode == "global": feedback = self.frame.np.pluginhandler.outgoing_global_search_event( text) if feedback is not None: text = feedback[0] elif search_mode == "rooms": name = self.frame.RoomSearchCombo.get_child().get_text() # Space after Joined Rooms is important, so it doesn't conflict # with any possible real room if name != _("Joined Rooms ") and not name.isspace(): room = name feedback = self.frame.np.pluginhandler.outgoing_room_search_event( room, text) if feedback is not None: (room, text) = feedback elif search_mode == "buddies": feedback = self.frame.np.pluginhandler.outgoing_buddy_search_event( text) if feedback is not None: text = feedback[0] elif search_mode == "user": user = self.frame.UserSearchCombo.get_child().get_text().strip() if user: users = [user] else: return feedback = self.frame.np.pluginhandler.outgoing_user_search_event( users, text) if feedback is not None: (users, text) = feedback else: log.add_warning( _("Unknown search mode, not using plugin system. Fix me!")) feedback = True if feedback is not None: self.do_search(text, search_mode, users, room) self.frame.search_entry.set_text("") def do_search(self, text, mode, users=[], room=None): # Get excluded words (starting with "-") searchterm_words = text.split() searchterm_words_ignore = (p[1:] for p in searchterm_words if p.startswith('-') and len(p) > 1) # Remove words starting with "-", results containing these are excluded by us later searchterm_without_excluded = re.sub(r'(\s)-\w+', r'\1', text) if self.frame.np.config.sections["searches"]["remove_special_chars"]: """ Remove special characters from search term SoulseekQt doesn't seem to send search results if special characters are included (July 7, 2020) """ searchterm_without_excluded = re.sub(r'\W+', ' ', searchterm_without_excluded) # Remove trailing whitespace searchterm_without_excluded = searchterm_without_excluded.strip() # Append excluded words searchterm_with_excluded = searchterm_without_excluded for word in searchterm_words_ignore: searchterm_with_excluded += " -" + word items = self.frame.np.config.sections["searches"]["history"] if searchterm_with_excluded in items: items.remove(searchterm_with_excluded) items.insert(0, searchterm_with_excluded) # Clear old items del items[15:] self.frame.np.config.write_configuration() # Repopulate the combo list self.frame.SearchEntryCombo.get_model().clear() templist = [] for i in items: if i not in templist: templist.append(i) for i in templist: self.frame.search_entry_combo_model.append([i]) if mode == "user" and users != [] and users[0] != '': self.usersearches[self.searchid] = users search = self.create_tab(self.searchid, searchterm_with_excluded, mode, showtab=True) if search[2] is not None: self.set_current_page(self.page_num(search[2].Main)) if mode == "global": self.do_global_search(self.searchid, searchterm_without_excluded) elif mode == "rooms": self.do_rooms_search(self.searchid, searchterm_without_excluded, room) elif mode == "buddies": self.do_buddies_search(self.searchid, searchterm_without_excluded) elif mode == "user" and users != [] and users[0] != '': self.do_peer_search(self.searchid, searchterm_without_excluded, users) self.searchid += 1 def do_global_search(self, id, text): self.frame.np.queue.put(slskmessages.FileSearch(id, text)) """ Request a list of related searches from the server. Seemingly non-functional since 2018 (always receiving empty lists). """ # self.frame.np.queue.put(slskmessages.RelatedSearch(text)) def do_rooms_search(self, id, text, room=None): if room is not None: self.frame.np.queue.put(slskmessages.RoomSearch(room, id, text)) else: for room in self.frame.chatrooms.roomsctrl.joinedrooms: self.frame.np.queue.put(slskmessages.RoomSearch( room, id, text)) def do_buddies_search(self, id, text): for i in self.frame.np.config.sections["server"]["userlist"]: user = i[0] self.frame.np.queue.put(slskmessages.UserSearch(user, id, text)) def do_peer_search(self, id, text, users): for user in users: self.frame.np.send_message_to_peer( user, slskmessages.FileSearchRequest(None, id, text)) def get_user_search_name(self, id): if id in self.usersearches: users = self.usersearches[id] if len(users) > 1: return _("Users") elif len(users) == 1: return users[0] return _("User") def create_tab(self, id, text, mode, remember=False, showtab=True, ignored=False): tab = Search(self, text, id, mode, remember, showtab) if showtab: self.show_tab(tab, id, text, mode) search = [id, text, tab, mode, remember, ignored] self.searches[id] = search return search def show_tab(self, tab, id, text, mode): length = 15 if mode == "rooms": fulltext = "(" + _("Rooms") + ") " + text elif mode == "buddies": fulltext = "(" + _("Buddies") + ") " + text elif mode == "user": fulltext = "(" + self.get_user_search_name(id) + ") " + text else: fulltext = text length = 20 label = fulltext[:length] self.append_page(tab.Main, label, tab.on_close, fulltext=fulltext) def show_result(self, msg, username, country): try: search = self.searches[msg.token] except KeyError: return if search[5]: # Tab is ignored return if search[2] is None: search = self.create_tab(search[0], search[1], search[3], search[4], showtab=False) counter = len(search[2].all_data) + 1 # No more things to add because we've reached the max_stored_results limit if counter > self.maxstoredresults: # Ignore tab search[5] = True return search[2].add_user_results(msg, username, country) def remove_tab(self, tab): if tab.id in self.searches: search = self.searches[tab.id] if search[5]: # Tab is ignored, delete search del self.searches[tab.id] else: search[2] = None self.remove_page(tab.Main) tab.Main.destroy() def update_visuals(self): for id in self.searches.values(): if id[2] is None: continue id[2].update_visuals() self.wish_list.update_visuals() def save_columns(self): page_num = self.get_current_page() if page_num is not None: page = self.get_nth_page(page_num) for name, search in self.searches.items(): if search[2] is None: continue if search[2].Main == page: search[2].save_columns() break def tab_popup(self, search_id): popup = PopupMenu(self.frame) popup.setup( ("#" + _("Copy Search Term"), self.searches[search_id][2].on_copy_search_term), ("", None), ("#" + _("Clear All Results"), self.searches[search_id][2].on_clear), ("#" + _("Close This Tab"), self.searches[search_id][2].on_close)) return popup def on_tab_click(self, widget, event, child): if event.type == Gdk.EventType.BUTTON_PRESS: search_id = None n = self.page_num(child) page = self.get_nth_page(n) for search, data in self.searches.items(): if data[2] is None: continue if data[2].Main is page: search_id = search break if search_id is None: log.add_warning(_("Search ID was none when clicking tab")) return if event.button == 2: self.searches[search_id][2].on_close(widget) return True if event.button == 3: menu = self.tab_popup(search_id) menu.popup(None, None, None, None, event.button, event.time) return True return False
class Searches(IconNotebook): def __init__(self, frame): self.frame = frame self.searches = {} self.usersearches = {} self.users = {} IconNotebook.__init__( self, self.frame.images, angle=config.sections["ui"]["labelsearch"], tabclosers=config.sections["ui"]["tabclosers"], show_hilite_image=config.sections["notifications"] ["notification_tab_icons"], reorderable=config.sections["ui"]["tab_reorderable"], notebookraw=self.frame.SearchNotebookRaw) self.popup_enable() self.load_config() self.wish_list = WishList(frame, self) self.update_visuals() def load_config(self): """ Add search history to SearchCombo later and connect Wishlist, after widgets have been created. """ items = config.sections["searches"]["history"] templist = [] for i in items: if not isinstance(i, str): continue if i not in templist: templist.append(i) for i in templist: self.frame.SearchCombo.append_text(i) def on_search(self): self.save_columns() text = self.frame.SearchEntry.get_text().strip() if not text: return users = [] room = None search_mode = self.frame.SearchMethod.get_active_id() feedback = None if search_mode == "global": feedback = self.frame.np.pluginhandler.outgoing_global_search_event( text) if feedback is not None: text = feedback[0] elif search_mode == "rooms": name = self.frame.RoomSearchEntry.get_text() # Space after Joined Rooms is important, so it doesn't conflict # with any possible real room if name != _("Joined Rooms ") and not name.isspace(): room = name feedback = self.frame.np.pluginhandler.outgoing_room_search_event( room, text) if feedback is not None: (room, text) = feedback elif search_mode == "buddies": feedback = self.frame.np.pluginhandler.outgoing_buddy_search_event( text) if feedback is not None: text = feedback[0] elif search_mode == "user": user = self.frame.UserSearchEntry.get_text().strip() if user: users = [user] else: return feedback = self.frame.np.pluginhandler.outgoing_user_search_event( users, text) if feedback is not None: (users, text) = feedback else: log.add_warning( "Unknown search mode, not using plugin system. Fix me!") feedback = True if feedback is None: return search_id, searchterm_with_excluded, searchterm_without_excluded = self.frame.np.search.do_search( text, search_mode, users, room) search = self.create_tab(search_id, searchterm_with_excluded, search_mode, showtab=True) if search["tab"] is not None: self.set_current_page(self.page_num(search["tab"].Main)) # Repopulate the combo list self.frame.SearchCombo.remove_all() items = config.sections["searches"]["history"] for i in items: if not isinstance(i, str): continue self.frame.SearchCombo.append_text(i) if search_mode == "user" and users: self.usersearches[search_id] = users def set_wishlist_interval(self, msg): self.wish_list.set_interval(msg) def clear_search_history(self): self.frame.SearchEntry.set_text("") config.sections["searches"]["history"] = [] config.write_configuration() self.frame.SearchCombo.remove_all() def clear_filter_history(self): # Clear filter history in config config.sections["searches"]["filterin"] = [] config.sections["searches"]["filterout"] = [] config.sections["searches"]["filtertype"] = [] config.sections["searches"]["filtersize"] = [] config.sections["searches"]["filterbr"] = [] config.sections["searches"]["filtercc"] = [] config.write_configuration() # Update filters in search tabs for id in self.searches.values(): if id["tab"] is None: continue id["tab"].populate_filters(set_default_filters=False) def get_user_search_name(self, id): if id in self.usersearches: users = self.usersearches[id] if len(users) > 1: return _("Users") elif len(users) == 1: return users[0] return _("User") def create_tab(self, id, text, mode, remember=False, showtab=True): tab = Search(self, text, id, mode, remember, showtab) if showtab: self.show_tab(tab, id, text, mode) ignore = False search = { "id": id, "term": text, "tab": tab, "mode": mode, "remember": remember, "ignore": ignore } self.searches[id] = search return search def show_tab(self, tab, id, text, mode): length = 25 template = "(%s) %s" if mode == "rooms": fulltext = template % (_("Rooms"), text) elif mode == "buddies": fulltext = template % (_("Buddies"), text) elif mode == "wishlist": fulltext = template % (_("Wish"), text) elif mode == "user": fulltext = template % (self.get_user_search_name(id), text) else: fulltext = text length = 20 label = fulltext[:length] self.append_page(tab.Main, label, tab.on_close, fulltext=fulltext) def show_search_result(self, msg, username, country): try: search = self.searches[msg.token] except KeyError: return if search["ignore"]: return if search["tab"] is None: search = self.create_tab(search["id"], search["term"], search["mode"], search["remember"], showtab=False) counter = len(search["tab"].all_data) + 1 # No more things to add because we've reached the max_stored_results limit if counter > config.sections["searches"]["max_stored_results"]: return search["tab"].add_user_results(msg, username, country) def remove_tab(self, tab): if tab.id in self.searches: search = self.searches[tab.id] if tab.text not in config.sections["server"]["autosearch"]: del self.searches[tab.id] else: search["tab"] = None search["ignore"] = True self.remove_page(tab.Main) def update_visuals(self): for id in self.searches.values(): if id["tab"] is None: continue id["tab"].update_visuals() self.wish_list.update_visuals() def save_columns(self): """ Save the treeview state of the currently selected tab """ current_page = self.get_nth_page(self.get_current_page()) for search in self.searches.values(): if search["tab"] is None: continue if search["tab"].Main == current_page: search["tab"].save_columns() break def get_search_id(self, child): search_id = None n = self.page_num(child) page = self.get_nth_page(n) for search, data in self.searches.items(): if data["tab"] is None: continue if data["tab"].Main is page: search_id = search break return search_id def on_tab_popup(self, widget, child): search_id = self.get_search_id(child) if search_id is None: log.add_warning(_("Search ID was none when clicking tab")) return False menu = self.searches[search_id]["tab"].tab_menu menu.popup() return True
class Searches(IconNotebook): def __init__(self, frame): self.frame = frame self.searches = {} self.usersearches = {} IconNotebook.__init__( self, self.frame.images, tabclosers=config.sections["ui"]["tabclosers"], show_hilite_image=config.sections["notifications"] ["notification_tab_icons"], notebookraw=self.frame.SearchNotebookRaw) self.load_config() self.wish_list = WishList(frame, self) self.update_visuals() def load_config(self): """ Add search history to SearchCombo later and connect Wishlist, after widgets have been created. """ items = config.sections["searches"]["history"] templist = [] for i in items: if not isinstance(i, str): continue if i not in templist: templist.append(i) for i in templist: self.frame.SearchCombo.append_text(i) def on_search(self): self.save_columns() text = self.frame.SearchEntry.get_text().strip() if not text: return mode = self.frame.SearchMethod.get_active_id() room = self.frame.RoomSearchEntry.get_text() user = self.frame.UserSearchEntry.get_text() search_response = self.frame.np.search.do_search(text, mode, room=room, user=user) if not search_response: return search_id, searchterm_with_excluded, searchterm_without_excluded = search_response if mode == "user" and user: self.usersearches[search_id] = [user] search = self.create_tab(search_id, searchterm_with_excluded, mode, showtab=True) if search["tab"] is not None: self.set_current_page(self.page_num(search["tab"].Main)) # Repopulate the combo list self.frame.SearchCombo.remove_all() items = config.sections["searches"]["history"] for i in items: if not isinstance(i, str): continue self.frame.SearchCombo.append_text(i) def set_wishlist_interval(self, msg): self.wish_list.set_interval(msg) def clear_search_history(self): self.frame.SearchEntry.set_text("") config.sections["searches"]["history"] = [] config.write_configuration() self.frame.SearchCombo.remove_all() def clear_filter_history(self): # Clear filter history in config config.sections["searches"]["filterin"] = [] config.sections["searches"]["filterout"] = [] config.sections["searches"]["filtertype"] = [] config.sections["searches"]["filtersize"] = [] config.sections["searches"]["filterbr"] = [] config.sections["searches"]["filtercc"] = [] config.write_configuration() # Update filters in search tabs for id in self.searches.values(): if id["tab"] is None: continue id["tab"].populate_filters(set_default_filters=False) def get_user_search_name(self, id): if id in self.usersearches: users = self.usersearches[id] if len(users) > 1: return _("Users") elif len(users) == 1: return users[0] return _("User") def create_tab(self, id, text, mode, remember=False, showtab=True): tab = Search(self, text, id, mode, remember, showtab) if showtab: self.show_tab(tab, id, text, mode) ignore = False search = { "id": id, "term": text, "tab": tab, "mode": mode, "remember": remember, "ignore": ignore } self.searches[id] = search return search def show_tab(self, tab, id, text, mode): length = 25 template = "(%s) %s" if mode == "rooms": fulltext = template % (_("Rooms"), text) elif mode == "buddies": fulltext = template % (_("Buddies"), text) elif mode == "wishlist": fulltext = template % (_("Wish"), text) elif mode == "user": fulltext = template % (self.get_user_search_name(id), text) else: fulltext = text length = 20 label = fulltext[:length] self.append_page(tab.Main, label, tab.on_close, fulltext=fulltext) tab.set_label(self.get_tab_label_inner(tab.Main)) def show_search_result(self, msg, username, country): try: search = self.searches[msg.token] except KeyError: return if search["ignore"]: return if search["tab"] is None: search = self.create_tab(search["id"], search["term"], search["mode"], search["remember"], showtab=False) counter = len(search["tab"].all_data) + 1 # No more things to add because we've reached the result limit if counter > config.sections["searches"]["max_displayed_results"]: return search["tab"].add_user_results(msg, username, country) def remove_tab(self, tab): if tab.id in self.searches: search = self.searches[tab.id] if tab.text not in config.sections["server"]["autosearch"]: del self.searches[tab.id] else: search["tab"] = None search["ignore"] = True self.remove_page(tab.Main) def update_visuals(self): for id in self.searches.values(): if id["tab"] is None: continue id["tab"].update_visuals() self.wish_list.update_visuals() def server_disconnect(self): self.wish_list.server_disconnect() def save_columns(self): """ Save the treeview state of the currently selected tab """ current_page = self.get_nth_page(self.get_current_page()) for search in self.searches.values(): if search["tab"] is None: continue if search["tab"].Main == current_page: search["tab"].save_columns() break