From 1468e17c1791b472e2e7a4626e25f3c2fa5517da Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Jan 2011 08:35:46 -0700 Subject: [PATCH 1/7] ... --- src/calibre/gui2/viewer/documentview.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index 13469f5622..55abae0392 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -279,7 +279,7 @@ class Document(QWebPage): # {{{ @pyqtSignature("") def init_hyphenate(self): - if self.hyphenate: + if self.hyphenate and getattr(self, 'loaded_lang', ''): self.javascript('do_hyphenation("%s")'%self.loaded_lang) def after_load(self): From 50dc7b1f09dcd18f2b70c54571ce2b4f2e3bd008 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Jan 2011 09:30:22 -0700 Subject: [PATCH 2/7] Plugin handling cleanups and warning message --- src/calibre/gui2/preferences/plugins.py | 34 +++++++++----- src/calibre/gui2/preferences/plugins.ui | 60 ++----------------------- src/calibre/gui2/ui.py | 10 ++++- 3 files changed, 34 insertions(+), 70 deletions(-) diff --git a/src/calibre/gui2/preferences/plugins.py b/src/calibre/gui2/preferences/plugins.py index 2fe2b3bf01..8b4a221f56 100644 --- a/src/calibre/gui2/preferences/plugins.py +++ b/src/calibre/gui2/preferences/plugins.py @@ -15,7 +15,8 @@ from calibre.gui2.preferences.plugins_ui import Ui_Form from calibre.customize.ui import initialized_plugins, is_disabled, enable_plugin, \ disable_plugin, plugin_customization, add_plugin, \ remove_plugin -from calibre.gui2 import NONE, error_dialog, info_dialog, choose_files +from calibre.gui2 import NONE, error_dialog, info_dialog, choose_files, \ + question_dialog class PluginModel(QAbstractItemModel): # {{{ @@ -132,7 +133,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.toggle_plugin_button.clicked.connect(self.toggle_plugin) self.customize_plugin_button.clicked.connect(self.customize_plugin) self.remove_plugin_button.clicked.connect(self.remove_plugin) - self.button_plugin_browse.clicked.connect(self.find_plugin) self.button_plugin_add.clicked.connect(self.add_plugin) def toggle_plugin(self, *args): @@ -149,23 +149,33 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.modify_plugin(op='remove') def add_plugin(self): - path = unicode(self.plugin_path.text()) - if path and os.access(path, os.R_OK) and path.lower().endswith('.zip'): - add_plugin(path) + path = choose_files(self, 'add a plugin dialog', _('Add plugin'), + filters=[(_('Plugins'), ['zip'])], all_files=False, + select_only_single_file=True) + if not path: + return + path = path[0] + if path and os.access(path, os.R_OK) and path.lower().endswith('.zip'): + if not question_dialog(self, _('Are you sure?'), '

' + \ + _('Installing plugins is a security risk. ' + 'Plugins can contain a virus/malware. ' + 'Only install it if you got it from a trusted source.' + ' Are you sure you want to proceed?'), + show_copy_button=False): + return + plugin = add_plugin(path) self._plugin_model.populate() self._plugin_model.reset() self.changed_signal.emit() - self.plugin_path.setText('') + info_dialog(self, _('Success'), + _('Plugin {0} successfully installed under ' + ' {1} plugins. You may have to restart calibre ' + 'for the plugin to take effect.').format(plugin.name, plugin.type), + show=True) else: error_dialog(self, _('No valid plugin path'), _('%s is not a valid plugin path')%path).exec_() - def find_plugin(self): - path = choose_files(self, 'choose plugin dialog', _('Choose plugin'), - filters=[('Plugins', ['zip'])], all_files=False, - select_only_single_file=True) - if path: - self.plugin_path.setText(path[0]) def modify_plugin(self, op=''): index = self.plugin_view.currentIndex() diff --git a/src/calibre/gui2/preferences/plugins.ui b/src/calibre/gui2/preferences/plugins.ui index 8979867bbc..18f0786a66 100644 --- a/src/calibre/gui2/preferences/plugins.ui +++ b/src/calibre/gui2/preferences/plugins.ui @@ -72,64 +72,10 @@ - - - Add new plugin + + + &Add a new plugin - - - - - - - Plugin &file: - - - plugin_path - - - - - - - - - - ... - - - - :/images/document_open.png:/images/document_open.png - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - &Add - - - - - - diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 7e22839bdf..0732ff4650 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -103,7 +103,15 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ self.gui_debug = gui_debug acmap = OrderedDict() for action in interface_actions(): - ac = action.load_actual_plugin(self) + try: + ac = action.load_actual_plugin(self) + except: + # Ignore errors in loading user supplied plugins + import traceback + traceback.print_exc() + if ac.plugin_path is None: + raise + ac.plugin_path = action.plugin_path ac.interface_action_base_plugin = action if ac.name in acmap: From 61c7b310377ac21fbd5e5497eadaf9277b2aa176 Mon Sep 17 00:00:00 2001 From: Charles Haley <> Date: Tue, 11 Jan 2011 16:41:09 +0000 Subject: [PATCH 3/7] Remove get_metadata cache --- src/calibre/gui2/ui.py | 3 --- src/calibre/library/caches.py | 4 ---- src/calibre/library/database2.py | 14 -------------- src/calibre/library/field_metadata.py | 9 --------- 4 files changed, 30 deletions(-) diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 7e22839bdf..0bdd155cbf 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -582,9 +582,6 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ # Goes here, because if cf is valid, db is valid. db.prefs['field_metadata'] = db.field_metadata.all_metadata() db.commit_dirty_cache() - if DEBUG and db.gm_count > 0: - print 'get_metadata cache: {0:d} calls, {1:4.2f}% misses'.format( - db.gm_count, (db.gm_missed*100.0)/db.gm_count) for action in self.iactions.values(): if not action.shutting_down(): return diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py index 0763318912..6aef45dbbd 100644 --- a/src/calibre/library/caches.py +++ b/src/calibre/library/caches.py @@ -598,7 +598,6 @@ class ResultCache(SearchQueryParser): # {{{ def set(self, row, col, val, row_is_id=False): id = row if row_is_id else self._map_filtered[row] - self._data[id][self.FIELD_MAP['all_metadata']] = None self._data[id][col] = val def get(self, row, col, row_is_id=False): @@ -629,7 +628,6 @@ class ResultCache(SearchQueryParser): # {{{ self._data[id] = CacheRow(db, self.composites, db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]) self._data[id].append(db.book_on_device_string(id)) - self._data[id].append(None) except IndexError: return None try: @@ -646,7 +644,6 @@ class ResultCache(SearchQueryParser): # {{{ self._data[id] = CacheRow(db, self.composites, db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]) self._data[id].append(db.book_on_device_string(id)) - self._data[id].append(None) self._map[0:0] = ids self._map_filtered[0:0] = ids @@ -671,7 +668,6 @@ class ResultCache(SearchQueryParser): # {{{ for item in self._data: if item is not None: item.append(db.book_on_device_string(item[0])) - item.append(None) self._map = [i[0] for i in self._data if i is not None] if field is not None: self.sort(field, ascending) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 138560020e..dc82825607 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -300,8 +300,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.FIELD_MAP['ondevice'] = base+1 self.field_metadata.set_field_record_index('ondevice', base+1, prefer_custom=False) - self.FIELD_MAP['all_metadata'] = base+2 - self.field_metadata.set_field_record_index('all_metadata', base+2, prefer_custom=False) script = ''' DROP VIEW IF EXISTS meta2; @@ -690,19 +688,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): ''' row = self.data._data[idx] if index_is_id else self.data[idx] fm = self.FIELD_MAP - - self.gm_count += 1 - mi = row[self.FIELD_MAP['all_metadata']] - if mi is not None: - if get_cover: - # Always get the cover, because the value can be wrong if the - # original mi was from the OPF - mi.cover = self.cover(idx, index_is_id=index_is_id, as_path=True) - return mi - - self.gm_missed += 1 mi = Metadata(None) - self.data.set(idx, fm['all_metadata'], mi, row_is_id = index_is_id) aut_list = row[fm['au_map']] aut_list = [p.split(':::') for p in aut_list.split(':#:')] diff --git a/src/calibre/library/field_metadata.py b/src/calibre/library/field_metadata.py index 676eb13d2b..2a9b7e7003 100644 --- a/src/calibre/library/field_metadata.py +++ b/src/calibre/library/field_metadata.py @@ -162,15 +162,6 @@ class FieldMetadata(dict): 'search_terms':['tags', 'tag'], 'is_custom':False, 'is_category':True}), - ('all_metadata',{'table':None, - 'column':None, - 'datatype':None, - 'is_multiple':None, - 'kind':'field', - 'name':None, - 'search_terms':[], - 'is_custom':False, - 'is_category':False}), ('author_sort',{'table':None, 'column':None, 'datatype':'text', From f7ae68a8c97aa5448f7dbacc575582c1fbcb7030 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Jan 2011 09:55:36 -0700 Subject: [PATCH 4/7] After adding plugin scroll to it in the plugins list --- src/calibre/gui2/__init__.py | 6 +++++- src/calibre/gui2/preferences/plugins.py | 21 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index df6ac45e5b..e699551150 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -269,10 +269,14 @@ def question_dialog(parent, title, msg, det_msg='', show_copy_button=True, return d.exec_() == yes_button -def info_dialog(parent, title, msg, det_msg='', show=False): +def info_dialog(parent, title, msg, det_msg='', show=False, + show_copy_button=True): d = MessageBox(QMessageBox.Information, title, msg, QMessageBox.Ok, parent, det_msg) d.setIconPixmap(QPixmap(I('dialog_information.png'))) + if not show_copy_button: + d.cb.setVisible(False) + if show: return d.exec_() return d diff --git a/src/calibre/gui2/preferences/plugins.py b/src/calibre/gui2/preferences/plugins.py index 8b4a221f56..c53c634ab4 100644 --- a/src/calibre/gui2/preferences/plugins.py +++ b/src/calibre/gui2/preferences/plugins.py @@ -77,6 +77,16 @@ class PluginModel(QAbstractItemModel): # {{{ return self.index(j, 0, parent) return QModelIndex() + def plugin_to_index_by_properties(self, plugin): + for i, category in enumerate(self.categories): + parent = self.index(i, 0, QModelIndex()) + for j, p in enumerate(self._data[category]): + if plugin.name == p.name and plugin.type == p.type and \ + plugin.author == p.author and plugin.version == p.version: + return self.index(j, 0, parent) + return QModelIndex() + + def refresh_plugin(self, plugin, rescan=False): if rescan: self.populate() @@ -171,7 +181,13 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): _('Plugin {0} successfully installed under ' ' {1} plugins. You may have to restart calibre ' 'for the plugin to take effect.').format(plugin.name, plugin.type), - show=True) + show=True, show_copy_button=False) + idx = self._plugin_model.plugin_to_index_by_properties(plugin) + if idx.isValid(): + self.plugin_view.scrollTo(idx, + self.plugin_view.PositionAtCenter) + self.plugin_view.scrollTo(idx, + self.plugin_view.PositionAtCenter) else: error_dialog(self, _('No valid plugin path'), _('%s is not a valid plugin path')%path).exec_() @@ -201,10 +217,13 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): if plugin.do_user_config(): self._plugin_model.refresh_plugin(plugin) elif op == 'remove': + msg = _('Plugin {0} successfully removed').format(plugin.name) if remove_plugin(plugin): self._plugin_model.populate() self._plugin_model.reset() self.changed_signal.emit() + info_dialog(self, _('Success'), msg, show=True, + show_copy_button=False) else: error_dialog(self, _('Cannot remove builtin plugin'), plugin.name + _(' cannot be removed. It is a ' From 2ea905dffd76f31f860962982a76ca997d219745 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Jan 2011 10:38:10 -0700 Subject: [PATCH 5/7] Fix bug that caused automatic news removal to remove any book that has a tag that contains the word 'news' instead of only books that have the tag News --- src/calibre/library/database2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 3b06064226..6ab003f2d5 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1373,7 +1373,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): if r is not None: if (now - r[self.FIELD_MAP['timestamp']]) > delta: tags = r[self.FIELD_MAP['tags']] - if tags and tag in tags.lower(): + if tags and tag in tags.lower().split(','): yield r[self.FIELD_MAP['id']] def get_next_series_num_for(self, series): From efda0e0275f2f3127a53dc619994dceba70dcc9d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Jan 2011 10:55:03 -0700 Subject: [PATCH 6/7] ... --- src/calibre/library/database2.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 6ab003f2d5..aa491aff28 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1373,7 +1373,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): if r is not None: if (now - r[self.FIELD_MAP['timestamp']]) > delta: tags = r[self.FIELD_MAP['tags']] - if tags and tag in tags.lower().split(','): + if tags and tag in [x.strip() for x in + tags.lower().split(',')]: yield r[self.FIELD_MAP['id']] def get_next_series_num_for(self, series): From 9eb8b031d97e6432683952c3e7bdcdd2a8117b97 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Jan 2011 11:14:19 -0700 Subject: [PATCH 7/7] Code to put downloaded news into the magazines category on the nook color. Commented out, pending testing --- src/calibre/devices/nook/driver.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/calibre/devices/nook/driver.py b/src/calibre/devices/nook/driver.py index 987b90c748..ca05885645 100644 --- a/src/calibre/devices/nook/driver.py +++ b/src/calibre/devices/nook/driver.py @@ -91,3 +91,19 @@ class NOOK_COLOR(NOOK): EBOOK_DIR_MAIN = 'My Files/Books' + ''' + def create_upload_path(self, path, mdata, fname, create_dirs=True): + filepath = NOOK.create_upload_path(self, path, mdata, fname, + create_dirs=create_dirs) + edm = self.EBOOK_DIR_MAIN.replace('/', os.sep) + npath = os.path.join(edm, _('News')) + os.sep + if npath in filepath: + filepath = filepath.replace(npath, os.sep.join('My Files', + 'Magazines')+os.sep) + filedir = os.path.dirname(filepath) + if create_dirs and not os.path.exists(filedir): + os.makedirs(filedir) + + return filepath + ''' +