Track changes to user data. Allow to undo changes.

This commit is contained in:
luxick
2017-08-10 12:17:10 +02:00
parent 4199ddf1ef
commit 81675725d2
3 changed files with 39 additions and 34 deletions

View File

@@ -31,7 +31,6 @@ class Application:
self.ui.add_from_file(util.get_ui_filename("dialogs.glade"))
self.current_page = None
self.unsaved_changes = False
self.current_lib_tag = "Untagged"
self.db = database.CardVaultDB(util.get_root_filename(util.DB_NAME))
@@ -200,21 +199,22 @@ class Application:
else:
return value
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)
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.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):
@@ -287,7 +287,6 @@ class Application:
del self.tags[old]
self.db.tag_rename(old, new)
util.log("Tag '" + old + "' renamed to '" + new + "'", util.LogLevel.Info)
self.unsaved_changes = True
def get_wanted_card_ids(self) -> List[str]:
all_ids = []

View File

@@ -9,6 +9,7 @@ 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 ##############################################################################################
@@ -37,7 +38,8 @@ class CardVaultDB:
"booster TEXT, oldcode TEXT)")
def db_card_insert(self, card: Card):
# Connect to database
"""Insert single card data into database"""
# Use own connection so that inserts are commited directly
con = sqlite3.connect(self.db_file)
try:
with con:
@@ -54,13 +56,12 @@ class CardVaultDB:
pass
def db_get_all(self):
"""Return data of all cards in database"""
sql = 'SELECT * FROM cards'
con = sqlite3.connect(self.db_file)
cur = con.cursor()
cur = self.connection.cursor()
cur.row_factory = sqlite3.Row
cur.execute(sql)
rows = cur.fetchall()
con.close()
output = []
for row in rows:
card = self.table_to_card_mapping(row)
@@ -85,7 +86,7 @@ class CardVaultDB:
set = Set(data)
s_rows.append(self.set_to_table_mapping(set))
# Connect to database
# Use separate connection to commit changes immediately
con = sqlite3.connect(self.db_file)
try:
with con:
@@ -117,12 +118,10 @@ class CardVaultDB:
def lib_get_all(self) -> dict:
"""Load library from database"""
con = sqlite3.connect(self.db_file)
cur = con.cursor()
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()
con.close()
return self.rows_to_card_dict(rows)
@@ -138,8 +137,7 @@ class CardVaultDB:
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()
cur = self.connection.cursor()
cur.row_factory = sqlite3.Row
# First load all tags
@@ -179,8 +177,7 @@ class CardVaultDB:
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)
cur = con.cursor()
cur = self.connection.cursor()
cur.row_factory = sqlite3.Row
cur.execute('SELECT `tag` FROM `tags` WHERE tags.multiverseid = ? ', (card.multiverse_id,))
rows = cur.fetchall()
@@ -197,8 +194,7 @@ class CardVaultDB:
def wants_get_all(self) -> dict:
"""Load all wants lists from database"""
con = sqlite3.connect(self.db_file)
cur = con.cursor()
cur = self.connection.cursor()
cur.row_factory = sqlite3.Row
# First load all lists
@@ -294,7 +290,6 @@ class CardVaultDB:
cur = con.cursor()
cur.row_factory = sqlite3.Row
# First load all tags
cur.execute("SELECT * FROM sets")
rows = cur.fetchall()
sets = []
@@ -313,16 +308,27 @@ class CardVaultDB:
output[card.multiverse_id] = card
return output
def db_operation(self, sql: str, parms: tuple=()):
def db_operation(self, sql: str, args: tuple=()):
"""Perform an arbitrary sql operation on the database"""
con = sqlite3.connect(self.db_file)
cur = self.connection.cursor()
try:
with con:
con.execute(sql, parms)
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)

View File

@@ -138,7 +138,7 @@ class Handlers(SearchHandlers, LibraryHandlers, WantsHandlers):
self.app.ui.get_object("mainWindow").set_title(app_title)
def do_delete_event(self, arg1, arg2):
if self.app.unsaved_changes:
if self.app.unsaved_changes():
response = self.app.show_dialog_ync("Unsaved Changes",
"You have unsaved changes in your library. "
"Save before exiting?")