def v1_upgrade(self): """Upgrade databse to version 1. Add fields: - created - timestamp document was modified - modified - timestamp document was modified - tags - list of tags associated with the document - order - display order in the documents list :return: """ with self.conn: try: Logger.info(f'Upgrading storage to version: {1}') self.conn.execute( """ALTER TABLE `documents` ADD COLUMN `created` timestamp""" ) self.conn.execute( """ALTER TABLE `documents` ADD COLUMN `modified` timestamp""" ) self.conn.execute( """ALTER TABLE `documents` ADD COLUMN `tags` TEXT""") self.conn.execute( """ALTER TABLE `documents` ADD COLUMN `order` INTEGER DEFAULT 0""" ) self.conn.execute("""INSERT INTO `version` VALUES (?, ?)""", ( 1, datetime.now(), )) Logger.info('Successfully upgraded to v1') return True except Exception: Logger.error(traceback.format_exc()) return False
def document_activate(self, doc_id): Logger.info(f'Document {doc_id} activated') editor = self.screens.get_child_by_name('editor-grid') editor.load_document(doc_id) editor.connect('update-document-stats', self.update_document_stats) self.screens.set_visible_child_name('editor-grid') self.header.toggle_document_mode() self.header.update_title(title=editor.document.title) self.settings.set_int('last-document-id', doc_id)
def init(self): if not os.path.exists(self.base_path): os.mkdir(self.base_path) Logger.info('Storage folder created at %s', self.base_path) Logger.info(f'Storage located at %s', self.file_path) self.conn = sqlite3.connect(self.file_path) self.conn.execute(""" CREATE TABLE IF NOT EXISTS `documents` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `content` TEXT, `archived` INTEGER NOT NULL DEFAULT 0 ) """)
def v2_upgrade(self) -> bool: """Upgrades database to version 2. Add tables: - folders - store folders :) Add fields: - path - internal path to the document, default to "/" - encrypted - indicates whether document is encrypted or not :return: True if upgrade was successful, otherwise False """ version = 2 with self.conn: try: self.conn.execute(""" CREATE TABLE IF NOT EXISTS `folders` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, "path" Text NOT NULL DEFAULT '/', "title" Text NOT NULL, `archived` INTEGER NOT NULL DEFAULT 0, `created` timestamp, `modified` timestamp, CONSTRAINT "uniq_full_path" UNIQUE ( "path", "title" ) ) """) Logger.info(f'Upgrading storage to version: {version}') self.conn.execute( """ALTER TABLE `documents` ADD COLUMN `path` TEXT default '/'""" ) self.conn.execute( """ALTER TABLE `documents` ADD COLUMN `encrypted` Boolean default False""" ) self.conn.execute("""INSERT INTO `version` VALUES (?, ?)""", ( version, datetime.now(), )) Logger.info(f'Successfully upgraded to v{version}') self.version = version return True except Exception: Logger.error(traceback.format_exc()) return False
def toggle_heading(self, text_view: Gtk.TextView, size: int) -> None: """Apply heading markup to currently selected line. If line starts with markup, and it matches required header size, it removes it. :param text_view: Gtk.TextView widget :param size: header size from 1 to 6 """ with user_action(self.buffer): cursor_mark = self.buffer.get_insert() cursor_iter = self.buffer.get_iter_at_mark(cursor_mark) offset = cursor_iter.get_offset() start = cursor_iter.copy() end = cursor_iter.copy() start.backward_chars(start.get_line_offset()) end.forward_to_line_end() # Get the origin text origin: str = self.buffer.get_text(start, end, True) markup = (size * '#') + ' ' Logger.info(f'origin: {origin}') pattern = re.compile(r'^(#{1,6})\s') match = pattern.match(origin) # If pattern found if match and match.group(1): # if line already header of `size` if len(match.group(1)) == size: text = pattern.sub('', origin) else: text = markup + origin else: text = markup + origin self.buffer.delete(start, end) self.buffer.insert(start, text)
def init(self) -> None: """Initialize database and create tables. Database path is based on the XDG Base Directory Specification. If it not exists then it will be created. Also this method checks if database is up to date and apply updates. """ if not os.path.exists(self.base_path): os.mkdir(self.base_path) Logger.info('Storage folder created at %s', self.base_path) Logger.info(f'Storage located at %s', self.file_path) self.connect() self.conn.execute(""" CREATE TABLE IF NOT EXISTS `documents` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `content` TEXT, `archived` INTEGER NOT NULL DEFAULT 0 ) """) self.conn.execute(""" CREATE TABLE IF NOT EXISTS `version` ( `version` INTEGER, `timestamp` timestamp ) """) # Check if storage DB needs to be upgraded version_response = self.conn.execute(""" SELECT version FROM version ORDER BY timestamp DESC LIMIT 1 """) version = version_response.fetchone() Logger.info(f'Current storage version: {version}') self.version = version if not version or version[0] < 1: self.v1_upgrade() if not version or version[0] < 2: self.v2_upgrade()
def init(self): if not os.path.exists(self.base_path): os.mkdir(self.base_path) Logger.info('Storage folder created at %s', self.base_path) Logger.info(f'Storage located at %s', self.file_path) self.conn = sqlite3.connect(self.file_path, detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES) self.conn.execute(""" CREATE TABLE IF NOT EXISTS `documents` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` TEXT NOT NULL, `content` TEXT, `archived` INTEGER NOT NULL DEFAULT 0 ) """) self.conn.execute(""" CREATE TABLE IF NOT EXISTS `version` ( `version` INTEGER, `timestamp` timestamp ) """) # Check if storage DB needs to be upgraded version_response = self.conn.execute(""" SELECT version FROM version ORDER BY timestamp DESC LIMIT 1 """) version = version_response.fetchone() Logger.info(f'Current storage version: {version}') self.version = version if not version or version[0] < 1: self.v1_upgrade()
def reload_items(self, sender: Gtk.Widget = None, path: str = None) -> None: order_desc = self.settings.get_boolean('sort-desc') self.model.clear() _old_path = self.current_path self.current_path = path or self.current_folder_path # For non-root path add virtual "upper" folder. if self.current_folder_path != '/': # /folder 1/folder 2 -> /folder 1 folder_path = self.current_folder_path[:self. current_folder_path[:-1]. rfind('/')] or '/' folder_open_icon = Pixbuf.new_from_resource( RESOURCE_PREFIX + '/icons/folder-open.svg') self.create_folder_model(title='..', path=folder_path, icon=folder_open_icon, tooltip=_('Go to the upper folder')) # Emit "path-changed" signal. self.emit('path-changed', _old_path, self.current_path) # Load folders first Logger.info(f"reload_items: {self.current_folder_path}") for folder in self.storage.get_folders(path=self.current_folder_path): self.create_folder_model(title=folder.title, path=folder.path) # Then load documents, not before foldes. for document in self.storage.all(path=self.current_folder_path, with_archived=self.show_archived, desc=order_desc): # icon = Gtk.IconTheme.get_default().load_icon('text-x-generic', 64, 0) opacity = 0.2 if document.archived else 1 # generate icon. It needs to stay in cache icon = self.gen_preview(document.content[:200], opacity=opacity) # Generate tooltip tooltip = f"{document.title}" if document.created: created = datetime.strptime(document.created, "%Y-%m-%d %H:%M:%S.%f") tooltip += f"\n<span weight='600' size='smaller' alpha='75%'>" \ + _('Created') + f": {created.strftime('%x')}</span>" if document.modified: modified = datetime.strptime(document.modified, "%Y-%m-%d %H:%M:%S.%f") tooltip += f"\n<span weight='600' size='smaller' alpha='75%'>" \ + _('Modified') + f": {modified.strftime('%x')}</span>" self.model.append([ icon, document.title, document.content, document.document_id, tooltip ]) if self.selected_path: self.view.select_path(self.selected_path)