From e88fdbbf3573a7d9c11020ae1d2fb32127525397 Mon Sep 17 00:00:00 2001 From: luxick Date: Thu, 29 Jun 2017 14:52:15 +0200 Subject: [PATCH] Add cards to want lists from search view. --- cardvault/application.py | 16 +-- cardvault/cardlist.py | 39 +++--- cardvault/gui/detailswindow.glade | 222 +++++++++++++++++------------- cardvault/gui/search.glade | 4 +- cardvault/gui/wants.glade | 1 + cardvault/handlers.py | 40 ++++-- cardvault/lib_funct.py | 6 +- cardvault/search_funct.py | 6 +- cardvault/util.py | 62 ++++++--- cardvault/wants_funct.py | 3 +- 10 files changed, 230 insertions(+), 169 deletions(-) diff --git a/cardvault/application.py b/cardvault/application.py index 7fd80fd..e9056a1 100644 --- a/cardvault/application.py +++ b/cardvault/application.py @@ -99,7 +99,7 @@ class Application: window.set_title(card.name) # Card Image container = builder.get_object("imageContainer") - pixbuf = self.get_card_image(card, 63 * 5, 88 * 5) + pixbuf = util.load_card_image(card, 63 * 5, 88 * 5, self.image_cache) image = Gtk.Image().new_from_pixbuf(pixbuf) container.add(image) # Name @@ -110,7 +110,7 @@ class Application: supertypes = " - " + " ".join(card.subtypes) types = " ".join(card.types) + supertypes builder.get_object("cardTypes").set_text(types) - # Rarity + # Rarityget_card_image builder.get_object("cardRarity").set_text(card.rarity if card.rarity else "") # Release builder.get_object("cardReleaseDate").set_text(card.release_date if card.release_date else "") @@ -339,16 +339,6 @@ class Application: l.remove(card) util.log("Removed '{}' from wants list '{}'".format(card.name, list), util.LogLevel.Info) - def get_card_image(self, card, sizex, sizey): - # Try using file from local cache, or load online - try: - pixbuf = self.image_cache[card.multiverse_id] - except KeyError as err: - util.log("No local image for " + card.name + ". Loading from " + card.image_url, util.LogLevel.Info) - pixbuf = util.load_card_image_online(card, sizex, sizey) - self.image_cache[card.multiverse_id] = pixbuf - return pixbuf - def get_mana_icons(self, mana_string): if not mana_string: util.log("No mana string provided", util.LogLevel.Warning) @@ -371,5 +361,5 @@ class Application: def main(): - win = Application() + Application() Gtk.main() diff --git a/cardvault/cardlist.py b/cardvault/cardlist.py index 1666872..3f605c9 100644 --- a/cardvault/cardlist.py +++ b/cardvault/cardlist.py @@ -12,15 +12,16 @@ gi.require_version('Gdk', '3.0') class CardList(Gtk.ScrolledWindow): - def __init__(self, with_filter, app : 'application.Application'): + def __init__(self, filtered, app: 'application.Application', row_colors: Dict[str, str]): Gtk.ScrolledWindow.__init__(self) self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.set_hexpand(True) self.set_vexpand(True) - self.filtered = with_filter + self.filtered = filtered self.lib = {} self.app = app + self.row_colors = row_colors # Columns are these: # 0 Multiverse ID @@ -127,34 +128,24 @@ class CardList(Gtk.ScrolledWindow): output[card_id] = card return output - def update(self, library: Dict[str, Type[Card]], colorize=False): + def update(self, library: Dict[str, Type[Card]]): self.store.clear() if library is None: return self.lib = library + # Disable update if tree is filtered (performance) if self.filtered: self.list.freeze_child_notify() self.list.set_model(None) util.log("Updating tree view", util.LogLevel.Info) - start = time.time() - all_wants = self.app.get_wanted_card_ids() - for card_id, card in library.items(): + for card in library.values(): if card.multiverse_id is not None: - - if self.app.library.__contains__(card_id) and colorize: - color = util.card_view_colors["owned"] - elif all_wants.__contains__(card_id) and colorize: - color = util.card_view_colors["wanted"] - else: - color = util.card_view_colors["unowned"] - if card.type == "Land": - mana_cost = None - else: - mana_cost = self.app.get_mana_icons(card.mana_cost) + color = self.get_row_color(card, self.app.library, all_wants, self.row_colors) + mana_cost = None if card.type == "Land" else self.app.get_mana_icons(card.mana_cost) item = [card.multiverse_id, card.name, " ".join(card.supertypes if card.supertypes else ""), @@ -169,15 +160,16 @@ class CardList(Gtk.ScrolledWindow): color] self.store.append(item) end = time.time() - util.log("Time to build Table: " + str(round(end - start, 3)) + "s", util.LogLevel.Info) util.log("Total entries: " + str(len(self.lib)), util.LogLevel.Info) + # Reactivate update for filtered trees if self.filtered: self.list.set_model(self.filter_and_sort) self.list.thaw_child_notify() - def compare_rarity(self, model, row1, row2, user_data): + @staticmethod + def compare_rarity(model, row1, row2, user_data): # Column for rarity sort_column = 4 value1 = model.get_value(row1, sort_column) @@ -189,4 +181,13 @@ class CardList(Gtk.ScrolledWindow): else: return 1 + @staticmethod + def get_row_color(card, lib: dict, wants: dict, colors: dict) -> str: + if lib.__contains__(card.multiverse_id): + return colors["owned"] + elif wants.__contains__(card.multiverse_id): + return colors["wanted"] + else: + return colors["unowned"] + diff --git a/cardvault/gui/detailswindow.glade b/cardvault/gui/detailswindow.glade index 4f864d3..1576cc2 100644 --- a/cardvault/gui/detailswindow.glade +++ b/cardvault/gui/detailswindow.glade @@ -9,10 +9,107 @@ True False - False - False + True + True 5 5 + + + True + False + + + + + + 0 + 0 + + + + + True + False + center + vertical + + + 1 + 0 + + + + + True + False + True + vertical + + + True + False + Rulings + + + + + + False + True + 0 + + + + + 200 + True + True + True + True + in + + + True + False + True + True + + + True + False + 10 + 20 + + + True + False + start + vertical + + + 0 + 0 + 2 + + + + + + + + + False + True + 1 + + + + + 0 + 1 + 3 + + True @@ -210,6 +307,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + 1 @@ -237,103 +358,6 @@ 0 - - - True - False - - - - - - 0 - 0 - - - - - True - False - center - vertical - - - 1 - 0 - - - - - True - False - True - vertical - - - True - False - Rulings - - - - - - False - True - 0 - - - - - 200 - True - True - True - True - in - - - True - False - True - True - - - True - False - 10 - 20 - - - True - False - start - vertical - - - 0 - 0 - 2 - - - - - - - - - False - True - 1 - - - - - 0 - 1 - 3 - - diff --git a/cardvault/gui/search.glade b/cardvault/gui/search.glade index e9c7b97..2e46fd2 100644 --- a/cardvault/gui/search.glade +++ b/cardvault/gui/search.glade @@ -7,10 +7,10 @@ False - + True False - Tag Cards + Add to Wants List True diff --git a/cardvault/gui/wants.glade b/cardvault/gui/wants.glade index 020d0a2..7b43dcc 100644 --- a/cardvault/gui/wants.glade +++ b/cardvault/gui/wants.glade @@ -68,6 +68,7 @@ True True New Wants List + False diff --git a/cardvault/handlers.py b/cardvault/handlers.py index 4f0b1eb..04ff724 100644 --- a/cardvault/handlers.py +++ b/cardvault/handlers.py @@ -3,7 +3,6 @@ gi.require_version('Gtk', '3.0') import datetime import os from gi.repository import Gtk -from typing import Type from cardvault import lib_funct from cardvault import search_funct @@ -32,8 +31,9 @@ class Handlers: if response == Gtk.ResponseType.OK: # prepare export file - file = {"library": self.app.library, "tags": self.app.tags} + file = {"library": self.app.library, "tags": self.app.tags, "wants": self.app.wants} util.export_library(dialog.get_filename(), file) + self.app.push_status("Library exported") dialog.destroy() @@ -54,9 +54,11 @@ class Handlers: imports = util.import_library(dialog.get_filename()) self.app.library = imports[0] self.app.tags = imports[1] + self.app.wants = imports[2] # Cause current page to reload with imported data self.app.current_page.emit('show') self.app.unsaved_changes = True + self.app.push_status("Library imported") dialog.destroy() def on_view_changed(self, item): @@ -90,7 +92,7 @@ class Handlers: results = search_funct.search_cards(search_term, filters) card_list = self.app.ui.get_object("searchResults").get_child() - card_list.update(results, colorize=True) + card_list.update(results) self.app.ui.get_object("searchOverlay").set_visible(False) @@ -111,12 +113,12 @@ class Handlers: card_id = model.get_value(tree_iter, 0) card = card_view.lib[card_id] self.app.add_card_to_lib(card) - search_funct.reload_serach_view(self.app) + search_funct.reload_search_view(self.app) self.app.ui.get_object("searchEntry").grab_focus() def search_tree_popup_showed(self, menu): # Create wants Submenu - wants_item = self.app.ui.get_object("searchListPopupTags") + wants_item = self.app.ui.get_object("searchListPopupWants") wants_sub = Gtk.Menu() wants_item.set_submenu(wants_sub) @@ -125,7 +127,6 @@ class Handlers: wants_sub.add(item) item.set_label(list_name) item.connect('activate', self.search_popup_add_wants) - wants_item.show_all() def search_popup_add_wants(self, item): @@ -134,7 +135,7 @@ class Handlers: cards = card_list.get_selected_cards() for card in cards.values(): self.app.add_card_to_want_list(item.get_label(), card) - search_funct.reload_serach_view(self.app) + search_funct.reload_search_view(self.app) self.app.push_status("Added " + str(len(cards)) + " card(s) to Want List '" + item.get_label() + "'") # ---------------------------------Library---------------------------------------------- @@ -255,6 +256,7 @@ class Handlers: def on_new_wants_list_clicked(self, entry): name = entry.get_text() + entry.set_text("") # Check if list name already exists if self.app.wants.__contains__(name): return @@ -271,7 +273,15 @@ class Handlers: def do_wants_tree_press_event(self, treeview, event): if event.button == 3: # right click path = treeview.get_path_at_pos(int(event.x), int(event.y)) + # Get the selection + selection = treeview.get_selection() + # Get the selected path(s) + rows = selection.get_selected_rows() + # If not clicked on selection, change selected rows if path: + if path[0] not in rows[1]: + selection.unselect_all() + selection.select_path(path[0]) self.app.ui.get_object("wants_wantsListPopup").popup(None, None, None, None, 0, event.time) return True @@ -282,8 +292,9 @@ class Handlers: tag = model.get_value(tree_iter, 0) new_name = self.app.show_rename_dialog(tag) - self.app.rename_want_list(tag, new_name) - self.app.current_page.emit('show') + if not tag == new_name: + self.app.rename_want_list(tag, new_name) + self.app.current_page.emit('show') def do_delete_wants_list(self, tree): (model, pathlist) = tree.get_selection().get_selected_rows() @@ -360,11 +371,12 @@ class Handlers: # Get the selected path(s) rows = selection.get_selected_rows() # If not clicked on selection, change selected rows - if path[0] not in rows[1]: - selection.unselect_all() - selection.select_path(path[0]) - self.app.ui.get_object("searchListPopup").emit('show') - self.app.ui.get_object("searchListPopup").popup(None, None, None, None, 0, event.time) + if path: + if path[0] not in rows[1]: + selection.unselect_all() + selection.select_path(path[0]) + self.app.ui.get_object("searchListPopup").emit('show') + self.app.ui.get_object("searchListPopup").popup(None, None, None, None, 0, event.time) return True # ---------------------------------Library Tree---------------------------------------------- diff --git a/cardvault/lib_funct.py b/cardvault/lib_funct.py index 95c9e01..de35640 100644 --- a/cardvault/lib_funct.py +++ b/cardvault/lib_funct.py @@ -1,13 +1,15 @@ -from cardvault import cardlist import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk +from cardvault import util +from cardvault import cardlist + def init_library_view(app): # Create Tree View for library container = app.ui.get_object("libraryContainer") - card_list = cardlist.CardList(True, app) + card_list = cardlist.CardList(True, app, util.GENERIC_TREE_COLORS) card_list.set_name("libScroller") # Show details card_list.list.connect("row-activated", app.handlers.on_library_card_selected) diff --git a/cardvault/search_funct.py b/cardvault/search_funct.py index c7d7350..0080b92 100644 --- a/cardvault/search_funct.py +++ b/cardvault/search_funct.py @@ -26,10 +26,10 @@ def init_search_view(app: 'application.Application'): _init_results_tree(app) -def reload_serach_view(app: 'application.Application'): +def reload_search_view(app: 'application.Application'): results_tree = app.ui.get_object("searchResults").get_child() cards = results_tree.lib - results_tree.update(cards, True) + results_tree.update(cards) def get_filters(app: 'application.Application') -> dict: @@ -94,7 +94,7 @@ def search_cards(term: str, filters: dict) -> dict: def _init_results_tree(app: 'application.Application'): overlay = app.ui.get_object("searchResults") - card_list = cardlist.CardList(False, app) + card_list = cardlist.CardList(False, app, util.SEARCH_TREE_COLORS) card_list.set_name("resultsScroller") card_list.list.connect("row-activated", app.handlers.on_search_card_selected) card_list.selection.connect("changed", app.handlers.on_search_selection_changed) diff --git a/cardvault/util.py b/cardvault/util.py index 6b2aaec..b82be5a 100644 --- a/cardvault/util.py +++ b/cardvault/util.py @@ -32,6 +32,21 @@ START_PAGE = "search" LOG_LEVEL = 1 +# Colors for card rows in search view +SEARCH_TREE_COLORS ={ + "unowned": "black", + "wanted": "#D39F30", + "owned": "#62B62F" +} + +# Colors for card rows in every default view +GENERIC_TREE_COLORS ={ + "unowned": "black", + "wanted": "black", + "owned": "black" +} + + default_config = { "hide_duplicates_in_search": False, "start_page": "search", @@ -49,12 +64,6 @@ legality_colors ={ "Legal": "#62B62F" } -card_view_colors ={ - "unowned": "black", - "wanted": "#D39F30", - "owned": "#62B62F" -} - rarity_dict = { "special": 0, "common": 1, @@ -126,7 +135,7 @@ def reload_image_cache(path: str) -> dict: pixbuf = GdkPixbuf.Pixbuf.new_from_file(path + imagefile) # Strip filename extension imagename = os.path.splitext(imagefile)[0] - cache[imagename] = pixbuf + cache[int(imagename)] = pixbuf except OSError as err: log("Error loading image: " + str(err), LogLevel.Error) except GLib.GError as err: @@ -172,14 +181,22 @@ def load_mana_icons(path: str) -> dict: return icons +def net_load_set_list() -> dict: + """ Load the list of all MTG sets from the Gather""" + try: + sets = Set.all() + except MtgException as err: + log(str(err), LogLevel.Error) + return {} + return sets + + def load_sets(filename: str) -> dict: - if not os.path.isfile(filename): + # TODO Update Data function + # if not os.path.isfile(filename): + if True: # use mtgsdk api to retrieve al list of all sets - try: - sets = Set.all() - except MtgException as err: - log(str(err), LogLevel.Error) - return {} + sets = net_load_set_list() # Serialize the loaded data to a file pickle.dump(sets, open(filename, 'wb')) # Deserialize set data from local file @@ -209,13 +226,15 @@ def import_library(path: str) -> (): try: library = imported["library"] tags = imported["tags"] + wants = imported["wants"] except KeyError as err: log("Invalid library format " + str(err), LogLevel.Error) library = {} tags = {} + wants = {} log("Library imported", LogLevel.Info) - return library, tags + return library, tags, wants def save_file(path, file): @@ -245,14 +264,25 @@ def load_dummy_image(size_x: int, size_y: int) -> GdkPixbuf: + '/resources/images/dummy.jpg', size_x, size_y) -def load_card_image_online(card, size_x: int, size_y: int) -> GdkPixbuf: +def load_card_image(card: 'mtgsdk.Card', size_x: int, size_y: int, cache: dict) -> GdkPixbuf: + """ Retrieve an card image from cache or alternatively load from gatherer""" + try: + image = cache[card.multiverse_id] + except KeyError as err: + log("No local image for " + card.name + ". Loading from " + card.image_url, LogLevel.Info) + filename, image = net_load_card_image(card, size_x, size_y) + cache[card.multiverse_id] = image + return image + + +def net_load_card_image(card, size_x: int, size_y: int) -> (str, GdkPixbuf): url = card.image_url if url is None: log("No Image URL for " + card.name, LogLevel.Warning) return load_dummy_image(size_x, size_y) filename = IMAGE_CACHE_PATH + str(card.multiverse_id) + ".png" request.urlretrieve(url, filename) - return GdkPixbuf.Pixbuf.new_from_file_at_size(filename, size_x, size_y) + return filename, GdkPixbuf.Pixbuf.new_from_file_at_size(filename, size_x, size_y) def create_mana_icons(icons: dict, mana_string: str) -> GdkPixbuf: diff --git a/cardvault/wants_funct.py b/cardvault/wants_funct.py index efefa0a..cb12f3e 100644 --- a/cardvault/wants_funct.py +++ b/cardvault/wants_funct.py @@ -4,13 +4,14 @@ from gi.repository import Gtk from cardvault import cardlist from cardvault import application +from cardvault import util def init_wants_view(app: 'application.Application'): # Get container for Cardlist Tree container = app.ui.get_object("wantsListContainer") # Create new Cardlist - card_list = cardlist.CardList(True, app) + card_list = cardlist.CardList(True, app, util.GENERIC_TREE_COLORS) card_list.set_name("wantsScroller") # Show details card_list.list.connect("row-activated", app.handlers.on_wants_card_selected)