From f2848014f3ba98798042ec6b39be618027671343 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Jun 2011 10:33:33 -0600 Subject: [PATCH 1/5] Change title of plugin updater dialog --- src/calibre/gui2/dialogs/plugin_updater.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/calibre/gui2/dialogs/plugin_updater.py b/src/calibre/gui2/dialogs/plugin_updater.py index 3656d908da..b1413c8179 100644 --- a/src/calibre/gui2/dialogs/plugin_updater.py +++ b/src/calibre/gui2/dialogs/plugin_updater.py @@ -477,10 +477,12 @@ class PluginUpdaterDialog(SizePersistedDialog): self.resize_dialog() def _initialize_controls(self): - self.setWindowTitle(_('Check for user plugin updates')) + self.setWindowTitle(_('User plugins')) + self.setWindowIcon(QIcon(I('plugins/plugin_updater.png'))) layout = QVBoxLayout(self) self.setLayout(layout) - title_layout = ImageTitleLayout(self, 'plugins/plugin_updater.png', _('User Plugin Status')) + title_layout = ImageTitleLayout(self, 'plugins/plugin_updater.png', + _('User Plugins')) layout.addLayout(title_layout) header_layout = QHBoxLayout() From d2d53c59614d354dfcd78f6e8f03ecd2a09047ca Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Jun 2011 10:36:05 -0600 Subject: [PATCH 2/5] ... --- src/calibre/gui2/dialogs/plugin_updater.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/calibre/gui2/dialogs/plugin_updater.py b/src/calibre/gui2/dialogs/plugin_updater.py index b1413c8179..42e2258ea9 100644 --- a/src/calibre/gui2/dialogs/plugin_updater.py +++ b/src/calibre/gui2/dialogs/plugin_updater.py @@ -14,7 +14,6 @@ from PyQt4.Qt import (Qt, QUrl, QFrame, QVBoxLayout, QLabel, QBrush, QTextEdit, QAbstractTableModel, QVariant, QTableView, QModelIndex, QSortFilterProxyModel, pyqtSignal, QAction, QIcon, QDialog, QFont, QPixmap, QSize) -from PyQt4 import QtCore from calibre import browser, prints from calibre.constants import numeric_version, iswindows, isosx, DEBUG from calibre.customize.ui import (initialized_plugins, is_disabled, remove_plugin, @@ -500,7 +499,7 @@ class PluginUpdaterDialog(SizePersistedDialog): self.plugin_view.setSelectionMode(QAbstractItemView.SingleSelection) self.plugin_view.setAlternatingRowColors(True) self.plugin_view.setSortingEnabled(True) - self.plugin_view.setIconSize(QtCore.QSize(28, 28)) + self.plugin_view.setIconSize(QSize(28, 28)) layout.addWidget(self.plugin_view) details_layout = QHBoxLayout() From d24bd6e57c1c12bb17d771149683ee4fd6f75280 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Jun 2011 12:09:35 -0600 Subject: [PATCH 3/5] When checking for updated plugins do not connect to the plugin index if no external plugins are installed --- src/calibre/customize/ui.py | 2 ++ src/calibre/gui2/dialogs/plugin_updater.py | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/calibre/customize/ui.py b/src/calibre/customize/ui.py index 24b720ec3e..e259400ec9 100644 --- a/src/calibre/customize/ui.py +++ b/src/calibre/customize/ui.py @@ -493,6 +493,8 @@ def initialize_plugin(plugin, path_to_zip_file): raise InvalidPlugin((_('Initialization of plugin %s failed with traceback:') %tb) + '\n'+tb) +def has_external_plugins(): + return bool(config['plugins']) def initialize_plugins(): global _initialized_plugins diff --git a/src/calibre/gui2/dialogs/plugin_updater.py b/src/calibre/gui2/dialogs/plugin_updater.py index 42e2258ea9..855dbd148a 100644 --- a/src/calibre/gui2/dialogs/plugin_updater.py +++ b/src/calibre/gui2/dialogs/plugin_updater.py @@ -17,7 +17,8 @@ from PyQt4.Qt import (Qt, QUrl, QFrame, QVBoxLayout, QLabel, QBrush, QTextEdit, from calibre import browser, prints from calibre.constants import numeric_version, iswindows, isosx, DEBUG from calibre.customize.ui import (initialized_plugins, is_disabled, remove_plugin, - add_plugin, enable_plugin, disable_plugin, NameConflict) + add_plugin, enable_plugin, disable_plugin, + NameConflict, has_external_plugins) from calibre.gui2 import error_dialog, question_dialog, info_dialog, NONE, open_url, gprefs from calibre.gui2.preferences.plugins import ConfigWidget from calibre.utils.date import UNDEFINED_DATE, format_date @@ -38,6 +39,8 @@ def get_plugin_updates_available(): Returns None if no updates found Returns list(DisplayPlugin) of plugins installed that have a new version ''' + if not has_external_plugins(): + return None display_plugins = read_available_plugins() if display_plugins: update_plugins = filter(filter_upgradeable_plugins, display_plugins) From f4e5714391a2a3e3f1cd785bf2ec86e375362398 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Jun 2011 13:08:13 -0600 Subject: [PATCH 4/5] Portable build: set a env var --- setup/installer/windows/portable.c | 5 +++++ src/calibre/constants.py | 1 + 2 files changed, 6 insertions(+) diff --git a/setup/installer/windows/portable.c b/setup/installer/windows/portable.c index 2a557e9174..05763bc303 100644 --- a/setup/installer/windows/portable.c +++ b/setup/installer/windows/portable.c @@ -95,6 +95,11 @@ void launch_calibre(LPCTSTR exe, LPCTSTR config_dir, LPCTSTR library_dir) { ExitProcess(1); } + if (! SetEnvironmentVariable(TEXT("CALIBRE_PORTABLE_BUILD"), exe)) { + show_last_error(TEXT("Failed to set environment variables")); + ExitProcess(1); + } + dwFlags = CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_PROCESS_GROUP; _sntprintf_s(cmdline, BUFSIZE, _TRUNCATE, TEXT(" \"--with-library=%s\""), library_dir); diff --git a/src/calibre/constants.py b/src/calibre/constants.py index f6b0a8d802..627f1b751a 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -32,6 +32,7 @@ isbsd = isfreebsd or isnetbsd islinux = not(iswindows or isosx or isbsd) isfrozen = hasattr(sys, 'frozen') isunix = isosx or islinux +isportable = os.environ.get('CALIBRE_PORTABLE_BUILD', None) is not None try: preferred_encoding = locale.getpreferredencoding() From 230cfe0877ed5f382aa68ec9d9a090295c85bfde Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Jun 2011 13:17:11 -0600 Subject: [PATCH 5/5] Updated plugin notifications --- src/calibre/gui2/init.py | 16 +---- src/calibre/gui2/update.py | 124 +++++++++++++++++++++++++++---------- 2 files changed, 93 insertions(+), 47 deletions(-) diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index a75ff01b21..874be6832f 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -27,7 +27,6 @@ def partial(*args, **kwargs): _keep_refs.append(ans) return ans - class LibraryViewMixin(object): # {{{ def __init__(self, db): @@ -145,6 +144,7 @@ class UpdateLabel(QLabel): # {{{ def __init__(self, *args, **kwargs): QLabel.__init__(self, *args, **kwargs) + self.setCursor(Qt.PointingHandCursor) def contextMenuEvent(self, e): pass @@ -182,14 +182,6 @@ class StatusBar(QStatusBar): # {{{ self.defmsg.setText(self.default_message) self.clearMessage() - def new_version_available(self, ver, url): - msg = (u'%s: %s') % ( - _('Update found'), ver, ver) - self.update_label.setText(msg) - self.update_label.setCursor(Qt.PointingHandCursor) - self.update_label.setVisible(True) - def get_version(self): dv = os.environ.get('CALIBRE_DEVELOP_FROM', None) v = __version__ @@ -257,12 +249,6 @@ class LayoutMixin(object): # {{{ self.setStatusBar(self.status_bar) self.status_bar.update_label.linkActivated.connect(self.update_link_clicked) - def update_link_clicked(self, url): - url = unicode(url) - if url.startswith('update:'): - version = url.partition(':')[-1] - self.update_found(version, force=True) - def finalize_layout(self): self.status_bar.initialize(self.system_tray_icon) self.book_details.show_book_info.connect(self.iactions['Show Book Details'].show_book_info) diff --git a/src/calibre/gui2/update.py b/src/calibre/gui2/update.py index 80d807c82b..ed159f4778 100644 --- a/src/calibre/gui2/update.py +++ b/src/calibre/gui2/update.py @@ -3,22 +3,34 @@ __copyright__ = '2008, Kovid Goyal ' import traceback -from PyQt4.Qt import QThread, pyqtSignal, Qt, QUrl, QDialog, QGridLayout, \ - QLabel, QCheckBox, QDialogButtonBox, QIcon, QPixmap +from PyQt4.Qt import (QThread, pyqtSignal, Qt, QUrl, QDialog, QGridLayout, + QLabel, QCheckBox, QDialogButtonBox, QIcon, QPixmap) import mechanize -from calibre.constants import __appname__, __version__, iswindows, isosx +from calibre.constants import (__appname__, __version__, iswindows, isosx, + isportable) from calibre import browser from calibre.utils.config import prefs from calibre.gui2 import config, dynamic, open_url from calibre.gui2.dialogs.plugin_updater import get_plugin_updates_available URL = 'http://status.calibre-ebook.com/latest' +NO_CALIBRE_UPDATE = '-0.0.0' +VSEP = '|' + +def get_newest_version(): + br = browser() + req = mechanize.Request(URL) + req.add_header('CALIBRE_VERSION', __version__) + req.add_header('CALIBRE_OS', + 'win' if iswindows else 'osx' if isosx else 'oth') + req.add_header('CALIBRE_INSTALL_UUID', prefs['installation_uuid']) + version = br.open(req).read().strip() + return version class CheckForUpdates(QThread): update_found = pyqtSignal(object) - plugin_update_found = pyqtSignal(object) INTERVAL = 24*60*60 def __init__(self, parent): @@ -26,29 +38,29 @@ class CheckForUpdates(QThread): def run(self): while True: + calibre_update_version = NO_CALIBRE_UPDATE + plugins_update_found = 0 try: - br = browser() - req = mechanize.Request(URL) - req.add_header('CALIBRE_VERSION', __version__) - req.add_header('CALIBRE_OS', - 'win' if iswindows else 'osx' if isosx else 'oth') - req.add_header('CALIBRE_INSTALL_UUID', prefs['installation_uuid']) - version = br.open(req).read().strip() + version = get_newest_version() if version and version != __version__ and len(version) < 10: - self.update_found.emit(version) + calibre_update_version = version except: traceback.print_exc() try: update_plugins = get_plugin_updates_available() - if update_plugins: - self.plugin_update_found.emit(update_plugins) + if update_plugins is not None: + plugins_update_found = len(update_plugins) except: traceback.print_exc() + if (calibre_update_version != NO_CALIBRE_UPDATE or + plugins_update_found > 0): + self.update_found.emit('%s%s%d'%(calibre_update_version, + VSEP, plugins_update_found)) self.sleep(self.INTERVAL) class UpdateNotification(QDialog): - def __init__(self, version, parent=None): + def __init__(self, calibre_version, plugin_updates, parent=None): QDialog.__init__(self, parent) self.resize(400, 250) self.l = QGridLayout() @@ -62,7 +74,8 @@ class UpdateNotification(QDialog): 'See the new features.') + '

'+_('Update only if one of the ' 'new features or bug fixes is important to you. ' - 'If the current version works well for you, do not update.'))%(__appname__, version)) + 'If the current version works well for you, do not update.'))%( + __appname__, calibre_version)) self.label.setOpenExternalLinks(True) self.label.setWordWrap(True) self.setWindowTitle(_('Update available!')) @@ -78,18 +91,30 @@ class UpdateNotification(QDialog): b = self.bb.addButton(_('&Get update'), self.bb.AcceptRole) b.setDefault(True) b.setIcon(QIcon(I('arrow-down.png'))) + if plugin_updates > 0: + b = self.bb.addButton(_('Update &plugins'), self.bb.ActionRole) + b.setIcon(QIcon(I('plugins/plugin_updater.png'))) + b.clicked.connect(self.get_plugins, type=Qt.QueuedConnection) self.bb.addButton(self.bb.Cancel) self.l.addWidget(self.bb, 2, 0, 1, -1) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) - dynamic.set('update to version %s'%version, False) + dynamic.set('update to version %s'%calibre_version, False) + + def get_plugins(self): + from calibre.gui2.dialogs.plugin_updater import (PluginUpdaterDialog, + FILTER_UPDATE_AVAILABLE) + d = PluginUpdaterDialog(self.parent(), + initial_filter=FILTER_UPDATE_AVAILABLE) + d.exec_() def show_future(self, *args): config.set('new_version_notification', bool(self.cb.isChecked())) def accept(self): - url = 'http://calibre-ebook.com/download_'+\ - ('windows' if iswindows else 'osx' if isosx else 'linux') + url = ('http://calibre-ebook.com/download_' + + ('portable' if isportable else 'windows' if iswindows + else 'osx' if isosx else 'linux')) open_url(QUrl(url)) QDialog.accept(self) @@ -101,33 +126,68 @@ class UpdateMixin(object): self.update_checker = CheckForUpdates(self) self.update_checker.update_found.connect(self.update_found, type=Qt.QueuedConnection) - self.update_checker.plugin_update_found.connect(self.plugin_update_found, - type=Qt.QueuedConnection) self.update_checker.start() def update_found(self, version, force=False): - os = 'windows' if iswindows else 'osx' if isosx else 'linux' - url = 'http://calibre-ebook.com/download_%s'%os - self.status_bar.new_version_available(version, url) + try: + calibre_version, plugin_updates = version.split(VSEP) + plugin_updates = int(plugin_updates) + except: + traceback.print_exc() + return + has_calibre_update = calibre_version and calibre_version != NO_CALIBRE_UPDATE + has_plugin_updates = plugin_updates > 0 + if not has_calibre_update and not has_plugin_updates: + self.status_bar.update_label.setVisible(False) + return + if has_calibre_update: + plt = u'' + if has_plugin_updates: + plt = ' (%d plugin updates)'%plugin_updates + msg = (u'%s: ' + u'%s%s') % ( + _('Update found'), version, calibre_version, plt) + else: + msg = (u'%d %s')%(version, plugin_updates, + _('updated plugins')) + self.status_bar.update_label.setText(msg) + self.status_bar.update_label.setVisible(True) - if force or (config.get('new_version_notification') and \ - dynamic.get('update to version %s'%version, True)): - self._update_notification__ = UpdateNotification(version, - parent=self) - self._update_notification__.show() + if has_plugin_updates: + self.plugin_update_found(plugin_updates) - def plugin_update_found(self, updates, icon_only=False): + if has_calibre_update: + if force or (config.get('new_version_notification') and \ + dynamic.get('update to version %s'%calibre_version, True)): + self._update_notification__ = UpdateNotification(calibre_version, + plugin_updates, parent=self) + self._update_notification__.show() + elif has_plugin_updates: + if force: + from calibre.gui2.dialogs.plugin_updater import (PluginUpdaterDialog, + FILTER_UPDATE_AVAILABLE) + d = PluginUpdaterDialog(self, + initial_filter=FILTER_UPDATE_AVAILABLE) + d.exec_() + + def plugin_update_found(self, number_of_updates): # Change the plugin icon to indicate there are updates available plugin = self.iactions.get('Plugin Updates', None) if not plugin: return - if updates: + if number_of_updates: plugin.qaction.setText(_('Plugin Updates')+'*') plugin.qaction.setIcon(QIcon(I('plugins/plugin_updater_updates.png'))) - plugin.qaction.setToolTip(_('There are %d plugin updates available')%len(updates)) + plugin.qaction.setToolTip( + _('There are %d plugin updates available')%number_of_updates) else: plugin.qaction.setText(_('Plugin Updates')) plugin.qaction.setIcon(QIcon(I('plugins/plugin_updater.png'))) plugin.qaction.setToolTip(_('Install and configure user plugins')) + def update_link_clicked(self, url): + url = unicode(url) + if url.startswith('update:'): + version = url[len('update:'):] + self.update_found(version, force=True)