diff --git a/mtg-collector/config.py b/mtg-collector/config.py index 7baaa39..63d674f 100644 --- a/mtg-collector/config.py +++ b/mtg-collector/config.py @@ -1,10 +1,11 @@ -import os import gi +import os gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') from gi.repository import Gdk # Title of the Program Window -application_title= "MTG Collector (working title) v0.1" +application_title = "MTG Collector (working title) v0.1" # Path of image cache cache_path= os.path.dirname(__file__) + "/.cache/" @@ -15,4 +16,4 @@ green_color = Gdk.color_parse('#87ff89') red_color = Gdk.color_parse('#ff6d6d') # When True Search view will list a card multiple times for each set they appear in -show_from_all_sets=False \ No newline at end of file +show_from_all_sets = False diff --git a/mtg-collector/library.py b/mtg-collector/library.py index d3b43fb..74166ef 100644 --- a/mtg-collector/library.py +++ b/mtg-collector/library.py @@ -1,8 +1,7 @@ -import os +import config import util import details import gi -from psutil._compat import xrange gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GdkPixbuf @@ -11,9 +10,7 @@ class LibraryView(Gtk.Grid): def __init__(self): Gtk.Grid.__init__(self) self.set_column_spacing(5) - - # Dictionary to keep link IDs in Flowbox to IDs of Cards - self.flowbox_ids = {} + self.current_card = None # region Demo left bar # Search Box @@ -36,59 +33,129 @@ class LibraryView(Gtk.Grid): # endregion # The Small Card Flow - self.cardScroller = Gtk.ScrolledWindow(hexpand=True, vexpand=True) - self.cardScroller.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) - self.cardFlow = Gtk.FlowBox() - self.cardFlow.set_valign(Gtk.Align.START) - self.cardFlow.set_max_children_per_line(50) - self.cardFlow.set_selection_mode(Gtk.SelectionMode.SINGLE) - self.cardFlow.connect("child-activated", self.card_clicked) - self.cardScroller.add(self.cardFlow) + # self.cardScroller = Gtk.ScrolledWindow(hexpand=True, vexpand=True) + # self.cardScroller.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + # self.cardFlow = Gtk.FlowBox() + # self.cardFlow.set_valign(Gtk.Align.START) + # self.cardFlow.set_max_children_per_line(50) + # self.cardFlow.set_selection_mode(Gtk.SelectionMode.SINGLE) + # self.cardFlow.connect("child-activated", self.card_clicked) + # self.cardScroller.add(self.cardFlow) + + # 0=ID, 1=Name, 2=Types, 3=Rarity, 4=Mana, 5=CMC(for sorting), + self.store = Gtk.ListStore(int, str, str, str, GdkPixbuf.Pixbuf, int) + self.lib_tree = Gtk.TreeView(self.store) + self.lib_tree.set_rules_hint(True) + + self.lib_list = Gtk.ScrolledWindow(hexpand=True, vexpand=True) + self.lib_list.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + self.lib_list.add(self.lib_tree) + + # region List Definitions + + renderer = Gtk.CellRendererText() + image_renderer = Gtk.CellRendererPixbuf() + + col_id = Gtk.TreeViewColumn(title="Multiverse ID", cell_renderer=renderer, text= 0) + col_id.set_visible(False) + + col_title = Gtk.TreeViewColumn(title="Card Name", cell_renderer=renderer, text= 1) + col_title.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) + col_title.set_sort_column_id(1) + + col_types = Gtk.TreeViewColumn(title="Card Types", cell_renderer=renderer, text=2) + col_types.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) + col_types.set_sort_column_id(2) + + col_rarity = Gtk.TreeViewColumn(title="Rarity", cell_renderer=renderer, text=3) + col_rarity.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) + col_rarity.set_sort_column_id(3) + + col_mana = Gtk.TreeViewColumn(title="Mana Cost", cell_renderer=image_renderer, pixbuf=4) + col_mana.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) + col_mana.set_sort_column_id(5) + + col_cmc = Gtk.TreeViewColumn(title="CMC", cell_renderer=renderer, text=5) + col_cmc.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) + col_cmc.set_visible(False) + + self.lib_tree.append_column(col_id) + self.lib_tree.append_column(col_title) + self.lib_tree.append_column(col_types) + self.lib_tree.append_column(col_rarity) + self.lib_tree.append_column(col_mana) + self.lib_tree.append_column(col_cmc) + + self.selection = self.lib_tree.get_selection() + self.selection.connect("changed", self.on_card_selected) + # endregion # Detailed Card View self.details = details.DetailBar() + self.remove_button = Gtk.Button("Remove from Library") + self.remove_button.modify_bg(Gtk.StateType.NORMAL, config.red_color) + self.remove_button.set_no_show_all(True) + self.remove_button.connect("clicked", self.remove_button_clicked) + left_pane = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) left_pane.pack_start(self.searchbox, False, False, 0) left_pane.pack_start(self.filterBox, False, False, 0) + right_pane = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) + right_pane.pack_start(self.details, True, True, 0) + right_pane.pack_start(Gtk.VSeparator(), False, False, 2) + right_pane.pack_start(self.remove_button, False, False, 2) + # Bring it all together self.attach(left_pane, 0, 0, 1, 1) + self.attach(Gtk.VSeparator(), 1, 0, 1, 1) - self.attach(self.cardScroller, 2, 0, 1, 1) + + self.attach(self.lib_list, 2, 0, 1, 1) + self.attach(Gtk.VSeparator(), 3, 0, 1, 1) - self.attach(self.details, 4, 0, 1, 1) - self.fill_flowbox() + self.attach(right_pane, 4, 0, 1, 1) + + self.fill_lib_list() + + def on_card_selected(self, selection): + (model, pathlist) = selection.get_selected_rows() + card_id = None + for path in pathlist: + iter = model.get_iter(path) + card_id = model.get_value(iter, 0) + + if not card_id is None: + selected_card = util.library[card_id] + + if not selected_card is None: + self.details.set_card_detail(selected_card) + self.current_card = selected_card + self.remove_button.set_visible(True) + + def fill_lib_list(self): + self.store.clear() + self.details.reset() + self.current_card = None + self.remove_button.set_visible(False) - def fill_flowbox(self): - id_counter = 0 for id, card in util.library.items(): - image = Gtk.Image() - pixbuf = util.load_card_image(card, 63 * 2, 88 * 2) - image.set_from_pixbuf(pixbuf) - - self.cardFlow.insert(image, id_counter) - - self.flowbox_ids[id_counter] = card.multiverse_id - id_counter += 1 + self.store.append([id, card.name, + " ".join(card.types), + card.rarity, + util.create_mana_icons(card.mana_cost), + card.cmc]) def card_clicked(self, flowbox, flowboxchild): card_id = self.flowbox_ids[flowboxchild.get_index()] card = util.library[card_id] + self.current_card = card self.details.set_card_detail(card) + self.remove_button.set_visible(True) - - def add_test_image(self): - image = Gtk.Image() - pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(os.path.dirname(__file__) + '/resources/images/demo.jpg', 63*2, 88*2) - image.set_from_pixbuf(pixbuf) - - return image - - def create_flowbox(self, flowbox): - - for nr in xrange(0, 50): - image = self.add_test_image() - flowbox.add(image) + def remove_button_clicked(self, button): + util.remove_card_from_lib(self.current_card) + self.fill_lib_list() diff --git a/mtg-collector/search.py b/mtg-collector/search.py index ea4457b..ef502d4 100644 --- a/mtg-collector/search.py +++ b/mtg-collector/search.py @@ -167,7 +167,7 @@ class SearchView(Gtk.Grid): col_id.set_visible(False) col_image = Gtk.TreeViewColumn(title="Image", cell_renderer=image, pixbuf=1) col_image.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) - col_name = Gtk.TreeViewColumn(title="Name", cell_renderer=title, text=2) + col_name = Gtk.TreeViewColumn(title="Card Name", cell_renderer=title, text=2) col_name.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) col_text = Gtk.TreeViewColumn(title="Card Text", cell_renderer=info, text=3) col_text.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) diff --git a/mtg-collector/util.py b/mtg-collector/util.py index 6c09f0e..14353f8 100644 --- a/mtg-collector/util.py +++ b/mtg-collector/util.py @@ -11,7 +11,7 @@ import six.moves.cPickle as pickle # Locally stored images for faster loading times -imagecache = [] +imagecache = {} manaicons = {} set_list = [] @@ -21,13 +21,20 @@ library = {} window = None status_bar = None +unsaved_changes = False + def add_card_to_lib(card): library[card.multiverse_id] = card + global unsaved_changes + unsaved_changes = True def remove_card_from_lib(card): del library[card.multiverse_id] + global unsaved_changes + unsaved_changes = True + # Debug function for library def print_lib(menuItem): @@ -46,6 +53,8 @@ def save_library(): # Serialize library object using pickle try: pickle.dump(library, open(path, 'wb')) + global unsaved_changes + unsaved_changes = False push_status("Library saved.") print("Library saved") except: @@ -120,8 +129,8 @@ def reload_image_cache(): imagecache.clear() for image in imageslist: try: - img = PImage.open(config.image_cache_path + image) - imagecache.append(img) + pixbuf = GdkPixbuf.Pixbuf.new_from_file(config.image_cache_path + image) + imagecache[image] = pixbuf except OSError as err: print("Error loading image: " + str(err)) @@ -137,20 +146,20 @@ def load_card_image_online(card, sizex, sizey): print("No Image URL provided") return load_dummy_image(sizex, sizey) filename = config.image_cache_path + card.multiverse_id.__str__() + ".PNG" - print("Loading image for " + card.name + "from: " + url) + print("Loading image for " + card.name + "from: " + url) response = request.urlretrieve(url, filename) + reload_image_cache() return GdkPixbuf.Pixbuf.new_from_file_at_size(filename, sizex, sizey) def load_card_image(card, sizex, sizey): # Try loading from disk, if file exists - for image in imagecache: - filename = os.path.basename(image.filename) - if filename == card.multiverse_id.__str__() + ".PNG": - return GdkPixbuf.Pixbuf.new_from_file_at_size(image.filename, sizex, sizey) - - # No file in local cache found - return load_card_image_online(card, sizex, sizey) + filename = str(card.multiverse_id) + ".PNG" + if imagecache.__contains__(filename): + pixbuf = imagecache[filename] + return pixbuf.scale_simple(sizex, sizey, GdkPixbuf.InterpType.BILINEAR) + else: + return load_card_image_online(card, sizex, sizey) def create_mana_icons(mana_string):