diff --git a/src/calibre/gui2/actions.py b/src/calibre/gui2/actions.py index 38ba922274..32552dde71 100644 --- a/src/calibre/gui2/actions.py +++ b/src/calibre/gui2/actions.py @@ -480,8 +480,8 @@ class DeleteAction(object): # {{{ return ids = self._get_selected_ids() if not ids: - #For some reason the delete dialog reports no selection, so - #we need to do it here + #_get_selected_ids shows a dialog box if nothing is selected, so we + #do not need to show one here return to_delete = {} some_to_delete = False diff --git a/src/calibre/gui2/dialogs/delete_matching_from_device.py b/src/calibre/gui2/dialogs/delete_matching_from_device.py index 63ee9c4012..dbac2fe4ad 100644 --- a/src/calibre/gui2/dialogs/delete_matching_from_device.py +++ b/src/calibre/gui2/dialogs/delete_matching_from_device.py @@ -3,22 +3,53 @@ __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' __license__ = 'GPL v3' -from PyQt4.Qt import Qt, QDialog, QTableWidgetItem, QAbstractItemView, QIcon +from PyQt4.Qt import Qt, QDialog, QTableWidgetItem, QAbstractItemView -from calibre.ebooks.metadata import authors_to_string -from calibre.gui2.dialogs.delete_matching_from_device_ui import Ui_DeleteMatchingFromDeviceDialog +from calibre import strftime +from calibre.ebooks.metadata import authors_to_string, authors_to_sort_string, \ + title_sort +from calibre.gui2.dialogs.delete_matching_from_device_ui import \ + Ui_DeleteMatchingFromDeviceDialog +from calibre.utils.date import UNDEFINED_DATE class tableItem(QTableWidgetItem): def __init__(self, text): QTableWidgetItem.__init__(self, text) self.setFlags(Qt.ItemIsEnabled) + self.sort = text.lower() def __ge__(self, other): - return unicode(self.text()).lower() >= unicode(other.text()).lower() + return self.sort >= other.sort def __lt__(self, other): - return unicode(self.text()).lower() < unicode(other.text()).lower() + return self.sort < other.sort + +class titleTableItem(tableItem): + + def __init__(self, text): + tableItem.__init__(self, text) + self.sort = title_sort(text.lower()) + +class authorTableItem(tableItem): + + def __init__(self, book): + tableItem.__init__(self, authors_to_string(book.authors)) + if book.author_sort is not None: + self.sort = book.author_sort.lower() + else: + self.sort = authors_to_sort_string(book.authors).lower() + +class dateTableItem(tableItem): + + def __init__(self, date): + if date is not None: + tableItem.__init__(self, strftime('%x', date)) + self.sort = date + else: + tableItem.__init__(self, '') + self.sort = UNDEFINED_DATE + class DeleteMatchingFromDeviceDialog(QDialog, Ui_DeleteMatchingFromDeviceDialog): @@ -27,13 +58,16 @@ class DeleteMatchingFromDeviceDialog(QDialog, Ui_DeleteMatchingFromDeviceDialog) Ui_DeleteMatchingFromDeviceDialog.__init__(self) self.setupUi(self) + self.explanation.setText('

'+_('All checked books will be ' + 'permanently deleted from your ' + 'device. Please verify the list.'+'

')) self.buttonBox.accepted.connect(self.accepted) self.table.cellClicked.connect(self.cell_clicked) self.table.setSelectionMode(QAbstractItemView.NoSelection) self.table.setColumnCount(5) - self.table.setHorizontalHeaderLabels(['', _('Location'), _('Title'), - _('Author'), _('Format')]) - del_icon = QIcon(I('list_remove.svg')) + self.table.setHorizontalHeaderLabels( + ['', _('Location'), _('Title'), + _('Author'), _('Date'), _('Format')]) rows = 0 for card in items: rows += len(items[card][1]) @@ -42,26 +76,34 @@ class DeleteMatchingFromDeviceDialog(QDialog, Ui_DeleteMatchingFromDeviceDialog) for card in items: (model,books) = items[card] for (id,book) in books: - item = QTableWidgetItem(del_icon, '') + item = QTableWidgetItem() + item.setFlags(Qt.ItemIsUserCheckable|Qt.ItemIsEnabled) + item.setCheckState(Qt.Checked) item.setData(Qt.UserRole, (model, id, book.path)) self.table.setItem(row, 0, item) self.table.setItem(row, 1, tableItem(card)) - self.table.setItem(row, 2, tableItem(book.title)) - self.table.setItem(row, 3, tableItem(authors_to_string(book.authors))) - self.table.setItem(row, 4, tableItem(book.path.rpartition('.')[2])) + self.table.setItem(row, 2, titleTableItem(book.title)) + self.table.setItem(row, 3, authorTableItem(book)) + self.table.setItem(row, 4, dateTableItem(book.datetime)) + self.table.setItem(row, 5, tableItem(book.path.rpartition('.')[2])) row += 1 + self.table.setCurrentCell(0, 1) self.table.resizeColumnsToContents() self.table.setSortingEnabled(True) self.table.sortByColumn(2, Qt.AscendingOrder) + self.table.setCurrentCell(0, 1) + + def cell_clicked(self, row, col): + if col == 0: + self.table.setCurrentCell(row, 1) def accepted(self): self.result = [] for row in range(self.table.rowCount()): + if self.table.item(row, 0).checkState() == Qt.Unchecked: + continue (model, id, path) = self.table.item(row, 0).data(Qt.UserRole).toPyObject() path = unicode(path) self.result.append((model, id, path)) return - def cell_clicked(self, row, col): - if col == 0: - self.table.removeRow(row) \ No newline at end of file diff --git a/src/calibre/gui2/dialogs/delete_matching_from_device.ui b/src/calibre/gui2/dialogs/delete_matching_from_device.ui index eabd4d6346..fec08e5b00 100644 --- a/src/calibre/gui2/dialogs/delete_matching_from_device.ui +++ b/src/calibre/gui2/dialogs/delete_matching_from_device.ui @@ -20,6 +20,10 @@ Delete from device + + + + diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py index f34c52d221..33b2f6a940 100644 --- a/src/calibre/gui2/search_box.py +++ b/src/calibre/gui2/search_box.py @@ -18,17 +18,20 @@ from calibre.utils.config import prefs from calibre.utils.search_query_parser import saved_searches class SearchLineEdit(QLineEdit): + key_pressed = pyqtSignal(object) + mouse_released = pyqtSignal(object) + focus_out = pyqtSignal(object) def keyPressEvent(self, event): - self.emit(SIGNAL('key_pressed(PyQt_PyObject)'), event) + self.key_pressed.emit(object) QLineEdit.keyPressEvent(self, event) def mouseReleaseEvent(self, event): - self.emit(SIGNAL('mouse_released(PyQt_PyObject)'), event) + self.mouse_released.emit(event) QLineEdit.mouseReleaseEvent(self, event) def focusOutEvent(self, event): - self.emit(SIGNAL('focus_out(PyQt_PyObject)'), event) + self.focus_out.emit(event) QLineEdit.focusOutEvent(self, event) def dropEvent(self, ev): @@ -68,10 +71,10 @@ class SearchBox2(QComboBox): self.normal_background = 'rgb(255, 255, 255, 0%)' self.line_edit = SearchLineEdit(self) self.setLineEdit(self.line_edit) - self.connect(self.line_edit, SIGNAL('key_pressed(PyQt_PyObject)'), - self.key_pressed, Qt.DirectConnection) - self.connect(self.line_edit, SIGNAL('mouse_released(PyQt_PyObject)'), - self.mouse_released, Qt.DirectConnection) + self.line_edit.key_pressed.connect(self.key_pressed, + type=Qt.DirectConnection) + self.line_edit.mouse_released.connect(self.mouse_released, + type=Qt.DirectConnection) self.setEditable(True) self.help_state = False self.as_you_type = True @@ -90,14 +93,18 @@ class SearchBox2(QComboBox): self.help_text = help_text self.colorize = colorize self.clear_to_help() - self.connect(self, SIGNAL('editTextChanged(QString)'), self.text_edited_slot) def normalize_state(self): - self.setEditText('') - self.line_edit.setStyleSheet( - 'QLineEdit { color: black; background-color: %s; }' % - self.normal_background) - self.help_state = False + if self.help_state: + self.setEditText('') + self.line_edit.setStyleSheet( + 'QLineEdit { color: black; background-color: %s; }' % + 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): if self.help_state: @@ -131,17 +138,15 @@ class SearchBox2(QComboBox): self.line_edit.setStyleSheet('QLineEdit { color: black; background-color: %s; }' % col) def key_pressed(self, event): - if self.help_state: - self.normalize_state() + self.normalize_state() if not self.as_you_type: if event.key() in (Qt.Key_Return, Qt.Key_Enter): self.do_search() + else: + self.timer = self.startTimer(self.__class__.INTERVAL) def mouse_released(self, event): - if self.help_state: - self.normalize_state() - - def text_edited_slot(self, text): + self.normalize_state() if self.as_you_type: self.timer = self.startTimer(self.__class__.INTERVAL) @@ -227,14 +232,13 @@ class SavedSearchBox(QComboBox): self.line_edit = SearchLineEdit(self) self.setLineEdit(self.line_edit) - self.connect(self.line_edit, SIGNAL('key_pressed(PyQt_PyObject)'), - self.key_pressed, Qt.DirectConnection) - self.connect(self.line_edit, SIGNAL('mouse_released(PyQt_PyObject)'), - self.mouse_released, Qt.DirectConnection) - self.connect(self.line_edit, SIGNAL('focus_out(PyQt_PyObject)'), - self.focus_out, Qt.DirectConnection) - self.connect(self, SIGNAL('activated(const QString&)'), - self.saved_search_selected) + self.line_edit.key_pressed.connect(self.key_pressed, + 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) completer = QCompleter(self) # turn off auto-completion self.setCompleter(completer) @@ -282,7 +286,7 @@ class SavedSearchBox(QComboBox): if self.help_state: self.normalize_state() - def saved_search_selected (self, qname): + def saved_search_selected(self, qname): qname = unicode(qname) if qname is None or not qname.strip(): return