diff --git a/cardvault/application.py b/cardvault/application.py index 95d3fa3..2400c74 100644 --- a/cardvault/application.py +++ b/cardvault/application.py @@ -48,7 +48,7 @@ class Application: self.db = database.CardVaultDB(util.get_root_filename(util.DB_NAME)) # Create database tables if they do not exist - self.db.create_database() + self.db.db_create() not_found = self.ui.get_object("pageNotFound") self.pages = { @@ -158,7 +158,7 @@ class Application: window.connect("key-press-event", eval_key_pressed) - def show_dialog_yes_no_cancel(self, title: str, message: str) -> Gtk.ResponseType: + 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")) @@ -168,7 +168,7 @@ class Application: dialog.hide() return response - def show_dialog_yes_no(self, title: str, message: str) -> Gtk.ResponseType: + 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")) @@ -202,23 +202,29 @@ class Application: else: return value + def save_config(self): + cf = util.get_root_filename("config.json") + util.save_config(self.config, cf) + util.log("Config saved to '{}'".format(cf), util.LogLevel.Info) + def save_data(self): - util.log("Saving Data to database", util.LogLevel.Info) - start = time.time() - self.db.save_library(self.library) - self.db.save_tags(self.tags) - self.db.save_wants(self.wants) - end = time.time() - util.log("Finished in {}s".format(str(round(end - start, 3))), util.LogLevel.Info) - self.unsaved_changes = False - self.push_status("All data saved.") + # util.log("Saving Data to database", util.LogLevel.Info) + # start = time.time() + # self.db.save_library(self.library) + # self.db.save_tags(self.tags) + # self.db.save_wants(self.wants) + # end = time.time() + # util.log("Finished in {}s".format(str(round(end - start, 3))), util.LogLevel.Info) + # self.unsaved_changes = False + # self.push_status("All data saved.") + pass def load_data(self): util.log("Loading Data from database", util.LogLevel.Info) start = time.time() - self.library = self.db.get_library() - self.tags = self.db.get_tags() - self.wants = self.db.get_wants() + 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.") @@ -242,33 +248,35 @@ class Application: lib[card_id] = self.library[card_id] return lib - def tag_card(self, card, tag): + def tag_card(self, card, tag: str): + """Add a card to tag""" list = self.tags[tag] list.append(card.multiverse_id) - self.unsaved_changes = True + self.db.tag_card_add(tag, card.multiverse_id) - def untag_card(self, card, tag): + def untag_card(self, card, tag: str): list = self.tags[tag] list.remove(card.multiverse_id) - self.unsaved_changes = True + self.db.tag_card_remove(tag, card.multiverse_id) - def add_tag(self, tag): + 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 + "\"") - self.unsaved_changes = True - def remove_tag(self, 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 + "\"") - self.unsaved_changes = True - def rename_tag(self, old, new): + 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) self.unsaved_changes = True @@ -284,61 +292,93 @@ class Application: out = {card.multiverse_id: card for card in self.wants[list_name]} return out - def delete_wants_list(self, name: str): + 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)) - self.unsaved_changes = True - def rename_want_list(self, old, new): + 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) - self.unsaved_changes = True - def add_want_list(self, name): - self.wants[name] = [] - util.log("Want list '" + name + "' created", util.LogLevel.Info) - self.push_status("Created want list '" + name + "'") - self.unsaved_changes = True - - def add_card_to_want_list(self, list_name: str, card: 'mtgsdk.Card'): + 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) - self.unsaved_changes = True - def add_card_to_lib(self, card, tag=None): + 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") - self.unsaved_changes = True - self.db.insert_card(card) - - def bulk_add_card_to_lib(self, cards: list, tag: str = None): + def lib_card_add_bulk(self, cards: list, tag: str = None): for card in cards: - self.add_card_to_lib(card, tag) + 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 remove_card_from_lib(self, card): + def lib_card_remove(self, card): # Check if card is tagged - for card_ids in self.tags.values(): - if card_ids.__contains__(card.multiverse_id): - card_ids.remove(card.multiverse_id) + 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") - self.unsaved_changes = True - def remove_card_from_want_list(self, card: mtgsdk.Card, list: str): - l = self.wants[list] - l.remove(card) - self.unsaved_changes = True - util.log("Removed '{}' from wants list '{}'".format(card.name, list), util.LogLevel.Info) + def 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 get_mana_icons(self, mana_string): if not mana_string: @@ -360,38 +400,6 @@ class Application: else: return filter_text.lower() in model[iter][1].lower() - def load_data_legacy(self): - all_existing = True - # Load library file - self.library = util.load_file(util.get_root_filename("library")) - if not self.library: - all_existing = False - self.library = {} - # Load tags file - self.tags = util.load_file(util.get_root_filename("tags")) - if not self.tags: - all_existing = False - self.tags = {} - # Load wants lists - self.wants = util.load_file(util.get_root_filename("wants")) - if not self.wants: - all_existing = False - self.wants = {} - # If parts were missing save to create the files - if not all_existing: - self.save_library_legacy() - self.push_status("Library loaded") - - def save_library_legacy(self): - # Save library file - util.save_file(util.get_root_filename("library"), self.library) - # Save tags file - util.save_file(util.get_root_filename("tags"), self.tags) - # Save wants file - util.save_file(util.get_root_filename("wants"), self.wants) - - self.unsaved_changes = False - self.push_status("Library saved") def main(): Application() diff --git a/cardvault/cardlist.py b/cardvault/cardlist.py index 0e01f30..794d3ed 100644 --- a/cardvault/cardlist.py +++ b/cardvault/cardlist.py @@ -16,7 +16,6 @@ gi.require_version('Gdk', '3.0') class CardList(Gtk.ScrolledWindow): def __init__(self, filtered, app: 'application.Application', row_colors: Dict[str, str]): Gtk.ScrolledWindow.__init__(self) - #self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.set_hexpand(True) self.set_vexpand(True) diff --git a/cardvault/database.py b/cardvault/database.py index 61186a2..d76a31e 100644 --- a/cardvault/database.py +++ b/cardvault/database.py @@ -1,10 +1,7 @@ import sqlite3 import ast -from pygments.lexers.robotframework import _Table - from mtgsdk import Card - from cardvault import util @@ -13,7 +10,9 @@ class CardVaultDB: def __init__(self, db_file: str): self.db_file = db_file - def create_database(self): + # Database operations ############################################################################################## + + def db_create(self): """Create initial database""" con = sqlite3.connect(self.db_file) @@ -35,7 +34,7 @@ class CardVaultDB: con.execute("CREATE TABLE IF NOT EXISTS tags ( tag TEXT, multiverseid INT )") con.execute("CREATE TABLE IF NOT EXISTS wants ( listName TEXT, multiverseid INT )") - def insert_card(self, card: Card): + def db_card_insert(self, card: Card): # Connect to database con = sqlite3.connect(self.db_file) try: @@ -51,90 +50,37 @@ class CardVaultDB: except sqlite3.IntegrityError: pass - def bulk_insert_card(self, card_list: list): + def db_card_insert_bulk(self, card_list: list): for card in card_list: - self.insert_card(card) - - def clear_card_data(self): - con = sqlite3.connect(self.db_file) - try: - with con: - con.execute("DELETE FROM cards") - except sqlite3.OperationalError as err: - util.log("Database Error", util.LogLevel.Error) - util.log(str(err), util.LogLevel.Error) - - def clear_database(self): - con = sqlite3.connect(self.db_file) - try: - with con: - con.execute('DELETE FROM library') - con.execute('DELETE FROM wants') - con.execute('DELETE FROM tags') - except sqlite3.OperationalError as err: - util.log("Database Error", util.LogLevel.Error) - util.log(str(err), util.LogLevel.Error) - - def search_cards_by_name_filtered(self, term: str, filters: dict, list_size: int) -> dict: - """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"].split(',') - - 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: - for color in filter_mana: - sql += ' AND `manaCost` LIKE ?' - parameters.append('%'+color+'%') - sql += ' LIMIT ?' - parameters.append(list_size) + self.db_card_insert(card) + def db_get_all(self): + sql = 'SELECT * FROM cards' con = sqlite3.connect(self.db_file) cur = con.cursor() cur.row_factory = sqlite3.Row - cur.execute(sql, parameters) + cur.execute(sql) rows = cur.fetchall() con.close() - - output = {} + output = [] for row in rows: card = self.table_to_card_mapping(row) - output[card.multiverse_id] = card + output.append(card) return output - def search_cards_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() + def db_clear_data_card(self): + """Delete all resource data from database""" + self.db_operation("DELETE FROM cards") - return self.rows_to_card_dict(rows) + 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') - def add_card_to_lib(self, card: Card): - """Insert card into library""" - con = sqlite3.connect(self.db_file) - try: - with con: - con.execute("INSERT INTO `library` (`copies`, `multiverseid`) VALUES (?, ?)", (1, card.multiverse_id)) - except sqlite3.OperationalError as err: - util.log("Database Error", util.LogLevel.Error) - util.log(str(err), util.LogLevel.Error) + # Library operations ############################################################################################### - def get_library(self) -> dict: + def lib_get_all(self) -> dict: """Load library from database""" con = sqlite3.connect(self.db_file) cur = con.cursor() @@ -145,7 +91,17 @@ class CardVaultDB: return self.rows_to_card_dict(rows) - def get_tags(self): + 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""" con = sqlite3.connect(self.db_file) cur = con.cursor() @@ -160,62 +116,51 @@ class CardVaultDB: # 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, )) + 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 add_tag(self, tag: str): + def tag_new(self, tag: str): """Add a new tag to the database""" - con = sqlite3.connect(self.db_file) - try: - with con: - con.execute("INSERT INTO `tags` VALUES (?, NULL)", (tag, )) - except sqlite3.OperationalError as err: - util.log("Database Error", util.LogLevel.Error) - util.log(str(err), util.LogLevel.Error) + self.db_operation("INSERT INTO `tags` VALUES (?, NULL)", (tag,)) - def tag_card(self, tag: str, card_id: int): + 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.""" con = sqlite3.connect(self.db_file) - try: - with con: - con.execute("INSERT INTO `tags` VALUES (?, ?)", (tag, card_id)) - except sqlite3.OperationalError as err: - util.log("Database Error", util.LogLevel.Error) - util.log(str(err), util.LogLevel.Error) + cur = con.cursor() + cur.row_factory = sqlite3.Row + cur.execute('SELECT `tag` FROM `tags` WHERE tags.multiverseid = ? ', (card.multiverse_id,)) + rows = cur.fetchall() - 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 + if len(rows) == 0: + return False, [] + else: + tags = [] + for row in rows: + tags.append(row["tag"]) + return True, tags - def add_wants_list(self, name: str): - """Add a new wants list to the database""" - con = sqlite3.connect(self.db_file) - try: - with con: - con.execute("INSERT INTO `wants` VALUES (?, NULL)", (name,)) - except sqlite3.OperationalError as err: - util.log("Database Error", util.LogLevel.Error) - util.log(str(err), util.LogLevel.Error) + # Wants operations ################################################################################################# - def add_card_to_wants(self, list_name: str, card_id: int): - """Add a card entry to a wants list""" - con = sqlite3.connect(self.db_file) - try: - with con: - con.execute("INSERT INTO `wants` VALUES (?, ?)", (list_name, card_id)) - except sqlite3.OperationalError as err: - util.log("Database Error", util.LogLevel.Error) - util.log(str(err), util.LogLevel.Error) - - def get_wants(self): + def wants_get_all(self) -> dict: """Load all wants lists from database""" con = sqlite3.connect(self.db_file) cur = con.cursor() @@ -232,51 +177,99 @@ class CardVaultDB: 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, )) + '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 save_library(self, cards: dict): - """Updates the library, adds new cards""" - con = sqlite3.connect(self.db_file) - try: - with con: - for multiverse_id in cards.keys(): - con.execute('UPDATE `library` SET `copies`=?, `multiverseid`=? WHERE multiverseid = ?;', (1, multiverse_id, multiverse_id)) - con.execute('INSERT INTO `library` (`copies`, `multiverseid`) ' - 'SELECT ?,? WHERE (Select Changes() = 0);', (1, multiverse_id)) - except sqlite3.OperationalError as err: - util.log("Database Error", util.LogLevel.Error) - util.log(str(err), util.LogLevel.Error) + def wants_new(self, name: str): + """Add a new wants list to the database""" + self.db_operation("INSERT INTO `wants` VALUES (?, NULL)", (name,)) - def save_tags(self, tags: dict): - """Updates the tags table""" - con = sqlite3.connect(self.db_file) - try: - with con: - for tag, id_list in tags.items(): - for id in id_list: - con.execute('UPDATE `tags` SET `tag`=?, `multiverseid`=? WHERE tags.multiverseid = ?;', (tag, id, id)) - con.execute('INSERT INTO `tags` (`tag`, `multiverseid`) ' - 'SELECT ?,? WHERE (Select Changes() = 0);', (tag, id)) - except sqlite3.OperationalError as err: - util.log("Database Error", util.LogLevel.Error) - util.log(str(err), util.LogLevel.Error) + def wants_delete(self, name: str): + """Remove a tag with all entries""" + self.db_operation("DELETE FROM `wants` WHERE `listName` = ?", (name,)) - def save_wants(self, wants: dict): - """Updates the wants table""" + 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) -> dict: + """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"].split(',') + + 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: + for color in filter_mana: + sql += ' AND `manaCost` LIKE ?' + parameters.append('%' + color + '%') + 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[card.multiverse_id] = 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) + + # 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, parms: tuple=()): + """Perform an arbitrary sql operation on the database""" con = sqlite3.connect(self.db_file) try: with con: - for name, cards in wants.items(): - for card in cards: - con.execute('UPDATE `wants` SET `listName`=?, `multiverseid`=? WHERE wants.multiverseid = ?;', - (name, card.multiverse_id, card.multiverse_id)) - con.execute('INSERT INTO `wants` (`listName`, `multiverseid`) ' - 'SELECT ?,? WHERE (Select Changes() = 0);', (name, card.multiverse_id)) + con.execute(sql, parms) except sqlite3.OperationalError as err: util.log("Database Error", util.LogLevel.Error) util.log(str(err), util.LogLevel.Error) @@ -349,3 +342,47 @@ class CardVaultDB: return card + + # def save_library(self, cards: dict): + # """Updates the library, adds new cards""" + # con = sqlite3.connect(self.db_file) + # try: + # with con: + # for multiverse_id in cards.keys(): + # con.execute('UPDATE `library` SET `copies`=?, `multiverseid`=? WHERE multiverseid = ?;', + # (1, multiverse_id, multiverse_id)) + # con.execute('INSERT INTO `library` (`copies`, `multiverseid`) ' + # 'SELECT ?,? WHERE (SELECT Changes() = 0);', (1, multiverse_id)) + # except sqlite3.OperationalError as err: + # util.log("Database Error", util.LogLevel.Error) + # util.log(str(err), util.LogLevel.Error) + # + # def save_tags(self, tags: dict): + # """Updates the tags table""" + # con = sqlite3.connect(self.db_file) + # try: + # with con: + # for tag, id_list in tags.items(): + # for id in id_list: + # con.execute('UPDATE `tags` SET `tag`=?, `multiverseid`=? WHERE tags.multiverseid = ?;', + # (tag, id, id)) + # con.execute('INSERT INTO `tags` (`tag`, `multiverseid`) ' + # 'SELECT ?,? WHERE (SELECT Changes() = 0);', (tag, id)) + # except sqlite3.OperationalError as err: + # util.log("Database Error", util.LogLevel.Error) + # util.log(str(err), util.LogLevel.Error) + # + # def save_wants(self, wants: dict): + # """Updates the wants table""" + # con = sqlite3.connect(self.db_file) + # try: + # with con: + # for name, cards in wants.items(): + # for card in cards: + # con.execute('UPDATE `wants` SET `listName`=?, `multiverseid`=? WHERE wants.multiverseid = ?;', + # (name, card.multiverse_id, card.multiverse_id)) + # con.execute('INSERT INTO `wants` (`listName`, `multiverseid`) ' + # 'SELECT ?,? WHERE (SELECT Changes() = 0);', (name, card.multiverse_id)) + # except sqlite3.OperationalError as err: + # util.log("Database Error", util.LogLevel.Error) + # util.log(str(err), util.LogLevel.Error) diff --git a/cardvault/gui/mainwindow.glade b/cardvault/gui/mainwindow.glade index a036d12..845d84d 100644 --- a/cardvault/gui/mainwindow.glade +++ b/cardvault/gui/mainwindow.glade @@ -213,15 +213,6 @@ - - - True - False - Load Library to DB - True - - - diff --git a/cardvault/handlers.py b/cardvault/handlers.py index 4b2a8b9..0887df3 100644 --- a/cardvault/handlers.py +++ b/cardvault/handlers.py @@ -52,6 +52,7 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers): 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, @@ -61,20 +62,20 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers): response = dialog.run() if response == Gtk.ResponseType.OK: # Show confirmation message - override_question = self.app.show_dialog_yes_no_cancel("Import Library", - "Importing a library will override your current library. " - "Proceed?") + 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] + # Save imported data to database + self.app.override_user_data() # Cause current page to reload with imported data self.app.current_page.emit('show') - self.app.unsaved_changes = True - self.app.push_status("Library imported") dialog.destroy() + def on_view_changed(self, item): if item.get_active(): container = self.app.ui.get_object("contentPage") @@ -91,8 +92,9 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers): def do_delete_event(self, arg1, arg2): if self.app.unsaved_changes: - response = self.app.show_dialog_yes_no_cancel("Unsaved Changes", "You have unsaved changes in your library. " - "Save before exiting?") + 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 @@ -121,6 +123,8 @@ 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.ui.get_object("loadDataDialog").destroy() self.app.push_status("Card data downloaded") util.log("Card data download finished", util.LogLevel.Info) @@ -130,7 +134,7 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers): info_string = "Start downloading card information from the internet?\n" \ "This process can take up to 10 minutes.\n" \ "You can cancel the download at any point." - response = self.app.show_dialog_yes_no("Download Card Data", info_string) + response = self.app.show_dialog_yn("Download Card Data", info_string) if response == Gtk.ResponseType.NO: return # Launch download info dialog @@ -153,7 +157,7 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers): all_cards = [] # Request total number of cards we are going to download all_num = util.get_all_cards_num() - all_pages = int(math.ceil(all_num/100)) + all_pages = int(math.ceil(all_num / 100)) # Download cards in pages until no new cards are added for i in range(all_pages): @@ -180,7 +184,7 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers): # All cards have been downloaded GObject.idle_add(self.load_show_insert_ui, "Saving data to disk...") - self.app.db.bulk_insert_card(all_cards) + self.app.db.db_card_insert_bulk(all_cards) self.download_finished() @@ -209,32 +213,12 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers): # ---------------------- Debug actions ------------------------------- - def do_load_data_to_db(self, item): - util.log("Attempt loading library to database", util.LogLevel.Info) - start = datetime.datetime.now() - - for card in self.app.library.values(): - self.app.db.add_card_to_lib(card) - - for tag, card_ids in self.app.tags.items(): - self.app.db.add_tag(tag) - for card_id in card_ids: - self.app.db.tag_card(tag, card_id) - - for list_name, cards in self.app.wants.items(): - self.app.db.add_wants_list(list_name) - for card in cards: - self.app.db.add_card_to_wants(list_name, card.multiverse_id) - - end = datetime.datetime.now() - util.log("Finished in {}s".format(str(end - start)), util.LogLevel.Info) - def do_clear_card_data(self, menu_item): util.log("Deleting all local card data", util.LogLevel.Info) - self.app.db.clear_card_data() + self.app.db.db_clear_data_card() util.log("Done", util.LogLevel.Info) def do_clear_data(self, item): util.log("Deleting all library data", util.LogLevel.Info) - self.app.db.clear_database() - util.log("Done", util.LogLevel.Info) \ No newline at end of file + self.app.db.db_clear_data_user() + util.log("Done", util.LogLevel.Info) diff --git a/cardvault/library.py b/cardvault/library.py index 28bf7a0..3211879 100644 --- a/cardvault/library.py +++ b/cardvault/library.py @@ -83,7 +83,7 @@ class LibraryHandlers: new_name = self.app.show_name_enter_dialog("Rename Tag", tag) if new_name and new_name != "": - self.app.rename_tag(tag, new_name) + self.app.tag_rename(tag, new_name) self.app.current_page.emit('show') def do_tag_list_delete(self, tree): @@ -98,7 +98,7 @@ class LibraryHandlers: dialog.destroy() if response == Gtk.ResponseType.NO: return - self.app.remove_tag(tag) + self.app.tag_delete(tag) self.app.current_page.emit('show') def do_refilter_library(self, container): @@ -139,7 +139,7 @@ class LibraryHandlers: cards = card_list.get_selected_cards() # Remove selected cards for card in cards.values(): - self.app.remove_card_from_lib(card) + self.app.lib_card_remove(card) self.reload_library(self.app.current_lib_tag) self.reload_tag_list(none_selected=True) @@ -191,7 +191,7 @@ class LibraryHandlers: self.app.ui.get_object("noResults").set_visible(True) def add_new_tag(self, name): - self.app.add_tag(name) + self.app.tag_new(name) self.reload_tag_list(True) def reload_tag_list(self, none_selected=False): @@ -209,7 +209,7 @@ class LibraryHandlers: def tag_cards(self, card_list, tag): # Check if tag exist and create if necessary if not self.app.tags.__contains__(tag): - self.app.add_tag(tag) + self.app.tag_new(tag) for card in card_list.values(): if not self.app.tags[tag].__contains__(card.multiverse_id): diff --git a/cardvault/resources/mana/BG.png b/cardvault/resources/mana/B-G.png similarity index 100% rename from cardvault/resources/mana/BG.png rename to cardvault/resources/mana/B-G.png diff --git a/cardvault/search.py b/cardvault/search.py index 13f605b..bb31790 100644 --- a/cardvault/search.py +++ b/cardvault/search.py @@ -59,7 +59,7 @@ class SearchHandlers: tree_iter = model.get_iter(path) card_id = model.get_value(tree_iter, 0) card = card_view.lib[card_id] - self.app.add_card_to_lib(card) + self.app.lib_card_add(card) self.reload_search_view() self.app.ui.get_object("searchEntry").grab_focus() @@ -110,9 +110,9 @@ class SearchHandlers: cards = card_list.get_selected_cards() response = self.app.show_name_enter_dialog("Enter name for new Tag", "") if not response == "": - self.app.add_tag(response) + self.app.tag_new(response) for card in cards.values(): - self.app.add_card_to_lib(card, response) + 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") @@ -124,9 +124,9 @@ class SearchHandlers: cards = card_list.get_selected_cards() response = self.app.show_name_enter_dialog("Enter name for new Want List", "") if not response == "": - self.app.add_want_list(response) + self.app.wants_new(response) for card in cards.values(): - self.app.add_card_to_want_list(response, card) + 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") @@ -137,7 +137,7 @@ class SearchHandlers: card_list = self.app.ui.get_object("searchResults").get_child() cards = card_list.get_selected_cards() for card in cards.values(): - self.app.add_card_to_lib(card, item.get_label()) + 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.") @@ -146,7 +146,7 @@ class SearchHandlers: card_list = self.app.ui.get_object("searchResults").get_child() cards = card_list.get_selected_cards() for card in cards.values(): - self.app.add_card_to_want_list(item.get_label(), card) + 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() + "'") @@ -168,7 +168,7 @@ class SearchHandlers: tree = self.app.ui.get_object("searchResults").get_child() cards = tree.get_selected_cards() for card in cards.values(): - self.app.add_card_to_lib(card) + self.app.lib_card_add(card) self.reload_search_view() def reload_search_view(self): @@ -209,7 +209,7 @@ class SearchHandlers: util.log("Starting local search for '" + term + "'", util.LogLevel.Info) start = time.time() - cards = self.app.db.search_cards_by_name_filtered(term, filters, 100) + 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) diff --git a/cardvault/wants.py b/cardvault/wants.py index 30c794e..056b5b7 100644 --- a/cardvault/wants.py +++ b/cardvault/wants.py @@ -21,7 +21,7 @@ class WantsHandlers: # Check if list name already exists if self.app.wants.__contains__(name): return - self.app.add_want_list(name) + self.app.wants_new(name) self.reload_wants_view() def on_want_list_selected(self, selection, path, column): @@ -54,7 +54,7 @@ class WantsHandlers: new_name = self.app.show_name_enter_dialog("Rename Want List", tag) if not tag == new_name: - self.app.rename_want_list(tag, new_name) + self.app.wants_rename(tag, new_name) self.app.current_page.emit('show') def do_delete_wants_list(self, tree): @@ -63,7 +63,7 @@ class WantsHandlers: tree_iter = model.get_iter(path) name = model.get_value(tree_iter, 0) - self.app.delete_wants_list(name) + self.app.wants_delete(name) self.app.current_page.emit('show') def on_want_cards_add_activated(self, menu_item): @@ -79,8 +79,8 @@ class WantsHandlers: list_name = model.get_value(tree_iter, 0) for card in selected.values(): - self.app.add_card_to_lib(card) - self.app.remove_card_from_want_list(card, list_name) + self.app.lib_card_add(card) + self.app.wants_card_remove(card, list_name) self.reload_wants_view(list_name) @@ -97,7 +97,7 @@ class WantsHandlers: list_name = model.get_value(tree_iter, 0) for card in selected.values(): - self.app.remove_card_from_want_list(card, list_name) + self.app.wants_card_remove(card, list_name) self.reload_wants_view(list_name) diff --git a/setup.py b/setup.py index 99b0a28..68e9ce4 100755 --- a/setup.py +++ b/setup.py @@ -38,4 +38,4 @@ setup( 'Programming Language :: Python :: 3.5', 'License :: OSI Approved :: MIT License', ], - ) +)