Esempio n. 1
0
    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()
Esempio n. 2
0
    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()
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
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