Add build script.
471
legacy/application.py
Normal file
@@ -0,0 +1,471 @@
|
||||
import gi
|
||||
import os
|
||||
import copy
|
||||
import re
|
||||
import mtgsdk
|
||||
import time
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk, GObject, Pango
|
||||
from typing import Type, Dict, List
|
||||
from cardvault import handlers
|
||||
from cardvault import util
|
||||
from cardvault import database
|
||||
|
||||
|
||||
class Application:
|
||||
# ---------------------------------Initialize the Application----------------------------------------------
|
||||
def __init__(self):
|
||||
# Load configuration file
|
||||
self.config = self.load_config()
|
||||
util.LOG_LEVEL = self.config["log_level"]
|
||||
util.log("Start using config file: '{}'".format(util.get_root_filename("config.json")), util.LogLevel.Info)
|
||||
|
||||
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.ui.add_from_file(util.get_ui_filename("dialogs.glade"))
|
||||
|
||||
self.current_page = None
|
||||
self.current_lib_tag = "Untagged"
|
||||
|
||||
self.db = database.CardVaultDB(util.get_root_filename(util.DB_NAME))
|
||||
# Create database tables if they do not exist
|
||||
self.db.db_create()
|
||||
|
||||
not_found = self.ui.get_object("pageNotFound")
|
||||
self.pages = {
|
||||
"search": self.ui.get_object("searchView"),
|
||||
"library": self.ui.get_object("libraryView"),
|
||||
"wants": self.ui.get_object("wantsView")
|
||||
}
|
||||
|
||||
# Load data from cache path
|
||||
util.log("Loading image cache...", util.LogLevel.Info)
|
||||
self.image_cache = util.reload_image_cache(util.CACHE_PATH + "images/")
|
||||
self.precon_icons = util.reload_preconstructed_icons(util.CACHE_PATH + "icons/")
|
||||
self.mana_icons = util.load_mana_icons(os.path.dirname(__file__) + "/resources/mana/")
|
||||
|
||||
self.library = Dict[str, Type[mtgsdk.Card]]
|
||||
self.tags = Dict[str, str]
|
||||
self.wants = Dict[str, List[Type[mtgsdk.Card]]]
|
||||
self.load_user_data()
|
||||
|
||||
self.ui.get_object('statusbar_icon').set_from_icon_name(util.online_icons[self.is_online()],
|
||||
Gtk.IconSize.BUTTON)
|
||||
self.ui.get_object('statusbar_icon').set_tooltip_text(util.online_tooltips[self.is_online()])
|
||||
|
||||
self.handlers = handlers.Handlers(self)
|
||||
self.ui.connect_signals(self.handlers)
|
||||
|
||||
self.ui.get_object("mainWindow").connect('delete-event', Gtk.main_quit)
|
||||
self.ui.get_object("mainWindow").show_all()
|
||||
self.push_status("Card Vault ready.")
|
||||
|
||||
view_menu = self.ui.get_object("viewMenu")
|
||||
view = self.config["start_page"] if not self.config["start_page"] == "dynamic" else self.config["last_viewed"]
|
||||
start_page = [page for page in view_menu.get_children() if page.get_name() == view]
|
||||
start_page[0].activate()
|
||||
|
||||
util.log("Launching Card Vault version {}".format(util.VERSION), util.LogLevel.Info)
|
||||
|
||||
if self.config.get('first_run'):
|
||||
ref = '<a href="' + util.MANUAL_LOCATION + '">' + util.MANUAL_LOCATION + '</a>'
|
||||
s = "Welcome to Card Vault.\n\nIf you need help using the application please refer to the manual at\n{}\n\n" \
|
||||
"To increase search performance and to be able to search while offline it is advised to use the " \
|
||||
"offline mode.\nDo you want to start the download?".format(ref)
|
||||
response = self.show_dialog_yn("Welcome", s)
|
||||
if response == Gtk.ResponseType.YES:
|
||||
self.handlers.do_download_card_data(Gtk.MenuItem())
|
||||
self.config['first_run'] = False
|
||||
self.save_config()
|
||||
|
||||
def push_status(self, msg):
|
||||
status_bar = self.ui.get_object("statusBar")
|
||||
status_bar.pop(0)
|
||||
status_bar.push(0, msg)
|
||||
|
||||
def show_card_details(self, card):
|
||||
builder = Gtk.Builder()
|
||||
builder.add_from_file(util.get_ui_filename("detailswindow.glade"))
|
||||
builder.add_from_file(util.get_ui_filename("overlays.glade"))
|
||||
window = builder.get_object("cardDetails")
|
||||
window.set_title(card.get('name'))
|
||||
# Card Image
|
||||
container = builder.get_object("imageContainer")
|
||||
pixbuf = util.load_card_image(card, 63 * 5, 88 * 5, self.image_cache)
|
||||
image = Gtk.Image().new_from_pixbuf(pixbuf)
|
||||
container.add(image)
|
||||
# Name
|
||||
builder.get_object("cardName").set_text(card.get('name'))
|
||||
# Types
|
||||
supertypes = ""
|
||||
if card.get('subtypes'):
|
||||
supertypes = " - " + " ".join(card.get('subtypes'))
|
||||
types = " ".join(card.get('types')) + supertypes
|
||||
builder.get_object("cardTypes").set_text(types)
|
||||
# Rarity
|
||||
builder.get_object("cardRarity").set_text(card.get('rarity') or "")
|
||||
# Release
|
||||
builder.get_object("cardReleaseDate").set_text(card.get('release_date') or "")
|
||||
# Set
|
||||
builder.get_object("cardSet").set_text(card.get('set_name'))
|
||||
# Printings
|
||||
all_sets = self.get_all_sets()
|
||||
prints = [all_sets[set_name].get('name') for set_name in card.get('printings')]
|
||||
builder.get_object("cardPrintings").set_text(", ".join(prints))
|
||||
# Legalities
|
||||
grid = builder.get_object("legalitiesGrid")
|
||||
rows = 1
|
||||
for legality in card.get('legalities') or {}:
|
||||
date_label = Gtk.Label()
|
||||
date_label.set_halign(Gtk.Align.END)
|
||||
text_label = Gtk.Label()
|
||||
text_label.set_line_wrap_mode(Pango.WrapMode.WORD)
|
||||
text_label.set_line_wrap(True)
|
||||
text_label.set_halign(Gtk.Align.END)
|
||||
color = util.LEGALITY_COLORS[legality["legality"]]
|
||||
date_label.set_markup("<span fgcolor=\"" + color + "\">" + legality["format"] + ":" + "</span>")
|
||||
text_label.set_markup("<span fgcolor=\"" + color + "\">" + legality["legality"] + "</span>")
|
||||
grid.attach(date_label, 0, rows + 2, 1, 1)
|
||||
grid.attach(text_label, 1, rows + 2, 1, 1)
|
||||
|
||||
rows += 1
|
||||
grid.show_all()
|
||||
|
||||
# Rulings
|
||||
if card.get('rulings'):
|
||||
store = builder.get_object("rulesStore")
|
||||
for rule in card.get('rulings'):
|
||||
store.append([rule["date"], rule["text"]])
|
||||
else:
|
||||
builder.get_object("ruleBox").set_visible(False)
|
||||
|
||||
window.show_all()
|
||||
|
||||
def eval_key_pressed(widget, event):
|
||||
key, modifier = Gtk.accelerator_parse('Escape')
|
||||
keyval = event.keyval
|
||||
if keyval == key:
|
||||
window.destroy()
|
||||
|
||||
window.connect("key-press-event", eval_key_pressed)
|
||||
|
||||
def show_dialog_ync(self, title: str, message: str) -> Gtk.ResponseType:
|
||||
"""Display a simple Yes/No Question dialog and return the result"""
|
||||
dialog = self.ui.get_object("ync_dialog")
|
||||
dialog.set_transient_for(self.ui.get_object("mainWindow"))
|
||||
dialog.set_title(title)
|
||||
self.ui.get_object("ync_label").set_markup(message)
|
||||
response = dialog.run()
|
||||
dialog.hide()
|
||||
return response
|
||||
|
||||
def show_dialog_yn(self, title: str, message: str) -> Gtk.ResponseType:
|
||||
"""Display a simple Yes/No Question dialog and return the result"""
|
||||
dialog = self.ui.get_object("yn_dialog")
|
||||
dialog.set_transient_for(self.ui.get_object("mainWindow"))
|
||||
dialog.set_title(title)
|
||||
self.ui.get_object("yn_label").set_markup(message)
|
||||
response = dialog.run()
|
||||
dialog.hide()
|
||||
return response
|
||||
|
||||
def show_message(self, title, message):
|
||||
dialog = Gtk.MessageDialog(self.ui.get_object("mainWindow"), 0, Gtk.MessageType.INFO,
|
||||
Gtk.ButtonsType.OK, title)
|
||||
dialog.format_secondary_text(message)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
def show_name_enter_dialog(self, title: str, value: str) -> str:
|
||||
dialog = self.ui.get_object("nameEnterDialog") # type: Gtk.Dialog
|
||||
dialog.set_transient_for(self.ui.get_object("mainWindow"))
|
||||
dialog.set_title(title)
|
||||
entry = self.ui.get_object("nameEnterEntry")
|
||||
entry.set_text(value)
|
||||
entry.grab_focus()
|
||||
|
||||
result = dialog.run()
|
||||
dialog.hide()
|
||||
|
||||
if result == Gtk.ResponseType.OK:
|
||||
return entry.get_text()
|
||||
else:
|
||||
return value
|
||||
|
||||
def show_preferences_dialog(self):
|
||||
"""Show a dialog to adjust user preferences"""
|
||||
dialog = self.ui.get_object("pref_dialog") # type: Gtk.Dialog
|
||||
dialog.set_transient_for(self.ui.get_object("mainWindow"))
|
||||
|
||||
store = Gtk.ListStore(str, str)
|
||||
for page in self.pages.keys():
|
||||
store.append([page.title(), page])
|
||||
store.append(["Continue where you left", "dynamic"])
|
||||
page_map = {"search": 0,
|
||||
"library": 1,
|
||||
"decks": 2,
|
||||
"wants": 3,
|
||||
"dynamic": 4}
|
||||
self.ui.get_object("pref_start_view_combo").set_model(store)
|
||||
self.ui.get_object("pref_start_view_combo").set_active(page_map[self.config["start_page"]])
|
||||
|
||||
self.ui.get_object("pref_show_all_check").set_active(self.config["show_all_in_search"])
|
||||
|
||||
result = dialog.run()
|
||||
dialog.hide()
|
||||
|
||||
if not result == Gtk.ResponseType.OK:
|
||||
return
|
||||
|
||||
tree_iter = self.ui.get_object("pref_start_view_combo").get_active_iter()
|
||||
value = self.ui.get_object("pref_start_view_combo").get_model().get_value(tree_iter, 1)
|
||||
self.config["start_page"] = value
|
||||
|
||||
self.config["show_all_in_search"] = self.ui.get_object("pref_show_all_check").get_active()
|
||||
|
||||
self.save_config()
|
||||
self.config = self.load_config()
|
||||
|
||||
def unsaved_changes(self) -> bool:
|
||||
"""Check if database is in transaction"""
|
||||
return self.db.db_unsaved_changes()
|
||||
|
||||
def save_config(self):
|
||||
cf = util.get_root_filename("config.json")
|
||||
util.save_config(self.config, cf)
|
||||
|
||||
@staticmethod
|
||||
def load_config() -> dict:
|
||||
configfile = util.get_root_filename("config.json")
|
||||
return util.parse_config(configfile, util.DEFAULT_CONFIG)
|
||||
|
||||
def save_data(self):
|
||||
util.log("Saving Data to database", util.LogLevel.Info)
|
||||
start = time.time()
|
||||
self.db.db_save_changes()
|
||||
end = time.time()
|
||||
util.log("Finished in {}s".format(str(round(end - start, 3))), util.LogLevel.Info)
|
||||
self.push_status("All data saved.")
|
||||
pass
|
||||
|
||||
def load_user_data(self):
|
||||
util.log("Loading User Data from form '{}'".format(util.get_root_filename(util.DB_NAME)), util.LogLevel.Info)
|
||||
start = time.time()
|
||||
self.library = self.db.lib_get_all()
|
||||
self.tags = self.db.tag_get_all()
|
||||
self.wants = self.db.wants_get_all()
|
||||
end = time.time()
|
||||
util.log("Finished in {}s".format(str(round(end - start, 3))), util.LogLevel.Info)
|
||||
self.push_status("All data loaded.")
|
||||
|
||||
def set_online(self, status: bool):
|
||||
"""Online status of the application. True if no local card data is present."""
|
||||
self.ui.get_object('statusbar_icon').set_from_icon_name(util.online_icons[status], Gtk.IconSize.BUTTON)
|
||||
self.ui.get_object('statusbar_icon').set_tooltip_text(util.online_tooltips[status])
|
||||
self.config['local_db'] = not status
|
||||
self.save_config()
|
||||
|
||||
def is_online(self) -> bool:
|
||||
"""Return the online status of the application. True if no local data present."""
|
||||
return not self.config['local_db']
|
||||
|
||||
def get_untagged_cards(self):
|
||||
lib = copy.copy(self.library)
|
||||
for ids in self.tags.values():
|
||||
for card_id in ids:
|
||||
try:
|
||||
del lib[card_id]
|
||||
except KeyError:
|
||||
pass
|
||||
return lib
|
||||
|
||||
def get_tagged_cards(self, tag):
|
||||
if not tag:
|
||||
return self.library
|
||||
else:
|
||||
lib = {}
|
||||
for card_id in self.tags[tag]:
|
||||
lib[card_id] = self.library[card_id]
|
||||
return lib
|
||||
|
||||
def tag_card(self, card, tag: str):
|
||||
"""Add a card to tag"""
|
||||
list = self.tags[tag]
|
||||
list.append(card.multiverse_id)
|
||||
self.db.tag_card_add(tag, card.multiverse_id)
|
||||
|
||||
def untag_card(self, card, tag: str):
|
||||
list = self.tags[tag]
|
||||
list.remove(card.multiverse_id)
|
||||
self.db.tag_card_remove(tag, card.multiverse_id)
|
||||
|
||||
def tag_new(self, tag: str):
|
||||
self.tags[tag] = []
|
||||
self.db.tag_new(tag)
|
||||
util.log("Tag '" + tag + "' added", util.LogLevel.Info)
|
||||
self.push_status("Added Tag \"" + tag + "\"")
|
||||
|
||||
def tag_delete(self, tag: str):
|
||||
del self.tags[tag]
|
||||
self.db.tag_delete(tag)
|
||||
util.log("Tag '" + tag + "' removed", util.LogLevel.Info)
|
||||
self.push_status("Removed Tag \"" + tag + "\"")
|
||||
|
||||
def tag_rename(self, old, new):
|
||||
if old == new:
|
||||
return
|
||||
self.tags[new] = self.tags[old]
|
||||
del self.tags[old]
|
||||
self.db.tag_rename(old, new)
|
||||
util.log("Tag '" + old + "' renamed to '" + new + "'", util.LogLevel.Info)
|
||||
|
||||
def get_wanted_card_ids(self) -> List[str]:
|
||||
all_ids = []
|
||||
for cards in self.wants.values():
|
||||
next_ids = [card['multiverse_id'] for card in cards]
|
||||
all_ids = list(set(all_ids) | set(next_ids))
|
||||
return all_ids
|
||||
|
||||
def get_wanted_cards(self, list_name: str = None) -> Dict[str, Type[mtgsdk.Card]]:
|
||||
if list_name:
|
||||
out = {card.multiverse_id: card for card in self.wants[list_name]}
|
||||
return out
|
||||
|
||||
def wants_new(self, name):
|
||||
"""Add a empty wants list"""
|
||||
self.wants[name] = []
|
||||
self.db.wants_new(name)
|
||||
util.log("Want list '" + name + "' created", util.LogLevel.Info)
|
||||
self.push_status("Created want list '" + name + "'")
|
||||
|
||||
def wants_delete(self, name: str):
|
||||
"""Delete an wants list an all cards in it"""
|
||||
del self.wants[name]
|
||||
self.db.wants_delete(name)
|
||||
util.log("Deleted Wants List '{}'".format(name), util.LogLevel.Info)
|
||||
self.push_status("Deleted Wants List '{}'".format(name))
|
||||
|
||||
def wants_rename(self, old: str, new: str):
|
||||
if old == new:
|
||||
return
|
||||
self.wants[new] = self.wants[old]
|
||||
del self.wants[old]
|
||||
self.db.wants_rename(old, new)
|
||||
util.log("Want List '" + old + "' renamed to '" + new + "'", util.LogLevel.Info)
|
||||
|
||||
def wants_card_add(self, list_name: str, card: 'mtgsdk.Card'):
|
||||
self.wants[list_name].append(card)
|
||||
self.db.wants_card_add(list_name, card.multiverse_id)
|
||||
util.log(card.name + " added to want list " + list_name, util.LogLevel.Info)
|
||||
|
||||
def wants_card_remove(self, card: mtgsdk.Card, list: str):
|
||||
"""Remove a card from a wants list"""
|
||||
l = self.wants[list]
|
||||
l.remove(card)
|
||||
self.db.wants_card_remove(list, card.multiverse_id)
|
||||
util.log("Removed '{}' from wants list '{}'".format(card.name, list), util.LogLevel.Info)
|
||||
|
||||
def lib_card_add(self, card, tag=None):
|
||||
if tag is not None:
|
||||
self.tag_card(card, tag)
|
||||
self.db.tag_card_add(tag, card.multiverse_id)
|
||||
self.library[card.multiverse_id] = card
|
||||
self.db.lib_card_add(card)
|
||||
self.push_status(card.name + " added to library")
|
||||
|
||||
def lib_card_add_bulk(self, cards: list, tag: str = None):
|
||||
for card in cards:
|
||||
if tag is not None:
|
||||
self.tag_card(card, tag)
|
||||
self.db.tag_card_add(tag, card.multiverse_id)
|
||||
self.lib_card_add(card, tag)
|
||||
self.db.lib_card_add(card)
|
||||
util.log("Added {} cards to library.".format(str(len(cards))), util.LogLevel.Info)
|
||||
self.push_status("Added {} cards to library.".format(str(len(cards))))
|
||||
|
||||
def lib_card_remove(self, card):
|
||||
# Check if card is tagged
|
||||
is_tagged, tags = self.db.tag_card_check_tagged(card)
|
||||
if is_tagged:
|
||||
for tag in tags:
|
||||
self.tags[tag].remove(card.multiverse_id)
|
||||
self.db.tag_card_remove(tag, card.multiverse_id)
|
||||
|
||||
del self.library[card.multiverse_id]
|
||||
self.db.lib_card_remove(card)
|
||||
util.log("Removed {} from library".format(card.name), util.LogLevel.Info)
|
||||
self.push_status(card.name + " removed from library")
|
||||
|
||||
def db_override_user_data(self):
|
||||
"""Called after import of user data. Overrides existing user data in database"""
|
||||
util.log("Clearing old user data", util.LogLevel.Info)
|
||||
self.db.db_clear_data_user()
|
||||
util.log("Attempt loading user data to database", util.LogLevel.Info)
|
||||
start = time.time()
|
||||
# Library
|
||||
for card in self.library.values():
|
||||
self.db.lib_card_add(card)
|
||||
# Tags
|
||||
for tag, card_ids in self.tags.items():
|
||||
self.db.tag_new(tag)
|
||||
for card_id in card_ids:
|
||||
self.db.tag_card_add(tag, card_id)
|
||||
# Wants
|
||||
for list_name, cards in self.wants.items():
|
||||
self.db.wants_new(list_name)
|
||||
for card in cards:
|
||||
self.db.wants_card_add(list_name, card.multiverse_id)
|
||||
end = time.time()
|
||||
util.log("Finished in {}s".format(str(round(end - start, 3))), util.LogLevel.Info)
|
||||
self.push_status("User data imported")
|
||||
|
||||
def db_delete_card_data(self):
|
||||
"""Called before before rebuilding local data storage"""
|
||||
util.log("Clearing local card data", util.LogLevel.Info)
|
||||
self.db.db_clear_data_card()
|
||||
self.set_online(True)
|
||||
util.log("Done", util.LogLevel.Info)
|
||||
|
||||
def db_delete_user_data(self):
|
||||
"""Delete all user data"""
|
||||
util.log("Clearing all user data", util.LogLevel.Info)
|
||||
self.db.db_clear_data_user()
|
||||
util.log("Done", util.LogLevel.Info)
|
||||
|
||||
def get_all_sets(self) -> dict:
|
||||
if not self.is_online():
|
||||
out = {s['code']: s for s in self.db.set_get_all()}
|
||||
else:
|
||||
out = util.load_sets(util.get_root_filename('sets'))
|
||||
return out
|
||||
|
||||
def get_mana_icons(self, mana_string):
|
||||
if not mana_string:
|
||||
util.log("No mana string provided", util.LogLevel.Info)
|
||||
return
|
||||
icon_list = re.findall("{(.*?)}", mana_string.replace("/", "-"))
|
||||
icon_name = "_".join(icon_list)
|
||||
try:
|
||||
icon = self.precon_icons[icon_name]
|
||||
except KeyError:
|
||||
icon = util.create_mana_icons(self.mana_icons, mana_string)
|
||||
self.precon_icons[icon_name] = icon
|
||||
return icon
|
||||
|
||||
def filter_lib_func(self, model, iter, data):
|
||||
filter_text = self.ui.get_object("searchLibEntry").get_text()
|
||||
if filter_text == "":
|
||||
return True
|
||||
else:
|
||||
return filter_text.lower() in model[iter][1].lower()
|
||||
|
||||
|
||||
def main():
|
||||
GObject.threads_init()
|
||||
Application()
|
||||
Gtk.main()
|
||||
114
legacy/cardlist.py
Normal file
@@ -0,0 +1,114 @@
|
||||
import copy
|
||||
|
||||
import gi
|
||||
from cardvault import util
|
||||
from cardvault import application
|
||||
from gi.repository import Gtk, GdkPixbuf, Gdk
|
||||
|
||||
from typing import Dict, Type
|
||||
|
||||
import time
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
|
||||
|
||||
class CardList(Gtk.ScrolledWindow):
|
||||
def __init__(self, filtered, app, row_colors: Dict[str, str]):
|
||||
Gtk.ScrolledWindow.__init__(self)
|
||||
self.set_hexpand(True)
|
||||
self.set_vexpand(True)
|
||||
|
||||
self.filtered = filtered
|
||||
self.lib = {}
|
||||
self.app = app
|
||||
self.row_colors = row_colors
|
||||
|
||||
builder = Gtk.Builder()
|
||||
builder.add_from_file(util.get_ui_filename("cardtree.glade"))
|
||||
|
||||
self.filter = builder.get_object("cardStoreFiltered")
|
||||
|
||||
self.store = builder.get_object("cardStore")
|
||||
|
||||
self.tree = builder.get_object("cardTree")
|
||||
|
||||
self.store.set_sort_func(4, self.compare_rarity, None)
|
||||
|
||||
self.add(self.tree)
|
||||
|
||||
self.selection = self.tree.get_selection()
|
||||
|
||||
def get_selected_cards(self) -> dict:
|
||||
(model, pathlist) = self.selection.get_selected_rows()
|
||||
output = {}
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
card_id = model.get_value(tree_iter, 0)
|
||||
card = self.lib[card_id]
|
||||
output[card_id] = card
|
||||
return output
|
||||
|
||||
def update(self, library: Dict[str, dict]):
|
||||
self.store.clear()
|
||||
if library is None:
|
||||
return
|
||||
self.lib = library
|
||||
# Disable update if tree is filtered (performance)
|
||||
if self.filtered:
|
||||
self.tree.freeze_child_notify()
|
||||
|
||||
util.log("Updating tree view", util.LogLevel.Info)
|
||||
start = time.time()
|
||||
all_wants = self.app.get_wanted_card_ids()
|
||||
|
||||
for card in library.values():
|
||||
if card['multiverse_id'] is not None:
|
||||
color = self.get_row_color(card, self.app.library, all_wants, self.row_colors)
|
||||
mana_cost = None
|
||||
if not card.get('types').__contains__("Land"):
|
||||
mana_cost = self.app.get_mana_icons(card.get('mana_cost'))
|
||||
item = [card['multiverse_id'],
|
||||
card['name'],
|
||||
" ".join(card.get('supertypes') or ""),
|
||||
" ".join(card.get('types') or ""),
|
||||
card.get('rarity'),
|
||||
card.get('power'),
|
||||
card.get('toughness'),
|
||||
", ".join(card.get('printings') or ""),
|
||||
mana_cost,
|
||||
card.get('cmc'),
|
||||
card.get('set_name'),
|
||||
color,
|
||||
card.get('original_text')]
|
||||
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.tree.thaw_child_notify()
|
||||
|
||||
@staticmethod
|
||||
def compare_rarity(model, row1, row2, user_data):
|
||||
# Column for rarity
|
||||
sort_column = 4
|
||||
value1 = model.get_value(row1, sort_column)
|
||||
value2 = model.get_value(row2, sort_column)
|
||||
if util.rarity_dict[value1.lower()] < util.rarity_dict[value2.lower()]:
|
||||
return -1
|
||||
elif value1 == value2:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
@staticmethod
|
||||
def get_row_color(card, lib: dict, wants: dict, colors: dict) -> str:
|
||||
if lib.__contains__(card.get('multiverse_id')):
|
||||
return colors["owned"]
|
||||
elif wants.__contains__(card.get('multiverse_id')):
|
||||
return colors["wanted"]
|
||||
else:
|
||||
return colors["unowned"]
|
||||
|
||||
|
||||
449
legacy/database.py
Normal file
@@ -0,0 +1,449 @@
|
||||
import sqlite3
|
||||
import ast
|
||||
|
||||
from mtgsdk import Card, Set
|
||||
from cardvault import util
|
||||
|
||||
|
||||
class CardVaultDB:
|
||||
"""Data access class for sqlite3"""
|
||||
def __init__(self, db_file: str):
|
||||
self.db_file = db_file
|
||||
self.connection = sqlite3.connect(self.db_file)
|
||||
|
||||
# Database operations ##############################################################################################
|
||||
|
||||
def db_create(self):
|
||||
"""Create initial database"""
|
||||
con = sqlite3.connect(self.db_file)
|
||||
|
||||
with con:
|
||||
# Create library table
|
||||
con.execute("CREATE TABLE IF NOT EXISTS `cards` "
|
||||
"( `name` TEXT, `layout` TEXT, `manaCost` TEXT, `cmc` INTEGER, "
|
||||
"`colors` TEXT, `names` TEXT, `type` TEXT, `supertypes` TEXT, "
|
||||
"`subtypes` TEXT, `types` TEXT, `rarity` TEXT, `text` TEXT, "
|
||||
"`flavor` TEXT, `artist` TEXT, `number` INTEGER, `power` TEXT, "
|
||||
"`toughness` TEXT, `loyalty` INTEGER, `multiverseid` INTEGER , "
|
||||
"`variations` TEXT, `watermark` TEXT, `border` TEXT, `timeshifted` "
|
||||
"TEXT, `hand` TEXT, `life` TEXT, `releaseDate` TEXT, `starter` TEXT, "
|
||||
"`printings` TEXT, `originalText` TEXT, `originalType` TEXT, "
|
||||
"`source` TEXT, `imageUrl` TEXT, `set` TEXT, `setName` TEXT, `id` TEXT, "
|
||||
"`legalities` TEXT, `rulings` TEXT, `foreignNames` TEXT, `fcolor` TEXT) ")
|
||||
con.execute("CREATE TABLE IF NOT EXISTS library ( multiverseid INT PRIMARY KEY, copies INT )")
|
||||
con.execute("CREATE TABLE IF NOT EXISTS tags ( tag TEXT, multiverseid INT )")
|
||||
con.execute("CREATE TABLE IF NOT EXISTS wants ( listName TEXT, multiverseid INT )")
|
||||
con.execute("CREATE TABLE IF NOT EXISTS sets ( code TEXT PRIMARY KEY , name TEXT, type TEXT, border TEXT, "
|
||||
"mkmid INT, mkmname TEXT, releasedate TEXT, gatherercode TEXT, magiccardsinfocode TEXT, "
|
||||
"booster TEXT, oldcode TEXT)")
|
||||
|
||||
def db_card_insert(self, card: Card):
|
||||
"""Insert single card data into database"""
|
||||
# Use own connection so that inserts are commited directly
|
||||
con = sqlite3.connect(self.db_file)
|
||||
try:
|
||||
with con:
|
||||
# Map card object to database tables
|
||||
db_values = self.card_to_table_mapping(card)
|
||||
sql_string = "INSERT INTO `cards` VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?," \
|
||||
"?,?,?,?,?,?,?,?,?,?,?)"
|
||||
# Insert into database
|
||||
con.execute(sql_string, db_values)
|
||||
except sqlite3.OperationalError as err:
|
||||
util.log("Database Error", util.LogLevel.Error)
|
||||
util.log(str(err), util.LogLevel.Error)
|
||||
except sqlite3.IntegrityError:
|
||||
pass
|
||||
|
||||
def db_get_all(self):
|
||||
"""Return data of all cards in database"""
|
||||
sql = 'SELECT * FROM cards'
|
||||
cur = self.connection.cursor()
|
||||
cur.row_factory = sqlite3.Row
|
||||
cur.execute(sql)
|
||||
rows = cur.fetchall()
|
||||
output = []
|
||||
for row in rows:
|
||||
card = self.table_to_card_mapping(row)
|
||||
output.append(card)
|
||||
return output
|
||||
|
||||
def db_insert_data_card(self, cards_json):
|
||||
"""Insert download from mtgjson"""
|
||||
c_rows = []
|
||||
s_rows = []
|
||||
for data in cards_json.values():
|
||||
cards = []
|
||||
for raw in data["cards"]:
|
||||
c = Card(raw)
|
||||
c.image_url = util.CARD_IMAGE_URL.format(c.multiverse_id)
|
||||
c.set = data["code"]
|
||||
c.set_name = data["name"]
|
||||
cards.append(c)
|
||||
|
||||
for c in cards:
|
||||
c_rows.append(self.card_to_table_mapping(c))
|
||||
set = Set(data)
|
||||
s_rows.append(self.set_to_table_mapping(set))
|
||||
|
||||
# Use separate connection to commit changes immediately
|
||||
con = sqlite3.connect(self.db_file)
|
||||
try:
|
||||
with con:
|
||||
sql_string = "INSERT INTO `cards` VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?," \
|
||||
"?,?,?,?,?,?,?,?,?,?,?)"
|
||||
con.executemany(sql_string, c_rows)
|
||||
sql_string = "INSERT INTO `sets` VALUES (?,?,?,?,?,?,?,?,?,?,?)"
|
||||
con.executemany(sql_string, s_rows)
|
||||
|
||||
except sqlite3.OperationalError as err:
|
||||
util.log("Database Error", util.LogLevel.Error)
|
||||
util.log(str(err), util.LogLevel.Error)
|
||||
except sqlite3.IntegrityError as err:
|
||||
util.log("Database Error", util.LogLevel.Error)
|
||||
util.log(str(err), util.LogLevel.Error)
|
||||
|
||||
def db_clear_data_card(self):
|
||||
"""Delete all resource data from database"""
|
||||
con = sqlite3.connect(self.db_file)
|
||||
try:
|
||||
with con:
|
||||
con.execute("DELETE FROM cards")
|
||||
con.execute("DELETE FROM sets")
|
||||
except sqlite3.OperationalError as err:
|
||||
util.log("Database Error", util.LogLevel.Error)
|
||||
util.log(str(err), util.LogLevel.Error)
|
||||
except sqlite3.IntegrityError as err:
|
||||
util.log("Database Error", util.LogLevel.Error)
|
||||
util.log(str(err), util.LogLevel.Error)
|
||||
|
||||
def db_clear_data_user(self):
|
||||
"""Delete all user data from database"""
|
||||
self.db_operation('DELETE FROM library')
|
||||
self.db_operation('DELETE FROM wants')
|
||||
self.db_operation('DELETE FROM tags')
|
||||
|
||||
# Library operations ###############################################################################################
|
||||
|
||||
def lib_get_all(self) -> dict:
|
||||
"""Load library from database"""
|
||||
cur = self.connection.cursor()
|
||||
cur.row_factory = sqlite3.Row
|
||||
cur.execute('SELECT * FROM `library` INNER JOIN `cards` ON library.multiverseid = cards.multiverseid')
|
||||
rows = cur.fetchall()
|
||||
|
||||
return self.rows_to_card_dict(rows)
|
||||
|
||||
def lib_card_add(self, card: Card):
|
||||
"""Insert card into library"""
|
||||
self.db_operation("INSERT INTO `library` (`copies`, `multiverseid`) VALUES (?, ?)", (1, card.multiverse_id))
|
||||
|
||||
def lib_card_remove(self, card: Card):
|
||||
"""Remove a from the library"""
|
||||
self.db_operation("DELETE FROM `library` WHERE `multiverseid` = ?", (card.multiverse_id,))
|
||||
|
||||
# Tag operations ###################################################################################################
|
||||
|
||||
def tag_get_all(self) -> dict:
|
||||
"""Loads a dict from database with all tags and the card ids tagged"""
|
||||
cur = self.connection.cursor()
|
||||
cur.row_factory = sqlite3.Row
|
||||
|
||||
# First load all tags
|
||||
cur.execute("SELECT `tag` FROM tags GROUP BY `tag`")
|
||||
rows = cur.fetchall()
|
||||
tags = {}
|
||||
for row in rows:
|
||||
tags[row["tag"]] = []
|
||||
|
||||
# Go trough all tags an load the card ids
|
||||
for tag in tags.keys():
|
||||
cur.execute('SELECT `multiverseid` FROM `tags` WHERE tags.tag = ? AND multiverseid NOT NULL', (tag,))
|
||||
rows = cur.fetchall()
|
||||
for row in rows:
|
||||
tags[tag].append(row["multiverseid"])
|
||||
return tags
|
||||
|
||||
def tag_new(self, tag: str):
|
||||
"""Add a new tag to the database"""
|
||||
self.db_operation("INSERT INTO `tags` VALUES (?, NULL)", (tag,))
|
||||
|
||||
def tag_delete(self, tag: str):
|
||||
"""Remove a tag with all entries"""
|
||||
self.db_operation("DELETE FROM `tags` WHERE `tag` = ?", (tag,))
|
||||
|
||||
def tag_rename(self, name_old: str, name_new: str):
|
||||
"""Rename a tag"""
|
||||
self.db_operation('UPDATE `tags` SET `tag`=? WHERE `tag` = ?;', (name_new, name_old))
|
||||
|
||||
def tag_card_add(self, tag: str, card_id: int):
|
||||
"""Add an entry for a tagged card"""
|
||||
self.db_operation("INSERT INTO `tags` VALUES (?, ?)", (tag, card_id))
|
||||
|
||||
def tag_card_remove(self, tag: str, card_id: int):
|
||||
"""Remove a card from a tag"""
|
||||
self.db_operation("DELETE FROM `tags` WHERE `tag` = ? AND `multiverseid` = ?", (tag, card_id))
|
||||
|
||||
def tag_card_check_tagged(self, card) -> tuple:
|
||||
"""Check if a card is tagged. Return True/False and a list of tags."""
|
||||
cur = self.connection.cursor()
|
||||
cur.row_factory = sqlite3.Row
|
||||
cur.execute('SELECT `tag` FROM `tags` WHERE tags.multiverseid = ? ', (card.multiverse_id,))
|
||||
rows = cur.fetchall()
|
||||
|
||||
if len(rows) == 0:
|
||||
return False, []
|
||||
else:
|
||||
tags = []
|
||||
for row in rows:
|
||||
tags.append(row["tag"])
|
||||
return True, tags
|
||||
|
||||
# Wants operations #################################################################################################
|
||||
|
||||
def wants_get_all(self) -> dict:
|
||||
"""Load all wants lists from database"""
|
||||
cur = self.connection.cursor()
|
||||
cur.row_factory = sqlite3.Row
|
||||
|
||||
# First load all lists
|
||||
cur.execute("SELECT `listName` FROM wants GROUP BY `listName`")
|
||||
rows = cur.fetchall()
|
||||
wants = {}
|
||||
for row in rows:
|
||||
wants[row["listName"]] = []
|
||||
|
||||
# Go trough all tags an load the card ids
|
||||
for list_name in wants.keys():
|
||||
cur.execute('SELECT * FROM '
|
||||
'(SELECT `multiverseid` FROM `wants` WHERE `listName` = ? AND multiverseid NOT NULL) tagged '
|
||||
'INNER JOIN `cards` ON tagged.multiverseid = cards.multiverseid', (list_name,))
|
||||
rows = cur.fetchall()
|
||||
for row in rows:
|
||||
wants[list_name].append(self.table_to_card_mapping(row))
|
||||
return wants
|
||||
|
||||
def wants_new(self, name: str):
|
||||
"""Add a new wants list to the database"""
|
||||
self.db_operation("INSERT INTO `wants` VALUES (?, NULL)", (name,))
|
||||
|
||||
def wants_delete(self, name: str):
|
||||
"""Remove a tag with all entries"""
|
||||
self.db_operation("DELETE FROM `wants` WHERE `listName` = ?", (name,))
|
||||
|
||||
def wants_rename(self, name_old: str, name_new: str):
|
||||
"""Rename a tag"""
|
||||
self.db_operation('UPDATE `wants` SET `listName`=? WHERE `listName` = ?;', (name_new, name_old))
|
||||
|
||||
def wants_card_add(self, list_name: str, card_id: int):
|
||||
"""Add a card entry to a wants list"""
|
||||
self.db_operation("INSERT INTO `wants` VALUES (?, ?)", (list_name, card_id))
|
||||
|
||||
def wants_card_remove(self, list_name: str, card_id: int):
|
||||
"""Remove a card from a want list """
|
||||
self.db_operation("DELETE FROM `wants` WHERE `listName` = ? AND `multiverseid` = ?", (list_name, card_id))
|
||||
|
||||
# Query operations #################################################################################################
|
||||
|
||||
def search_by_name_filtered(self, term: str, filters: dict, list_size: int) -> list:
|
||||
"""Search for cards based on the cards name with filter constrains"""
|
||||
filter_rarity = filters["rarity"]
|
||||
filer_type = filters["type"]
|
||||
filter_set = filters["set"]
|
||||
filter_mana = filters["mana"]
|
||||
filter_mana.sort(key=lambda val: util.color_sort_order[val[0]])
|
||||
|
||||
sql = 'SELECT * FROM cards WHERE `name` LIKE ?'
|
||||
parameters = ['%' + term + '%']
|
||||
if filter_rarity != "":
|
||||
sql += ' AND `rarity` = ?'
|
||||
parameters.append(filter_rarity)
|
||||
if filer_type != "":
|
||||
sql += ' AND `types` LIKE ?'
|
||||
parameters.append('%' + filer_type + '%')
|
||||
if filter_set != "":
|
||||
sql += ' AND `set` = ?'
|
||||
parameters.append(filter_set)
|
||||
if len(filter_mana) != 0:
|
||||
sql += ' AND `fcolor` = ?'
|
||||
parameters.append(self.filter_colors_list(filter_mana))
|
||||
sql += ' LIMIT ?'
|
||||
parameters.append(list_size)
|
||||
|
||||
con = sqlite3.connect(self.db_file)
|
||||
cur = con.cursor()
|
||||
cur.row_factory = sqlite3.Row
|
||||
cur.execute(sql, parameters)
|
||||
rows = cur.fetchall()
|
||||
con.close()
|
||||
|
||||
output = []
|
||||
for row in rows:
|
||||
card = self.table_to_card_mapping(row)
|
||||
output.append(card)
|
||||
return output
|
||||
|
||||
def search_by_name(self, term: str) -> dict:
|
||||
"""Search for cards based on the cards name"""
|
||||
con = sqlite3.connect(self.db_file)
|
||||
cur = con.cursor()
|
||||
cur.row_factory = sqlite3.Row
|
||||
cur.execute("SELECT * FROM cards WHERE `name` LIKE ? LIMIT 50", ('%' + term + '%',))
|
||||
rows = cur.fetchall()
|
||||
con.close()
|
||||
|
||||
return self.rows_to_card_dict(rows)
|
||||
|
||||
def set_get_all(self):
|
||||
con = sqlite3.connect(self.db_file)
|
||||
cur = con.cursor()
|
||||
cur.row_factory = sqlite3.Row
|
||||
|
||||
cur.execute("SELECT * FROM sets")
|
||||
rows = cur.fetchall()
|
||||
sets = []
|
||||
for row in rows:
|
||||
sets.append(self.table_to_set_mapping(row))
|
||||
|
||||
return sets
|
||||
|
||||
# DB internal functions ############################################################################################
|
||||
|
||||
def rows_to_card_dict(self, rows):
|
||||
"""Convert database rows to a card dict"""
|
||||
output = {}
|
||||
for row in rows:
|
||||
card = self.table_to_card_mapping(row)
|
||||
output[card.multiverse_id] = card
|
||||
return output
|
||||
|
||||
def db_operation(self, sql: str, args: tuple=()):
|
||||
"""Perform an arbitrary sql operation on the database"""
|
||||
cur = self.connection.cursor()
|
||||
try:
|
||||
cur.execute(sql, args)
|
||||
except sqlite3.OperationalError as err:
|
||||
util.log("Database Error", util.LogLevel.Error)
|
||||
util.log(str(err), util.LogLevel.Error)
|
||||
|
||||
def db_save_changes(self):
|
||||
try:
|
||||
self.connection.commit()
|
||||
except sqlite3.Error as err:
|
||||
self.connection.rollback()
|
||||
util.log("Database Error", util.LogLevel.Error)
|
||||
util.log(str(err), util.LogLevel.Error)
|
||||
|
||||
def db_unsaved_changes(self) -> bool:
|
||||
"""Checks if database is currently in transaction"""
|
||||
return self.connection.in_transaction
|
||||
|
||||
@staticmethod
|
||||
def filter_colors_list(mana: list) -> str:
|
||||
symbols = util.unique_list(mana)
|
||||
output = [s for s in symbols if (s in util.card_colors.values())]
|
||||
return "-".join(output)
|
||||
|
||||
@staticmethod
|
||||
def filter_colors(card) -> str:
|
||||
"""Extracts the colors of a card for filtering."""
|
||||
output = []
|
||||
if card.colors is not None:
|
||||
for color in card.colors:
|
||||
output.append(util.card_colors[color])
|
||||
else:
|
||||
output.append("C")
|
||||
# TODO extract symbols from card text
|
||||
|
||||
return "-".join(output)
|
||||
|
||||
def card_to_table_mapping(self, card: Card):
|
||||
"""Return the database representation of a card object"""
|
||||
return (str(card.name), str(card.layout), str(card.mana_cost), card.cmc, str(card.colors), str(card.names),
|
||||
str(card.type), str(card.supertypes), str(card.subtypes), str(card.types), str(card.rarity),
|
||||
str(card.text),
|
||||
str(card.flavor), str(card.artist), str(card.number), str(card.power), str(card.toughness),
|
||||
str(card.loyalty),
|
||||
card.multiverse_id, str(card.variations), str(card.watermark), str(card.border),
|
||||
str(card.timeshifted),
|
||||
str(card.hand), str(card.life), str(card.release_date), str(card.starter), str(card.printings),
|
||||
str(card.original_text),
|
||||
str(card.original_type), str(card.source), str(card.image_url), str(card.set), str(card.set_name),
|
||||
str(card.id),
|
||||
str(card.legalities), str(card.rulings), str(card.foreign_names), self.filter_colors(card))
|
||||
|
||||
@staticmethod
|
||||
def table_to_card_mapping(row: sqlite3.Row):
|
||||
"""Return card object representation of a table row"""
|
||||
card = Card()
|
||||
card.multiverse_id = row["multiverseid"]
|
||||
tmp = row["name"]
|
||||
card.name = tmp
|
||||
card.layout = row["layout"]
|
||||
card.mana_cost = row["manacost"]
|
||||
card.cmc = row["cmc"]
|
||||
card.colors = row["colors"]
|
||||
card.type = row["type"]
|
||||
card.rarity = row["rarity"]
|
||||
card.text = row["text"]
|
||||
card.flavor = row["flavor"]
|
||||
card.artist = row["artist"]
|
||||
card.number = row["number"]
|
||||
card.power = row["power"]
|
||||
card.toughness = row["toughness"]
|
||||
card.loyalty = row["loyalty"]
|
||||
card.watermark = row["watermark"]
|
||||
card.border = row["border"]
|
||||
card.hand = row["hand"]
|
||||
card.life = row["life"]
|
||||
card.release_date = row["releaseDate"]
|
||||
card.starter = row["starter"]
|
||||
card.original_text = row["originalText"]
|
||||
card.original_type = row["originalType"]
|
||||
card.source = row["source"]
|
||||
card.image_url = row["imageUrl"]
|
||||
card.set = row["set"]
|
||||
card.set_name = row["setName"]
|
||||
card.id = row["id"]
|
||||
|
||||
# Bool attributes
|
||||
card.timeshifted = ast.literal_eval(row["timeshifted"])
|
||||
|
||||
# List attributes
|
||||
card.names = ast.literal_eval(row["names"])
|
||||
card.supertypes = ast.literal_eval(row["supertypes"])
|
||||
card.subtypes = ast.literal_eval(row["subtypes"])
|
||||
card.types = ast.literal_eval(row["types"])
|
||||
card.printings = ast.literal_eval(row["printings"])
|
||||
card.variations = ast.literal_eval(row["variations"])
|
||||
|
||||
# Dict attributes
|
||||
card.legalities = ast.literal_eval(row["legalities"])
|
||||
card.rulings = ast.literal_eval(row["rulings"])
|
||||
card.foreign_names = ast.literal_eval(row["foreignNames"])
|
||||
|
||||
return card
|
||||
|
||||
@staticmethod
|
||||
def set_to_table_mapping(set: Set):
|
||||
"""Convert Set object to a table row"""
|
||||
return (set.code, set.name, set.type, set.border, set.mkm_id, set.mkm_name, set.release_date, set.gatherer_code,
|
||||
set.magic_cards_info_code, str(set.booster), set.old_code)
|
||||
|
||||
@staticmethod
|
||||
def table_to_set_mapping(row):
|
||||
"""Return Set object representation of a table row"""
|
||||
set = Set()
|
||||
set.code = row['code']
|
||||
set.name = row['name']
|
||||
set.type = row['type']
|
||||
set.border = row['border']
|
||||
set.mkm_id = row['mkmid']
|
||||
set.mkm_name = row['mkmname']
|
||||
set.release_date = row['releasedate']
|
||||
set.gatherer_code = row['gatherercode']
|
||||
set.magic_cards_info_code = row['magiccardsinfocode']
|
||||
set.booster = ast.literal_eval(row['booster'])
|
||||
set.old_code = row['oldcode']
|
||||
|
||||
return set
|
||||
157
legacy/gui/cardtree.glade
Normal file
@@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkListStore" id="cardStore">
|
||||
<columns>
|
||||
<!-- column-name multiverse_id -->
|
||||
<column type="gint"/>
|
||||
<!-- column-name name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name supertypes -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name types -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name rarity -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name power -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name toughness -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name printings -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name mana_cost -->
|
||||
<column type="GdkPixbuf"/>
|
||||
<!-- column-name cmc -->
|
||||
<column type="gint"/>
|
||||
<!-- column-name set_name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name color -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name original_text -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkTreeModelFilter" id="cardStoreFiltered">
|
||||
<property name="child_model">cardStore</property>
|
||||
</object>
|
||||
<object class="GtkTreeModelSort" id="cardStoreFilteredSorted">
|
||||
<property name="model">cardStoreFiltered</property>
|
||||
</object>
|
||||
<object class="GtkTreeView" id="cardTree">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="model">cardStoreFilteredSorted</property>
|
||||
<property name="search_column">2</property>
|
||||
<property name="enable_grid_lines">horizontal</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection">
|
||||
<property name="mode">multiple</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="col_name">
|
||||
<property name="resizable">True</property>
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="title" translatable="yes">Card Name</property>
|
||||
<property name="sort_indicator">True</property>
|
||||
<property name="sort_column_id">1</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="cell_bold">
|
||||
<property name="xpad">2</property>
|
||||
<property name="weight">800</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="foreground">11</attribute>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="col_text">
|
||||
<property name="visible">False</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="title" translatable="yes">Card Text</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="wrap_mode">word-char</property>
|
||||
<property name="wrap_width">400</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="foreground">11</attribute>
|
||||
<attribute name="text">12</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="col_types">
|
||||
<property name="resizable">True</property>
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="title" translatable="yes">Types</property>
|
||||
<property name="sort_column_id">3</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xpad">2</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="foreground">11</attribute>
|
||||
<attribute name="text">3</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="col_rarity">
|
||||
<property name="resizable">True</property>
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="title" translatable="yes">Rarity</property>
|
||||
<property name="sort_column_id">4</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xpad">2</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="foreground">11</attribute>
|
||||
<attribute name="text">4</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="col_set">
|
||||
<property name="resizable">True</property>
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="title" translatable="yes">Edition</property>
|
||||
<property name="sort_column_id">10</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="xpad">2</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="foreground">11</attribute>
|
||||
<attribute name="text">10</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="col_mana">
|
||||
<property name="resizable">True</property>
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="title" translatable="yes">Mana Cost</property>
|
||||
<property name="sort_column_id">9</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererPixbuf">
|
||||
<property name="xalign">0.019999999552965164</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="pixbuf">8</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
387
legacy/gui/detailswindow.glade
Normal file
@@ -0,0 +1,387 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkListStore" id="rulesStore">
|
||||
<columns>
|
||||
<!-- column-name date -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name rule -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkWindow" id="cardDetails">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="default_width">600</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="row_spacing">5</property>
|
||||
<property name="column_spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkOverlay" id="imageContainer">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="orientation">vertical</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="ruleBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Rulings</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="1.2"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="rulesTree">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="model">rulesStore</property>
|
||||
<property name="headers_clickable">False</property>
|
||||
<property name="enable_search">False</property>
|
||||
<property name="show_expanders">False</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection">
|
||||
<property name="mode">none</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="sizing">autosize</property>
|
||||
<property name="title" translatable="yes">Date</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn">
|
||||
<property name="title" translatable="yes">Rule</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText">
|
||||
<property name="wrap_mode">word-char</property>
|
||||
<property name="wrap_width">300</property>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="row_spacing">10</property>
|
||||
<property name="column_spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="label" translatable="yes">Card Name:</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="xalign">0.89999997615814209</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="cardName">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Loading...</property>
|
||||
<property name="xalign">0.10000000149011612</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="scale" value="1.3"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="label" translatable="yes">Type:</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="xalign">0.89999997615814209</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="cardTypes">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Loading...</property>
|
||||
<property name="xalign">0.10000000149011612</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="label" translatable="yes">Rarity:</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="xalign">0.89999997615814209</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="cardRarity">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Loading...</property>
|
||||
<property name="xalign">0.10000000149011612</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="label" translatable="yes">Release:</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="xalign">0.89999997615814209</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="cardReleaseDate">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Loading...</property>
|
||||
<property name="xalign">0.10000000149011612</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="label" translatable="yes">Edition:</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="xalign">0.89999997615814209</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="cardSet">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Loading...</property>
|
||||
<property name="xalign">0.10000000149011612</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="label" translatable="yes">Other Printings:</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="xalign">0.89999997615814209</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="cardPrintings">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Loading...</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="max_width_chars">50</property>
|
||||
<property name="xalign">0.10000000149011612</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="legalitiesGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="row_spacing">2</property>
|
||||
<property name="column_spacing">2</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Legality:</property>
|
||||
<property name="justify">right</property>
|
||||
<property name="xalign">0.89999997615814209</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="titlebar">
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
671
legacy/gui/dialogs.glade
Normal file
@@ -0,0 +1,671 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkTreeStore" id="export_treestore">
|
||||
<columns>
|
||||
<!-- column-name check -->
|
||||
<column type="gboolean"/>
|
||||
<!-- column-name visible -->
|
||||
<column type="gboolean"/>
|
||||
<!-- column-name element -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkDialog" id="export_dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Export Data</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="default_width">320</property>
|
||||
<property name="default_height">260</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">4</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="export_ok">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="export_cancel">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Choose what to export</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="export_sel_tree">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="model">export_treestore</property>
|
||||
<property name="headers_clickable">False</property>
|
||||
<property name="enable_search">False</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="export_col_check">
|
||||
<property name="min_width">30</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererToggle">
|
||||
<signal name="toggled" handler="export_cell_toggled" swapped="no"/>
|
||||
</object>
|
||||
<attributes>
|
||||
<attribute name="visible">1</attribute>
|
||||
<attribute name="active">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="export_col_element">
|
||||
<property name="title" translatable="yes">Element</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">2</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-5">export_ok</action-widget>
|
||||
<action-widget response="-6">export_cancel</action-widget>
|
||||
</action-widgets>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDialog" id="loadDataDialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Download</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="window_position">center</property>
|
||||
<property name="default_width">280</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="deletable">False</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
<property name="margin_right">5</property>
|
||||
<property name="margin_top">5</property>
|
||||
<property name="margin_bottom">5</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">15</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="do_cancel_download" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="dl_info_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Connecting to the Internet</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinner" id="dl_spinner">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkProgressBar" id="dl_progress_bar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="dl_progress_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDialog" id="nameEnterDialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="deletable">False</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">4</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="okButtonRename">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="cancelButtonRename">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="nameEnterEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-5">okButtonRename</action-widget>
|
||||
<action-widget response="-6">cancelButtonRename</action-widget>
|
||||
</action-widgets>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkListStore" id="views_store">
|
||||
<columns>
|
||||
<!-- column-name view -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Last used view</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkDialog" id="pref_dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Preferences</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button1">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button2">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">5</property>
|
||||
<property name="column_spacing">5</property>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">General</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="semibold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="label" translatable="yes">Start View</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="pref_start_view_combo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="model">views_store</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Search</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="semibold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="pref_show_all_check">
|
||||
<property name="label" translatable="yes">Show results from all sets</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Display mutliple cards with the same name from diffrents sets in search results.</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-5">button1</action-widget>
|
||||
<action-widget response="-6">button2</action-widget>
|
||||
</action-widgets>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDialog" id="yn_dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="deletable">False</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">15</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="yn_yes">
|
||||
<property name="label">gtk-yes</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="yn_no">
|
||||
<property name="label">gtk-no</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="yn_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">2</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="margin_top">2</property>
|
||||
<property name="margin_bottom">2</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-8">yn_yes</action-widget>
|
||||
<action-widget response="-9">yn_no</action-widget>
|
||||
</action-widgets>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDialog" id="ync_dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<property name="deletable">False</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">15</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkButtonBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="ync_yes">
|
||||
<property name="label">gtk-yes</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="ync_no">
|
||||
<property name="label">gtk-no</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="ync_cancel">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="ync_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">2</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="margin_top">2</property>
|
||||
<property name="margin_bottom">2</property>
|
||||
<property name="justify">center</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-8">ync_yes</action-widget>
|
||||
<action-widget response="-9">ync_no</action-widget>
|
||||
<action-widget response="-6">ync_cancel</action-widget>
|
||||
</action-widgets>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
346
legacy/gui/library.glade
Normal file
@@ -0,0 +1,346 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkMenu" id="libListPopup">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<signal name="show" handler="lib_tree_popup_showed" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="tagItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Tag Card</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="untagItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Untag Card</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_popup_untag_cards" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="removeItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Remove from Library</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_popup_remove_card" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkMenu" id="tagListPopup">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="tagRename">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Rename</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_tag_list_rename" object="tagTree" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="tagDelete">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Delete</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_tag_list_delete" object="tagTree" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkListStore" id="tagStore">
|
||||
<columns>
|
||||
<!-- column-name tag -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name display -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkEntryCompletion" id="tagCompleter">
|
||||
<property name="model">tagStore</property>
|
||||
<property name="text_column">0</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkPaned" id="libraryView">
|
||||
<property name="name">Library</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<signal name="show" handler="do_reload_library" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkBox" id="lib_left_pane">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="tagTree">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="model">tagStore</property>
|
||||
<property name="search_column">1</property>
|
||||
<signal name="button-press-event" handler="do_tag_tree_press_event" swapped="no"/>
|
||||
<signal name="row-activated" handler="on_tag_selected" object="tagTreeSelection" swapped="no"/>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="tagTreeSelection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="col_tag">
|
||||
<property name="visible">False</property>
|
||||
<property name="title" translatable="yes">tag</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="col_tag_display">
|
||||
<property name="title" translatable="yes">Tags</property>
|
||||
<property name="clickable">True</property>
|
||||
<property name="alignment">0.5</property>
|
||||
<property name="sort_indicator">True</property>
|
||||
<property name="sort_column_id">0</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="cell_tag"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="showUntagged">
|
||||
<property name="label" translatable="yes">Untagged</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="do_show_untagged_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="showAllButton">
|
||||
<property name="label" translatable="yes">All</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="do_show_all_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="addTagBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="vexpand">False</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="newTagEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="placeholder_text" translatable="yes">New Tag</property>
|
||||
<signal name="changed" handler="do_tag_entry_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="newTagButton">
|
||||
<property name="label" translatable="yes">Add</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="do_new_tag_clicked" object="newTagEntry" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">False</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="lib_right_pane">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="libTools">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">2</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="vexpand">False</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Showing:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="lib_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
<property name="margin_right">5</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSearchEntry" id="searchLibEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_name">edit-find-symbolic</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">False</property>
|
||||
<property name="placeholder_text" translatable="yes">Search</property>
|
||||
<signal name="changed" handler="do_refilter_library" object="libraryContainer" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBoxText" id="tagCardCombo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="has_entry">True</property>
|
||||
<child internal-child="entry">
|
||||
<object class="GtkEntry" id="tagCardEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="caps_lock_warning">False</property>
|
||||
<property name="placeholder_text" translatable="yes">Tag selected cards</property>
|
||||
<property name="completion">tagCompleter</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="tagCardButton">
|
||||
<property name="label" translatable="yes">Tag card(s)</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="do_tag_cards" object="tagCardEntry" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkOverlay" id="libraryContainer">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">True</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
299
legacy/gui/mainwindow.glade
Normal file
@@ -0,0 +1,299 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.1 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkWindow" id="mainWindow">
|
||||
<property name="name">Card Vault</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="title" translatable="yes">Card Vault</property>
|
||||
<property name="default_width">900</property>
|
||||
<property name="default_height">700</property>
|
||||
<property name="icon_name">cardvault</property>
|
||||
<signal name="delete-event" handler="do_delete_event" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">5</property>
|
||||
<property name="margin_right">5</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkMenuBar" id="menuBar">
|
||||
<property name="name">menuBar</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="Main">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">_Data</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu" id="mainMenu">
|
||||
<property name="name">mainMenu</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="saveLibrary">
|
||||
<property name="label">gtk-save</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Save library to disk</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="do_save_library" swapped="no"/>
|
||||
<accelerator key="s" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="exportLibrary">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Export Library Data</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_export_library" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="importLibrary">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Import Library Data</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_import_library" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="main_load_data">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">Download card data to hard drive</property>
|
||||
<property name="label" translatable="yes">Download Card Data</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_download_card_data" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Clear Data</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="main_clr_usr_data">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Clear User Data</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_card_data_user" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="main_clr_crd_data">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Clear Card Data</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_card_data_card" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="quitProgram">
|
||||
<property name="label">gtk-quit</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="do_delete_event" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="View">
|
||||
<property name="name">View</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">_View</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu" id="viewMenu">
|
||||
<property name="name">viewMenu</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkRadioMenuItem" id="searchViewItem">
|
||||
<property name="name">search</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Search</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<signal name="activate" handler="on_view_changed" swapped="no"/>
|
||||
<accelerator key="1" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioMenuItem" id="libraryViewItem">
|
||||
<property name="name">library</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Library</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">searchViewItem</property>
|
||||
<signal name="activate" handler="on_view_changed" swapped="no"/>
|
||||
<accelerator key="2" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkRadioMenuItem" id="wantsViewItem">
|
||||
<property name="name">wants</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Wants</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="draw_as_radio">True</property>
|
||||
<property name="group">searchViewItem</property>
|
||||
<signal name="activate" handler="on_view_changed" swapped="no"/>
|
||||
<accelerator key="3" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="Options">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">_Options</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child type="submenu">
|
||||
<object class="GtkMenu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="prefs_item">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Preferences</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="prefs_open" swapped="no"/>
|
||||
<accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="contentPage">
|
||||
<property name="name">contentPage</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkStatusbar" id="statusBar">
|
||||
<property name="name">statusBar</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">10</property>
|
||||
<property name="margin_right">10</property>
|
||||
<property name="margin_start">10</property>
|
||||
<property name="margin_end">10</property>
|
||||
<property name="margin_top">6</property>
|
||||
<property name="margin_bottom">6</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkSpinner" id="statusbar_spinner">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="statusbar_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="statusbar_icon">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="titlebar">
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
281
legacy/gui/overlays.glade
Normal file
@@ -0,0 +1,281 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkGrid" id="imageLoding">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">10</property>
|
||||
<property name="row_homogeneous">True</property>
|
||||
<property name="column_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Loading Image</property>
|
||||
<property name="wrap">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSpinner">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkGrid" id="libEmpty">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="column_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="pixel_size">100</property>
|
||||
<property name="icon_name">edit-find-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Use the Search View to add cards to your library</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="label" translatable="yes">No cards in library</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="scale" value="2"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkGrid" id="noResults">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="column_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="pixel_size">100</property>
|
||||
<property name="icon_name">edit-find-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="label" translatable="yes">No Results</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="scale" value="2"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">No cards found</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkGrid" id="pageNotFound">
|
||||
<property name="name">Not Found</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="row_spacing">10</property>
|
||||
<property name="row_homogeneous">True</property>
|
||||
<property name="column_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="pixel_size">100</property>
|
||||
<property name="icon_name">edit-find-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Page not found</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkGrid" id="searchOverlay">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="row_spacing">10</property>
|
||||
<property name="column_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="label" translatable="yes">Search</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="scale" value="2"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Use the entry on the left to search for cards</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="pixel_size">100</property>
|
||||
<property name="icon_name">edit-find-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkGrid" id="wantsOverlay">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="row_spacing">10</property>
|
||||
<property name="column_homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">end</property>
|
||||
<property name="pixel_size">100</property>
|
||||
<property name="icon_name">edit-find-symbolic</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">center</property>
|
||||
<property name="label" translatable="yes">No Results</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
<attribute name="scale" value="2"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="label" translatable="yes">Use the Search function to add cards to your wants</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
410
legacy/gui/search.glade
Normal file
@@ -0,0 +1,410 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkMenu" id="searchListPopup">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<signal name="show" handler="search_tree_popup_showed" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="searchListPopupDetails">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Show Details</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_show_card_details" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="searchListPopupAdd">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Add to Library</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_search_add_to_lib" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="searchListPopupAddTag">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Add & Tag</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="searchListPopupWants">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Add to Wants List</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkPaned" id="searchView">
|
||||
<property name="name">Search</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="searchLeftPane">
|
||||
<property name="name">leftPane</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="searchBox">
|
||||
<property name="name">searchBox</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="searchEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<signal name="activate" handler="do_search_cards" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="searchButton">
|
||||
<property name="label" translatable="yes">Search</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="do_search_cards" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparator">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">5</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="filterGrid">
|
||||
<property name="name">filterGrid</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="row_spacing">2</property>
|
||||
<property name="column_spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Filters</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Mana Color</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="manaFilterGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="whiteManaButton">
|
||||
<property name="name">W</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="always_show_image">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="blueManaButton">
|
||||
<property name="name">U</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="redManaButton">
|
||||
<property name="name">R</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="greenManaButton">
|
||||
<property name="name">G</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton" id="blackManaButton">
|
||||
<property name="name">B</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="clearManaFilterButton">
|
||||
<property name="label">gtk-clear</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="clicked" handler="do_clear_mana_filter" object="manaFilterGrid" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Rarity</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="rarityCombo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active_id">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Type</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="typeCombo">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="active_id">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Edition</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="setEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="secondary_icon_stock">gtk-clear</property>
|
||||
<signal name="icon-press" handler="do_clear_set_filter" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="searchClearAll">
|
||||
<property name="label" translatable="yes">Clear All</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="do_search_clear_all_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">False</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="searchRightPane">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="selectionToolsBox">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">2</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="search_title_label">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="no_show_all">True</property>
|
||||
<property name="label" translatable="yes">Showing results for:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="search_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">2</property>
|
||||
<property name="margin_right">2</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="semibold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="addRemoveButton">
|
||||
<property name="label" translatable="yes">Add to Library</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="do_add_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkOverlay" id="searchResults">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">True</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
222
legacy/gui/wants.glade
Normal file
@@ -0,0 +1,222 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.20.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkListStore" id="wantsListsStore">
|
||||
<columns>
|
||||
<!-- column-name name -->
|
||||
<column type="gchararray"/>
|
||||
<!-- column-name Displayname -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
</object>
|
||||
<object class="GtkPaned" id="wantsView">
|
||||
<property name="name">Wants</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<signal name="show" handler="do_reload_wants" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkBox" id="wantsLeftPane">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">never</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="wantsListsTree">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="model">wantsListsStore</property>
|
||||
<property name="search_column">0</property>
|
||||
<signal name="button-press-event" handler="do_wants_tree_press_event" swapped="no"/>
|
||||
<signal name="row-activated" handler="on_want_list_selected" object="wantsTreeSelection" swapped="no"/>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="wantsTreeSelection"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="col_name">
|
||||
<property name="title" translatable="yes">Wants List</property>
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="cell"/>
|
||||
<attributes>
|
||||
<attribute name="text">1</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="addWantsListEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="placeholder_text" translatable="yes">New Wants List</property>
|
||||
<signal name="activate" handler="on_new_wants_list_clicked" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="addWatnsListButton">
|
||||
<property name="label" translatable="yes">Add</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="clicked" handler="on_new_wants_list_clicked" object="addWantsListEntry" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">False</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="wantsRightPane">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="wantsToolBar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">2</property>
|
||||
<property name="margin_right">2</property>
|
||||
<property name="spacing">2</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Showing:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="wants_title">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="margin_left">2</property>
|
||||
<property name="margin_right">2</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="semibold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkOverlay" id="wantsListContainer">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="hexpand">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">True</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkMenu" id="wants_cardListPopup">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="wntCrdLst_add">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Add to Library</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_want_cards_add_activated" swapped="no"/>
|
||||
<accelerator key="a" signal="activate" modifiers="GDK_CONTROL_MASK"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="wntCrdLst_remove">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Remove Card</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_want_cards_remove_activated" swapped="no"/>
|
||||
<accelerator key="Delete" signal="activate"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkMenu" id="wants_wantsListPopup">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="wantsListRenameItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Rename</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_rename_wants_list" object="wantsListsTree" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="wantsListDeleteItem">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="label" translatable="yes">Delete</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="do_delete_wants_list" object="wantsListsTree" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
326
legacy/handlers.py
Normal file
@@ -0,0 +1,326 @@
|
||||
import math
|
||||
import sys
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
import time, datetime
|
||||
import os
|
||||
import threading
|
||||
from gi.repository import Gtk, GObject
|
||||
|
||||
from cardvault import util, application
|
||||
from legacy.search import SearchHandlers
|
||||
from legacy.library import LibraryHandlers
|
||||
from legacy.wants import WantsHandlers
|
||||
|
||||
|
||||
class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers):
|
||||
def __init__(self, app: 'application.Application'):
|
||||
"""Initialize handlers for UI signals"""
|
||||
self.app = app
|
||||
# Token to cancel a running download
|
||||
self.cancel_token = False
|
||||
|
||||
# Call constructor of view handlers classes
|
||||
SearchHandlers.__init__(self, app)
|
||||
LibraryHandlers.__init__(self, app)
|
||||
WantsHandlers.__init__(self, app)
|
||||
|
||||
# --------------------------------- Main Window Handlers ----------------------------------------------
|
||||
|
||||
def do_save_library(self, item):
|
||||
self.app.save_data()
|
||||
|
||||
def do_export_library(self, item):
|
||||
dialog = Gtk.FileChooserDialog("Export Library", self.app.ui.get_object("mainWindow"),
|
||||
Gtk.FileChooserAction.SAVE,
|
||||
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
|
||||
dialog.set_current_name("mtg_export-" + datetime.datetime.now().strftime("%Y-%m-%d"))
|
||||
dialog.set_current_folder(os.path.expanduser("~"))
|
||||
response = dialog.run()
|
||||
|
||||
if response == Gtk.ResponseType.OK:
|
||||
# prepare export file
|
||||
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()
|
||||
|
||||
def export_cell_toggled(self, widget, pos):
|
||||
model = self.app.ui.get_object("export_treestore")
|
||||
iter = model.get_iter(pos)
|
||||
model.set_value(iter, 0, not widget.get_active())
|
||||
|
||||
if len(pos.split(":")) > 1:
|
||||
# A child node has been clicked
|
||||
pass
|
||||
|
||||
def do_export_json(self, item):
|
||||
"""
|
||||
Export user data to file
|
||||
Called By: Export menu item
|
||||
"""
|
||||
# dialog = self.app.ui.get_object("export_dialog")
|
||||
# dialog.set_transient_for(self.app.ui.get_object("mainWindow"))
|
||||
#
|
||||
# store = self.app.ui.get_object("export_treestore") # type: Gtk.TreeStore
|
||||
# store.clear()
|
||||
# store.append(None, [True, False, "Library"])
|
||||
# store.append(None, [True, False, "Decks"])
|
||||
# store.append(None, [True, False, "Wants Lists"])
|
||||
#
|
||||
# lib_iter = store.get_iter_first()
|
||||
# deck_iter = store.iter_next(lib_iter)
|
||||
# wants_iter = store.iter_next(deck_iter)
|
||||
#
|
||||
# store.append(lib_iter, [True, True, "Untagged Cards"])
|
||||
# for tag in self.app.tags.keys():
|
||||
# store.append(lib_iter, [True, True, tag])
|
||||
#
|
||||
# for name in self.app.wants.keys():
|
||||
# store.append(wants_iter, [True, True, name])
|
||||
#
|
||||
# self.app.ui.get_object("export_sel_tree").expand_all()
|
||||
#
|
||||
# response = dialog.run()
|
||||
# dialog.hide()
|
||||
#
|
||||
# if not response == Gtk.ResponseType.OK:
|
||||
# return
|
||||
|
||||
# TODO Read treemodel to select witch parts to export
|
||||
|
||||
dialog = Gtk.FileChooserDialog("Export Library", self.app.ui.get_object("mainWindow"),
|
||||
Gtk.FileChooserAction.SAVE,
|
||||
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
|
||||
dialog.set_current_name("mtg_export-" + datetime.datetime.now().strftime("%Y-%m-%d") + ".json")
|
||||
dialog.set_current_folder(os.path.expanduser("~"))
|
||||
response = dialog.run()
|
||||
|
||||
if response == Gtk.ResponseType.OK:
|
||||
# prepare export file
|
||||
file = {"library": self.app.library, "tags": self.app.tags, "wants": self.app.wants}
|
||||
util.export_json(dialog.get_filename(), file)
|
||||
self.app.push_status("Library exported")
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
def do_import_library(self, item):
|
||||
"""Called by menu item import library"""
|
||||
# Show file picker dialog for import
|
||||
dialog = Gtk.FileChooserDialog("Import Library", self.app.ui.get_object("mainWindow"),
|
||||
Gtk.FileChooserAction.OPEN,
|
||||
(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
|
||||
Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
|
||||
dialog.set_current_folder(os.path.expanduser("~"))
|
||||
response = dialog.run()
|
||||
if response == Gtk.ResponseType.OK:
|
||||
override_question = self.app.show_dialog_yn(
|
||||
"Import Library", "Importing a library will override your current library.\nProceed?")
|
||||
if override_question == Gtk.ResponseType.YES:
|
||||
imports = util.import_library(dialog.get_filename())
|
||||
self.app.library = imports[0]
|
||||
self.app.tags = imports[1]
|
||||
self.app.wants = imports[2]
|
||||
self.app.db_override_user_data()
|
||||
self.app.current_page.emit('show')
|
||||
dialog.destroy()
|
||||
|
||||
def do_card_data_user(self, menu_item):
|
||||
"""
|
||||
Handler for Clear User Data menu item.
|
||||
"""
|
||||
response = self.app.show_dialog_yn("Deleting All User Data", "You are about to delete all data in the "
|
||||
"library.\nThis can not be undone.\nProceed?")
|
||||
if response == Gtk.ResponseType.YES:
|
||||
util.log("Deleting all local card data", util.LogLevel.Info)
|
||||
self.app.db_delete_user_data()
|
||||
util.log("Done", util.LogLevel.Info)
|
||||
self.app.push_status("Library deleted")
|
||||
|
||||
def do_card_data_card(self, item):
|
||||
"""Handler for Clear Card Data menu item"""
|
||||
response = self.app.show_dialog_yn("Deleting All Card Data", "You are about to delete all local card data.\n"
|
||||
"Further searches will use the internet to search "
|
||||
"for cards.\nProceed?")
|
||||
if response == Gtk.ResponseType.YES:
|
||||
util.log("Deleting all library data", util.LogLevel.Info)
|
||||
self.app.db_delete_card_data()
|
||||
util.log("Done", util.LogLevel.Info)
|
||||
self.app.push_status("Local card data deleted. Switching to online mode.")
|
||||
|
||||
def prefs_open(self, item):
|
||||
"""
|
||||
Handler for open preferences menu item
|
||||
Called By: prefs_item menu item
|
||||
"""
|
||||
self.app.show_preferences_dialog()
|
||||
|
||||
def on_view_changed(self, item):
|
||||
if item.get_active():
|
||||
container = self.app.ui.get_object("contentPage")
|
||||
new_page = self.app.pages[item.get_name()]
|
||||
if self.app.current_page:
|
||||
container.remove(self.app.current_page)
|
||||
self.app.current_page = new_page
|
||||
container.pack_start(self.app.current_page, True, True, 0)
|
||||
container.show_all()
|
||||
self.app.current_page.emit('show')
|
||||
|
||||
app_title = new_page.get_name() + " - " + util.APPLICATION_TITLE
|
||||
self.app.ui.get_object("mainWindow").set_title(app_title)
|
||||
|
||||
self.app.config["last_viewed"] = new_page.get_name().lower()
|
||||
self.app.save_config()
|
||||
|
||||
def do_delete_event(self, arg1, arg2):
|
||||
if self.app.unsaved_changes():
|
||||
response = self.app.show_dialog_ync("Unsaved Changes",
|
||||
"You have unsaved changes in your library. "
|
||||
"Save before exiting?")
|
||||
if response == Gtk.ResponseType.YES:
|
||||
self.app.save_data()
|
||||
return False
|
||||
elif response == Gtk.ResponseType.CANCEL:
|
||||
return True
|
||||
|
||||
def do_cancel_download(self, item: Gtk.MenuItem):
|
||||
"""The cancel button was pressed, set cancel_token to stop download thread"""
|
||||
self.cancel_token = True
|
||||
# Delete Dialog
|
||||
self.app.ui.get_object("loadDataDialog").hide()
|
||||
self.app.push_status("Download canceled")
|
||||
util.log("Download canceled by user", util.LogLevel.Info)
|
||||
|
||||
def download_canceled(self):
|
||||
"""The download thread was canceled and finished executing"""
|
||||
self.cancel_token = False
|
||||
util.log("Download thread ended", util.LogLevel.Info)
|
||||
|
||||
def download_failed(self, err):
|
||||
# Delete Dialog
|
||||
self.app.ui.get_object("loadDataDialog").hide()
|
||||
self.app.push_status("Download canceled")
|
||||
self.app.show_message("Download Failed", str(err))
|
||||
|
||||
def download_finished(self):
|
||||
"""Download thread finished without errors"""
|
||||
self.cancel_token = False
|
||||
self.app.set_online(False)
|
||||
self.app.ui.get_object("loadDataDialog").hide()
|
||||
self.app.push_status("Card data downloaded")
|
||||
util.log("Card data download finished", util.LogLevel.Info)
|
||||
|
||||
def do_download_card_data(self, item: Gtk.MenuItem):
|
||||
"""Download button was pressed in the menu bar. Starts a thread to load data from the internet"""
|
||||
info_string = "Start downloading card information from the internet?\n" \
|
||||
"You can cancel the download at any point."
|
||||
response = self.app.show_dialog_yn("Download Card Data", info_string)
|
||||
if response == Gtk.ResponseType.NO:
|
||||
return
|
||||
# Launch download info dialog
|
||||
dl_dialog = self.app.ui.get_object("loadDataDialog")
|
||||
dl_dialog.set_transient_for(self.app.ui.get_object("mainWindow"))
|
||||
dl_dialog.show()
|
||||
|
||||
# Hide Progress UI until download started
|
||||
self.app.ui.get_object("dl_progress_bar").set_visible(False)
|
||||
self.app.ui.get_object("dl_progress_label").set_visible(False)
|
||||
|
||||
# Create and start the download in a separate thread so it will not block the UI
|
||||
thread = threading.Thread(target=self.load_thread)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
util.log("Attempt downloading all cards. This may take a while...", util.LogLevel.Info)
|
||||
|
||||
def load_thread(self):
|
||||
"""Worker thread to download info using the mtgsdk"""
|
||||
|
||||
# Gatherer uses rate limit on Card.all()
|
||||
# Takes ~10 minutes to download all cards
|
||||
# all = self.load_thread_gatherer()
|
||||
|
||||
# Download from mtgjson.com
|
||||
GObject.idle_add(self.load_show_insert_ui, "Downloading...")
|
||||
|
||||
# Waiting in case a canceled thread is still running.
|
||||
while self.cancel_token:
|
||||
continue
|
||||
|
||||
util.log("Starting download", util.LogLevel.Info)
|
||||
s = time.time()
|
||||
all_json = util.net_all_cards_mtgjson()
|
||||
e = time.time()
|
||||
util.log("Finished in {}s".format(round(e - s, 3)), util.LogLevel.Info)
|
||||
|
||||
if self.cancel_token:
|
||||
GObject.idle_add(self.download_canceled)
|
||||
return
|
||||
|
||||
self.app.db_delete_card_data()
|
||||
|
||||
GObject.idle_add(self.load_show_insert_ui, "Saving data to disk...")
|
||||
util.log("Saving to sqlite", util.LogLevel.Info)
|
||||
s = time.time()
|
||||
GObject.idle_add(self.app.db.db_insert_data_card, all_json)
|
||||
e = time.time()
|
||||
util.log("Finished in {}s".format(round(e - s, 3)), util.LogLevel.Info)
|
||||
|
||||
self.download_finished()
|
||||
|
||||
def load_thread_gatherer(self):
|
||||
all = []
|
||||
all_num = util.get_all_cards_num()
|
||||
all_pages = int(math.ceil(all_num / 100))
|
||||
|
||||
# Paging for ui control between downloads
|
||||
for i in range(all_pages):
|
||||
req_start = time.time()
|
||||
try:
|
||||
new_cards = Card.where(page=i).where(pageSize=100).all()
|
||||
except MtgException as err:
|
||||
util.log(str(err), util.LogLevel.Error)
|
||||
return
|
||||
all = all + new_cards
|
||||
req_end = time.time()
|
||||
|
||||
# Check if the action was canceled during download
|
||||
if self.cancel_token:
|
||||
GObject.idle_add(self.download_canceled)
|
||||
return
|
||||
|
||||
# Activate download UI
|
||||
self.app.ui.get_object("dl_spinner").set_visible(False)
|
||||
self.app.ui.get_object("dl_progress_bar").set_visible(True)
|
||||
self.app.ui.get_object("dl_progress_label").set_visible(True)
|
||||
passed = str(round(req_end - req_start, 3))
|
||||
GObject.idle_add(self.load_update_ui, all, all_num, passed)
|
||||
|
||||
return all
|
||||
|
||||
def load_update_ui(self, current_list: list, max_cards: int, time_passed: str):
|
||||
"""Called from withing the worker thread. Updates the download dialog with infos."""
|
||||
# Get info widgets
|
||||
info_label = self.app.ui.get_object("dl_info_label")
|
||||
progress_label = self.app.ui.get_object("dl_progress_label")
|
||||
bar = self.app.ui.get_object("dl_progress_bar")
|
||||
# Compute numbers for display
|
||||
size_human = util.sizeof_fmt(sys.getsizeof(current_list))
|
||||
size_bytes = sys.getsizeof(current_list)
|
||||
percent = len(current_list) / max_cards
|
||||
# Update UI
|
||||
info_label.set_text("Downloading Cards...")
|
||||
progress_label.set_text("{:.1%} ({})".format(percent, size_human))
|
||||
bar.set_fraction(percent)
|
||||
util.log("Downloading: {:.1%} | {} Bytes | {}s".format(percent, size_bytes, time_passed), util.LogLevel.Info)
|
||||
|
||||
def load_show_insert_ui(self, info: str):
|
||||
"""Called from worker thread after download finished. Sets UI to display the passed string"""
|
||||
self.app.ui.get_object("dl_info_label").set_text(info)
|
||||
self.app.ui.get_object("dl_spinner").set_visible(True)
|
||||
self.app.ui.get_object("dl_progress_bar").set_visible(False)
|
||||
self.app.ui.get_object("dl_progress_label").set_visible(False)
|
||||
249
legacy/library.py
Normal file
@@ -0,0 +1,249 @@
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
from cardvault import application
|
||||
from cardvault import util
|
||||
from cardvault import cardlist
|
||||
|
||||
|
||||
class LibraryHandlers:
|
||||
def __init__(self, app: 'application.Application'):
|
||||
"""Initialize the library view"""
|
||||
self.app = app
|
||||
self.active_tag = "All"
|
||||
# Create Tree View for library
|
||||
container = self.app.ui.get_object("libraryContainer")
|
||||
card_list = cardlist.CardList(True, self.app, util.GENERIC_TREE_COLORS)
|
||||
card_list.set_name("libScroller")
|
||||
# Show details
|
||||
card_list.tree.connect("row-activated", self.on_library_card_selected)
|
||||
# Show Context menu
|
||||
card_list.tree.connect("button-press-event", self.on_library_tree_press_event)
|
||||
card_list.filter.set_visible_func(self.app.filter_lib_func)
|
||||
container.add(card_list)
|
||||
container.add_overlay(self.app.ui.get_object("noResults"))
|
||||
container.show_all()
|
||||
|
||||
self.app.ui.get_object("noResults").set_visible(False)
|
||||
|
||||
def do_reload_library(self, view):
|
||||
"""Handler for the 'show' signal"""
|
||||
self.reload_library()
|
||||
|
||||
def do_tag_entry_changed(self, entry):
|
||||
input_valid = entry.get_text() and entry.get_text() != ""
|
||||
self.app.ui.get_object("newTagButton").set_sensitive(input_valid)
|
||||
|
||||
def do_new_tag_clicked(self, entry):
|
||||
self.add_new_tag(entry.get_text())
|
||||
entry.set_text("")
|
||||
|
||||
def do_show_all_clicked(self, button):
|
||||
# Clear selection in tag list
|
||||
self.app.ui.get_object("tagTree").get_selection().unselect_all()
|
||||
self.active_tag = "All"
|
||||
self.reload_library("All")
|
||||
|
||||
def do_show_untagged_clicked(self, button):
|
||||
# Clear selection in tag list
|
||||
self.app.ui.get_object("tagTree").get_selection().unselect_all()
|
||||
self.active_tag = "Untagged"
|
||||
self.reload_library("Untagged")
|
||||
|
||||
def do_tag_cards(self, entry):
|
||||
card_view = self.app.ui.get_object("libraryContainer").get_child()
|
||||
selected_cards = card_view.get_selected_cards()
|
||||
tag = entry.get_text()
|
||||
if tag != "":
|
||||
self.tag_cards(selected_cards, tag)
|
||||
self.reload_library(tag)
|
||||
entry.set_text("")
|
||||
|
||||
def on_tag_selected(self, selection, path, column):
|
||||
(model, pathlist) = selection.get_selected_rows()
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
tag = model.get_value(tree_iter, 0)
|
||||
self.active_tag = tag
|
||||
self.reload_library(tag)
|
||||
|
||||
def do_tag_tree_press_event(self, tree, event):
|
||||
if event.button == 3: # right click
|
||||
path = tree.get_path_at_pos(int(event.x), int(event.y))
|
||||
if path:
|
||||
tree_iter = tree.get_model().get_iter(path[0])
|
||||
tag = tree.get_model().get_value(tree_iter, 0)
|
||||
self.app.ui.get_object("tagListPopup").popup(None, None, None, None, 0, event.time)
|
||||
|
||||
def do_tag_list_rename(self, tree):
|
||||
(model, pathlist) = tree.get_selection().get_selected_rows()
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
tag = model.get_value(tree_iter, 0)
|
||||
|
||||
new_name = self.app.show_name_enter_dialog("Rename Tag", tag)
|
||||
if new_name and new_name != "":
|
||||
self.app.tag_rename(tag, new_name)
|
||||
self.app.current_page.emit('show')
|
||||
|
||||
def do_tag_list_delete(self, tree):
|
||||
(model, pathlist) = tree.get_selection().get_selected_rows()
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
tag = model.get_value(tree_iter, 0)
|
||||
|
||||
question = "Really delete '{}'?".format(tag)
|
||||
response = self.app.show_dialog_yn("Delete Tag", question)
|
||||
|
||||
if response == Gtk.ResponseType.YES:
|
||||
self.app.tag_delete(tag)
|
||||
self.app.current_page.emit('show')
|
||||
|
||||
@staticmethod
|
||||
def do_refilter_library(container):
|
||||
# Access Card View inside of container
|
||||
container.get_child().filter.refilter()
|
||||
|
||||
def lib_tree_popup_showed(self, menu):
|
||||
"""
|
||||
Construct the context menu for the card tree in library view.
|
||||
Menu items can vary if one or more cards are selected an if they are already tagged.
|
||||
Called By: libListPopup UI Element
|
||||
"""
|
||||
tree = self.app.ui.get_object("libraryContainer").get_child()
|
||||
selected = tree.get_selected_cards()
|
||||
|
||||
root = self.app.ui.get_object("tagItem")
|
||||
tags_men = Gtk.Menu()
|
||||
root.set_submenu(tags_men)
|
||||
|
||||
for list_name in self.app.tags.keys():
|
||||
item = Gtk.MenuItem()
|
||||
tags_men.add(item)
|
||||
item.set_label(list_name)
|
||||
item.connect('activate', self.tag_cards_sig, selected, list_name)
|
||||
|
||||
# Add separator
|
||||
tags_men.add(Gtk.SeparatorMenuItem())
|
||||
# Add new tag item
|
||||
new_tag = Gtk.MenuItem("New Tag")
|
||||
new_tag.connect('activate', self.lib_new_tag_and_add, selected)
|
||||
tags_men.add(new_tag)
|
||||
|
||||
root.show_all()
|
||||
|
||||
# Check if a selected card is tagged
|
||||
for id_list in self.app.tags.values():
|
||||
for card_id in selected.keys():
|
||||
if id_list.__contains__(card_id):
|
||||
self.app.ui.get_object("untagItem").set_sensitive(True)
|
||||
return
|
||||
|
||||
def do_popup_untag_cards(self, item):
|
||||
# Get selected cards
|
||||
card_list = self.app.ui.get_object("libraryContainer").get_child()
|
||||
cards = card_list.get_selected_cards()
|
||||
tag = self.active_tag
|
||||
for card in cards.values():
|
||||
self.app.untag_card(card, tag)
|
||||
self.reload_library(tag)
|
||||
self.reload_tag_list(clear_selection=True)
|
||||
|
||||
def do_popup_remove_card(self, item):
|
||||
# Get selected cards
|
||||
card_list = self.app.ui.get_object("libraryContainer").get_child()
|
||||
cards = card_list.get_selected_cards()
|
||||
# Remove selected cards
|
||||
for card in cards.values():
|
||||
self.app.lib_card_remove(card)
|
||||
self.reload_library(self.active_tag)
|
||||
self.reload_tag_list(clear_selection=True)
|
||||
|
||||
# ---------------------------------Library Tree----------------------------------------------
|
||||
|
||||
def on_library_card_selected(self, tree, row_no, column):
|
||||
(model, path_list) = tree.get_selection().get_selected_rows()
|
||||
for path in path_list:
|
||||
tree_iter = model.get_iter(path)
|
||||
card_id = model.get_value(tree_iter, 0)
|
||||
card_list = self.app.ui.get_object("libraryContainer").get_child()
|
||||
card = card_list.lib[card_id]
|
||||
self.app.show_card_details(card)
|
||||
|
||||
def on_library_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[0] not in rows[1]:
|
||||
selection.unselect_all()
|
||||
selection.select_path(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
|
||||
|
||||
# -------------------------- Class Functions -------------------------------
|
||||
|
||||
def reload_library(self, tag="All"):
|
||||
if tag == "Untagged":
|
||||
lib = self.app.get_untagged_cards()
|
||||
elif tag == "All":
|
||||
lib = self.app.library
|
||||
else:
|
||||
lib = self.app.get_tagged_cards(tag)
|
||||
self.reload_tag_list(not (tag == "All" or tag == "Untagged"))
|
||||
tag_combo = self.app.ui.get_object("tagCardCombo")
|
||||
tag_combo.set_model(self.app.ui.get_object("tagStore"))
|
||||
|
||||
card_tree = self.app.ui.get_object("libraryContainer").get_child()
|
||||
if lib:
|
||||
self.app.ui.get_object("noResults").set_visible(False)
|
||||
card_tree.update(lib)
|
||||
else:
|
||||
card_tree.store.clear()
|
||||
self.app.ui.get_object("noResults").set_visible(True)
|
||||
|
||||
self.app.ui.get_object("lib_title").set_text(tag)
|
||||
|
||||
def lib_new_tag_and_add(self, item, cards):
|
||||
response = self.app.show_name_enter_dialog("Enter name for new Tag", "")
|
||||
if not response == "":
|
||||
self.app.tag_new(response)
|
||||
self.tag_cards(cards, response)
|
||||
else:
|
||||
util.log("No tag name entered", util.LogLevel.Warning)
|
||||
self.app.push_status("No name for new tag entered")
|
||||
self.reload_library(self.active_tag)
|
||||
|
||||
def add_new_tag(self, name):
|
||||
self.app.tag_new(name)
|
||||
self.reload_tag_list(True)
|
||||
|
||||
def reload_tag_list(self, clear_selection=False):
|
||||
"""Reload left pane tag list"""
|
||||
tree = self.app.ui.get_object("tagTree")
|
||||
(path, column) = tree.get_cursor()
|
||||
store = tree.get_model()
|
||||
store.clear()
|
||||
for tag, ids in self.app.tags.items():
|
||||
store.append([tag, tag + " (" + str(len(ids)) + ")"])
|
||||
if clear_selection:
|
||||
tree.set_cursor(path if path else 0)
|
||||
store.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
||||
|
||||
def tag_cards_sig(self, wigdet, cards, tag):
|
||||
self.tag_cards(cards, tag)
|
||||
self.reload_library(self.active_tag)
|
||||
|
||||
def tag_cards(self, card_list, tag):
|
||||
# Check if tag exist and create if necessary
|
||||
if not self.app.tags.__contains__(tag):
|
||||
self.app.tag_new(tag)
|
||||
|
||||
for card in card_list.values():
|
||||
if not self.app.tags[tag].__contains__(card.multiverse_id):
|
||||
self.app.tag_card(card, tag)
|
||||
BIN
legacy/resources/images/demo.jpg
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
legacy/resources/images/dummy.jpg
Normal file
|
After Width: | Height: | Size: 147 KiB |
BIN
legacy/resources/images/dummy_315x450.png
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
legacy/resources/mana/0.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
legacy/resources/mana/1.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
legacy/resources/mana/10.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
legacy/resources/mana/11.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
legacy/resources/mana/12.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
legacy/resources/mana/13.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
legacy/resources/mana/14.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
legacy/resources/mana/15.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
legacy/resources/mana/16.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
legacy/resources/mana/17.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
legacy/resources/mana/18.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
legacy/resources/mana/19.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
legacy/resources/mana/2.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
legacy/resources/mana/20.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
legacy/resources/mana/2b.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
legacy/resources/mana/2g.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
legacy/resources/mana/2r.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
legacy/resources/mana/2u.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
legacy/resources/mana/2w.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
legacy/resources/mana/3.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
legacy/resources/mana/4.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
legacy/resources/mana/5.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
legacy/resources/mana/6.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
legacy/resources/mana/7.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
legacy/resources/mana/8.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
legacy/resources/mana/9.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
legacy/resources/mana/B-G.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
legacy/resources/mana/B-P.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
legacy/resources/mana/B-R.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
legacy/resources/mana/B.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
legacy/resources/mana/B_alt.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
legacy/resources/mana/C.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
legacy/resources/mana/C_alt.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
legacy/resources/mana/G-P.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
legacy/resources/mana/G-U.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
legacy/resources/mana/G-W.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
legacy/resources/mana/G.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
legacy/resources/mana/G_alt.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
legacy/resources/mana/R-G.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
legacy/resources/mana/R-P.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
legacy/resources/mana/R-W.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
legacy/resources/mana/R.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
legacy/resources/mana/R_alt.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
legacy/resources/mana/S.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
legacy/resources/mana/T.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
legacy/resources/mana/U-B.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
legacy/resources/mana/U-P.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
legacy/resources/mana/U-R.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
legacy/resources/mana/U.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
legacy/resources/mana/U_alt.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
legacy/resources/mana/W-B.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
legacy/resources/mana/W-P.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
BIN
legacy/resources/mana/W-U.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
legacy/resources/mana/W.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
legacy/resources/mana/W_alt.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
legacy/resources/mana/X.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
legacy/resources/mana/Y.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
legacy/resources/mana/Z.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
legacy/resources/mana/flip.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
legacy/resources/mana/half.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
legacy/resources/mana/infinite.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
legacy/resources/mana/tap_old.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
legacy/resources/mana/untap.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
341
legacy/search.py
Normal file
@@ -0,0 +1,341 @@
|
||||
import time
|
||||
from urllib.error import URLError, HTTPError
|
||||
from cardvault import application, cardlist, util
|
||||
|
||||
# Deprecated
|
||||
from mtgsdk import Card
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
|
||||
class SearchHandlers:
|
||||
def __init__(self, app: 'application.Application'):
|
||||
self.app = app
|
||||
|
||||
buttons = [x for x in self.app.ui.get_object("manaFilterGrid").get_children()
|
||||
if isinstance(x, Gtk.ToggleButton)]
|
||||
self._init_mana_buttons(buttons)
|
||||
self._init_set_entry(self.app.ui.get_object("setEntry"))
|
||||
self._init_combo_box(self.app.ui.get_object("rarityCombo"), util.rarity_dict.keys())
|
||||
self._init_combo_box(self.app.ui.get_object("typeCombo"), util.card_types)
|
||||
self._init_results_tree()
|
||||
|
||||
def do_search_cards(self, sender):
|
||||
search_term = self.app.ui.get_object("searchEntry").get_text()
|
||||
|
||||
filters = self.get_filters()
|
||||
|
||||
results = self.search_cards(search_term, filters)
|
||||
|
||||
card_list = self.app.ui.get_object("searchResults").get_child()
|
||||
card_list.update(results)
|
||||
|
||||
self.app.ui.get_object("searchOverlay").set_visible(False)
|
||||
self.app.ui.get_object("search_title_label").set_visible(True)
|
||||
self.app.ui.get_object("search_title").set_text(search_term)
|
||||
|
||||
@staticmethod
|
||||
def do_clear_mana_filter(mana_filter_grid):
|
||||
for toggle_button in mana_filter_grid.get_children():
|
||||
if isinstance(toggle_button, Gtk.ToggleButton):
|
||||
toggle_button.set_active(False)
|
||||
|
||||
@staticmethod
|
||||
def do_clear_set_filter(entry, icon_pos, button):
|
||||
entry.set_text("")
|
||||
|
||||
def do_add_clicked(self, button):
|
||||
card_view = self.app.ui.get_object("searchResults").get_child()
|
||||
(model, pathlist) = card_view.selection.get_selected_rows()
|
||||
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
card_id = model.get_value(tree_iter, 0)
|
||||
card = card_view.lib[card_id]
|
||||
self.app.lib_card_add(card)
|
||||
self.reload_search_view()
|
||||
self.app.ui.get_object("searchEntry").grab_focus()
|
||||
|
||||
def search_tree_popup_showed(self, menu):
|
||||
# Create tag submenu
|
||||
tags_item = self.app.ui.get_object("searchListPopupAddTag")
|
||||
tags_sub = Gtk.Menu()
|
||||
tags_item.set_submenu(tags_sub)
|
||||
|
||||
for list_name in self.app.tags.keys():
|
||||
item = Gtk.MenuItem()
|
||||
tags_sub.add(item)
|
||||
item.set_label(list_name)
|
||||
item.connect('activate', self.search_popup_add_tags)
|
||||
|
||||
# Add separator
|
||||
tags_sub.add(Gtk.SeparatorMenuItem())
|
||||
# Add new tag item
|
||||
new_tag = Gtk.MenuItem("New Tag")
|
||||
new_tag.connect('activate', self.new_tag_and_add)
|
||||
tags_sub.add(new_tag)
|
||||
|
||||
tags_item.show_all()
|
||||
|
||||
# Create wants Submenu
|
||||
wants_item = self.app.ui.get_object("searchListPopupWants")
|
||||
wants_sub = Gtk.Menu()
|
||||
wants_item.set_submenu(wants_sub)
|
||||
|
||||
for list_name in self.app.wants.keys():
|
||||
item = Gtk.MenuItem()
|
||||
wants_sub.add(item)
|
||||
item.set_label(list_name)
|
||||
item.connect('activate', self.search_popup_add_wants)
|
||||
|
||||
# Add separator
|
||||
wants_sub.add(Gtk.SeparatorMenuItem())
|
||||
# Add new tag item
|
||||
new_want = Gtk.MenuItem("New Want List")
|
||||
new_want.connect('activate', self.new_wants_and_add)
|
||||
wants_sub.add(new_want)
|
||||
|
||||
wants_item.show_all()
|
||||
|
||||
def new_tag_and_add(self, menu_item):
|
||||
# Get selected cards
|
||||
card_list = self.app.ui.get_object("searchResults").get_child()
|
||||
cards = card_list.get_selected_cards()
|
||||
response = self.app.show_name_enter_dialog("Enter name for new Tag", "")
|
||||
if not response == "":
|
||||
self.app.tag_new(response)
|
||||
for card in cards.values():
|
||||
self.app.lib_card_add(card, response)
|
||||
else:
|
||||
util.log("No tag name entered", util.LogLevel.Warning)
|
||||
self.app.push_status("No name for new tag entered")
|
||||
self.reload_search_view()
|
||||
|
||||
def new_wants_and_add(self, menu_item):
|
||||
# Get selected cards
|
||||
card_list = self.app.ui.get_object("searchResults").get_child()
|
||||
cards = card_list.get_selected_cards()
|
||||
response = self.app.show_name_enter_dialog("Enter name for new Want List", "")
|
||||
if not response == "":
|
||||
self.app.wants_new(response)
|
||||
for card in cards.values():
|
||||
self.app.wants_card_add(response, card)
|
||||
else:
|
||||
util.log("No list name entered", util.LogLevel.Warning)
|
||||
self.app.push_status("No name for new wants list entered")
|
||||
self.reload_search_view()
|
||||
|
||||
def search_popup_add_tags(self, item):
|
||||
# Get selected cards
|
||||
card_list = self.app.ui.get_object("searchResults").get_child()
|
||||
cards = card_list.get_selected_cards()
|
||||
for card in cards.values():
|
||||
self.app.lib_card_add(card, item.get_label())
|
||||
self.reload_search_view()
|
||||
self.app.push_status("Added " + str(len(cards)) + " card(s) to library.")
|
||||
|
||||
def search_popup_add_wants(self, item):
|
||||
# Get selected cards
|
||||
card_list = self.app.ui.get_object("searchResults").get_child()
|
||||
cards = card_list.get_selected_cards()
|
||||
for card in cards.values():
|
||||
self.app.wants_card_add(item.get_label(), card)
|
||||
self.reload_search_view()
|
||||
self.app.push_status("Added " + str(len(cards)) + " card(s) to Want List '" + item.get_label() + "'")
|
||||
|
||||
def do_search_clear_all_clicked(self, button):
|
||||
""" Rest all controls in search view """
|
||||
self.app.ui.get_object("searchEntry").set_text("")
|
||||
self.do_clear_mana_filter(self.app.ui.get_object("manaFilterGrid"))
|
||||
self.app.ui.get_object("rarityCombo").set_active(0)
|
||||
self.app.ui.get_object("typeCombo").set_active(0)
|
||||
self.app.ui.get_object("setEntry").set_text("")
|
||||
|
||||
def do_show_card_details(self, menu_item):
|
||||
tree = self.app.ui.get_object("searchResults").get_child()
|
||||
cards = tree.get_selected_cards()
|
||||
for card in cards.values():
|
||||
self.app.show_card_details(card)
|
||||
|
||||
def do_search_add_to_lib(self, menu_item):
|
||||
tree = self.app.ui.get_object("searchResults").get_child()
|
||||
cards = tree.get_selected_cards()
|
||||
for card in cards.values():
|
||||
self.app.lib_card_add(card)
|
||||
self.reload_search_view()
|
||||
|
||||
def reload_search_view(self):
|
||||
""" Reload the card tree """
|
||||
results_tree = self.app.ui.get_object("searchResults").get_child()
|
||||
cards = results_tree.lib
|
||||
results_tree.update(cards)
|
||||
|
||||
def get_filters(self) -> dict:
|
||||
""" Read selected filters from UI and return values as dict """
|
||||
output = {"mana": []}
|
||||
|
||||
for button in self.app.ui.get_object("manaFilterGrid").get_children():
|
||||
if isinstance(button, Gtk.ToggleButton):
|
||||
if button.get_active():
|
||||
output["mana"].append(button.get_name())
|
||||
|
||||
# Rarity
|
||||
combo = self.app.ui.get_object("rarityCombo")
|
||||
output["rarity"] = self._get_combo_value(combo)
|
||||
# Type
|
||||
combo = self.app.ui.get_object("typeCombo")
|
||||
output["type"] = self._get_combo_value(combo)
|
||||
# Set
|
||||
name = self.app.ui.get_object("setEntry").get_text()
|
||||
output["set"] = ""
|
||||
for mtgset in self.app.get_all_sets().values():
|
||||
if mtgset['name'] == name:
|
||||
output["set"] = mtgset['code']
|
||||
return output
|
||||
|
||||
def search_cards(self, term: str, filters: dict) -> dict:
|
||||
"""Return a dict of cards based on a search term and filters"""
|
||||
cards = {}
|
||||
# Check if a local database can be used for searching
|
||||
if self.app.config["local_db"]:
|
||||
util.log("Starting local search for '" + term + "'", util.LogLevel.Info)
|
||||
start = time.time()
|
||||
|
||||
cards = self.app.db.search_by_name_filtered(term, filters, 100)
|
||||
|
||||
end = time.time()
|
||||
util.log("Card info fetched in {}s".format(round(end - start, 3)), util.LogLevel.Info)
|
||||
else:
|
||||
util.log("Starting online search for '" + term + "'", util.LogLevel.Info)
|
||||
util.log("Used Filters: " + str(filters), util.LogLevel.Info)
|
||||
|
||||
# Load card info from internet
|
||||
try:
|
||||
util.log("Fetching card info ...", util.LogLevel.Info)
|
||||
start = time.time()
|
||||
cards = Card.where(name=term) \
|
||||
.where(colorIdentity=",".join(filters["mana"])) \
|
||||
.where(types=filters["type"]) \
|
||||
.where(set=filters["set"]) \
|
||||
.where(rarity=filters["rarity"]) \
|
||||
.where(pageSize=50) \
|
||||
.where(page=1).all()
|
||||
cards = [card.__dict__ for card in cards]
|
||||
end = time.time()
|
||||
util.log("Card info fetched in {}s".format(round(end - start, 3)), util.LogLevel.Info)
|
||||
except (URLError, HTTPError) as err:
|
||||
util.log(err, util.LogLevel.Error)
|
||||
return {}
|
||||
|
||||
if not self.app.config["show_all_in_search"]:
|
||||
cards = self._remove_duplicates(cards)
|
||||
|
||||
if len(cards) == 0:
|
||||
# TODO UI show no cards found
|
||||
util.log("No Cards found", util.LogLevel.Info)
|
||||
return {}
|
||||
util.log("Found " + str(len(cards)) + " cards", util.LogLevel.Info)
|
||||
|
||||
return {card['multiverse_id']: card for card in cards}
|
||||
|
||||
# ---------------------------------Search Tree----------------------------------------------
|
||||
|
||||
def on_search_card_selected(self, tree, row_no, column):
|
||||
(model, path_list) = tree.get_selection().get_selected_rows()
|
||||
for path in path_list:
|
||||
tree_iter = model.get_iter(path)
|
||||
card_id = model.get_value(tree_iter, 0)
|
||||
card_list = self.app.ui.get_object("searchResults").get_child()
|
||||
card = card_list.lib[card_id]
|
||||
self.app.show_card_details(card)
|
||||
|
||||
def on_search_selection_changed(self, selection):
|
||||
(model, pathlist) = selection.get_selected_rows()
|
||||
tools = self.app.ui.get_object("selectionToolsBox")
|
||||
add_remove_button = self.app.ui.get_object("addRemoveButton")
|
||||
|
||||
if pathlist:
|
||||
add_remove_button.set_sensitive(True)
|
||||
else:
|
||||
add_remove_button.set_sensitive(False)
|
||||
|
||||
def on_search_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("searchListPopup").emit('show')
|
||||
self.app.ui.get_object("searchListPopup").popup(None, None, None, None, 0, event.time)
|
||||
return True
|
||||
|
||||
# -------------------------- Class Functions -------------------------------
|
||||
|
||||
def _init_results_tree(self):
|
||||
overlay = self.app.ui.get_object("searchResults")
|
||||
card_list = cardlist.CardList(False, self.app, util.SEARCH_TREE_COLORS)
|
||||
card_list.set_name("resultsScroller")
|
||||
card_list.tree.connect("row-activated", self.on_search_card_selected)
|
||||
card_list.selection.connect("changed", self.on_search_selection_changed)
|
||||
overlay.add(card_list)
|
||||
overlay.add_overlay(self.app.ui.get_object("searchOverlay"))
|
||||
overlay.show_all()
|
||||
|
||||
# Connect signal for context menu
|
||||
card_list.tree.connect("button-press-event", self.on_search_tree_press_event)
|
||||
|
||||
@staticmethod
|
||||
def _init_combo_box(combo, card_list: list):
|
||||
""" Initialize a combo box model """
|
||||
model = Gtk.ListStore(str)
|
||||
model.append(["All"])
|
||||
for entry in card_list:
|
||||
model.append([entry.title()])
|
||||
combo.set_model(model)
|
||||
cell = Gtk.CellRendererText()
|
||||
combo.pack_start(cell, True)
|
||||
combo.add_attribute(cell, "text", 0)
|
||||
combo.set_active(0)
|
||||
|
||||
@staticmethod
|
||||
def _remove_duplicates(cards: list) -> list:
|
||||
""" Remove cards with the same name from a list """
|
||||
unique_cards = []
|
||||
unique_names = []
|
||||
# Reverse cardlist so we get the version with the most modern art
|
||||
for card in reversed(cards):
|
||||
if card['name'] not in unique_names:
|
||||
unique_names.append(card['name'])
|
||||
unique_cards.append(card)
|
||||
return unique_cards
|
||||
|
||||
@staticmethod
|
||||
def _get_combo_value(combo) -> str:
|
||||
""" Get value from a combo box control """
|
||||
tree_iter = combo.get_active_iter()
|
||||
value = combo.get_model().get_value(tree_iter, 0)
|
||||
return value.replace("All", "")
|
||||
|
||||
def _init_mana_buttons(self, button_list):
|
||||
""" Initialize mana buttons """
|
||||
for button in button_list:
|
||||
image = Gtk.Image.new_from_pixbuf(self.app.get_mana_icons("{" + button.get_name() + "}"))
|
||||
button.set_image(image)
|
||||
|
||||
def _init_set_entry(self, entry):
|
||||
""" Initialize model for set entry """
|
||||
set_store = Gtk.ListStore(str, str)
|
||||
for mtgset in self.app.get_all_sets().values():
|
||||
set_store.append([mtgset.get('name'), mtgset.get('code')])
|
||||
completer = Gtk.EntryCompletion()
|
||||
completer.set_model(set_store)
|
||||
completer.set_text_column(0)
|
||||
entry.set_completion(completer)
|
||||
420
legacy/util.py
Normal file
@@ -0,0 +1,420 @@
|
||||
import copy
|
||||
import enum
|
||||
import json
|
||||
import jsonpickle
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import six.moves.cPickle as pickle
|
||||
from time import localtime, strftime, time
|
||||
from PIL import Image as PImage
|
||||
import urllib.request
|
||||
from urllib import request
|
||||
from mtgsdk import Set, Card, MtgException
|
||||
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import GdkPixbuf, GLib
|
||||
|
||||
# Title of the Program Window
|
||||
APPLICATION_TITLE = "Card Vault"
|
||||
|
||||
# Program version
|
||||
VERSION = "0.6.0"
|
||||
|
||||
# Path of image cache
|
||||
CACHE_PATH = os.path.expanduser('~') + "/.cardvault/"
|
||||
IMAGE_CACHE_PATH = os.path.expanduser('~') + "/.cardvault/images/"
|
||||
ICON_CACHE_PATH = os.path.expanduser('~') + "/.cardvault/icons/"
|
||||
|
||||
# Log level of the application
|
||||
# 1 Info
|
||||
# 2 Warning
|
||||
# 3 Error
|
||||
LOG_LEVEL = 1
|
||||
|
||||
# Name of the database
|
||||
DB_NAME = "cardvault.db"
|
||||
|
||||
ALL_NUM_URL = 'https://api.magicthegathering.io/v1/cards?page=0&pageSize=100'
|
||||
|
||||
ALL_SETS_JSON_URL = 'https://mtgjson.com/json/AllSets-x.json'
|
||||
|
||||
# URL for card images. Insert card.multiverse_id.
|
||||
CARD_IMAGE_URL = 'http://gatherer.wizards.com/Handlers/Image.ashx?multiverseid={}&type=card'
|
||||
|
||||
# Location of manual wiki
|
||||
MANUAL_LOCATION = 'https://github.com/luxick/cardvault'
|
||||
|
||||
# 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"
|
||||
}
|
||||
|
||||
LEGALITY_COLORS = {
|
||||
"Banned": "#C65642",
|
||||
"Restricted": "#D39F30",
|
||||
"Legal": "#62B62F"
|
||||
}
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
"last_viewed": "",
|
||||
"show_all_in_search": True,
|
||||
"start_page": "search",
|
||||
"local_db": False,
|
||||
"first_run": True,
|
||||
"log_level": 3
|
||||
}
|
||||
|
||||
card_colors = {
|
||||
'White': 'W',
|
||||
'Blue': 'U',
|
||||
'Black': 'B',
|
||||
'Red': 'R',
|
||||
'Green': 'G'
|
||||
}
|
||||
|
||||
color_sort_order = {
|
||||
'W': 0,
|
||||
'U': 1,
|
||||
'B': 2,
|
||||
'R': 3,
|
||||
'G': 4
|
||||
}
|
||||
|
||||
rarity_dict = {
|
||||
"special": 0,
|
||||
"common": 1,
|
||||
"uncommon": 2,
|
||||
"rare": 3,
|
||||
"mythic rare": 4
|
||||
}
|
||||
card_types = ["Creature", "Artifact", "Instant", "Enchantment", "Sorcery", "Land", "Planeswalker"]
|
||||
|
||||
online_icons = {
|
||||
True: 'network-wired',
|
||||
False: 'drive-harddisk'
|
||||
}
|
||||
|
||||
online_tooltips = {
|
||||
True: 'Using online card data',
|
||||
False: 'Using card data from local database.'
|
||||
}
|
||||
|
||||
|
||||
class LogLevel(enum.Enum):
|
||||
Error = 1
|
||||
Warning = 2
|
||||
Info = 3
|
||||
|
||||
|
||||
class TerminalColors:
|
||||
HEADER = '\033[95m'
|
||||
OKBLUE = '\033[94m'
|
||||
OKGREEN = '\033[92m'
|
||||
WARNING = '\033[93m'
|
||||
FAIL = '\033[91m'
|
||||
ENDC = '\033[0m'
|
||||
BOLD = '\033[1m'
|
||||
UNDERLINE = '\033[4m'
|
||||
|
||||
|
||||
def log(msg: str, ll: LogLevel):
|
||||
if ll.value <= LOG_LEVEL:
|
||||
lv = "[" + ll.name + "] "
|
||||
if ll.value == 2:
|
||||
c = TerminalColors.WARNING
|
||||
elif ll.value == 1:
|
||||
c = TerminalColors.BOLD + TerminalColors.FAIL
|
||||
else:
|
||||
c = ""
|
||||
tc = strftime("%H:%M:%S ", localtime())
|
||||
print(c + lv + tc + msg + TerminalColors.ENDC)
|
||||
|
||||
|
||||
def parse_config(filename: str, default: dict):
|
||||
config = copy.copy(default)
|
||||
try:
|
||||
with open(filename) as configfile:
|
||||
loaded_config = json.load(configfile)
|
||||
config.update(loaded_config)
|
||||
except IOError:
|
||||
# Will just use the default config
|
||||
# and create the file for manual editing
|
||||
save_config(config, filename)
|
||||
except ValueError:
|
||||
# There's a syntax error in the config file
|
||||
log("Syntax error wihle parsing config file", LogLevel.Error)
|
||||
return
|
||||
return config
|
||||
|
||||
|
||||
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, sort_keys=True,
|
||||
indent=4, separators=(',', ': ')).encode('utf-8'))
|
||||
|
||||
|
||||
def resource_path(relative_path):
|
||||
if hasattr(sys, '_MEIPASS'):
|
||||
return os.path.join(sys._MEIPASS, relative_path)
|
||||
return os.path.join(os.path.abspath("."), relative_path)
|
||||
|
||||
|
||||
def get_root_filename(filename: str) -> str:
|
||||
return os.path.expanduser(os.path.join('~', '.cardvault', filename))
|
||||
|
||||
|
||||
def get_ui_filename(filename: str) -> str:
|
||||
return os.path.join(os.path.dirname(__file__), 'gui', filename)
|
||||
|
||||
|
||||
def reload_image_cache(path: str) -> dict:
|
||||
cache = {}
|
||||
if not os.path.isdir(path):
|
||||
os.mkdir(path)
|
||||
imagefiles = os.listdir(path)
|
||||
for imagefile in imagefiles:
|
||||
try:
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file(path + imagefile)
|
||||
# Strip filename extension
|
||||
imagename = os.path.splitext(imagefile)[0]
|
||||
cache[int(imagename)] = pixbuf
|
||||
except OSError as err:
|
||||
log("Error loading image: " + str(err), LogLevel.Error)
|
||||
except GLib.GError as err:
|
||||
log("Error loading image: " + str(err), LogLevel.Error)
|
||||
return cache
|
||||
|
||||
|
||||
def reload_preconstructed_icons(path: str) -> dict:
|
||||
cache = {}
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
files = os.listdir(path)
|
||||
for file in files:
|
||||
# Split filename into single icon names and remove extension
|
||||
without_ext = file.split(".")[0]
|
||||
names = without_ext.split("_")
|
||||
# Compute size of the finished icon
|
||||
pic_width = len(names) * 105
|
||||
pic_height = 105
|
||||
try:
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file(ICON_CACHE_PATH + file)
|
||||
pixbuf = pixbuf.scale_simple(pic_width / 5, pic_height / 5, GdkPixbuf.InterpType.HYPER)
|
||||
# Set name for icon
|
||||
iconname = "_".join(names)
|
||||
cache[iconname] = pixbuf
|
||||
except OSError as err:
|
||||
log("Error loading image: " + str(err), LogLevel.Error)
|
||||
return cache
|
||||
|
||||
|
||||
def load_mana_icons(path: str) -> dict:
|
||||
if not os.path.exists(path):
|
||||
log("Directory for mana icons not found " + path, LogLevel.Error)
|
||||
return {}
|
||||
icons = {}
|
||||
files = os.listdir(path)
|
||||
for file in files:
|
||||
img = PImage.open(path + file)
|
||||
# Strip file extension
|
||||
name = os.path.splitext(file)[0]
|
||||
icons[name] = img
|
||||
return icons
|
||||
|
||||
|
||||
def net_all_cards_mtgjson() -> dict:
|
||||
with urllib.request.urlopen(ALL_SETS_JSON_URL) as url:
|
||||
data = json.loads(url.read().decode())
|
||||
return data
|
||||
|
||||
|
||||
def net_load_set_list() -> dict:
|
||||
""" Load the list of all MTG sets from the Gather"""
|
||||
try:
|
||||
start = time()
|
||||
sets = Set.all()
|
||||
stop = time()
|
||||
log("Fetched set list in {}s".format(round(stop - start, 3)), LogLevel.Info)
|
||||
except MtgException as err:
|
||||
log(str(err), LogLevel.Error)
|
||||
return {}
|
||||
return [set.__dict__ for set in sets]
|
||||
|
||||
|
||||
def load_sets(filename: str) -> dict:
|
||||
"""
|
||||
Load sets from local file if possible.
|
||||
Called by: Application if in online mode
|
||||
"""
|
||||
if not os.path.isfile(filename):
|
||||
# use mtgsdk api to retrieve al list of all sets
|
||||
sets = net_load_set_list()
|
||||
# Serialize the loaded data to a file
|
||||
pickle.dump(sets, open(filename, 'wb'))
|
||||
# Deserialize set data from local file
|
||||
sets = pickle.load(open(filename, 'rb'))
|
||||
# Sort the loaded sets based on the sets name
|
||||
output = {}
|
||||
for set in sorted(sets, key=lambda x: x.get('name')):
|
||||
output[set.get('code')] = set
|
||||
return output
|
||||
|
||||
|
||||
def export_library(path, file):
|
||||
try:
|
||||
pickle.dump(file, open(path, 'wb'))
|
||||
log("Library exported to \"" + path + "\"", LogLevel.Info)
|
||||
except OSError as err:
|
||||
log(str(err), LogLevel.Error)
|
||||
|
||||
|
||||
def export_json(path, file):
|
||||
"""Write file in json format"""
|
||||
try:
|
||||
f = open(path, 'w')
|
||||
s = jsonpickle.encode(file)
|
||||
f.write(s)
|
||||
except OSError as err:
|
||||
log(str(err), LogLevel.Error)
|
||||
|
||||
|
||||
def import_library(path: str) -> ():
|
||||
try:
|
||||
imported = pickle.load(open(path, 'rb'))
|
||||
except pickle.UnpicklingError as err:
|
||||
log(str(err) + " while importing", LogLevel.Error)
|
||||
return
|
||||
# Parse imported file
|
||||
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, wants
|
||||
|
||||
|
||||
def save_file(path, file):
|
||||
# Serialize using cPickle
|
||||
try:
|
||||
pickle.dump(file, open(path, 'wb'))
|
||||
except OSError as err:
|
||||
log(str(err), LogLevel.Error)
|
||||
return
|
||||
log("Saved file " + path, LogLevel.Info)
|
||||
|
||||
|
||||
def load_file(path: str):
|
||||
if not os.path.isfile(path):
|
||||
log(path + " does not exist", LogLevel.Warning)
|
||||
return
|
||||
try:
|
||||
loaded = pickle.load(open(path, 'rb'))
|
||||
except OSError as err:
|
||||
log(str(err), LogLevel.Error)
|
||||
return
|
||||
return loaded
|
||||
|
||||
|
||||
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', size_x, size_y)
|
||||
|
||||
|
||||
def load_card_image(card: dict, size_x: int, size_y: int, cache: dict) -> GdkPixbuf:
|
||||
""" Retrieve an card image from cache or alternatively load from gatherer"""
|
||||
try:
|
||||
image = cache[card.get('multiverse_id')]
|
||||
except KeyError:
|
||||
log("No local image for " + card.get('name') + ". Loading from " + card.get('image_url'), LogLevel.Info)
|
||||
filename, image = net_load_card_image(card, size_x, size_y)
|
||||
cache[card.get('multiverse_id')] = image
|
||||
return image
|
||||
|
||||
|
||||
def net_load_card_image(card: dict, size_x: int, size_y: int) -> (str, GdkPixbuf):
|
||||
url = card.get('image_url')
|
||||
if url is None:
|
||||
log("No Image URL for " + card.get('name'), LogLevel.Warning)
|
||||
return load_dummy_image(size_x, size_y)
|
||||
filename = IMAGE_CACHE_PATH + str(card.get('multiverse_id')) + ".png"
|
||||
request.urlretrieve(url, filename)
|
||||
return filename, GdkPixbuf.Pixbuf.new_from_file_at_size(filename, size_x, size_y)
|
||||
|
||||
|
||||
def create_mana_icons(icons: dict, mana_string: str) -> GdkPixbuf:
|
||||
# Convert the string to a List
|
||||
safe_string = mana_string.replace("/", "-")
|
||||
glyphs = re.findall("{(.*?)}", safe_string)
|
||||
if len(glyphs) == 0:
|
||||
return
|
||||
# Compute horizontal size for the final image
|
||||
size = len(glyphs) * 105
|
||||
image = PImage.new("RGBA", (size, 105))
|
||||
# Increment for each position of an icon
|
||||
# (Workaround: 2 or more of the same icon will be rendered in the same position)
|
||||
c = 0
|
||||
# Go through all entries an add the correspondent icon to the final image
|
||||
for icon in glyphs:
|
||||
x_pos = c * 105
|
||||
try:
|
||||
loaded = icons[icon]
|
||||
except KeyError:
|
||||
log("No icon file named '" + icon + "' found.", LogLevel.Warning)
|
||||
return
|
||||
image.paste(loaded, (x_pos, 0))
|
||||
c += 1
|
||||
# Save Icon file
|
||||
path = ICON_CACHE_PATH + "_".join(glyphs) + ".png"
|
||||
image.save(path)
|
||||
try:
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file(path)
|
||||
pixbuf = pixbuf.scale_simple(image.width / 5, image.height / 5, GdkPixbuf.InterpType.HYPER)
|
||||
except:
|
||||
return
|
||||
return pixbuf
|
||||
|
||||
|
||||
def unique_list(seq):
|
||||
seen = set()
|
||||
seen_add = seen.add
|
||||
return [x for x in seq if not (x in seen or seen_add(x))]
|
||||
|
||||
|
||||
def sizeof_fmt(num, suffix='B'):
|
||||
for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
|
||||
if abs(num) < 1024.0:
|
||||
return "%3.1f%s%s" % (num, unit, suffix)
|
||||
num /= 1024.0
|
||||
return "%.1f%s%s" % (num, 'Yi', suffix)
|
||||
|
||||
|
||||
def get_all_cards_num() -> int:
|
||||
req = urllib.request.Request(ALL_NUM_URL, headers={'User-Agent': 'Mozilla/5.0'})
|
||||
response = urllib.request.urlopen(req)
|
||||
headers = response.info()._headers
|
||||
for header, value in headers:
|
||||
if header == 'Total-Count':
|
||||
return int(value)
|
||||
173
legacy/wants.py
Normal file
@@ -0,0 +1,173 @@
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
from cardvault import cardlist
|
||||
from cardvault import application
|
||||
from cardvault import util
|
||||
|
||||
|
||||
class WantsHandlers:
|
||||
def __init__(self, app: 'application.Application'):
|
||||
self.app = app
|
||||
self.init_wants_view()
|
||||
|
||||
def do_reload_wants(self, view):
|
||||
self.reload_wants_view()
|
||||
|
||||
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
|
||||
self.app.wants_new(name)
|
||||
self.reload_wants_view()
|
||||
|
||||
def on_want_list_selected(self, selection, path, column):
|
||||
(model, pathlist) = selection.get_selected_rows()
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
list_name = model.get_value(tree_iter, 0)
|
||||
self.reload_wants_view(list_name)
|
||||
|
||||
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
|
||||
|
||||
def do_rename_wants_list(self, tree):
|
||||
(model, pathlist) = tree.get_selection().get_selected_rows()
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
tag = model.get_value(tree_iter, 0)
|
||||
|
||||
new_name = self.app.show_name_enter_dialog("Rename Want List", tag)
|
||||
if not tag == new_name:
|
||||
self.app.wants_rename(tag, new_name)
|
||||
self.app.current_page.emit('show')
|
||||
|
||||
def do_delete_wants_list(self, tree):
|
||||
(model, pathlist) = tree.get_selection().get_selected_rows()
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
name = model.get_value(tree_iter, 0)
|
||||
|
||||
self.app.wants_delete(name)
|
||||
self.app.current_page.emit('show')
|
||||
|
||||
def on_want_cards_add_activated(self, menu_item):
|
||||
# Get selected cards
|
||||
tree = self.app.ui.get_object("wantsListContainer").get_child()
|
||||
selected = tree.get_selected_cards()
|
||||
|
||||
# Get selected list
|
||||
list_tree = self.app.ui.get_object("wantsListsTree")
|
||||
(model, pathlist) = list_tree.get_selection().get_selected_rows()
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
list_name = model.get_value(tree_iter, 0)
|
||||
|
||||
for card in selected.values():
|
||||
self.app.lib_card_add(card)
|
||||
self.app.wants_card_remove(card, list_name)
|
||||
|
||||
self.reload_wants_view(list_name)
|
||||
|
||||
def on_want_cards_remove_activated(self, menu_item):
|
||||
# Get selected cards
|
||||
tree = self.app.ui.get_object("wantsListContainer").get_child()
|
||||
selected = tree.get_selected_cards()
|
||||
|
||||
# Get selected list
|
||||
list_tree = self.app.ui.get_object("wantsListsTree")
|
||||
(model, pathlist) = list_tree.get_selection().get_selected_rows()
|
||||
for path in pathlist:
|
||||
tree_iter = model.get_iter(path)
|
||||
list_name = model.get_value(tree_iter, 0)
|
||||
|
||||
for card in selected.values():
|
||||
self.app.wants_card_remove(card, list_name)
|
||||
|
||||
self.reload_wants_view(list_name)
|
||||
|
||||
# ---------------------------------Wants Tree----------------------------------------------
|
||||
|
||||
def on_wants_card_selected(self, tree, row, column):
|
||||
(model, path_list) = tree.get_selection().get_selected_rows()
|
||||
for path in path_list:
|
||||
tree_iter = model.get_iter(path)
|
||||
card_id = model.get_value(tree_iter, 0)
|
||||
card_list = self.app.ui.get_object("wantsListContainer").get_child()
|
||||
card = card_list.lib[card_id]
|
||||
self.app.show_card_details(card)
|
||||
|
||||
def on_wants_cards_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[0] not in rows[1]:
|
||||
selection.unselect_all()
|
||||
selection.select_path(path[0])
|
||||
|
||||
# Show popup and emit 'show' to trigger update function of popup
|
||||
self.app.ui.get_object("wants_cardListPopup").emit('show')
|
||||
self.app.ui.get_object("wants_cardListPopup").popup(None, None, None, None, 0, event.time)
|
||||
return True
|
||||
|
||||
# -------------------------- Class Functions -------------------------------
|
||||
|
||||
def init_wants_view(self):
|
||||
# Get container for Cardlist Tree
|
||||
container = self.app.ui.get_object("wantsListContainer")
|
||||
# Create new Cardlist
|
||||
card_list = cardlist.CardList(True, self.app, util.GENERIC_TREE_COLORS)
|
||||
card_list.set_name("wantsScroller")
|
||||
# Show details
|
||||
card_list.tree.connect("row-activated", self.on_wants_card_selected)
|
||||
card_list.tree.connect("button-press-event", self.on_wants_cards_press_event)
|
||||
# Add card list to container
|
||||
container.add(card_list)
|
||||
container.add_overlay(self.app.ui.get_object("wantsOverlay"))
|
||||
container.show_all()
|
||||
# Hide no results overlay
|
||||
self.app.ui.get_object("wantsOverlay").set_visible(False)
|
||||
|
||||
def reload_wants_view(self, selected_list: str = None):
|
||||
tree = self.app.ui.get_object("wantsListContainer").get_child() # type: cardlist.CardList
|
||||
cards = self.app.get_wanted_cards(selected_list)
|
||||
self.reload_wants_list(True)
|
||||
if cards:
|
||||
self.app.ui.get_object("wantsOverlay").set_visible(False)
|
||||
tree.update(cards)
|
||||
else:
|
||||
tree.store.clear()
|
||||
self.app.ui.get_object("wantsOverlay").set_visible(True)
|
||||
|
||||
self.app.ui.get_object("wants_title").set_text(str(selected_list))
|
||||
|
||||
def reload_wants_list(self, preserve=False):
|
||||
tree = self.app.ui.get_object("wantsListsTree")
|
||||
(path, column) = tree.get_cursor()
|
||||
store = tree.get_model()
|
||||
store.clear()
|
||||
|
||||
for list_name, cards in self.app.wants.items():
|
||||
store.append([list_name, list_name + " (" + str(len(cards)) + ")"])
|
||||
if preserve:
|
||||
tree.set_cursor(path if path else 0)
|
||||
store.set_sort_column_id(1, Gtk.SortType.ASCENDING)
|
||||