diff --git a/src/calibre/customize/__init__.py b/src/calibre/customize/__init__.py index f49c8496c5..5198969430 100644 --- a/src/calibre/customize/__init__.py +++ b/src/calibre/customize/__init__.py @@ -590,11 +590,23 @@ class StorePlugin(Plugin): # {{{ # This needs to be changed to (0, 8, 0) minimum_calibre_version = (0, 4, 118) - def open(self, gui, parent=None, detail_item=None): + def open(self, gui, parent=None, detail_item=None, external=False): ''' - Open a dialog for displaying the store. - start_item is a refernce unique to the store - plugin and opens to the item when specified. + Open the store. + + :param gui: The main GUI. This will be used to have the job + system start downloading an item from the store. + + :param parent: The parent of the store dialog. This is used + to create modal dialogs. + + :param detail_item: A plugin specific reference to an item + in the store that the user should be shown. + + :param external: When False open an internal dialog with the + store. When True open the users default browser to the store's + web site. :param:`detail_item` should still be respected when external + is True. ''' raise NotImplementedError() @@ -607,12 +619,21 @@ class StorePlugin(Plugin): # {{{ :param max_results: The maximum number of results to return. :param timeout: The maximum amount of time in seconds to spend download the search results. - :return: calibre.gui2.store.search_result.SearchResult object + :return: :class:`calibre.gui2.store.search_result.SearchResult` objects item_data is plugin specific and is used in :meth:`open` to open to a specifc place in the store. ''' raise NotImplementedError() def get_settings(self): + ''' + This is only useful for plugins that implement + :attr:`config_widget` that is the only way to save + settings. This is used by plugins to get the saved + settings and apply when necessary. + + :return: A dictionary filled with the settings used + by this plugin. + ''' raise NotImplementedError() # }}} diff --git a/src/calibre/gui2/store/search.py b/src/calibre/gui2/store/search.py index f12c1fac4b..89e2cf2696 100644 --- a/src/calibre/gui2/store/search.py +++ b/src/calibre/gui2/store/search.py @@ -33,16 +33,24 @@ class SearchDialog(QDialog, Ui_Dialog): QDialog.__init__(self, *args) self.setupUi(self) + # We pass this on to the store plugins so they can + # tell the gui's job system to start downloading an + # item. self.gui = gui + # We keep a cache of store plugins and reference them by name. self.store_plugins = {} self.search_pool = SearchThreadPool(SearchThread, SEARCH_THREAD_TOTAL) + # Check for results and hung threads. self.checker = QTimer() self.hang_check = 0 self.model = Matches() self.results_view.setModel(self.model) + # Add check boxes for each store so the user + # can disable searching specific stores on a + # per search basis. stores_group_layout = QVBoxLayout() self.stores_group.setLayout(stores_group_layout) for x in store_plugins(): @@ -96,6 +104,7 @@ class SearchDialog(QDialog, Ui_Dialog): if not store_names: return shuffle(store_names) + # Add plugins that the user has checked to the search pool's work queue. for n in store_names: if getattr(self, 'store_check_' + n).isChecked(): self.search_pool.add_task(query, n, self.store_plugins[n], TIMEOUT) @@ -117,7 +126,7 @@ class SearchDialog(QDialog, Ui_Dialog): self.checker.stop() while self.search_pool.has_results(): - res = self.search_pool.get_result_no_wait() + res = self.search_pool.get_result() if res: self.results_view.model().add_result(res) @@ -126,6 +135,9 @@ class SearchDialog(QDialog, Ui_Dialog): self.store_plugins[result.store_name].open(self.gui, self, result.detail_item) def get_store_checks(self): + ''' + Returns a list of QCheckBox's for each store. + ''' checks = [] for x in self.store_plugins: check = getattr(self, 'store_check_' + x, None) @@ -158,6 +170,9 @@ class GenericDownloadThreadPool(object): self.tasks = Queue() self.results = Queue() self.threads = [] + + def add_task(self): + raise NotImplementedError() def start_threads(self): for i in range(self.thread_count): diff --git a/src/calibre/gui2/store/web_control.py b/src/calibre/gui2/store/web_control.py index e73279ce58..295fde8b37 100644 --- a/src/calibre/gui2/store/web_control.py +++ b/src/calibre/gui2/store/web_control.py @@ -68,6 +68,7 @@ class NPWebView(QWebView): def get_cookies(self): cj = CookieJar() + # Translate Qt cookies to cookielib cookies for use by mechanize. for c in self.page().networkAccessManager().cookieJar().allCookies(): version = 0 name = unicode(QString(c.name())) diff --git a/src/calibre/gui2/store_download.py b/src/calibre/gui2/store_download.py index b3c5e6279a..55f39c9ad0 100644 --- a/src/calibre/gui2/store_download.py +++ b/src/calibre/gui2/store_download.py @@ -47,6 +47,13 @@ class StoreDownloadJob(BaseJob): def job_done(self): self.duration = time.time() - self.start_time self.percent = 1 + + try: + os.remove(self.tmp_file_name) + except: + import traceback + self.log_write(traceback.format_exc()) + # Dump log onto disk lf = PersistentTemporaryFile('store_log') lf.write(self._log_file.getvalue()) @@ -55,11 +62,6 @@ class StoreDownloadJob(BaseJob): self._log_file.close() self._log_file = None - try: - os.remove(self.tmp_file_name) - except: - pass - self.job_manager.changed_queue.put(self) def log_write(self, what): @@ -97,8 +99,11 @@ class StoreDownloader(Thread): continue try: + job.percent = .1 self._download(job) + job.percent = .7 self._add(job) + job.percent = .8 self._save_as(job) except Exception, e: if not self._run: