diff --git a/CHANGELOG.md b/CHANGELOG.md index 92f3ab4..8997e49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.4.5 + + * Make it possible to delete revisions + # 0.4.4.1 * Adjust some widget heights/settings text wrap diff --git a/bouquin/db.py b/bouquin/db.py index 6a862b5..baa54e0 100644 --- a/bouquin/db.py +++ b/bouquin/db.py @@ -369,6 +369,17 @@ class DBManager: (version_id, date_iso), ) + def delete_version(self, *, version_id: int) -> bool | None: + """ + Delete a specific version by version_id. + """ + cur = self.conn.cursor() + row = cur.execute( + "DELETE FROM versions WHERE id=?;", + (version_id,), + ) + return True + # ------------------------- Export logic here ------------------------# def get_all_entries(self) -> List[Entry]: """ diff --git a/bouquin/history_dialog.py b/bouquin/history_dialog.py index 8429f5e..f2cdc1c 100644 --- a/bouquin/history_dialog.py +++ b/bouquin/history_dialog.py @@ -13,6 +13,7 @@ from PySide6.QtWidgets import ( QMessageBox, QTextBrowser, QTabWidget, + QAbstractItemView, ) from . import strings @@ -82,6 +83,7 @@ class HistoryDialog(QDialog): # Top: list of versions top = QHBoxLayout() self.list = QListWidget() + self.list.setSelectionMode(QAbstractItemView.ExtendedSelection) self.list.setMinimumSize(500, 650) self.list.currentItemChanged.connect(self._on_select) top.addWidget(self.list, 1) @@ -104,9 +106,12 @@ class HistoryDialog(QDialog): row.addStretch(1) self.btn_revert = QPushButton(strings._("history_dialog_revert_to_selected")) self.btn_revert.clicked.connect(self._revert) + self.btn_delete = QPushButton(strings._("history_dialog_delete")) + self.btn_delete.clicked.connect(self._delete) self.btn_close = QPushButton(strings._("close")) self.btn_close.clicked.connect(self.reject) row.addWidget(self.btn_revert) + row.addWidget(self.btn_delete) row.addWidget(self.btn_close) root.addLayout(row) @@ -145,20 +150,24 @@ class HistoryDialog(QDialog): @Slot() def _on_select(self): + selected_items = self.list.selectedItems() item = self.list.currentItem() - if not item: + if not item or len(selected_items) > 1: self.preview.clear() self.diff.clear() self.btn_revert.setEnabled(False) return + sel_id = item.data(Qt.UserRole) sel = self._db.get_version(version_id=sel_id) self.preview.setMarkdown(sel["content"]) # Diff vs current (textual diff) cur = self._db.get_version(version_id=self._current_id) self.diff.setHtml(_colored_unified_diff_html(cur["content"], sel["content"])) - # Enable revert only if selecting a non-current version + + # Enable revert and delete buttons only if selecting a non-current version self.btn_revert.setEnabled(sel_id != self._current_id) + self.btn_delete.setEnabled(sel_id != self._current_id) @Slot() def _revert(self): @@ -175,3 +184,19 @@ class HistoryDialog(QDialog): ) return self.accept() + + @Slot() + def _delete(self): + selected_items = self.list.selectedItems() + for item in selected_items: + sel_id = item.data(Qt.UserRole) + if sel_id == self._current_id: + return + try: + self._db.delete_version(version_id=sel_id) + except Exception as e: + QMessageBox.critical( + self, strings._("history_dialog_delete_failed"), str(e) + ) + return + return self._load_versions() diff --git a/bouquin/locales/en.json b/bouquin/locales/en.json index d92c819..a769ceb 100644 --- a/bouquin/locales/en.json +++ b/bouquin/locales/en.json @@ -22,7 +22,7 @@ "key_changed_explanation": "The notebook was re-encrypted with the new key!", "error": "Error", "success": "Success", - "close": "Close", + "close": "&Close", "find": "Find", "file": "File", "locale": "Language", @@ -81,8 +81,10 @@ "find_bar_match_case": "Match case", "history_dialog_preview": "Preview", "history_dialog_diff": "Diff", - "history_dialog_revert_to_selected": "Revert to selected", + "history_dialog_revert_to_selected": "&Revert to selected", "history_dialog_revert_failed": "Revert failed", + "history_dialog_delete": "&Delete revision", + "history_dialog_delete_failed": "Could not delete revision", "key_prompt_enter_key": "Enter key", "lock_overlay_locked_due_to_inactivity": "Locked due to inactivity", "lock_overlay_unlock": "Unlock",