Feature: Add cards to library via search view

This commit is contained in:
luxick
2017-03-08 14:08:53 +01:00
parent b533094648
commit b4d1c47eb3
5 changed files with 128 additions and 13 deletions

View File

@@ -1,11 +1,16 @@
# Title of the Program Window
import os import os
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 # Path of image cache
cache_path= os.path.dirname(__file__) + "/.cache/" cache_path= os.path.dirname(__file__) + "/.cache/"
image_cache_path=os.path.dirname(__file__) + "/.cache/images/" image_cache_path=os.path.dirname(__file__) + "/.cache/images/"
# Colors to use in the Application
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 # When True Search view will list a card multiple times for each set they appear in
show_from_all_sets=False show_from_all_sets=False

View File

@@ -12,7 +12,7 @@ class DetailBar(Gtk.ScrolledWindow):
self.add(self.grid) self.add(self.grid)
self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
# Create area for big card an fill it with a dummy image # Create area for big card
self.image_area = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10) self.image_area = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
self.bigcard = Gtk.Image() self.bigcard = Gtk.Image()
pixbuf = util.load_dummy_image(63 * 5, 88 * 5) pixbuf = util.load_dummy_image(63 * 5, 88 * 5)
@@ -67,8 +67,6 @@ class DetailBar(Gtk.ScrolledWindow):
self.rulesstore.clear() self.rulesstore.clear()
def set_card_detail(self, card): def set_card_detail(self, card):
print("Loading infos for \"" + card.name + "\"")
self.update_big_card(card) self.update_big_card(card)
self.rulesstore.clear() self.rulesstore.clear()
self.rulingslabel.set_visible(False) self.rulingslabel.set_visible(False)

View File

@@ -13,6 +13,13 @@ class MainWindow(Gtk.Window):
self.set_border_width(2) self.set_border_width(2)
self.set_size_request(1000, 700) self.set_size_request(1000, 700)
self.status_bar = Gtk.Statusbar()
self.status_bar.set_no_show_all(True)
# Set reference to status bar in util
util.status_bar = self.status_bar
util.push_status("Application started")
# Load local image Data # Load local image Data
util.reload_image_cache() util.reload_image_cache()
util.load_mana_icons() util.load_mana_icons()
@@ -20,31 +27,53 @@ class MainWindow(Gtk.Window):
util.window = self util.window = self
util.load_sets() util.load_sets()
util.load_library()
self.status_bar = Gtk.Statusbar()
self.status_bar.set_no_show_all(True)
self.notebook = Gtk.Notebook() self.notebook = Gtk.Notebook()
# region Menu Bar # region Menu Bar
mb_main = Gtk.Menu() mb_main = Gtk.Menu()
mb_lib = Gtk.Menu()
self.menu_import = Gtk.MenuItem("Import Library") self.menu_import = Gtk.MenuItem("Import Library")
self.menu_export = Gtk.MenuItem("Export Library") self.menu_export = Gtk.MenuItem("Export Library")
self.menu_quit = Gtk.ImageMenuItem('Quit', Gtk.Image.new_from_icon_name(Gtk.STOCK_QUIT, 0)) self.menu_quit = Gtk.ImageMenuItem('Quit', Gtk.Image.new_from_icon_name(Gtk.STOCK_QUIT, 0))
self.menu_quit.connect("activate", Gtk.main_quit) self.menu_quit.connect("activate", Gtk.main_quit)
self.lib_save = Gtk.ImageMenuItem("Save", Gtk.Image.new_from_icon_name(Gtk.STOCK_SAVE, 0))
self.lib_save.connect("activate", self.mb_save_lib)
self.lib_debug_print = Gtk.MenuItem("DEBUG: Print Library")
self.lib_debug_print.connect("activate", util.print_lib)
mb_main.append(self.menu_import) mb_main.append(self.menu_import)
mb_main.append(self.menu_export) mb_main.append(self.menu_export)
mb_main.append(Gtk.SeparatorMenuItem()) mb_main.append(Gtk.SeparatorMenuItem())
mb_main.append(self.menu_quit) mb_main.append(self.menu_quit)
mb_lib.append(self.lib_save)
mb_lib.append(self.lib_debug_print)
root_menu_main = Gtk.MenuItem("Main") root_menu_main = Gtk.MenuItem("Main")
root_menu_main.set_submenu(mb_main) root_menu_main.set_submenu(mb_main)
root_menu_lib = Gtk.MenuItem("Library")
root_menu_lib.set_submenu(mb_lib)
mb = Gtk.MenuBar() mb = Gtk.MenuBar()
mb.append(root_menu_main) mb.append(root_menu_main)
mb.append(root_menu_lib)
# endregion
# region Accelerators
accelgrp = Gtk.AccelGroup()
key, mod = Gtk.accelerator_parse("<Control>Q")
self.menu_quit.add_accelerator("activate", accelgrp, key, mod, Gtk.AccelFlags.VISIBLE)
self.add_accel_group(accelgrp)
# endregion # endregion
@@ -53,10 +82,6 @@ class MainWindow(Gtk.Window):
vbox.pack_start(self.notebook, True, True, 0) vbox.pack_start(self.notebook, True, True, 0)
vbox.pack_start(self.status_bar, False, False, 0) vbox.pack_start(self.status_bar, False, False, 0)
# Set reference to status bar in util
util.status_bar = self.status_bar
util.push_status("Application started")
self.collectionView = Gtk.Box() self.collectionView = Gtk.Box()
self.collectionView.add(collection.CollectionView()) self.collectionView.add(collection.CollectionView())
@@ -72,6 +97,8 @@ class MainWindow(Gtk.Window):
self.add(vbox) self.add(vbox)
def mb_save_lib(self, menu_item):
util.save_library()
win = MainWindow() win = MainWindow()
win.connect('delete-event', Gtk.main_quit) win.connect('delete-event', Gtk.main_quit)

View File

@@ -16,6 +16,7 @@ class SearchView(Gtk.Grid):
def __init__(self): def __init__(self):
Gtk.Grid.__init__(self) Gtk.Grid.__init__(self)
self.set_column_spacing(5) self.set_column_spacing(5)
self.current_card = None
# region Search Box # region Search Box
self.searchbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5, self.searchbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5,
@@ -178,6 +179,12 @@ class SearchView(Gtk.Grid):
# Detail View for selected Card # Detail View for selected Card
self.details = details.DetailBar() self.details = details.DetailBar()
# Button to add to library
self.add_delete_button = Gtk.Button()
self.add_delete_button.set_no_show_all(True)
self.add_delete_button.connect("clicked", self.on_add_delete)
# Bring it all together # Bring it all together
left_pane = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) left_pane = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
left_pane.pack_start(self.searchbox, False, False, 0) left_pane.pack_start(self.searchbox, False, False, 0)
@@ -193,6 +200,8 @@ class SearchView(Gtk.Grid):
self.attach(Gtk.VSeparator(), 3, 0, 1, 1) self.attach(Gtk.VSeparator(), 3, 0, 1, 1)
# Details # Details
self.attach(self.details, 4, 0, 1, 1) self.attach(self.details, 4, 0, 1, 1)
# Add/delete Button
self.attach(self.add_delete_button, 4, 1, 1, 1)
self.selection = self.list.get_selection() self.selection = self.list.get_selection()
self.selection.connect("changed", self.on_card_selected) self.selection.connect("changed", self.on_card_selected)
@@ -201,11 +210,24 @@ class SearchView(Gtk.Grid):
# region UI Events # region UI Events
def on_add_delete(self, button):
if util.library.__contains__(self.current_card.multiverse_id):
util.remove_card_from_lib(self.current_card)
print(self.current_card.name + " removed to library")
else:
util.add_card_to_lib(self.current_card)
print(self.current_card.name + " added to library")
self._do_update_add_button()
def online_search_clicked(self, button): def online_search_clicked(self, button):
# Clear old data from liststore # Clear old data from liststore
self.store.clear() self.store.clear()
# Reset details pane # Reset details pane
self.details.reset() self.details.reset()
# Reset selected card
self.current_card = None
# Hide Add delete button
self.add_delete_button.set_visible(False)
# Define the function to load cards in a seperate thread, so the UI is not blocked # Define the function to load cards in a seperate thread, so the UI is not blocked
self.loadthread = threading.Thread(target=self.load_cards) self.loadthread = threading.Thread(target=self.load_cards)
# Deamonize Thread so it tops if the main thread exits # Deamonize Thread so it tops if the main thread exits
@@ -235,6 +257,10 @@ class SearchView(Gtk.Grid):
selected_card = card selected_card = card
if selected_card is not None: if selected_card is not None:
self.details.set_card_detail(selected_card) self.details.set_card_detail(selected_card)
self.current_card = selected_card
self.add_delete_button.set_visible(True)
self._do_update_add_button()
# endregion # endregion
@@ -332,6 +358,14 @@ class SearchView(Gtk.Grid):
# region Private Functions # region Private Functions
def _do_update_add_button(self):
if not util.library.__contains__(self.current_card.multiverse_id):
self.add_delete_button.set_label("Add to Library")
self.add_delete_button.modify_bg(Gtk.StateType.NORMAL, config.green_color)
else:
self.add_delete_button.set_label("Remove from Library")
self.add_delete_button.modify_bg(Gtk.StateType.NORMAL, config.red_color)
def _match_selected(self, completion, model, iter): def _match_selected(self, completion, model, iter):
self.set_combo.set_active_iter(iter) self.set_combo.set_active_iter(iter)

View File

@@ -8,18 +8,69 @@ import network
from gi.repository import GdkPixbuf, Gtk from gi.repository import GdkPixbuf, Gtk
from PIL import Image as PImage from PIL import Image as PImage
from urllib import request from urllib import request
from mtgsdk import Card
gi.require_version('Gtk', '3.0') gi.require_version('Gtk', '3.0')
# Locally stored images for faster loading times # Locally stored images for faster loading times
imagecache = [] imagecache = []
manaicons = {} manaicons = {}
#Card library object
library = {}
set_list = [] set_list = []
window = None window = None
status_bar = None status_bar = None
def add_card_to_lib(card):
library[card.multiverse_id] = card
def remove_card_from_lib(card):
del library[card.multiverse_id]
def print_lib(menuItem):
print("Printing library:\n")
counter = 1
for card_id, card in library.items():
print(str(counter) + ": " + card.name + " (" + str(card_id) + ")")
counter += 1
print("\nDone.")
def save_library():
if not os.path.exists(config.cache_path):
os.makedirs(config.cache_path)
path = config.cache_path + "library"
# Serialize library object using pickle
try:
pickle.dump(library, open(path, 'wb'))
push_status("Library saved.")
print("Library saved")
except:
show_message("Error", "Error while saving library to disk")
def load_library():
path = config.cache_path + "library"
library.clear()
if os.path.isfile(path):
# Deserialize using pickle
try:
library_loaded = pickle.load(open(path, 'rb'))
for id, card in library_loaded.items():
library[id] = card
push_status("Library loaded.")
except :
show_message("Error", "Error while loading library from disk")
else:
save_library()
print("No library file found on disk, created new one")
def load_sets(): def load_sets():
path = config.cache_path + "sets" path = config.cache_path + "sets"
if not os.path.isfile(path): if not os.path.isfile(path):
@@ -29,9 +80,9 @@ def load_sets():
show_message("API Error", "Could not retrieve Set infos") show_message("API Error", "Could not retrieve Set infos")
return return
# Serialize the loaded data to a file # Serialize the loaded data to a file
pickle.dump(new_sets, open(config.cache_path + "sets", 'wb')) pickle.dump(new_sets, open(path, 'wb'))
# Deserialize set data from local file # Deserialize set data from local file
sets = pickle.load(open(config.cache_path + "sets", 'rb')) sets = pickle.load(open(path, 'rb'))
# Sort the loaded sets based on the sets name # Sort the loaded sets based on the sets name
for set in sorted(sets, key=lambda x: x.name): for set in sorted(sets, key=lambda x: x.name):
set_list.append(set) set_list.append(set)