diff --git a/cardvault/__init__.py b/cardvault/__init__.py index e69de29..5315975 100644 --- a/cardvault/__init__.py +++ b/cardvault/__init__.py @@ -0,0 +1 @@ +from cardvault import application \ No newline at end of file diff --git a/cardvault/application.py b/cardvault/application.py index 2a8cb51..995147e 100644 --- a/cardvault/application.py +++ b/cardvault/application.py @@ -18,19 +18,19 @@ from cardvault import handlers from cardvault import util from cardvault import search_funct from cardvault import lib_funct +from cardvault import wants_funct class Application: - # ---------------------------------Initialize the Application---------------------------------------------- def __init__(self): - # Load ui files self.ui = Gtk.Builder() self.ui.add_from_file(util.get_ui_filename("mainwindow.glade")) self.ui.add_from_file(util.get_ui_filename("overlays.glade")) self.ui.add_from_file(util.get_ui_filename("search.glade")) self.ui.add_from_file(util.get_ui_filename("library.glade")) + self.ui.add_from_file(util.get_ui_filename("wants.glade")) self.current_page = None self.unsaved_changes = False @@ -40,7 +40,8 @@ class Application: self.pages = { "search": self.ui.get_object("searchView"), "library": self.ui.get_object("libraryView"), - "decks": not_found + "decks": not_found, + "wants": self.ui.get_object("wantsView") } # Load configuration file @@ -58,15 +59,20 @@ class Application: self.library = None self.tags = None + self.wants = None self.load_library() self.handlers = handlers.Handlers(self) self.ui.connect_signals(self.handlers) + # Inizialize the views + search_funct.init_search_view(self) lib_funct.init_library_view(self) + wants_funct.init_wants_view(self) + self.ui.get_object("mainWindow").connect('delete-event', Gtk.main_quit) self.ui.get_object("mainWindow").show_all() self.push_status("Card Vault ready.") @@ -206,16 +212,26 @@ class Application: def load_library(self): all_existing = True + # Load library file self.library = util.load_file(util.get_root_filename("library")) if not self.library: all_existing = False self.library = {} + # Load tags file self.tags = util.load_file(util.get_root_filename("tags")) if not self.tags: all_existing = False self.tags = {} + + # Load wants lists + self.wants = util.load_file(util.get_root_filename("wants")) + if not self.wants: + all_existing = False + self.wants = {} + + # If parts were missing save to create the files if not all_existing: self.save_library() self.push_status("Library loaded") @@ -267,6 +283,12 @@ class Application: util.log("Tag '" + old + "' renamed to '" + new + "'", util.LogLevel.Info) self.unsaved_changes = True + def add_want_list(self, name): + self.wants[name] = {} + util.log("Want list '" + name + "' created", util.LogLevel.Info) + self.push_status("Created want list '" + name + "'") + self.unsaved_changes = True + def add_card_to_lib(self, card, tag=None): if tag is not None: self.tag_card(card, tag) diff --git a/cardvault/gui/library.glade b/cardvault/gui/library.glade index fd79874..81ada8e 100644 --- a/cardvault/gui/library.glade +++ b/cardvault/gui/library.glade @@ -6,6 +6,14 @@ True False + + + True + False + Tag Card + True + + True diff --git a/cardvault/gui/mainwindow.glade b/cardvault/gui/mainwindow.glade index fafcf09..f9be887 100644 --- a/cardvault/gui/mainwindow.glade +++ b/cardvault/gui/mainwindow.glade @@ -138,6 +138,19 @@ + + + wants + True + False + Wants + True + True + searchViewItem + + + + diff --git a/cardvault/gui/overlays.glade b/cardvault/gui/overlays.glade index 28ba536..d0f3e0f 100644 --- a/cardvault/gui/overlays.glade +++ b/cardvault/gui/overlays.glade @@ -225,4 +225,57 @@ + + True + False + center + center + vertical + 10 + True + + + True + False + True + end + 100 + edit-find-symbolic + + + 0 + 0 + + + + + True + False + True + center + No Results + + + + + + + 0 + 1 + + + + + True + False + True + start + Use the Search function to add cards to your wants + + + 0 + 2 + + + diff --git a/cardvault/gui/search.glade b/cardvault/gui/search.glade index aaf5b3f..bdfe174 100644 --- a/cardvault/gui/search.glade +++ b/cardvault/gui/search.glade @@ -287,6 +287,7 @@ Add to Library True + False True True diff --git a/cardvault/gui/wants.glade b/cardvault/gui/wants.glade new file mode 100644 index 0000000..5b72104 --- /dev/null +++ b/cardvault/gui/wants.glade @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + Wants + True + True + + + + True + False + vertical + + + True + True + never + in + + + True + True + True + True + wantsListsStore + 0 + + + + + + Wants List + + + + 1 + + + + + + + + + False + True + 0 + + + + + True + False + + + True + True + New Wants List + + + False + True + 0 + + + + + Add + True + True + True + + + + False + True + 1 + + + + + False + True + 1 + + + + + False + True + + + + + True + False + vertical + + + True + False + + + + + + + + + + + + False + True + 0 + + + + + True + False + True + True + + + + + + False + True + 1 + + + + + True + True + + + + diff --git a/cardvault/handlers.py b/cardvault/handlers.py index 1f96103..d7f62ff 100644 --- a/cardvault/handlers.py +++ b/cardvault/handlers.py @@ -1,20 +1,23 @@ import gi +gi.require_version('Gtk', '3.0') import datetime import os from gi.repository import Gtk - -gi.require_version('Gtk', '3.0') +from typing import Type from cardvault import lib_funct from cardvault import search_funct +from cardvault import wants_funct from cardvault import util +from cardvault import application class Handlers: def __init__(self, app): + self.app = Type[application.Application] self.app = app - # ---------------------------------Main Window---------------------------------------------- + # ---------------------------------Main Window---------------------------------------------- def do_save_library(self, item): self.app.save_library() @@ -78,7 +81,7 @@ class Handlers: if response == Gtk.ResponseType.YES: self.app.save_library() - # ---------------------------------Search---------------------------------------------- + # ---------------------------------Search---------------------------------------------- def do_search_cards(self, sender): search_term = self.app.ui.get_object("searchEntry").get_text() @@ -110,8 +113,9 @@ class Handlers: card = card_view.lib[card_id] self.app.add_card_to_lib(card) search_funct.reload_serach_view(self.app) + self.app.ui.get_object("searchEntry").grab_focus() - # ---------------------------------Library---------------------------------------------- + # ---------------------------------Library---------------------------------------------- def do_reload_library(self, view): lib_funct.reload_library(self.app) @@ -222,6 +226,19 @@ class Handlers: lib_funct.reload_library(self.app, self.app.current_lib_tag) lib_funct.reload_tag_list(self.app, preserve=True) + # ---------------------------------Wants---------------------------------------------- + + def do_reload_wants(self, view): + wants_funct.reload_wants_view(self.app) + + def on_new_wants_list_clicked(self, entry): + name = entry.get_text() + # Check if list name already exists + if self.app.wants.__contains__(name): + return + self.app.add_want_list(name) + wants_funct.reload_wants_view(self.app) + # Handlers for TreeViews etc. wich have been not added by Glade # ---------------------------------Search Tree---------------------------------------------- @@ -263,3 +280,10 @@ class Handlers: tree_iter = treeview.get_model().get_iter(path[0]) self.app.ui.get_object("libListPopup").emit('show') self.app.ui.get_object("libListPopup").popup(None, None, None, None, 0, event.time) + return True + + # ---------------------------------Wants Tree---------------------------------------------- + + def on_wants_card_selected(self, tree, row, column): + # TODO + pass diff --git a/cardvault/lib_funct.py b/cardvault/lib_funct.py index 45037a1..95c9e01 100644 --- a/cardvault/lib_funct.py +++ b/cardvault/lib_funct.py @@ -1,7 +1,7 @@ from cardvault import cardlist import gi -from gi.repository import Gtk gi.require_version('Gtk', '3.0') +from gi.repository import Gtk def init_library_view(app): @@ -22,7 +22,7 @@ def init_library_view(app): def reload_library(app, tag=None): - if tag == "Untagged": + if tag == "Untagged" or tag == "All": lib = app.get_untagged_cards() tag = None else: diff --git a/cardvault/search_funct.py b/cardvault/search_funct.py index 67d2d9f..5035f2d 100644 --- a/cardvault/search_funct.py +++ b/cardvault/search_funct.py @@ -28,7 +28,9 @@ def init_search_view(app): def reload_serach_view(app): - pass + results_tree = app.ui.get_object("searchResults").get_child() + cards = results_tree.lib + results_tree.update(cards, True) def get_filters(app): diff --git a/cardvault/util.py b/cardvault/util.py index da53b30..6d176b6 100644 --- a/cardvault/util.py +++ b/cardvault/util.py @@ -6,13 +6,13 @@ import re from urllib import request import gi +gi.require_version('Gtk', '3.0') +from gi.repository import GdkPixbuf import six.moves.cPickle as pickle from PIL import Image as PImage -from gi.repository import GdkPixbuf - -gi.require_version('Gtk', '3.0') from mtgsdk import Set +from mtgsdk import Card from mtgsdk import MtgException # Title of the Program Window @@ -72,13 +72,13 @@ class LogLevel(enum.Enum): Info = 3 -def log(message, log_level): +def log(message: str, log_level: LogLevel): if log_level.value <= LOG_LEVEL: level_string = "[" + log_level.name + "] " print(level_string + message) -def parse_config(filename, default): +def parse_config(filename: str, default: dict): config = copy.copy(default) try: with open(filename) as configfile: @@ -99,24 +99,25 @@ def parse_config(filename, default): return config -def save_config(config_dict, filename): +def save_config(config: dict, filename: str): path = os.path.dirname(filename) if not os.path.isdir(path): os.mkdir(path) with open(filename, 'wb') as configfile: - configfile.write(json.dumps(config_dict, sort_keys=True, - indent=4, separators=(',', ': ')).encode('utf-8')) + configfile.write(json.dumps(config, sort_keys=True, + indent=4, separators=(',', ': ')).encode('utf-8')) -def get_root_filename(filename): +def get_root_filename(filename: str) -> str: return os.path.expanduser(os.path.join('~', '.cardvault', filename)) -def get_ui_filename(filename): + +def get_ui_filename(filename: str) -> str: return os.path.expanduser(os.path.join(os.path.dirname(__file__), 'gui', filename)) -def reload_image_cache(path): +def reload_image_cache(path: str) -> dict: cache = {} if not os.path.isdir(path): os.mkdir(path) @@ -132,7 +133,7 @@ def reload_image_cache(path): return cache -def reload_preconstructed_icons(path): +def reload_preconstructed_icons(path: str) -> dict: cache = {} if not os.path.exists(path): os.makedirs(path) @@ -156,10 +157,10 @@ def reload_preconstructed_icons(path): return cache -def load_mana_icons(path): +def load_mana_icons(path: str) -> dict: if not os.path.exists(path): log("Directory for mana icons not found " + path, LogLevel.Error) - return + return {} icons = {} filenames = os.listdir(path) for file in filenames: @@ -170,14 +171,14 @@ def load_mana_icons(path): return icons -def load_sets(filename): +def load_sets(filename: str) -> dict: if not os.path.isfile(filename): # use mtgsdk api to retrieve al list of all sets try: sets = Set.all() except MtgException as err: log(str(err), LogLevel.Error) - return + return {} # Serialize the loaded data to a file pickle.dump(sets, open(filename, 'wb')) # Deserialize set data from local file @@ -197,7 +198,7 @@ def export_library(path, file): log(str(err), LogLevel.Error) -def import_library(path): +def import_library(path: str) -> (): try: imported = pickle.load(open(path, 'rb')) except pickle.UnpicklingError as err: @@ -213,7 +214,7 @@ def import_library(path): tags = {} log("Library imported", LogLevel.Info) - return (library, tags) + return library, tags def save_file(path, file): @@ -226,7 +227,7 @@ def save_file(path, file): log("Saved file " + path, LogLevel.Info) -def load_file(path): +def load_file(path: str): if not os.path.isfile(path): log(path + " does not exist", LogLevel.Warning) return @@ -238,22 +239,22 @@ def load_file(path): return loaded -def load_dummy_image(sizex, sizey): +def load_dummy_image(size_x: int, size_y: int) -> GdkPixbuf: return GdkPixbuf.Pixbuf.new_from_file_at_size(os.path.dirname(__file__) - + '/resources/images/dummy.jpg', sizex, sizey) + + '/resources/images/dummy.jpg', size_x, size_y) -def load_card_image_online(card, sizex, sizey): +def load_card_image_online(card, size_x: int, size_y: int) -> GdkPixbuf: url = card.image_url if url is None: log("No Image URL for " + card.name, LogLevel.Warning) - return load_dummy_image(sizex, sizey) + 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, sizex, sizey) + return GdkPixbuf.Pixbuf.new_from_file_at_size(filename, size_x, size_y) -def create_mana_icons(icon_dict, mana_string): +def create_mana_icons(icons: dict, mana_string: str) -> GdkPixbuf: # Convert the string to a List safe_string = mana_string.replace("/", "-") list = re.findall("{(.*?)}", safe_string) @@ -262,13 +263,14 @@ def create_mana_icons(icon_dict, mana_string): # Compute horizontal size for the final image imagesize = len(list) * 105 image = PImage.new("RGBA", (imagesize, 105)) - # incerment for each position of an icon (Workaround: 2 or more of the same icon will be rendered in the same poisition) + # Increment for each position of an icon + # (Workaround: 2 or more of the same icon will be rendered in the same position) poscounter = 0 # Go through all entries an add the correspondent icon to the final image for icon in list: xpos = poscounter * 105 try: - loaded = icon_dict[icon] + loaded = icons[icon] except KeyError as err: log("No icon file named '" + icon + "' found.", LogLevel.Warning) return diff --git a/cardvault/wants_funct.py b/cardvault/wants_funct.py new file mode 100644 index 0000000..57078c3 --- /dev/null +++ b/cardvault/wants_funct.py @@ -0,0 +1,28 @@ +from cardvault import cardlist +from cardvault import application + + +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.set_name("wantsScroller") + # Show details + card_list.list.connect("row-activated", app.handlers.on_wants_card_selected) + # Add card list to container + container.add(card_list) + container.add_overlay(app.ui.get_object("wantsOverlay")) + container.show_all() + # Hide no results overlay + app.ui.get_object("wantsOverlay").set_visible(False) + + +def reload_wants_view(app: 'application.Application'): + store = app.ui.get_object("wantsListsStore") + store.clear() + for list_name in app.wants.keys(): + display_name = list_name + " (" + str(len(app.wants[list_name])) + ")" + store.append([list_name, display_name]) + + diff --git a/setup.py b/setup.py index 57c7fce..99b0a28 100755 --- a/setup.py +++ b/setup.py @@ -37,5 +37,5 @@ setup( 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'License :: OSI Approved :: MIT License', - ] + ], )