mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Refactor search boxes to use Qt 4.7 facility for displaying help text. Pressing Enter in the search box int he main calibre GUI now focusses the book list
This commit is contained in:
commit
3fcebe8383
@ -10,7 +10,8 @@ Scheduler for automated recipe downloads
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from PyQt4.Qt import QDialog, SIGNAL, Qt, QTime, QObject, QMenu, \
|
from PyQt4.Qt import QDialog, SIGNAL, Qt, QTime, QObject, QMenu, \
|
||||||
QAction, QIcon, QMutex, QTimer, pyqtSignal
|
QAction, QIcon, QMutex, QTimer, pyqtSignal, QWidget, QHBoxLayout, \
|
||||||
|
QLabel
|
||||||
|
|
||||||
from calibre.gui2.dialogs.scheduler_ui import Ui_Dialog
|
from calibre.gui2.dialogs.scheduler_ui import Ui_Dialog
|
||||||
from calibre.gui2.search_box import SearchBox2
|
from calibre.gui2.search_box import SearchBox2
|
||||||
@ -28,15 +29,21 @@ class SchedulerDialog(QDialog, Ui_Dialog):
|
|||||||
self.recipe_model = recipe_model
|
self.recipe_model = recipe_model
|
||||||
self.recipe_model.do_refresh()
|
self.recipe_model.do_refresh()
|
||||||
|
|
||||||
|
self._cont = QWidget(self)
|
||||||
|
self._cont.l = QHBoxLayout()
|
||||||
|
self._cont.setLayout(self._cont.l)
|
||||||
|
self._cont.la = QLabel(_('&Search:'))
|
||||||
|
self._cont.l.addWidget(self._cont.la, 1)
|
||||||
self.search = SearchBox2(self)
|
self.search = SearchBox2(self)
|
||||||
|
self._cont.l.addWidget(self.search, 100)
|
||||||
|
self._cont.la.setBuddy(self.search)
|
||||||
self.search.setMinimumContentsLength(25)
|
self.search.setMinimumContentsLength(25)
|
||||||
self.search.initialize('scheduler_search_history')
|
self.search.initialize('scheduler_search_history')
|
||||||
self.recipe_box.layout().insertWidget(0, self.search)
|
self.recipe_box.layout().insertWidget(0, self._cont)
|
||||||
self.search.search.connect(self.recipe_model.search)
|
self.search.search.connect(self.recipe_model.search)
|
||||||
self.connect(self.recipe_model, SIGNAL('searched(PyQt_PyObject)'),
|
self.recipe_model.searched.connect(self.search.search_done,
|
||||||
self.search.search_done)
|
type=Qt.QueuedConnection)
|
||||||
self.connect(self.recipe_model, SIGNAL('searched(PyQt_PyObject)'),
|
self.recipe_model.searched.connect(self.search_done)
|
||||||
self.search_done)
|
|
||||||
self.search.setFocus(Qt.OtherFocusReason)
|
self.search.setFocus(Qt.OtherFocusReason)
|
||||||
self.commit_on_change = True
|
self.commit_on_change = True
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ class Main(MainWindow, Ui_MainWindow):
|
|||||||
self.progress_label.setText('Parsing '+ self.file_name)
|
self.progress_label.setText('Parsing '+ self.file_name)
|
||||||
self.renderer = RenderWorker(self, stream, self.logger, self.opts)
|
self.renderer = RenderWorker(self, stream, self.logger, self.opts)
|
||||||
QObject.connect(self.renderer, SIGNAL('finished()'), self.parsed, Qt.QueuedConnection)
|
QObject.connect(self.renderer, SIGNAL('finished()'), self.parsed, Qt.QueuedConnection)
|
||||||
self.search.clear_to_help()
|
self.search.clear()
|
||||||
self.last_search = None
|
self.last_search = None
|
||||||
else:
|
else:
|
||||||
self.stack.setCurrentIndex(0)
|
self.stack.setCurrentIndex(0)
|
||||||
|
@ -8,9 +8,8 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from PyQt4.Qt import QComboBox, Qt, QLineEdit, QStringList, pyqtSlot, \
|
from PyQt4.Qt import QComboBox, Qt, QLineEdit, QStringList, pyqtSlot, QDialog, \
|
||||||
pyqtSignal, SIGNAL, QObject, QDialog, QCompleter, \
|
pyqtSignal, QCompleter, QAction, QKeySequence, QTimer
|
||||||
QAction, QKeySequence, QTimer
|
|
||||||
|
|
||||||
from calibre.gui2 import config
|
from calibre.gui2 import config
|
||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
@ -20,34 +19,29 @@ from calibre.utils.search_query_parser import saved_searches
|
|||||||
|
|
||||||
class SearchLineEdit(QLineEdit):
|
class SearchLineEdit(QLineEdit):
|
||||||
key_pressed = pyqtSignal(object)
|
key_pressed = pyqtSignal(object)
|
||||||
mouse_released = pyqtSignal(object)
|
|
||||||
focus_out = pyqtSignal(object)
|
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
self.key_pressed.emit(event)
|
self.key_pressed.emit(event)
|
||||||
QLineEdit.keyPressEvent(self, event)
|
QLineEdit.keyPressEvent(self, event)
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event):
|
def mouseReleaseEvent(self, event):
|
||||||
self.mouse_released.emit(event)
|
|
||||||
QLineEdit.mouseReleaseEvent(self, event)
|
QLineEdit.mouseReleaseEvent(self, event)
|
||||||
|
QLineEdit.selectAll(self)
|
||||||
|
|
||||||
def focusOutEvent(self, event):
|
def focusInEvent(self, event):
|
||||||
self.focus_out.emit(event)
|
QLineEdit.focusInEvent(self, event)
|
||||||
QLineEdit.focusOutEvent(self, event)
|
QLineEdit.selectAll(self)
|
||||||
|
|
||||||
def dropEvent(self, ev):
|
def dropEvent(self, ev):
|
||||||
if self.parent().help_state:
|
|
||||||
self.parent().normalize_state()
|
self.parent().normalize_state()
|
||||||
return QLineEdit.dropEvent(self, ev)
|
return QLineEdit.dropEvent(self, ev)
|
||||||
|
|
||||||
def contextMenuEvent(self, ev):
|
def contextMenuEvent(self, ev):
|
||||||
if self.parent().help_state:
|
|
||||||
self.parent().normalize_state()
|
self.parent().normalize_state()
|
||||||
return QLineEdit.contextMenuEvent(self, ev)
|
return QLineEdit.contextMenuEvent(self, ev)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def paste(self, *args):
|
def paste(self, *args):
|
||||||
if self.parent().help_state:
|
|
||||||
self.parent().normalize_state()
|
self.parent().normalize_state()
|
||||||
return QLineEdit.paste(self)
|
return QLineEdit.paste(self)
|
||||||
|
|
||||||
@ -59,14 +53,17 @@ class SearchBox2(QComboBox):
|
|||||||
* Call initialize()
|
* Call initialize()
|
||||||
* Connect to the search() and cleared() signals from this widget.
|
* Connect to the search() and cleared() signals from this widget.
|
||||||
* Connect to the cleared() signal to know when the box content changes
|
* Connect to the cleared() signal to know when the box content changes
|
||||||
|
* Connect to focus_to_library signal to be told to manually change focus
|
||||||
* Call search_done() after every search is complete
|
* Call search_done() after every search is complete
|
||||||
* Use clear() to clear back to the help message
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
INTERVAL = 1500 #: Time to wait before emitting search signal
|
INTERVAL = 1500 #: Time to wait before emitting search signal
|
||||||
MAX_COUNT = 25
|
MAX_COUNT = 25
|
||||||
|
|
||||||
search = pyqtSignal(object)
|
search = pyqtSignal(object)
|
||||||
|
cleared = pyqtSignal()
|
||||||
|
changed = pyqtSignal()
|
||||||
|
focus_to_library = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QComboBox.__init__(self, parent)
|
QComboBox.__init__(self, parent)
|
||||||
@ -75,13 +72,9 @@ class SearchBox2(QComboBox):
|
|||||||
self.setLineEdit(self.line_edit)
|
self.setLineEdit(self.line_edit)
|
||||||
c = self.line_edit.completer()
|
c = self.line_edit.completer()
|
||||||
c.setCompletionMode(c.PopupCompletion)
|
c.setCompletionMode(c.PopupCompletion)
|
||||||
self.line_edit.key_pressed.connect(self.key_pressed,
|
self.line_edit.key_pressed.connect(self.key_pressed, type=Qt.DirectConnection)
|
||||||
type=Qt.DirectConnection)
|
|
||||||
self.line_edit.mouse_released.connect(self.mouse_released,
|
|
||||||
type=Qt.DirectConnection)
|
|
||||||
self.activated.connect(self.history_selected)
|
self.activated.connect(self.history_selected)
|
||||||
self.setEditable(True)
|
self.setEditable(True)
|
||||||
self.help_state = False
|
|
||||||
self.as_you_type = True
|
self.as_you_type = True
|
||||||
self.prev_search = ''
|
self.prev_search = ''
|
||||||
self.timer = QTimer()
|
self.timer = QTimer()
|
||||||
@ -98,96 +91,69 @@ class SearchBox2(QComboBox):
|
|||||||
self.as_you_type = config['search_as_you_type']
|
self.as_you_type = config['search_as_you_type']
|
||||||
self.opt_name = opt_name
|
self.opt_name = opt_name
|
||||||
self.addItems(QStringList(list(set(config[opt_name]))))
|
self.addItems(QStringList(list(set(config[opt_name]))))
|
||||||
self.help_text = help_text
|
try:
|
||||||
|
self.line_edit.setPlaceholderText(help_text)
|
||||||
|
except:
|
||||||
|
# Using Qt < 4.7
|
||||||
|
pass
|
||||||
self.colorize = colorize
|
self.colorize = colorize
|
||||||
self.clear_to_help()
|
self.clear()
|
||||||
|
|
||||||
def normalize_state(self):
|
def normalize_state(self):
|
||||||
self.setToolTip(self.tool_tip_text)
|
self.setToolTip(self.tool_tip_text)
|
||||||
if self.help_state:
|
|
||||||
self.setEditText('')
|
|
||||||
self.line_edit.setStyleSheet(
|
self.line_edit.setStyleSheet(
|
||||||
'QLineEdit { color: black; background-color: %s; }' %
|
'QLineEdit{color:black;background-color:%s;}' % self.normal_background)
|
||||||
self.normal_background)
|
|
||||||
self.help_state = False
|
|
||||||
else:
|
|
||||||
self.line_edit.setStyleSheet(
|
|
||||||
'QLineEdit { color: black; background-color: %s; }' %
|
|
||||||
self.normal_background)
|
|
||||||
|
|
||||||
def clear_to_help(self):
|
|
||||||
self.setToolTip(self.tool_tip_text)
|
|
||||||
if self.help_state:
|
|
||||||
return
|
|
||||||
self.help_state = True
|
|
||||||
self.search.emit('')
|
|
||||||
self._in_a_search = False
|
|
||||||
self.setEditText(self.help_text)
|
|
||||||
self.line_edit.home(False)
|
|
||||||
self.line_edit.setStyleSheet(
|
|
||||||
'QLineEdit { color: gray; background-color: %s; }' %
|
|
||||||
self.normal_background)
|
|
||||||
self.emit(SIGNAL('cleared()'))
|
|
||||||
|
|
||||||
def text(self):
|
def text(self):
|
||||||
return self.currentText()
|
return self.currentText()
|
||||||
|
|
||||||
def clear(self):
|
def clear(self, emit_search=False):
|
||||||
self.clear_to_help()
|
self.normalize_state()
|
||||||
|
self.setEditText('')
|
||||||
|
self.search.emit('')
|
||||||
|
self._in_a_search = False
|
||||||
|
self.cleared.emit()
|
||||||
|
|
||||||
def search_done(self, ok):
|
def search_done(self, ok):
|
||||||
if isinstance(ok, basestring):
|
if isinstance(ok, basestring):
|
||||||
self.setToolTip(ok)
|
self.setToolTip(ok)
|
||||||
ok = False
|
ok = False
|
||||||
if not unicode(self.currentText()).strip():
|
if not unicode(self.currentText()).strip():
|
||||||
return self.clear_to_help()
|
self.clear(emit_search=False)
|
||||||
|
return
|
||||||
self._in_a_search = ok
|
self._in_a_search = ok
|
||||||
col = 'rgba(0,255,0,20%)' if ok else 'rgb(255,0,0,20%)'
|
col = 'rgba(0,255,0,20%)' if ok else 'rgb(255,0,0,20%)'
|
||||||
if not self.colorize:
|
if not self.colorize:
|
||||||
col = self.normal_background
|
col = self.normal_background
|
||||||
self.line_edit.setStyleSheet('QLineEdit { color: black; background-color: %s; }' % col)
|
self.line_edit.setStyleSheet('QLineEdit{color:black;background-color:%s;}' % col)
|
||||||
|
|
||||||
def key_pressed(self, event):
|
def key_pressed(self, event):
|
||||||
k = event.key()
|
k = event.key()
|
||||||
if k in (Qt.Key_Left, Qt.Key_Right, Qt.Key_Up, Qt.Key_Down,
|
if k in (Qt.Key_Left, Qt.Key_Right, Qt.Key_Up, Qt.Key_Down,
|
||||||
Qt.Key_Home, Qt.Key_End, Qt.Key_PageUp, Qt.Key_PageDown):
|
Qt.Key_Home, Qt.Key_End, Qt.Key_PageUp, Qt.Key_PageDown,
|
||||||
|
Qt.Key_unknown):
|
||||||
return
|
return
|
||||||
self.normalize_state()
|
self.normalize_state()
|
||||||
if self._in_a_search:
|
if self._in_a_search:
|
||||||
self.emit(SIGNAL('changed()'))
|
self.changed.emit()
|
||||||
self._in_a_search = False
|
self._in_a_search = False
|
||||||
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
|
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
|
||||||
self.do_search()
|
self.do_search()
|
||||||
|
self.focus_to_library.emit()
|
||||||
if self.as_you_type:
|
if self.as_you_type:
|
||||||
self.timer.start(1500)
|
self.timer.start(1500)
|
||||||
|
|
||||||
def mouse_released(self, event):
|
|
||||||
self.normalize_state()
|
|
||||||
# Dont trigger a search since it make
|
|
||||||
# re-positioning the cursor using the mouse
|
|
||||||
# impossible
|
|
||||||
#if self.as_you_type:
|
|
||||||
# self.timer.start(1500)
|
|
||||||
|
|
||||||
def timer_event(self):
|
def timer_event(self):
|
||||||
self.do_search()
|
self.do_search()
|
||||||
|
|
||||||
def history_selected(self, text):
|
def history_selected(self, text):
|
||||||
self.emit(SIGNAL('changed()'))
|
self.changed.emit()
|
||||||
self.do_search()
|
self.do_search()
|
||||||
|
|
||||||
@property
|
|
||||||
def smart_text(self):
|
|
||||||
text = unicode(self.currentText()).strip()
|
|
||||||
if not text or text == self.help_text:
|
|
||||||
return ''
|
|
||||||
return text
|
|
||||||
|
|
||||||
def do_search(self, *args):
|
def do_search(self, *args):
|
||||||
text = unicode(self.currentText()).strip()
|
text = unicode(self.currentText()).strip()
|
||||||
if not text or text == self.help_text:
|
if not text:
|
||||||
return self.clear()
|
return self.clear()
|
||||||
self.help_state = False
|
|
||||||
self.prev_search = text
|
self.prev_search = text
|
||||||
self.search.emit(text)
|
self.search.emit(text)
|
||||||
|
|
||||||
@ -220,7 +186,7 @@ class SearchBox2(QComboBox):
|
|||||||
|
|
||||||
def set_search_string(self, txt):
|
def set_search_string(self, txt):
|
||||||
if not txt:
|
if not txt:
|
||||||
self.clear_to_help()
|
self.clear()
|
||||||
return
|
return
|
||||||
self.normalize_state()
|
self.normalize_state()
|
||||||
self.setEditText(txt)
|
self.setEditText(txt)
|
||||||
@ -243,25 +209,24 @@ class SavedSearchBox(QComboBox):
|
|||||||
if you care about changes to the list of saved searches.
|
if you care about changes to the list of saved searches.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
changed = pyqtSignal()
|
||||||
|
focus_to_library = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QComboBox.__init__(self, parent)
|
QComboBox.__init__(self, parent)
|
||||||
self.normal_background = 'rgb(255, 255, 255, 0%)'
|
self.normal_background = 'rgb(255, 255, 255, 0%)'
|
||||||
|
|
||||||
self.line_edit = SearchLineEdit(self)
|
self.line_edit = SearchLineEdit(self)
|
||||||
self.setLineEdit(self.line_edit)
|
self.setLineEdit(self.line_edit)
|
||||||
self.line_edit.key_pressed.connect(self.key_pressed,
|
self.line_edit.key_pressed.connect(self.key_pressed, type=Qt.DirectConnection)
|
||||||
type=Qt.DirectConnection)
|
|
||||||
self.line_edit.mouse_released.connect(self.mouse_released,
|
|
||||||
type=Qt.DirectConnection)
|
|
||||||
self.line_edit.focus_out.connect(self.focus_out,
|
|
||||||
type=Qt.DirectConnection)
|
|
||||||
self.activated[str].connect(self.saved_search_selected)
|
self.activated[str].connect(self.saved_search_selected)
|
||||||
|
|
||||||
completer = QCompleter(self) # turn off auto-completion
|
# Turn off auto-completion so that it doesn't interfere with typing
|
||||||
|
# names of new searches.
|
||||||
|
completer = QCompleter(self)
|
||||||
self.setCompleter(completer)
|
self.setCompleter(completer)
|
||||||
|
|
||||||
self.setEditable(True)
|
self.setEditable(True)
|
||||||
self.help_state = True
|
|
||||||
self.prev_search = ''
|
|
||||||
self.setInsertPolicy(self.NoInsert)
|
self.setInsertPolicy(self.NoInsert)
|
||||||
self.setSizeAdjustPolicy(self.AdjustToMinimumContentsLengthWithIcon)
|
self.setSizeAdjustPolicy(self.AdjustToMinimumContentsLengthWithIcon)
|
||||||
self.setMinimumContentsLength(10)
|
self.setMinimumContentsLength(10)
|
||||||
@ -269,50 +234,40 @@ class SavedSearchBox(QComboBox):
|
|||||||
|
|
||||||
def initialize(self, _search_box, colorize=False, help_text=_('Search')):
|
def initialize(self, _search_box, colorize=False, help_text=_('Search')):
|
||||||
self.search_box = _search_box
|
self.search_box = _search_box
|
||||||
self.help_text = help_text
|
self.line_edit.setPlaceholderText(help_text)
|
||||||
self.colorize = colorize
|
self.colorize = colorize
|
||||||
self.clear_to_help()
|
self.clear()
|
||||||
|
|
||||||
def normalize_state(self):
|
def normalize_state(self):
|
||||||
self.setEditText('')
|
# need this because line_edit will call it in some cases such as paste
|
||||||
self.line_edit.setStyleSheet(
|
pass
|
||||||
'QLineEdit { color: black; background-color: %s; }' %
|
|
||||||
self.normal_background)
|
|
||||||
self.help_state = False
|
|
||||||
|
|
||||||
def clear_to_help(self):
|
def clear(self):
|
||||||
self.setToolTip(self.tool_tip_text)
|
QComboBox.clear(self)
|
||||||
self.initialize_saved_search_names()
|
self.initialize_saved_search_names()
|
||||||
self.setEditText(self.help_text)
|
self.setEditText('')
|
||||||
self.line_edit.home(False)
|
self.line_edit.home(False)
|
||||||
self.help_state = True
|
|
||||||
self.line_edit.setStyleSheet(
|
|
||||||
'QLineEdit { color: gray; background-color: %s; }' %
|
|
||||||
self.normal_background)
|
|
||||||
|
|
||||||
def focus_out(self, event):
|
|
||||||
if self.currentText() == '':
|
|
||||||
self.clear_to_help()
|
|
||||||
|
|
||||||
def key_pressed(self, event):
|
def key_pressed(self, event):
|
||||||
if self.help_state:
|
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
|
||||||
self.normalize_state()
|
self.saved_search_selected(self.currentText())
|
||||||
|
self.focus_to_library.emit()
|
||||||
def mouse_released(self, event):
|
|
||||||
if self.help_state:
|
|
||||||
self.normalize_state()
|
|
||||||
|
|
||||||
def saved_search_selected(self, qname):
|
def saved_search_selected(self, qname):
|
||||||
qname = unicode(qname)
|
qname = unicode(qname)
|
||||||
if qname is None or not qname.strip():
|
if qname is None or not qname.strip():
|
||||||
|
self.search_box.clear()
|
||||||
|
return
|
||||||
|
if not saved_searches().lookup(qname):
|
||||||
|
self.search_box.clear()
|
||||||
|
self.setEditText(qname)
|
||||||
return
|
return
|
||||||
self.normalize_state()
|
|
||||||
self.search_box.set_search_string(u'search:"%s"' % qname)
|
self.search_box.set_search_string(u'search:"%s"' % qname)
|
||||||
self.setEditText(qname)
|
self.setEditText(qname)
|
||||||
self.setToolTip(saved_searches().lookup(qname))
|
self.setToolTip(saved_searches().lookup(qname))
|
||||||
|
self.focus_to_library.emit()
|
||||||
|
|
||||||
def initialize_saved_search_names(self):
|
def initialize_saved_search_names(self):
|
||||||
self.clear()
|
|
||||||
qnames = saved_searches().names()
|
qnames = saved_searches().names()
|
||||||
self.addItems(qnames)
|
self.addItems(qnames)
|
||||||
self.setCurrentIndex(-1)
|
self.setCurrentIndex(-1)
|
||||||
@ -330,25 +285,24 @@ class SavedSearchBox(QComboBox):
|
|||||||
if ss is None:
|
if ss is None:
|
||||||
return
|
return
|
||||||
saved_searches().delete(unicode(self.currentText()))
|
saved_searches().delete(unicode(self.currentText()))
|
||||||
self.clear_to_help()
|
self.clear()
|
||||||
self.search_box.clear_to_help()
|
self.search_box.clear()
|
||||||
self.emit(SIGNAL('changed()'))
|
self.changed.emit()
|
||||||
|
|
||||||
# SIGNALed from the main UI
|
# SIGNALed from the main UI
|
||||||
def save_search_button_clicked(self):
|
def save_search_button_clicked(self):
|
||||||
name = unicode(self.currentText())
|
name = unicode(self.currentText())
|
||||||
if self.help_state or not name.strip():
|
if not name.strip():
|
||||||
name = unicode(self.search_box.text()).replace('"', '')
|
name = unicode(self.search_box.text()).replace('"', '')
|
||||||
saved_searches().delete(name)
|
saved_searches().delete(name)
|
||||||
saved_searches().add(name, unicode(self.search_box.text()))
|
saved_searches().add(name, unicode(self.search_box.text()))
|
||||||
# now go through an initialization cycle to ensure that the combobox has
|
# now go through an initialization cycle to ensure that the combobox has
|
||||||
# the new search in it, that it is selected, and that the search box
|
# the new search in it, that it is selected, and that the search box
|
||||||
# references the new search instead of the text in the search.
|
# references the new search instead of the text in the search.
|
||||||
self.clear_to_help()
|
self.clear()
|
||||||
self.normalize_state()
|
|
||||||
self.setCurrentIndex(self.findText(name))
|
self.setCurrentIndex(self.findText(name))
|
||||||
self.saved_search_selected (name)
|
self.saved_search_selected (name)
|
||||||
self.emit(SIGNAL('changed()'))
|
self.changed.emit()
|
||||||
|
|
||||||
# SIGNALed from the main UI
|
# SIGNALed from the main UI
|
||||||
def copy_search_button_clicked (self):
|
def copy_search_button_clicked (self):
|
||||||
@ -362,11 +316,11 @@ class SearchBoxMixin(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.search.initialize('main_search_history', colorize=True,
|
self.search.initialize('main_search_history', colorize=True,
|
||||||
help_text=_('Search (For Advanced Search click the button to the left)'))
|
help_text=_('Search (For Advanced Search click the button to the left)'))
|
||||||
self.connect(self.search, SIGNAL('cleared()'), self.search_box_cleared)
|
self.search.cleared.connect(self.search_box_cleared)
|
||||||
self.connect(self.search, SIGNAL('changed()'), self.search_box_changed)
|
self.search.changed.connect(self.search_box_changed)
|
||||||
self.connect(self.clear_button, SIGNAL('clicked()'), self.search.clear)
|
self.search.focus_to_library.connect(self.focus_to_library)
|
||||||
QObject.connect(self.advanced_search_button, SIGNAL('clicked(bool)'),
|
self.clear_button.clicked.connect(self.search.clear)
|
||||||
self.do_advanced_search)
|
self.advanced_search_button.clicked[bool].connect(self.do_advanced_search)
|
||||||
|
|
||||||
self.search.clear()
|
self.search.clear()
|
||||||
self.search.setMaximumWidth(self.width()-150)
|
self.search.setMaximumWidth(self.width()-150)
|
||||||
@ -384,11 +338,11 @@ class SearchBoxMixin(object):
|
|||||||
|
|
||||||
def search_box_cleared(self):
|
def search_box_cleared(self):
|
||||||
self.tags_view.clear()
|
self.tags_view.clear()
|
||||||
self.saved_search.clear_to_help()
|
self.saved_search.clear()
|
||||||
self.set_number_of_books_shown()
|
self.set_number_of_books_shown()
|
||||||
|
|
||||||
def search_box_changed(self):
|
def search_box_changed(self):
|
||||||
self.saved_search.clear_to_help()
|
self.saved_search.clear()
|
||||||
self.tags_view.clear()
|
self.tags_view.clear()
|
||||||
|
|
||||||
def do_advanced_search(self, *args):
|
def do_advanced_search(self, *args):
|
||||||
@ -396,20 +350,24 @@ class SearchBoxMixin(object):
|
|||||||
if d.exec_() == QDialog.Accepted:
|
if d.exec_() == QDialog.Accepted:
|
||||||
self.search.set_search_string(d.search_string())
|
self.search.set_search_string(d.search_string())
|
||||||
|
|
||||||
|
def focus_to_library(self):
|
||||||
|
self.current_view().setFocus(Qt.OtherFocusReason)
|
||||||
|
|
||||||
class SavedSearchBoxMixin(object):
|
class SavedSearchBoxMixin(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.connect(self.saved_search, SIGNAL('changed()'), self.saved_searches_changed)
|
self.saved_search.changed.connect(self.saved_searches_changed)
|
||||||
|
self.clear_button.clicked.connect(self.saved_search.clear)
|
||||||
|
self.saved_search.focus_to_library.connect(self.focus_to_library)
|
||||||
|
self.save_search_button.clicked.connect(
|
||||||
|
self.saved_search.save_search_button_clicked)
|
||||||
|
self.delete_search_button.clicked.connect(
|
||||||
|
self.saved_search.delete_search_button_clicked)
|
||||||
|
self.copy_search_button.clicked.connect(
|
||||||
|
self.saved_search.copy_search_button_clicked)
|
||||||
self.saved_searches_changed()
|
self.saved_searches_changed()
|
||||||
self.connect(self.clear_button, SIGNAL('clicked()'), self.saved_search.clear_to_help)
|
|
||||||
self.saved_search.initialize(self.search, colorize=True,
|
self.saved_search.initialize(self.search, colorize=True,
|
||||||
help_text=_('Saved Searches'))
|
help_text=_('Saved Searches'))
|
||||||
self.connect(self.save_search_button, SIGNAL('clicked()'),
|
|
||||||
self.saved_search.save_search_button_clicked)
|
|
||||||
self.connect(self.delete_search_button, SIGNAL('clicked()'),
|
|
||||||
self.saved_search.delete_search_button_clicked)
|
|
||||||
self.connect(self.copy_search_button, SIGNAL('clicked()'),
|
|
||||||
self.saved_search.copy_search_button_clicked)
|
|
||||||
self.saved_search.setToolTip(
|
self.saved_search.setToolTip(
|
||||||
_('Choose saved search or enter name for new saved search'))
|
_('Choose saved search or enter name for new saved search'))
|
||||||
self.saved_search.setStatusTip(self.saved_search.toolTip())
|
self.saved_search.setStatusTip(self.saved_search.toolTip())
|
||||||
@ -420,7 +378,8 @@ class SavedSearchBoxMixin(object):
|
|||||||
def saved_searches_changed(self):
|
def saved_searches_changed(self):
|
||||||
p = sorted(saved_searches().names(), cmp=lambda x,y: cmp(x.lower(), y.lower()))
|
p = sorted(saved_searches().names(), cmp=lambda x,y: cmp(x.lower(), y.lower()))
|
||||||
t = unicode(self.search_restriction.currentText())
|
t = unicode(self.search_restriction.currentText())
|
||||||
self.search_restriction.clear() # rebuild the restrictions combobox using current saved searches
|
# rebuild the restrictions combobox using current saved searches
|
||||||
|
self.search_restriction.clear()
|
||||||
self.search_restriction.addItem('')
|
self.search_restriction.addItem('')
|
||||||
self.tags_view.recount()
|
self.tags_view.recount()
|
||||||
for s in p:
|
for s in p:
|
||||||
@ -433,6 +392,8 @@ class SavedSearchBoxMixin(object):
|
|||||||
d.exec_()
|
d.exec_()
|
||||||
if d.result() == d.Accepted:
|
if d.result() == d.Accepted:
|
||||||
self.saved_searches_changed()
|
self.saved_searches_changed()
|
||||||
self.saved_search.clear_to_help()
|
self.saved_search.clear()
|
||||||
|
|
||||||
|
def focus_to_library(self):
|
||||||
|
self.current_view().setFocus(Qt.OtherFocusReason)
|
||||||
|
|
||||||
|
@ -49,8 +49,8 @@ class SearchRestrictionMixin(object):
|
|||||||
restriction = ''
|
restriction = ''
|
||||||
self.restriction_count_of_books_in_view = \
|
self.restriction_count_of_books_in_view = \
|
||||||
self.library_view.model().set_search_restriction(restriction)
|
self.library_view.model().set_search_restriction(restriction)
|
||||||
self.search.clear_to_help()
|
self.search.clear()
|
||||||
self.saved_search.clear_to_help()
|
self.saved_search.clear()
|
||||||
self.tags_view.set_search_restriction(restriction)
|
self.tags_view.set_search_restriction(restriction)
|
||||||
self.set_number_of_books_shown()
|
self.set_number_of_books_shown()
|
||||||
|
|
||||||
|
@ -843,7 +843,7 @@ class TagBrowserMixin(object): # {{{
|
|||||||
self.tags_view.set_database(self.library_view.model().db,
|
self.tags_view.set_database(self.library_view.model().db,
|
||||||
self.tag_match, self.sort_by)
|
self.tag_match, self.sort_by)
|
||||||
self.tags_view.tags_marked.connect(self.search.search_from_tags)
|
self.tags_view.tags_marked.connect(self.search.search_from_tags)
|
||||||
self.tags_view.tags_marked.connect(self.saved_search.clear_to_help)
|
self.tags_view.tags_marked.connect(self.saved_search.clear)
|
||||||
self.tags_view.tag_list_edit.connect(self.do_tags_list_edit)
|
self.tags_view.tag_list_edit.connect(self.do_tags_list_edit)
|
||||||
self.tags_view.user_category_edit.connect(self.do_user_categories_edit)
|
self.tags_view.user_category_edit.connect(self.do_user_categories_edit)
|
||||||
self.tags_view.saved_search_edit.connect(self.do_saved_search_edit)
|
self.tags_view.saved_search_edit.connect(self.do_saved_search_edit)
|
||||||
@ -910,14 +910,14 @@ class TagBrowserMixin(object): # {{{
|
|||||||
self.library_view.model().refresh()
|
self.library_view.model().refresh()
|
||||||
self.tags_view.set_new_model()
|
self.tags_view.set_new_model()
|
||||||
self.tags_view.recount()
|
self.tags_view.recount()
|
||||||
self.saved_search.clear_to_help()
|
self.saved_search.clear()
|
||||||
self.search.clear_to_help()
|
self.search.clear()
|
||||||
|
|
||||||
def do_tag_item_renamed(self):
|
def do_tag_item_renamed(self):
|
||||||
# Clean up library view and search
|
# Clean up library view and search
|
||||||
self.library_view.model().refresh()
|
self.library_view.model().refresh()
|
||||||
self.saved_search.clear_to_help()
|
self.saved_search.clear()
|
||||||
self.search.clear_to_help()
|
self.search.clear()
|
||||||
|
|
||||||
def do_author_sort_edit(self, parent, id):
|
def do_author_sort_edit(self, parent, id):
|
||||||
db = self.library_view.model().db
|
db = self.library_view.model().db
|
||||||
|
@ -383,8 +383,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
self.tags_view.set_database(db, self.tag_match, self.sort_by)
|
self.tags_view.set_database(db, self.tag_match, self.sort_by)
|
||||||
self.library_view.model().set_book_on_device_func(self.book_on_device)
|
self.library_view.model().set_book_on_device_func(self.book_on_device)
|
||||||
self.status_bar.clear_message()
|
self.status_bar.clear_message()
|
||||||
self.search.clear_to_help()
|
self.search.clear()
|
||||||
self.saved_search.clear_to_help()
|
self.saved_search.clear()
|
||||||
self.book_details.reset_info()
|
self.book_details.reset_info()
|
||||||
self.library_view.model().count_changed()
|
self.library_view.model().count_changed()
|
||||||
prefs['library_path'] = self.library_path
|
prefs['library_path'] = self.library_path
|
||||||
|
@ -237,9 +237,9 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.connect(self.action_previous_page, SIGNAL('triggered(bool)'),
|
self.connect(self.action_previous_page, SIGNAL('triggered(bool)'),
|
||||||
lambda x:self.view.previous_page())
|
lambda x:self.view.previous_page())
|
||||||
self.connect(self.action_find_next, SIGNAL('triggered(bool)'),
|
self.connect(self.action_find_next, SIGNAL('triggered(bool)'),
|
||||||
lambda x:self.find(self.search.smart_text, repeat=True))
|
lambda x:self.find(unicode(self.search.text()), repeat=True))
|
||||||
self.connect(self.action_find_previous, SIGNAL('triggered(bool)'),
|
self.connect(self.action_find_previous, SIGNAL('triggered(bool)'),
|
||||||
lambda x:self.find(self.search.smart_text,
|
lambda x:self.find(unicode(self.search.text()),
|
||||||
repeat=True, backwards=True))
|
repeat=True, backwards=True))
|
||||||
|
|
||||||
self.connect(self.action_full_screen, SIGNAL('triggered(bool)'),
|
self.connect(self.action_full_screen, SIGNAL('triggered(bool)'),
|
||||||
|
@ -9,7 +9,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import os, copy
|
import os, copy
|
||||||
|
|
||||||
from PyQt4.Qt import QAbstractItemModel, QVariant, Qt, QColor, QFont, QIcon, \
|
from PyQt4.Qt import QAbstractItemModel, QVariant, Qt, QColor, QFont, QIcon, \
|
||||||
QModelIndex, SIGNAL, QMetaObject, pyqtSlot
|
QModelIndex, QMetaObject, pyqtSlot, pyqtSignal
|
||||||
|
|
||||||
from calibre.utils.search_query_parser import SearchQueryParser
|
from calibre.utils.search_query_parser import SearchQueryParser
|
||||||
from calibre.gui2 import NONE
|
from calibre.gui2 import NONE
|
||||||
@ -120,6 +120,7 @@ class NewsItem(NewsTreeItem):
|
|||||||
class RecipeModel(QAbstractItemModel, SearchQueryParser):
|
class RecipeModel(QAbstractItemModel, SearchQueryParser):
|
||||||
|
|
||||||
LOCATIONS = ['all']
|
LOCATIONS = ['all']
|
||||||
|
searched = pyqtSignal(object)
|
||||||
|
|
||||||
def __init__(self, db, *args):
|
def __init__(self, db, *args):
|
||||||
QAbstractItemModel.__init__(self, *args)
|
QAbstractItemModel.__init__(self, *args)
|
||||||
@ -254,14 +255,17 @@ class RecipeModel(QAbstractItemModel, SearchQueryParser):
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
def search(self, query):
|
def search(self, query):
|
||||||
|
results = []
|
||||||
try:
|
try:
|
||||||
results = self.parse(unicode(query))
|
query = unicode(query).strip()
|
||||||
|
if query:
|
||||||
|
results = self.parse(query)
|
||||||
if not results:
|
if not results:
|
||||||
results = None
|
results = None
|
||||||
except ParseException:
|
except ParseException:
|
||||||
results = []
|
results = []
|
||||||
self.do_refresh(restrict_to_urns=results)
|
self.do_refresh(restrict_to_urns=results)
|
||||||
self.emit(SIGNAL('searched(PyQt_PyObject)'), True)
|
self.searched.emit(True)
|
||||||
|
|
||||||
def columnCount(self, parent):
|
def columnCount(self, parent):
|
||||||
return 1
|
return 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user