mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Edit Book: Add support for saved searches. Click Search->Saved searches to bring up a dialog where you can create and manage saved searches
Needs testing
This commit is contained in:
parent
cb2b41f28e
commit
4a34618df4
@ -106,6 +106,8 @@ class Boss(QObject):
|
|||||||
self.gui.image_browser.image_activated.connect(self.image_activated)
|
self.gui.image_browser.image_activated.connect(self.image_activated)
|
||||||
self.gui.checkpoints.revert_requested.connect(self.revert_requested)
|
self.gui.checkpoints.revert_requested.connect(self.revert_requested)
|
||||||
self.gui.checkpoints.compare_requested.connect(self.compare_requested)
|
self.gui.checkpoints.compare_requested.connect(self.compare_requested)
|
||||||
|
self.gui.saved_searches.run_saved_searches.connect(self.run_saved_searches)
|
||||||
|
self.gui.central.search_panel.save_search.connect(self.save_search)
|
||||||
|
|
||||||
def preferences(self):
|
def preferences(self):
|
||||||
p = Preferences(self.gui)
|
p = Preferences(self.gui)
|
||||||
@ -683,6 +685,27 @@ class Boss(QObject):
|
|||||||
run_search(state, action, ed, name, searchable_names,
|
run_search(state, action, ed, name, searchable_names,
|
||||||
self.gui, self.show_editor, self.edit_file, self.show_current_diff, self.add_savepoint, self.rewind_savepoint, self.set_modified)
|
self.gui, self.show_editor, self.edit_file, self.show_current_diff, self.add_savepoint, self.rewind_savepoint, self.set_modified)
|
||||||
|
|
||||||
|
def saved_searches(self):
|
||||||
|
self.gui.saved_searches.show(), self.gui.saved_searches.raise_()
|
||||||
|
|
||||||
|
def save_search(self):
|
||||||
|
state = self.gui.central.search_panel.state
|
||||||
|
self.gui.saved_searches.show(), self.gui.saved_searches.raise_()
|
||||||
|
self.gui.saved_searches.add_predefined_search(state)
|
||||||
|
|
||||||
|
def run_saved_searches(self, searches, action):
|
||||||
|
ed = self.gui.central.current_editor
|
||||||
|
name = None
|
||||||
|
for n, x in editors.iteritems():
|
||||||
|
if x is ed:
|
||||||
|
name = n
|
||||||
|
break
|
||||||
|
searchable_names = self.gui.file_list.searchable_names
|
||||||
|
if not searches or not validate_search_request(name, searchable_names, getattr(ed, 'has_marked_text', False), searches[0], self.gui):
|
||||||
|
return
|
||||||
|
run_search(searches, action, ed, name, searchable_names,
|
||||||
|
self.gui, self.show_editor, self.edit_file, self.show_current_diff, self.add_savepoint, self.rewind_savepoint, self.set_modified)
|
||||||
|
|
||||||
def create_checkpoint(self):
|
def create_checkpoint(self):
|
||||||
text, ok = QInputDialog.getText(self.gui, _('Choose name'), _(
|
text, ok = QInputDialog.getText(self.gui, _('Choose name'), _(
|
||||||
'Choose a name for the checkpoint.\nYou can later restore the book'
|
'Choose a name for the checkpoint.\nYou can later restore the book'
|
||||||
|
@ -39,6 +39,7 @@ class PushButton(QPushButton):
|
|||||||
class HistoryLineEdit(HistoryLineEdit2):
|
class HistoryLineEdit(HistoryLineEdit2):
|
||||||
|
|
||||||
max_history_items = 100
|
max_history_items = 100
|
||||||
|
save_search = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent, clear_msg):
|
def __init__(self, parent, clear_msg):
|
||||||
HistoryLineEdit2.__init__(self, parent)
|
HistoryLineEdit2.__init__(self, parent)
|
||||||
@ -51,6 +52,8 @@ class HistoryLineEdit(HistoryLineEdit2):
|
|||||||
menu.addAction(self.clear_msg, self.clear_history)
|
menu.addAction(self.clear_msg, self.clear_history)
|
||||||
menu.addAction((_('Enable completion based on search history') if self.disable_popup else _(
|
menu.addAction((_('Enable completion based on search history') if self.disable_popup else _(
|
||||||
'Disable completion based on search history')), self.toggle_popups)
|
'Disable completion based on search history')), self.toggle_popups)
|
||||||
|
menu.addSeparator()
|
||||||
|
menu.addAction(_('Save current search'), self.save_search.emit)
|
||||||
menu.exec_(event.globalPos())
|
menu.exec_(event.globalPos())
|
||||||
|
|
||||||
def toggle_popups(self):
|
def toggle_popups(self):
|
||||||
@ -123,6 +126,7 @@ class SearchWidget(QWidget):
|
|||||||
}
|
}
|
||||||
|
|
||||||
search_triggered = pyqtSignal(object)
|
search_triggered = pyqtSignal(object)
|
||||||
|
save_search = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
@ -133,6 +137,7 @@ class SearchWidget(QWidget):
|
|||||||
self.fl = fl = QLabel(_('&Find:'))
|
self.fl = fl = QLabel(_('&Find:'))
|
||||||
fl.setAlignment(Qt.AlignRight | Qt.AlignCenter)
|
fl.setAlignment(Qt.AlignRight | Qt.AlignCenter)
|
||||||
self.find_text = ft = HistoryLineEdit(self, _('Clear search history'))
|
self.find_text = ft = HistoryLineEdit(self, _('Clear search history'))
|
||||||
|
ft.save_search.connect(self.save_search)
|
||||||
ft.initialize('tweak_book_find_edit')
|
ft.initialize('tweak_book_find_edit')
|
||||||
ft.returnPressed.connect(lambda : self.search_triggered.emit('find'))
|
ft.returnPressed.connect(lambda : self.search_triggered.emit('find'))
|
||||||
fl.setBuddy(ft)
|
fl.setBuddy(ft)
|
||||||
@ -142,6 +147,7 @@ class SearchWidget(QWidget):
|
|||||||
self.rl = rl = QLabel(_('&Replace:'))
|
self.rl = rl = QLabel(_('&Replace:'))
|
||||||
rl.setAlignment(Qt.AlignRight | Qt.AlignCenter)
|
rl.setAlignment(Qt.AlignRight | Qt.AlignCenter)
|
||||||
self.replace_text = rt = HistoryLineEdit(self, _('Clear replace history'))
|
self.replace_text = rt = HistoryLineEdit(self, _('Clear replace history'))
|
||||||
|
rt.save_search.connect(self.save_search)
|
||||||
rt.initialize('tweak_book_replace_edit')
|
rt.initialize('tweak_book_replace_edit')
|
||||||
rl.setBuddy(rt)
|
rl.setBuddy(rt)
|
||||||
l.addWidget(rl, 1, 0)
|
l.addWidget(rl, 1, 0)
|
||||||
@ -298,6 +304,7 @@ regex_cache = {}
|
|||||||
class SearchPanel(QWidget): # {{{
|
class SearchPanel(QWidget): # {{{
|
||||||
|
|
||||||
search_triggered = pyqtSignal(object)
|
search_triggered = pyqtSignal(object)
|
||||||
|
save_search = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
@ -316,6 +323,7 @@ class SearchPanel(QWidget): # {{{
|
|||||||
l.addWidget(self.widget)
|
l.addWidget(self.widget)
|
||||||
self.restore_state, self.save_state = self.widget.restore_state, self.widget.save_state
|
self.restore_state, self.save_state = self.widget.restore_state, self.widget.save_state
|
||||||
self.widget.search_triggered.connect(self.search_triggered)
|
self.widget.search_triggered.connect(self.search_triggered)
|
||||||
|
self.widget.save_search.connect(self.save_search)
|
||||||
self.pre_fill = self.widget.pre_fill
|
self.pre_fill = self.widget.pre_fill
|
||||||
|
|
||||||
def hide_panel(self):
|
def hide_panel(self):
|
||||||
@ -401,11 +409,16 @@ class SearchesModel(QAbstractListModel):
|
|||||||
|
|
||||||
class EditSearch(Dialog): # {{{
|
class EditSearch(Dialog): # {{{
|
||||||
|
|
||||||
def __init__(self, search=None, search_index=-1, parent=None):
|
def __init__(self, search=None, search_index=-1, parent=None, state=None):
|
||||||
self.search = search or {}
|
self.search = search or {}
|
||||||
self.original_name = self.search.get('name', None)
|
self.original_name = self.search.get('name', None)
|
||||||
self.search_index = search_index
|
self.search_index = search_index
|
||||||
Dialog.__init__(self, _('Edit search'), 'edit-saved-search', parent=parent)
|
Dialog.__init__(self, _('Edit search'), 'edit-saved-search', parent=parent)
|
||||||
|
if state is not None:
|
||||||
|
self.find.setText(state['find'])
|
||||||
|
self.replace.setText(state['replace'])
|
||||||
|
self.case_sensitive.setChecked(state['case_sensitive'])
|
||||||
|
self.dot_all.setChecked(state['dot_all'])
|
||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
ans = Dialog.sizeHint(self)
|
ans = Dialog.sizeHint(self)
|
||||||
@ -481,6 +494,8 @@ class SearchDelegate(QStyledItemDelegate):
|
|||||||
|
|
||||||
class SavedSearches(Dialog):
|
class SavedSearches(Dialog):
|
||||||
|
|
||||||
|
run_saved_searches = pyqtSignal(object, object)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
Dialog.__init__(self, _('Saved Searches'), 'saved-searches', parent=parent)
|
Dialog.__init__(self, _('Saved Searches'), 'saved-searches', parent=parent)
|
||||||
|
|
||||||
@ -633,6 +648,7 @@ class SavedSearches(Dialog):
|
|||||||
searches.append(search)
|
searches.append(search)
|
||||||
if not searches:
|
if not searches:
|
||||||
return
|
return
|
||||||
|
self.run_saved_searches.emit(searches, action)
|
||||||
|
|
||||||
def move_entry(self, delta):
|
def move_entry(self, delta):
|
||||||
rows = {index.row() for index in self.searches.selectionModel().selectedIndexes()} - {-1}
|
rows = {index.row() for index in self.searches.selectionModel().selectedIndexes()} - {-1}
|
||||||
@ -661,6 +677,9 @@ class SavedSearches(Dialog):
|
|||||||
|
|
||||||
def add_search(self):
|
def add_search(self):
|
||||||
d = EditSearch(parent=self)
|
d = EditSearch(parent=self)
|
||||||
|
self._add_search(d)
|
||||||
|
|
||||||
|
def _add_search(self, d):
|
||||||
if d.exec_() == d.Accepted:
|
if d.exec_() == d.Accepted:
|
||||||
self.model.add_search()
|
self.model.add_search()
|
||||||
index = self.model.index(self.model.rowCount() - 1)
|
index = self.model.index(self.model.rowCount() - 1)
|
||||||
@ -669,6 +688,10 @@ class SavedSearches(Dialog):
|
|||||||
sm.setCurrentIndex(index, sm.ClearAndSelect)
|
sm.setCurrentIndex(index, sm.ClearAndSelect)
|
||||||
self.show_details()
|
self.show_details()
|
||||||
|
|
||||||
|
def add_predefined_search(self, state):
|
||||||
|
d = EditSearch(parent=self, state=state)
|
||||||
|
self._add_search(d)
|
||||||
|
|
||||||
def show_details(self):
|
def show_details(self):
|
||||||
self.description.setText(' \n \n ')
|
self.description.setText(' \n \n ')
|
||||||
i = self.searches.currentIndex()
|
i = self.searches.currentIndex()
|
||||||
|
@ -29,6 +29,7 @@ from calibre.gui2.tweak_book.undo import CheckpointView
|
|||||||
from calibre.gui2.tweak_book.preview import Preview
|
from calibre.gui2.tweak_book.preview import Preview
|
||||||
from calibre.gui2.tweak_book.search import SearchPanel
|
from calibre.gui2.tweak_book.search import SearchPanel
|
||||||
from calibre.gui2.tweak_book.check import Check
|
from calibre.gui2.tweak_book.check import Check
|
||||||
|
from calibre.gui2.tweak_book.search import SavedSearches
|
||||||
from calibre.gui2.tweak_book.toc import TOCViewer
|
from calibre.gui2.tweak_book.toc import TOCViewer
|
||||||
from calibre.gui2.tweak_book.char_select import CharSelect
|
from calibre.gui2.tweak_book.char_select import CharSelect
|
||||||
from calibre.gui2.tweak_book.editor.widget import register_text_editor_actions
|
from calibre.gui2.tweak_book.editor.widget import register_text_editor_actions
|
||||||
@ -221,6 +222,7 @@ class Main(MainWindow):
|
|||||||
self.setCentralWidget(self.central)
|
self.setCentralWidget(self.central)
|
||||||
self.check_book = Check(self)
|
self.check_book = Check(self)
|
||||||
self.toc_view = TOCViewer(self)
|
self.toc_view = TOCViewer(self)
|
||||||
|
self.saved_searches = SavedSearches(self)
|
||||||
self.image_browser = InsertImage(self, for_browsing=True)
|
self.image_browser = InsertImage(self, for_browsing=True)
|
||||||
self.insert_char = CharSelect(self)
|
self.insert_char = CharSelect(self)
|
||||||
|
|
||||||
@ -393,6 +395,7 @@ class Main(MainWindow):
|
|||||||
'count', keys=('Ctrl+N'), description=_('Count number of matches'))
|
'count', keys=('Ctrl+N'), description=_('Count number of matches'))
|
||||||
self.action_mark = reg(None, _('&Mark selected text'), self.boss.mark_selected_text, 'mark-selected-text', ('Ctrl+Shift+M',), _('Mark selected text'))
|
self.action_mark = reg(None, _('&Mark selected text'), self.boss.mark_selected_text, 'mark-selected-text', ('Ctrl+Shift+M',), _('Mark selected text'))
|
||||||
self.action_go_to_line = reg(None, _('Go to &line'), self.boss.go_to_line_number, 'go-to-line-number', ('Ctrl+.',), _('Go to line number'))
|
self.action_go_to_line = reg(None, _('Go to &line'), self.boss.go_to_line_number, 'go-to-line-number', ('Ctrl+.',), _('Go to line number'))
|
||||||
|
self.action_saved_searches = reg(None, _('Sa&ved searches'), self.boss.saved_searches, 'saved-searches', (), _('Show the saved searches dialog'))
|
||||||
|
|
||||||
# Check Book actions
|
# Check Book actions
|
||||||
group = _('Check Book')
|
group = _('Check Book')
|
||||||
@ -507,6 +510,8 @@ class Main(MainWindow):
|
|||||||
a(self.action_mark)
|
a(self.action_mark)
|
||||||
e.addSeparator()
|
e.addSeparator()
|
||||||
a(self.action_go_to_line)
|
a(self.action_go_to_line)
|
||||||
|
e.addSeparator()
|
||||||
|
a(self.action_saved_searches)
|
||||||
|
|
||||||
e = b.addMenu(_('&Help'))
|
e = b.addMenu(_('&Help'))
|
||||||
a = e.addAction
|
a = e.addAction
|
||||||
|
Loading…
x
Reference in New Issue
Block a user