From a45783be5e78a41fdad8dfd9e2b258e8876b1b86 Mon Sep 17 00:00:00 2001 From: "Anders H. Rebner" <anderhre@stud.ntnu.no> Date: Thu, 9 Apr 2020 17:14:44 +0200 Subject: [PATCH] #40 db-tabell SOI laget og SOI'er lagres her gjennom toppmeny --- soitool/database.py | 33 ++++++++++++++++++++++++++++++++- soitool/main_window.py | 17 +++++++++++++++++ test/test_database.py | 26 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/soitool/database.py b/soitool/database.py index cc0c69d..45d04f9 100644 --- a/soitool/database.py +++ b/soitool/database.py @@ -5,6 +5,8 @@ import json from datetime import datetime import soitool.coder from soitool.enumerates import CodebookSort +from soitool.serialize_export_import_soi import serialize_soi +from soitool.compressor import compress # Set name and path to default (future) database DBNAME = "database" @@ -15,6 +17,7 @@ DBPATH = os.path.join(CURDIR, DBNAME) SECONDS_IN_24H = 24 * 60 * 60 # DDL-statements for creating tables +SOI = "CREATE TABLE SOI(Title VARCHAR PRIMARY KEY, SOI TEXT, Date DATETIME)" CODEBOOK = ( "CREATE TABLE CodeBook(" "Word VARCHAR PRIMARY KEY NOT NULL CHECK(length(Word) > 0), " @@ -66,7 +69,7 @@ class Database: def create_tables(self): """Create tables CodeBook, CategoryWords and ByHeart.""" - stmts = [CODEBOOK, CATEGORYWORDS, BYHEART, LASTUPDATED] + stmts = [SOI, CODEBOOK, CATEGORYWORDS, BYHEART, LASTUPDATED] for stmt in stmts: self.conn.execute(stmt) @@ -337,3 +340,31 @@ class Database: stmt = "UPDATE CodeBook SET Code = ? WHERE Word = ?" self.conn.execute(stmt, (code, word)) self.conn.commit() + + def insert_soi(self, soi): + """Serialize, compress and insert SOI into database-table SOI. + + If one or more SOI's with the same title exists in db, (1), (2), ... + is added to the Title-column of the SOI to insert. + + Parameters + ---------- + soi : soitool.soi.SOI + The SOI-instance to insert into database. + """ + title = soi.title + date = datetime.now().strftime("%Y-%m-%d") + serialized_soi = serialize_soi(soi) + compressed_soi = compress(serialized_soi) + + # Count SOI's with equal title + length = len(title) + stmt = "SELECT COUNT(*) FROM SOI WHERE substr(Title,0,?)=?" + count = self.conn.execute(stmt, (length + 1, title)).fetchone()[0] + # Add '(x)' to title if SOI with equal title exists + if count > 0: + title += "(" + str(count + 1) + ")" + + stmt = "INSERT INTO SOI (Title, SOI, Date) VALUES(?,?,?)" + self.conn.execute(stmt, (title, compressed_soi, date)) + self.conn.commit() diff --git a/soitool/main_window.py b/soitool/main_window.py index 4cd761f..555948f 100644 --- a/soitool/main_window.py +++ b/soitool/main_window.py @@ -6,6 +6,7 @@ import sys import os from enum import Enum from functools import partial +from sqlite3 import IntegrityError from PySide2.QtWidgets import ( QTabWidget, QMainWindow, @@ -26,6 +27,7 @@ from soitool.serialize_export_import_soi import ( export_soi, import_soi, ) +from soitool.compressor import compress class ModuleType(Enum): @@ -118,6 +120,7 @@ class MainWindow(QMainWindow): save_soi = QAction("Lagre i DB", self) save_soi.setShortcut("Ctrl+s") save_soi.setStatusTip("Lagre SOI i databasen") + save_soi.triggered.connect(self.save_soi_db) file_menu.addAction(save_soi) # Export SOI @@ -276,6 +279,20 @@ class MainWindow(QMainWindow): else: regenerate() + def save_soi_db(self): + """Save the SOI of the current tab in the database.""" + tab_widget = self.tabs.currentWidget() + + # If tab contains an SOI + if isinstance(tab_widget, SOIWorkspaceWidget): + self.database.insert_soi(tab_widget.soi) + else: + exec_info_dialog( + "Valgt tab er ingen SOI-tab", + "Den valgte taben inneholder ingen SOI.\n" + "Riktig tab må velges for å lagre en SOI i DB.", + ) + def open_shortcut_help(self): """Open shortcut dialog.""" self.popup_shortcut_help.setWindowTitle("Hurtigtaster") diff --git a/test/test_database.py b/test/test_database.py index b34691a..848cdd6 100644 --- a/test/test_database.py +++ b/test/test_database.py @@ -6,6 +6,7 @@ import json from time import sleep from datetime import datetime from soitool.database import Database +from soitool.soi import SOI from soitool.coder import get_code_length_needed TESTDBNAME = "testDatabase" @@ -293,6 +294,31 @@ class DatabaseTest(unittest.TestCase): ] self.assertRegex(code, "[A-Z0-9]") + def test_insert_soi(self): + """Test inserting an SOI to SOI-table.""" + test_title = "TestTitle" + test_date = datetime.now().strftime("%Y-%m-%d") + # Create and insert SOI + soi = SOI(title=test_title, date=test_date) + self.database.insert_soi(soi) + + # Assert only one SOI is in table + stmt = "SELECT * FROM SOI" + queried = self.database.conn.execute(stmt).fetchall() + self.assertEqual(len(queried), 1) + + # Assert SOI was written correctly + self.assertEqual(queried[0]["Title"], test_title) + self.assertEqual(queried[0]["Date"], test_date) + + # Insert same SOI again and assert '(2)' is added to title + self.database.insert_soi(soi) + stmt = "SELECT COUNT(*) FROM SOI WHERE Title=?" + count = self.database.conn.execute( + stmt, (test_title + "(2)",) + ).fetchone()[0] + self.assertEqual(count, 1) + def delete_db(self): """Delete generated database-file.""" if os.path.exists(TESTDBPATH): -- GitLab