From 6eef57563cfe8717c5524d3f38f8e77007cdeccd Mon Sep 17 00:00:00 2001 From: GRiker Date: Sun, 23 Jan 2011 06:46:39 -0700 Subject: [PATCH 1/7] GwR patch mapping ESC to clear search box --- src/calibre/gui2/search_box.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py index e4073a01c9..99d435c913 100644 --- a/src/calibre/gui2/search_box.py +++ b/src/calibre/gui2/search_box.py @@ -76,7 +76,10 @@ class SearchBox2(QComboBox): # {{{ c.setCompletionMode(c.PopupCompletion) c.highlighted[QString].connect(self.completer_used) c.activated[QString].connect(self.history_selected) - + self.esc_action = QAction(self) + self.addAction(self.esc_action) + self.esc_action.setShortcut(QKeySequence(Qt.Key_Escape)) + self.esc_action.triggered.connect(self.esc) self.line_edit.key_pressed.connect(self.key_pressed, type=Qt.DirectConnection) self.activated.connect(self.history_selected) self.setEditable(True) @@ -91,6 +94,9 @@ class SearchBox2(QComboBox): # {{{ self._in_a_search = False self.tool_tip_text = self.toolTip() + def esc(self, *args): + self.clear() + def initialize(self, opt_name, colorize=False, help_text=_('Search')): self.as_you_type = config['search_as_you_type'] self.opt_name = opt_name From 323ddfe8fd4542e4362097ae1778b7487861188e Mon Sep 17 00:00:00 2001 From: John Schember Date: Sun, 23 Jan 2011 09:53:15 -0500 Subject: [PATCH 2/7] RgexBuilder: Addb back return when user declines to select a format. --- src/calibre/gui2/convert/regex_builder.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/calibre/gui2/convert/regex_builder.py b/src/calibre/gui2/convert/regex_builder.py index bdcbe3356d..bdd219d733 100644 --- a/src/calibre/gui2/convert/regex_builder.py +++ b/src/calibre/gui2/convert/regex_builder.py @@ -166,6 +166,8 @@ class RegexEdit(QWidget, Ui_Edit): def builder(self): bld = RegexBuilder(self.db, self.book_id, self.edit.text(), self) + if bld.cancelled: + return if bld.exec_() == bld.Accepted: self.edit.setText(bld.regex.text()) From b5a4e263e86f13aa728816af1e772b3688c74f1d Mon Sep 17 00:00:00 2001 From: John Schember Date: Sun, 23 Jan 2011 12:51:08 -0500 Subject: [PATCH 3/7] Implement ticket #7834: Enhance Send Specific Formats dialog to better display existing formats. --- src/calibre/gui2/device.py | 20 +++- .../gui2/dialogs/choose_format_device.py | 53 +++++++++ .../gui2/dialogs/choose_format_device.ui | 111 ++++++++++++++++++ 3 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 src/calibre/gui2/dialogs/choose_format_device.py create mode 100644 src/calibre/gui2/dialogs/choose_format_device.ui diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 28b5e178ac..8a0a368cd3 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -13,7 +13,7 @@ from calibre.customize.ui import available_input_formats, available_output_forma device_plugins from calibre.devices.interface import DevicePlugin from calibre.devices.errors import UserFeedback, OpenFeedback -from calibre.gui2.dialogs.choose_format import ChooseFormatDialog +from calibre.gui2.dialogs.choose_format_device import ChooseFormatDeviceDialog from calibre.utils.ipc.job import BaseJob from calibre.devices.scanner import DeviceScanner from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \ @@ -826,8 +826,22 @@ class DeviceMixin(object): # {{{ fmt = None if specific: - d = ChooseFormatDialog(self, _('Choose format to send to device'), - self.device_manager.device.settings().format_map) + formats = [] + aval_out_formats = available_output_formats() + format_count = {} + for row in rows: + for f in self.library_view.model().db.formats(row.row()).split(','): + f = f.lower() + if format_count.has_key(f): + format_count[f] += 1 + else: + format_count[f] = 1 + for f in self.device_manager.device.settings().format_map: + if f in format_count.keys(): + formats.append((f, _('%i of %i Books' % (format_count[f], len(rows))), True if f in aval_out_formats else False)) + elif f in aval_out_formats: + formats.append((f, _('0 of %i Books' % len(rows)), True)) + d = ChooseFormatDeviceDialog(self, _('Choose format to send to device'), formats) if d.exec_() != QDialog.Accepted: return if d.format(): diff --git a/src/calibre/gui2/dialogs/choose_format_device.py b/src/calibre/gui2/dialogs/choose_format_device.py new file mode 100644 index 0000000000..fde00bb70a --- /dev/null +++ b/src/calibre/gui2/dialogs/choose_format_device.py @@ -0,0 +1,53 @@ +__license__ = 'GPL v3' +__copyright__ = '2011, John Schember ' + +from PyQt4.Qt import QDialog, QTreeWidgetItem, QIcon, SIGNAL + +from calibre.gui2 import file_icon_provider +from calibre.gui2.dialogs.choose_format_device_ui import Ui_ChooseFormatDeviceDialog + +class ChooseFormatDeviceDialog(QDialog, Ui_ChooseFormatDeviceDialog): + + def __init__(self, window, msg, formats): + ''' + formats is a list of tuples: [(format, exists, convertable)]. + format: Lower case format identifier. E.G. mobi + exists: String representing the number of books that + exist in the format. + convertable: True if the format is a convertable format. + formats should be ordered in the device's preferred format ordering. + ''' + QDialog.__init__(self, window) + Ui_ChooseFormatDeviceDialog.__init__(self) + self.setupUi(self) + self.connect(self.formats, SIGNAL('activated(QModelIndex)'), + self.activated_slot) + + self.msg.setText(msg) + for i, (format, exists, convertable) in enumerate(formats): + t_item = QTreeWidgetItem() + t_item.setIcon(0, file_icon_provider().icon_from_ext(format.lower())) + t_item.setText(0, format.upper()) + t_item.setText(1, exists) + if convertable: + t_item.setIcon(2, QIcon(I('ok.png'))) + self.formats.addTopLevelItem(t_item) + if i == 0: + self.formats.setCurrentItem(t_item) + t_item.setSelected(True) + self.formats.resizeColumnToContents(2) + self.formats.resizeColumnToContents(1) + self.formats.resizeColumnToContents(0) + self.formats.header().resizeSection(0, self.formats.header().sectionSize(0) * 2) + self._format = None + + def activated_slot(self, *args): + self.accept() + + def format(self): + return self._format + + def accept(self): + self._format = unicode(self.formats.currentItem().text(0)) + return QDialog.accept(self) + diff --git a/src/calibre/gui2/dialogs/choose_format_device.ui b/src/calibre/gui2/dialogs/choose_format_device.ui new file mode 100644 index 0000000000..c52a728d16 --- /dev/null +++ b/src/calibre/gui2/dialogs/choose_format_device.ui @@ -0,0 +1,111 @@ + + + ChooseFormatDeviceDialog + + + + 0 + 0 + 507 + 377 + + + + Choose Format + + + + :/images/mimetypes/unknown.png:/images/mimetypes/unknown.png + + + + + + TextLabel + + + + + + + true + + + + 64 + 64 + + + + true + + + + Format + + + + + Existing + + + AlignLeft|AlignVCenter + + + + + Convertable + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + ChooseFormatDeviceDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ChooseFormatDeviceDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + From 4cefbf0aa80280e323bad0b56a07e9300d5086af Mon Sep 17 00:00:00 2001 From: John Schember Date: Sun, 23 Jan 2011 12:53:41 -0500 Subject: [PATCH 4/7] Fix spelling error. --- src/calibre/gui2/dialogs/choose_format_device.py | 6 +++--- src/calibre/gui2/dialogs/choose_format_device.ui | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/calibre/gui2/dialogs/choose_format_device.py b/src/calibre/gui2/dialogs/choose_format_device.py index fde00bb70a..d51040ef44 100644 --- a/src/calibre/gui2/dialogs/choose_format_device.py +++ b/src/calibre/gui2/dialogs/choose_format_device.py @@ -10,11 +10,11 @@ class ChooseFormatDeviceDialog(QDialog, Ui_ChooseFormatDeviceDialog): def __init__(self, window, msg, formats): ''' - formats is a list of tuples: [(format, exists, convertable)]. + formats is a list of tuples: [(format, exists, convertible)]. format: Lower case format identifier. E.G. mobi exists: String representing the number of books that exist in the format. - convertable: True if the format is a convertable format. + convertible: True if the format is a convertible format. formats should be ordered in the device's preferred format ordering. ''' QDialog.__init__(self, window) @@ -29,7 +29,7 @@ class ChooseFormatDeviceDialog(QDialog, Ui_ChooseFormatDeviceDialog): t_item.setIcon(0, file_icon_provider().icon_from_ext(format.lower())) t_item.setText(0, format.upper()) t_item.setText(1, exists) - if convertable: + if convertible: t_item.setIcon(2, QIcon(I('ok.png'))) self.formats.addTopLevelItem(t_item) if i == 0: diff --git a/src/calibre/gui2/dialogs/choose_format_device.ui b/src/calibre/gui2/dialogs/choose_format_device.ui index c52a728d16..d527296144 100644 --- a/src/calibre/gui2/dialogs/choose_format_device.ui +++ b/src/calibre/gui2/dialogs/choose_format_device.ui @@ -54,7 +54,7 @@ - Convertable + Convertible From 199895ac7570b12bb71be56026cfc88e04d7c20e Mon Sep 17 00:00:00 2001 From: John Schember Date: Sun, 23 Jan 2011 12:54:08 -0500 Subject: [PATCH 5/7] ... --- src/calibre/gui2/dialogs/choose_format_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/gui2/dialogs/choose_format_device.py b/src/calibre/gui2/dialogs/choose_format_device.py index d51040ef44..f5e0761e4f 100644 --- a/src/calibre/gui2/dialogs/choose_format_device.py +++ b/src/calibre/gui2/dialogs/choose_format_device.py @@ -24,7 +24,7 @@ class ChooseFormatDeviceDialog(QDialog, Ui_ChooseFormatDeviceDialog): self.activated_slot) self.msg.setText(msg) - for i, (format, exists, convertable) in enumerate(formats): + for i, (format, exists, convertible) in enumerate(formats): t_item = QTreeWidgetItem() t_item.setIcon(0, file_icon_provider().icon_from_ext(format.lower())) t_item.setText(0, format.upper()) From 2be9281390cb693b4c9a5506801f216c82117938 Mon Sep 17 00:00:00 2001 From: GRiker Date: Sun, 23 Jan 2011 11:39:26 -0700 Subject: [PATCH 6/7] GwR 2nd patch mapping ESC to SearchBox2.clear() --- src/calibre/gui2/search_box.py | 8 +------- src/calibre/gui2/ui.py | 9 +++++++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py index 99d435c913..e4073a01c9 100644 --- a/src/calibre/gui2/search_box.py +++ b/src/calibre/gui2/search_box.py @@ -76,10 +76,7 @@ class SearchBox2(QComboBox): # {{{ c.setCompletionMode(c.PopupCompletion) c.highlighted[QString].connect(self.completer_used) c.activated[QString].connect(self.history_selected) - self.esc_action = QAction(self) - self.addAction(self.esc_action) - self.esc_action.setShortcut(QKeySequence(Qt.Key_Escape)) - self.esc_action.triggered.connect(self.esc) + self.line_edit.key_pressed.connect(self.key_pressed, type=Qt.DirectConnection) self.activated.connect(self.history_selected) self.setEditable(True) @@ -94,9 +91,6 @@ class SearchBox2(QComboBox): # {{{ self._in_a_search = False self.tool_tip_text = self.toolTip() - def esc(self, *args): - self.clear() - def initialize(self, opt_name, colorize=False, help_text=_('Search')): self.as_you_type = config['search_as_you_type'] self.opt_name = opt_name diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index b33c059c9b..6a74ccd6ea 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -16,7 +16,7 @@ from PyQt4.Qt import Qt, SIGNAL, QTimer, \ QPixmap, QMenu, QIcon, pyqtSignal, \ QDialog, \ QSystemTrayIcon, QApplication, QKeySequence, \ - QMessageBox, QHelpEvent + QMessageBox, QHelpEvent, QAction from calibre import prints from calibre.constants import __appname__, isosx @@ -198,6 +198,10 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ self.system_tray_icon.activated.connect( self.system_tray_icon_activated) + self.esc_action = QAction(self) + self.addAction(self.esc_action) + self.esc_action.setShortcut(QKeySequence(Qt.Key_Escape)) + self.esc_action.triggered.connect(self.esc) ####################### Start spare job server ######################## QTimer.singleShot(1000, self.add_spare_server) @@ -294,6 +298,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ 'the file: %s

The ' 'log will be displayed automatically.')%self.gui_debug, show=True) + def esc(self, *args): + self.search.clear() def start_content_server(self): from calibre.library.server.main import start_threaded_server @@ -305,7 +311,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ self.content_server.state_callback(True) self.test_server_timer = QTimer.singleShot(10000, self.test_server) - def resizeEvent(self, ev): MainWindow.resizeEvent(self, ev) self.search.setMaximumWidth(self.width()-150) From f95cc7eddc02153cc280e7f93dab695b388e7a86 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 23 Jan 2011 16:58:57 -0700 Subject: [PATCH 7/7] Heuristics, italicize common cases: Enhance pattern matching to match punctuation after pattern. --- src/calibre/ebooks/conversion/utils.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/calibre/ebooks/conversion/utils.py b/src/calibre/ebooks/conversion/utils.py index aabb1b8bc4..ad7f5f117d 100644 --- a/src/calibre/ebooks/conversion/utils.py +++ b/src/calibre/ebooks/conversion/utils.py @@ -137,17 +137,17 @@ class HeuristicProcessor(object): ] ITALICIZE_STYLE_PATS = [ - r'(?msu)(?<=\s)_(?P\S[^_]{0,40}?\S)?_(?=\s)', - r'(?msu)(?<=\s)/(?P\S[^/]{0,40}?\S)?/(?=\s)', - r'(?msu)(?<=\s)~~(?P\S[^~]{0,40}?\S)?~~(?=\s)', - r'(?msu)(?<=\s)\*(?P\S[^\*]{0,40}?\S)?\*(?=\s)', - r'(?msu)(?<=\s)~(?P\S[^~]{0,40}?\S)?~(?=\s)', - r'(?msu)(?<=\s)_/(?P\S[^/_]{0,40}?\S)?/_(?=\s)', - r'(?msu)(?<=\s)_\*(?P\S[^\*_]{0,40}?\S)?\*_(?=\s)', - r'(?msu)(?<=\s)\*/(?P\S[^/\*]{0,40}?\S)?/\*(?=\s)', - r'(?msu)(?<=\s)_\*/(?P\S[^\*_]{0,40}?\S)?/\*_(?=\s)', - r'(?msu)(?<=\s)/:(?P\S[^:/]{0,40}?\S)?:/(?=\s)', - r'(?msu)(?<=\s)\|:(?P\S[^:\|]{0,40}?\S)?:\|(?=\s)', + r'(?msu)(?<=\s)_(?P\S[^_]{0,40}?\S)?_(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)/(?P\S[^/]{0,40}?\S)?/(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)~~(?P\S[^~]{0,40}?\S)?~~(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)\*(?P\S[^\*]{0,40}?\S)?\*(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)~(?P\S[^~]{0,40}?\S)?~(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)_/(?P\S[^/_]{0,40}?\S)?/_(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)_\*(?P\S[^\*_]{0,40}?\S)?\*_(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)\*/(?P\S[^/\*]{0,40}?\S)?/\*(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)_\*/(?P\S[^\*_]{0,40}?\S)?/\*_(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)/:(?P\S[^:/]{0,40}?\S)?:/(?=[\s\.,\!\?])', + r'(?msu)(?<=\s)\|:(?P\S[^:\|]{0,40}?\S)?:\|(?=[\s\.,\!\?])', ] for word in ITALICIZE_WORDS: