From 5d63fe7e271e8f9ec5979365cfddf02237c74b07 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 24 Sep 2023 21:25:05 +0530 Subject: [PATCH] Start work on notes browser --- src/calibre/gui2/__init__.py | 1 + .../gui2/dialogs/edit_category_notes.py | 2 +- .../gui2/dialogs/show_category_note.py | 2 +- src/calibre/gui2/library/notes.py | 108 ++++++++++++++++++ 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 src/calibre/gui2/library/notes.py diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index fd574a1ff2..9f50262558 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -391,6 +391,7 @@ def create_defs(): defs['browse_annots_restrict_to_user'] = None defs['browse_annots_restrict_to_type'] = None defs['browse_annots_use_stemmer'] = True + defs['browse_notes_use_stemmer'] = True defs['fts_library_use_stemmer'] = True defs['fts_library_restrict_books'] = False defs['annots_export_format'] = 'txt' diff --git a/src/calibre/gui2/dialogs/edit_category_notes.py b/src/calibre/gui2/dialogs/edit_category_notes.py index ee2599509f..5ebacf5a23 100644 --- a/src/calibre/gui2/dialogs/edit_category_notes.py +++ b/src/calibre/gui2/dialogs/edit_category_notes.py @@ -292,7 +292,7 @@ class EditNoteDialog(Dialog): self.field, self.item_id = field, item_id self.item_val = self.db.get_item_name(field, item_id) super().__init__(_('Edit notes for {}').format(self.item_val), 'edit-notes-for-category', parent=parent) - self.setWindowIcon(QIcon.ic('edit_input.png')) + self.setWindowIcon(QIcon.ic('notes.png')) def setup_ui(self): self.l = l = QVBoxLayout(self) diff --git a/src/calibre/gui2/dialogs/show_category_note.py b/src/calibre/gui2/dialogs/show_category_note.py index a079efd605..c152da008b 100644 --- a/src/calibre/gui2/dialogs/show_category_note.py +++ b/src/calibre/gui2/dialogs/show_category_note.py @@ -49,7 +49,7 @@ class ShowNoteDialog(Dialog): self.extra_link, self.extra_link_tooltip = render_author_link(lk, self.item_val) self.field, self.item_id = field, item_id super().__init__(self.item_val, 'show-notes-for-category', parent=parent) - self.setWindowIcon(QIcon.ic('tag.png')) + self.setWindowIcon(QIcon.ic('notes.png')) self.refresh() def refresh(self): diff --git a/src/calibre/gui2/library/notes.py b/src/calibre/gui2/library/notes.py new file mode 100644 index 0000000000..1539f157f7 --- /dev/null +++ b/src/calibre/gui2/library/notes.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# License: GPLv3 Copyright: 2023, Kovid Goyal + +import os +from qt.core import ( + QCheckBox, QDialogButtonBox, QHBoxLayout, QIcon, QSize, Qt, QToolButton, + QVBoxLayout, QWidget, pyqtSignal, +) + +from calibre.gui2 import Application, gprefs +from calibre.gui2.viewer.widgets import SearchBox +from calibre.gui2.widgets2 import Dialog + + +def current_db(): + from calibre.gui2.ui import get_gui + return (getattr(current_db, 'ans', None) or get_gui().current_db).new_api + + +class RestrictFields(QWidget): + pass + + +class SearchInput(QWidget): + + cleared_signal = pyqtSignal() + show_next_signal = pyqtSignal() + show_previous_signal = pyqtSignal() + + def __init__(self, parent=None): + super().__init__(parent) + self.l = l = QVBoxLayout(self) + l.setContentsMargins(0, 0, 0, 0) + h = QHBoxLayout() + l.addLayout(h) + self.search_box = sb = SearchBox(self) + sb.initialize('library-notes-browser-search-box') + sb.cleared.connect(self.cleared, type=Qt.ConnectionType.QueuedConnection) + sb.lineEdit().returnPressed.connect(self.show_next) + sb.lineEdit().setPlaceholderText(_('Enter words to search for')) + h.addWidget(sb) + + self.next_button = nb = QToolButton(self) + h.addWidget(nb) + nb.setFocusPolicy(Qt.FocusPolicy.NoFocus) + nb.setIcon(QIcon.ic('arrow-down.png')) + nb.clicked.connect(self.show_next) + nb.setToolTip(_('Find next match')) + + self.prev_button = nb = QToolButton(self) + h.addWidget(nb) + nb.setFocusPolicy(Qt.FocusPolicy.NoFocus) + nb.setIcon(QIcon.ic('arrow-up.png')) + nb.clicked.connect(self.show_previous) + nb.setToolTip(_('Find previous match')) + + @property + def current_query(self): + return { + 'query': self.search_box.lineEdit().text().strip(), + } + + def cleared(self): + raise NotImplementedError('TODO: Implement me') + + def show_next(self): + raise NotImplementedError('TODO: Implement me') + + def show_previous(self): + raise NotImplementedError('TODO: Implement me') + + +class NotesBrowser(Dialog): + + def __init__(self, parent=None): + super().__init__(_('Browse notes'), 'browse-notes-dialog', default_buttons=QDialogButtonBox.StandardButton.Close) + self.setWindowIcon(QIcon.ic('notes.png')) + + def sizeHint(self): + return QSize(900, 600) + + def setup_ui(self): + self.l = l = QVBoxLayout(self) + + self.search_input = si = SearchInput(self) + l.addWidget(si) + + self.use_stemmer = us = QCheckBox(_('&Match on related words')) + us.setChecked(gprefs['browse_notes_use_stemmer']) + us.setToolTip('

' + _( + 'With this option searching for words will also match on any related words (supported in several languages). For' + ' example, in the English language: correction matches correcting and corrected as well')) + us.stateChanged.connect(lambda state: gprefs.set('browse_notes_use_stemmer', state != Qt.CheckState.Unchecked.value)) + + h = QHBoxLayout() + l.addLayout(h) + h.addWidget(us), h.addStretch(10), h.addWidget(self.bb) + + + +if __name__ == '__main__': + from calibre.library import db + app = Application([]) + current_db.ans = db(os.path.expanduser('~/test library')) + br = NotesBrowser() + br.exec() + del br + del app