Feature: Add cards to library via search view
This commit is contained in:
@@ -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
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user