diff --git a/cardvault/application.py b/cardvault/application.py
index edc2840..b8a4bd6 100644
--- a/cardvault/application.py
+++ b/cardvault/application.py
@@ -2,9 +2,7 @@ import sys
try:
import gi
gi.require_version('Gtk', '3.0')
- from gi.repository import Gtk
- from gi.repository import Pango
- from gi.repository import GdkPixbuf
+ from gi.repository import Gtk, GObject, Pango, GdkPixbuf
except ImportError as ex:
print("Couldn't import GTK dependencies. Make sure you "
"installed the PyGTK package and %s module." % ex.name)
@@ -22,6 +20,8 @@ from cardvault import util
from cardvault import database
+
+
class Application:
# ---------------------------------Initialize the Application----------------------------------------------
def __init__(self):
@@ -32,7 +32,6 @@ class Application:
util.LOG_LEVEL = self.config["log_level"]
util.log("Start using config file: '{}'".format(self.configfile), util.LogLevel.Info)
- # Load ui files
self.ui = Gtk.Builder()
self.ui.add_from_file(util.get_ui_filename("mainwindow.glade"))
self.ui.add_from_file(util.get_ui_filename("overlays.glade"))
@@ -64,14 +63,14 @@ class Application:
self.precon_icons = util.reload_preconstructed_icons(util.CACHE_PATH + "icons/")
self.mana_icons = util.load_mana_icons(os.path.dirname(__file__) + "/resources/mana/")
- util.log("Loading set list...", util.LogLevel.Info)
- self.sets = util.load_sets(util.get_root_filename("sets"))
-
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.load_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)
@@ -119,7 +118,7 @@ class Application:
# Printings
prints = []
for set in card.printings:
- prints.append(self.sets[set].name)
+ prints.append(self.get_all_sets()[set].name)
builder.get_object("cardPrintings").set_text(", ".join(prints))
# Legalities
grid = builder.get_object("legalitiesGrid")
@@ -219,7 +218,7 @@ class Application:
# self.push_status("All data saved.")
pass
- def load_data(self):
+ def load_user_data(self):
util.log("Loading Data from database", util.LogLevel.Info)
start = time.time()
self.library = self.db.lib_get_all()
@@ -229,6 +228,17 @@ class Application:
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():
@@ -384,8 +394,19 @@ class Application:
"""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 get_all_sets(self) -> dict:
+ if not self.is_online ():
+ l = self.db.set_get_all()
+ out = {}
+ for s in l:
+ out[s.code] = s
+ 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)
@@ -408,5 +429,6 @@ class Application:
def main():
+ GObject.threads_init()
Application()
Gtk.main()
diff --git a/cardvault/database.py b/cardvault/database.py
index 18590ad..bda845a 100644
--- a/cardvault/database.py
+++ b/cardvault/database.py
@@ -1,7 +1,7 @@
import sqlite3
import ast
-from mtgsdk import Card
+from mtgsdk import Card, Set
from cardvault import util
@@ -32,6 +32,9 @@ class CardVaultDB:
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):
# Connect to database
@@ -66,7 +69,8 @@ class CardVaultDB:
def db_insert_data_card(self, cards_json):
"""Insert download from mtgjson"""
- rows = []
+ c_rows = []
+ s_rows = []
for data in cards_json.values():
cards = []
for raw in data["cards"]:
@@ -77,14 +81,20 @@ class CardVaultDB:
cards.append(c)
for c in cards:
- rows.append(self.card_to_table_mapping(c))
+ c_rows.append(self.card_to_table_mapping(c))
+ set = Set(data)
+ s_rows.append(self.set_to_table_mapping(set))
+
# Connect to database
con = sqlite3.connect(self.db_file)
try:
with con:
sql_string = "INSERT INTO `cards` VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?," \
"?,?,?,?,?,?,?,?,?,?,?)"
- con.executemany(sql_string, rows)
+ 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)
@@ -95,6 +105,7 @@ class CardVaultDB:
def db_clear_data_card(self):
"""Delete all resource data from database"""
self.db_operation("DELETE FROM cards")
+ self.db_operation("DELETE FROM sets")
def db_clear_data_user(self):
"""Delete all user data from database"""
@@ -278,6 +289,20 @@ class CardVaultDB:
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
+
+ # First load all tags
+ 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):
@@ -383,3 +408,27 @@ class CardVaultDB:
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
diff --git a/cardvault/gui/mainwindow.glade b/cardvault/gui/mainwindow.glade
index 6b86e15..c558fb8 100644
--- a/cardvault/gui/mainwindow.glade
+++ b/cardvault/gui/mainwindow.glade
@@ -264,10 +264,9 @@
-
-
+
True
False
- network-idle
False
diff --git a/cardvault/handlers.py b/cardvault/handlers.py
index 51ebb24..a9449b6 100644
--- a/cardvault/handlers.py
+++ b/cardvault/handlers.py
@@ -122,8 +122,7 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers):
def download_finished(self):
"""Download thread finished without errors"""
self.cancel_token = False
- self.app.config["local_db"] = True
- self.app.save_config()
+ 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)
@@ -238,6 +237,7 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers):
def do_clear_card_data(self, menu_item):
util.log("Deleting all local card data", util.LogLevel.Info)
self.app.db.db_clear_data_card()
+ self.app.set_online(True)
util.log("Done", util.LogLevel.Info)
def do_clear_data(self, item):
diff --git a/cardvault/search.py b/cardvault/search.py
index d908408..ee98ece 100644
--- a/cardvault/search.py
+++ b/cardvault/search.py
@@ -195,7 +195,7 @@ class SearchHandlers:
# Set
name = self.app.ui.get_object("setEntry").get_text()
output["set"] = ""
- for mtgset in self.app.sets.values():
+ for mtgset in self.app.get_all_sets().values():
if mtgset.name == name:
output["set"] = mtgset.code
return output
@@ -343,7 +343,7 @@ class SearchHandlers:
def _init_set_entry(self, entry):
""" Initialize model for set entry """
set_store = Gtk.ListStore(str, str)
- for mtgset in self.app.sets.values():
+ for mtgset in self.app.get_all_sets().values():
set_store.append([mtgset.name, mtgset.code])
completer = Gtk.EntryCompletion()
completer.set_model(set_store)
diff --git a/cardvault/util.py b/cardvault/util.py
index 648341d..b27b7f7 100644
--- a/cardvault/util.py
+++ b/cardvault/util.py
@@ -106,6 +106,16 @@ rarity_dict = {
}
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
@@ -258,7 +268,10 @@ def net_load_set_list() -> dict:
def load_sets(filename: str) -> dict:
- # TODO Update Data function
+ """
+ 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()