コード例 #1
0
    def closeEvent(self, e):
        self.write_settings()
        if self.system_tray_icon.isVisible():
            if not dynamic["systray_msg"] and not isosx:
                info_dialog(
                    self,
                    "calibre",
                    "calibre "
                    + _(
                        "will keep running in the system tray. To close it, "
                        "choose <b>Quit</b> in the context menu of the "
                        "system tray."
                    ),
                    show_copy_button=False,
                ).exec_()
                dynamic["systray_msg"] = True
            self.hide_windows()
            e.ignore()
        else:
            if self.confirm_quit():
                try:
                    self.shutdown(write_settings=False)
                except:
                    import traceback

                    traceback.print_exc()
                e.accept()
            else:
                e.ignore()
コード例 #2
0
ファイル: config.py プロジェクト: Eksmo/calibre
 def accept(self, *args):
     if self.shortcut_config.is_editing:
         from calibre.gui2 import info_dialog
         info_dialog(self, _('Still editing'),
                 _('You are in the middle of editing a keyboard shortcut'
                     ' first complete that, by clicking outside the '
                     ' shortcut editing box.'), show=True)
         return
     c = config()
     c.set('serif_family', unicode(self.serif_family.currentFont().family()))
     c.set('sans_family', unicode(self.sans_family.currentFont().family()))
     c.set('mono_family', unicode(self.mono_family.currentFont().family()))
     c.set('default_font_size', self.default_font_size.value())
     c.set('mono_font_size', self.mono_font_size.value())
     c.set('standard_font', {0:'serif', 1:'sans', 2:'mono'}[self.standard_font.currentIndex()])
     c.set('user_css', unicode(self.css.toPlainText()))
     c.set('remember_window_size', self.opt_remember_window_size.isChecked())
     c.set('fit_images', self.opt_fit_images.isChecked())
     c.set('max_fs_width', int(self.max_fs_width.value()))
     c.set('hyphenate', self.hyphenate.isChecked())
     c.set('remember_current_page', self.opt_remember_current_page.isChecked())
     c.set('wheel_flips_pages', self.opt_wheel_flips_pages.isChecked())
     c.set('page_flip_duration', self.opt_page_flip_duration.value())
     c.set('font_magnification_step',
             float(self.opt_font_mag_step.value())/100.)
     idx = self.hyphenate_default_lang.currentIndex()
     c.set('hyphenate_default_lang',
             str(self.hyphenate_default_lang.itemData(idx).toString()))
     c.set('line_scrolling_stops_on_pagebreaks',
             self.opt_line_scrolling_stops_on_pagebreaks.isChecked())
     c.set('fullscreen_clock', self.opt_fullscreen_clock.isChecked())
     return QDialog.accept(self, *args)
コード例 #3
0
ファイル: main.py プロジェクト: JackonYang/calibre
    def apply_diff(self, identical_msg, cache, syntax_map, changed_names, renamed_names, removed_names, added_names):
        self.view.clear()
        self.apply_diff_calls = calls = []
        def add(args, kwargs):
            self.view.add_diff(*args, **kwargs)
            calls.append((args, kwargs))

        if len(changed_names) + len(renamed_names) + len(removed_names) + len(added_names) < 1:
            info_dialog(self, _('No changes found'), identical_msg, show=True)
            return True

        kwargs = lambda name: {'context':self.context, 'beautify':self.beautify, 'syntax':syntax_map.get(name, None)}

        if isinstance(changed_names, dict):
            for name, other_name in sorted(changed_names.iteritems(), key=lambda x:numeric_sort_key(x[0])):
                args = (name, other_name, cache.left(name), cache.right(other_name))
                add(args, kwargs(name))
        else:
            for name in sorted(changed_names, key=numeric_sort_key):
                args = (name, name, cache.left(name), cache.right(name))
                add(args, kwargs(name))

        for name in sorted(added_names, key=numeric_sort_key):
            args = (_('[%s was added]') % name, name, None, cache.right(name))
            add(args, kwargs(name))

        for name in sorted(removed_names, key=numeric_sort_key):
            args = (name, _('[%s was removed]') % name, cache.left(name), None)
            add(args, kwargs(name))

        for name, new_name in sorted(renamed_names.iteritems(), key=lambda x:numeric_sort_key(x[0])):
            args = (name, new_name, None, None)
            add(args, kwargs(name))
コード例 #4
0
ファイル: boss.py プロジェクト: CharlesSong/calibre
 def copy_saved(self, job):
     if job.traceback is not None:
         return error_dialog(self.gui, _('Failed to save copy'),
                 _('Failed to save copy, click Show details for more information.'), det_msg=job.traceback, show=True)
     msg = _('Copy saved to %s') % job.result
     info_dialog(self.gui, _('Copy saved'), msg, show=True)
     self.gui.show_status_message(msg, 5)
コード例 #5
0
ファイル: config.py プロジェクト: javisar/FindDuplicates
 def reset_dialogs(self):
     for key in dynamic.keys():
         if key.startswith('find_duplicates_') and key.endswith('_again') \
                                               and dynamic[key] is False:
             dynamic[key] = True
     info_dialog(self, _('Done'),
             _('Confirmation dialogs have all been reset'), show=True)
コード例 #6
0
ファイル: add.py プロジェクト: booster72/calibre
    def _files_added(self, paths=[], names=[], infos=[], on_card=None):
        self.gui.tags_view.disable_recounting = False
        if paths:
            self.gui.upload_books(paths, list(map(ascii_filename, names)), infos, on_card=on_card)
            self.gui.status_bar.show_message(_("Uploading books to device."), 2000)
        if getattr(self._adder, "number_of_books_added", 0) > 0:
            self.gui.library_view.model().books_added(self._adder.number_of_books_added)
            self.gui.library_view.set_current_row(0)
            if hasattr(self.gui, "db_images"):
                self.gui.db_images.reset()
            self.gui.tags_view.recount()

        if getattr(self._adder, "merged_books", False):
            books = u"\n".join(
                [
                    x if isinstance(x, unicode) else x.decode(preferred_encoding, "replace")
                    for x in self._adder.merged_books
                ]
            )
            info_dialog(
                self.gui,
                _("Merged some books"),
                _(
                    "The following %d duplicate books were found and incoming "
                    "book formats were processed and merged into your "
                    "Calibre database according to your automerge "
                    "settings:"
                )
                % len(self._adder.merged_books),
                det_msg=books,
                show=True,
            )

        if getattr(self._adder, "number_of_books_added", 0) > 0 or getattr(self._adder, "merged_books", False):
            # The formats of the current book could have changed if
            # automerge is enabled
            current_idx = self.gui.library_view.currentIndex()
            if current_idx.isValid():
                self.gui.library_view.model().current_changed(current_idx, current_idx)

        if getattr(self._adder, "critical", None):
            det_msg = []
            for name, log in self._adder.critical.items():
                if isinstance(name, str):
                    name = name.decode(filesystem_encoding, "replace")
                det_msg.append(name + "\n" + log)

            warning_dialog(
                self.gui,
                _("Failed to read metadata"),
                _("Failed to read metadata from the following") + ":",
                det_msg="\n\n".join(det_msg),
                show=True,
            )

        if hasattr(self._adder, "cleanup"):
            self._adder.cleanup()
            self._adder.setParent(None)
            del self._adder
            self._adder = None
コード例 #7
0
ファイル: catalog.py プロジェクト: ZRhinoceros/calibre
    def help(self):
        """
        To add help functionality for a specific format:
        In gui2.catalog.catalog_<format>.py, add the following:
            from calibre.gui2 import open_url
            from PyQt5.Qt import QUrl

        In the PluginWidget() class, add this method:
            def show_help(self):
                url = 'file:///' + P('catalog/help_<format>.html')
                open_url(QUrl(url))

        Create the help file at resources/catalog/help_<format>.html
        """
        if self.tabs.count() > 1 and hasattr(self.tabs.widget(1), "show_help"):
            try:
                self.tabs.widget(1).show_help()
            except:
                info_dialog(
                    self,
                    _("No help available"),
                    _("No help available for this output format."),
                    show_copy_button=False,
                    show=True,
                )
コード例 #8
0
ファイル: behavior.py プロジェクト: JimmXinu/calibre
 def reset_confirmation_dialogs(self, *args):
     for key in dynamic.keys():
         if key.endswith('_again') and dynamic[key] is False:
             dynamic[key] = True
     gprefs['questions_to_auto_skip'] = []
     info_dialog(self, _('Done'),
             _('Confirmation dialogs have all been reset'), show=True)
コード例 #9
0
ファイル: config.py プロジェクト: chiorc/DeDRM_tools
    def add_key(self):
        d = self.create_key(self)
        d.exec_()

        if d.result() != d.Accepted:
            # New key generation cancelled.
            return
        new_key_value = d.key_value
        if type(self.plugin_keys) == dict:
            if new_key_value in self.plugin_keys.values():
                old_key_name = [name for name, value in self.plugin_keys.iteritems() if value == new_key_value][0]
                info_dialog(
                    None,
                    "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name),
                    u"The new {1} is the same as the existing {1} named <strong>{0}</strong> and has not been added.".format(
                        old_key_name, self.key_type_name
                    ),
                    show=True,
                )
                return
            self.plugin_keys[d.key_name] = new_key_value
        else:
            if new_key_value in self.plugin_keys:
                info_dialog(
                    None,
                    "{0} {1}: Duplicate {2}".format(PLUGIN_NAME, PLUGIN_VERSION, self.key_type_name),
                    u"This {0} is already in the list of {0}s has not been added.".format(self.key_type_name),
                    show=True,
                )
                return

            self.plugin_keys.append(d.key_value)
        self.listy.clear()
        self.populate_list()
コード例 #10
0
ファイル: main.py プロジェクト: j-howell/calibre
 def check_multi_selection(self):
     if len(self.selectedItems()) > 1:
         info_dialog(self, _('Multiple items selected'), _(
             'You are trying to move multiple items at once, this is not supported. Instead use'
             ' Drag and Drop to move multiple items'), show=True)
         return False
     return True
コード例 #11
0
ファイル: search.py プロジェクト: Qyy/calibre
    def get_results(self):
        # We only want the search plugins to run
        # a maximum set amount of time before giving up.
        self.hang_check += 1
        if self.hang_check >= self.hang_time:
            self.search_pool.abort()
            self.checker.stop()
        else:
            # Stop the checker if not threads are running.
            if not self.search_pool.threads_running() and not self.search_pool.has_tasks():
                self.checker.stop()

        while self.search_pool.has_results():
            res, store_plugin = self.search_pool.get_result()
            if res:
                self.results_view.model().add_result(res, store_plugin)

        if not self.search_pool.threads_running() and not self.results_view.model().has_results():
            info_dialog(
                self,
                _("No matches"),
                _("Couldn't find any books matching your query."),
                show=True,
                show_copy_button=False,
            )
コード例 #12
0
ファイル: action.py プロジェクト: javisar/FindDuplicates
 def mark_groups_as_duplicate_exemptions(self, all_groups):
     can_exempt = self.duplicate_finder.check_can_mark_exemption(all_groups)
     if can_exempt:
         # Ensure that the selection is moved onto the current duplicate group
         duplicate_ids = self.duplicate_finder.get_current_duplicate_group_ids()
         self.gui.library_view.select_rows(duplicate_ids)
         exemption_type = 'books'
         if self.duplicate_finder.is_searching_for_authors():
             exemption_type = 'authors'
         dialog_name = 'find_duplicates_mark_all_groups' if all_groups else 'find_duplicates_mark_group'
         if not confirm('<p>' + _(
                         'This action will ensure that each of the %s in the group '
                         'are exempt from appearing together again in future.<p>'
                         'Are you <b>sure</b> you want to proceed?')%exemption_type,
                         dialog_name, self.gui):
             return
         if all_groups:
             self.duplicate_finder.mark_groups_as_duplicate_exemptions()
         else:
             self.duplicate_finder.mark_current_group_as_duplicate_exemptions()
     else:
         info_dialog(self.gui, _('No duplicates in group'),
                     _('There are no duplicates remaining in this group.'),
                     show=True, show_copy_button=False)
     self.update_actions_enabled()
コード例 #13
0
ファイル: view.py プロジェクト: BobPyron/calibre
    def view_specific_format(self, triggered):
        rows = list(self.gui.library_view.selectionModel().selectedRows())
        if not rows or len(rows) == 0:
            d = error_dialog(self.gui, _('Cannot view'), _('No book selected'))
            d.exec_()
            return

        db = self.gui.library_view.model().db
        rows = [r.row() for r in rows]
        formats = [db.formats(row) for row in rows]
        formats = [list(f.upper().split(',')) if f else None for f in formats]
        all_fmts = set([])
        for x in formats:
            if x:
                for f in x: all_fmts.add(f)
        if not all_fmts:
            error_dialog(self.gui,  _('Format unavailable'),
                    _('Selected books have no formats'), show=True)
            return
        d = ChooseFormatDialog(self.gui, _('Choose the format to view'),
                list(sorted(all_fmts)))
        if d.exec_() == d.Accepted:
            fmt = d.format()
            orig_num = len(rows)
            rows = [rows[i] for i in range(len(rows)) if formats[i] and fmt in
                    formats[i]]
            if self._view_check(len(rows)):
                for row in rows:
                    self.view_format(row, fmt)
                if len(rows) < orig_num:
                    info_dialog(self.gui, _('Format unavailable'),
                            _('Not all the selected books were available in'
                                ' the %s format. You should convert'
                                ' them first.')%fmt, show=True)
コード例 #14
0
ファイル: preferences.py プロジェクト: hojel/calibre
 def restore_confirmations(self):
     changed = 0
     for key in tuple(tprefs):
         if key.endswith('_again') and tprefs.get(key) is False:
             del tprefs[key]
             changed += 1
     info_dialog(self, _('Disabled confirmations restored'), _(
         '%d disabled confirmation prompts were restored') % changed, show=True)
コード例 #15
0
ファイル: manage_fonts.py プロジェクト: JimmXinu/calibre
 def install_fonts(self):
     from calibre.gui2.font_family_chooser import add_fonts
     families = add_fonts(self)
     if not families:
         return
     font_scanner.do_scan()
     self.refresh()
     info_dialog(self, _('Added fonts'), _('Added font families: %s')%(', '.join(families)), show=True)
コード例 #16
0
    def copy_to_library(self, loc, delete_after=False):
        rows = self.gui.library_view.selectionModel().selectedRows()
        if not rows or len(rows) == 0:
            return error_dialog(self.gui, _('Cannot copy'),
                    _('No books selected'), show=True)
        ids = list(map(self.gui.library_view.model().id, rows))
        db = self.gui.library_view.model().db
        if not db.exists_at(loc):
            return error_dialog(self.gui, _('No library'),
                    _('No library found at %s')%loc, show=True)

        aname = _('Moving to') if delete_after else _('Copying to')
        dtitle = '%s %s'%(aname, os.path.basename(loc))

        self.pd = ProgressDialog(dtitle, min=0, max=len(ids)-1,
                parent=self.gui, cancelable=False)

        def progress(idx, title):
            self.pd.set_msg(title)
            self.pd.set_value(idx)

        self.worker = Worker(ids, db, loc, Dispatcher(progress),
                             Dispatcher(self.pd.accept), delete_after)
        self.worker.start()

        self.pd.exec_()

        donemsg = _('Copied %(num)d books to %(loc)s')
        if delete_after:
            donemsg = _('Moved %(num)d books to %(loc)s')

        if self.worker.error is not None:
            e, tb = self.worker.error
            error_dialog(self.gui, _('Failed'), _('Could not copy books: ') + e,
                    det_msg=tb, show=True)
        else:
            self.gui.status_bar.show_message(donemsg %
                    dict(num=len(ids), loc=loc), 2000)
            if self.worker.auto_merged_ids:
                books = '\n'.join(self.worker.auto_merged_ids.itervalues())
                info_dialog(self.gui, _('Auto merged'),
                        _('Some books were automatically merged into existing '
                            'records in the target library. Click Show '
                            'details to see which ones. This behavior is '
                            'controlled by the Auto merge option in '
                            'Preferences->Adding books.'), det_msg=books,
                        show=True)
            if delete_after and self.worker.processed:
                v = self.gui.library_view
                ci = v.currentIndex()
                row = None
                if ci.isValid():
                    row = ci.row()

                v.model().delete_books_by_id(self.worker.processed,
                        permanent=True)
                self.gui.iactions['Remove Books'].library_ids_deleted(
                        self.worker.processed, row)
コード例 #17
0
ファイル: config.py プロジェクト: MorantHypopolia/DeDRM_tools
 def migrate_files(self):
     unique_dlg_name = PLUGIN_NAME + u"import {0} keys".format(self.key_type_name).replace(' ', '_') #takes care of automatically remembering last directory
     caption = u"Select {0} files to import".format(self.key_type_name)
     filters = [(u"{0} files".format(self.key_type_name), [self.keyfile_ext])]
     files = choose_files(self, unique_dlg_name, caption, filters, all_files=False)
     counter = 0
     skipped = 0
     if files:
         for filename in files:
             fpath = os.path.join(config_dir, filename)
             filename = os.path.basename(filename)
             if type(self.plugin_keys) != dict:
                 # must be the new Kindle for Android section
                 print u"Getting keys from "+fpath
                 new_keys = get_serials(fpath)
                 for key in new_keys:
                     if key in self.plugin_keys:
                         skipped += 1
                     else:
                         counter += 1
                         self.plugin_keys.append(key)
             else:
                 new_key_name = os.path.splitext(os.path.basename(filename))[0]
                 with open(fpath,'rb') as keyfile:
                     new_key_value = keyfile.read()
                 if self.binary_file:
                     new_key_value = new_key_value.encode('hex')
                 elif self.json_file:
                     new_key_value = json.loads(new_key_value)
                 match = False
                 for key in self.plugin_keys.keys():
                     if uStrCmp(new_key_name, key, True):
                         skipped += 1
                         msg = u"A key with the name <strong>{0}</strong> already exists!\nSkipping key file  <strong>{1}</strong>.\nRename the existing key and import again".format(new_key_name,filename)
                         inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION),
                                 _(msg), show_copy_button=False, show=True)
                         match = True
                         break
                 if not match:
                     if new_key_value in self.plugin_keys.values():
                         old_key_name = [name for name, value in self.plugin_keys.iteritems() if value == new_key_value][0]
                         skipped += 1
                         info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION),
                                             u"The key in file {0} is the same as the existing key <strong>{1}</strong> and has been skipped.".format(filename,old_key_name), show_copy_button=False, show=True)
                     else:
                         counter += 1
                         self.plugin_keys[new_key_name] = new_key_value
                         
         msg = u""
         if counter+skipped > 1:
             if counter > 0:
                 msg += u"Imported <strong>{0:d}</strong> key {1}. ".format(counter, u"file" if counter == 1 else u"files")
             if skipped > 0:
                 msg += u"Skipped <strong>{0:d}</strong> key {1}.".format(skipped, u"file" if counter == 1 else u"files")
             inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION),
                                 _(msg), show_copy_button=False, show=True)
     return counter > 0
コード例 #18
0
ファイル: add.py プロジェクト: Hainish/calibre
    def _files_added(self, paths=[], names=[], infos=[], on_card=None):
        self.gui.tags_view.disable_recounting = False
        if paths:
            self.gui.upload_books(paths,
                                list(map(ascii_filename, names)),
                                infos, on_card=on_card)
            self.gui.status_bar.show_message(
                    _('Uploading books to device.'), 2000)
        if getattr(self._adder, 'number_of_books_added', 0) > 0:
            self.gui.library_view.model().books_added(self._adder.number_of_books_added)
            self.gui.library_view.set_current_row(0)
            if hasattr(self.gui, 'db_images'):
                self.gui.db_images.reset()
            self.gui.tags_view.recount()

        if getattr(self._adder, 'merged_books', False):
            merged = defaultdict(list)
            for title, author in self._adder.merged_books:
                merged[author].append(title)
            lines = []
            for author in sorted(merged, key=sort_key):
                lines.append(author)
                for title in sorted(merged[author], key=sort_key):
                    lines.append('\t' + title)
                lines.append('')
            info_dialog(self.gui, _('Merged some books'),
                _('The following %d duplicate books were found and incoming '
                    'book formats were processed and merged into your '
                    'Calibre database according to your automerge '
                    'settings:')%len(self._adder.merged_books),
                    det_msg='\n'.join(lines), show=True)

        if getattr(self._adder, 'number_of_books_added', 0) > 0 or \
                getattr(self._adder, 'merged_books', False):
            # The formats of the current book could have changed if
            # automerge is enabled
            current_idx = self.gui.library_view.currentIndex()
            if current_idx.isValid():
                self.gui.library_view.model().current_changed(current_idx,
                        current_idx)

        if getattr(self._adder, 'critical', None):
            det_msg = []
            for name, log in self._adder.critical.items():
                if isinstance(name, str):
                    name = name.decode(filesystem_encoding, 'replace')
                det_msg.append(name+'\n'+log)

            warning_dialog(self.gui, _('Failed to read metadata'),
                    _('Failed to read metadata from the following')+':',
                    det_msg='\n\n'.join(det_msg), show=True)

        if hasattr(self._adder, 'cleanup'):
            self._adder.cleanup()
            self._adder.setParent(None)
            del self._adder
            self._adder = None
コード例 #19
0
ファイル: config.py プロジェクト: JimmXinu/EpubMerge
 def reset_dialogs(self):
     for key in dynamic.keys():
         if key.startswith('epubmerge_') and key.endswith('_again') \
                                               and dynamic[key] is False:
             dynamic[key] = True
     info_dialog(self, _('Done'),
                 _('Confirmation dialogs have all been reset'),
                 show=True,
                 show_copy_button=False)
コード例 #20
0
ファイル: choose_library.py プロジェクト: jackpinto/calibre
    def check_library(self):
        from calibre.gui2.dialogs.check_library import CheckLibraryDialog, DBCheck, DBCheckNew

        self.gui.library_view.save_state()
        m = self.gui.library_view.model()
        m.stop_metadata_backup()
        db = m.db
        db.prefs.disable_setting = True

        if hasattr(db, "new_api"):
            d = DBCheckNew(self.gui, db)
        else:
            d = DBCheck(self.gui, db)
        d.start()
        try:
            d.conn.close()
        except:
            pass
        d.break_cycles()
        self.gui.library_moved(db.library_path, call_close=not d.closed_orig_conn)
        if d.rejected:
            return
        if d.error is None:
            if not question_dialog(
                self.gui,
                _("Success"),
                _(
                    "Found no errors in your calibre library database."
                    " Do you want calibre to check if the files in your "
                    " library match the information in the database?"
                ),
            ):
                return
        else:
            return error_dialog(
                self.gui,
                _("Failed"),
                _("Database integrity check failed, click Show details" " for details."),
                show=True,
                det_msg=d.error[1],
            )

        self.gui.status_bar.show_message(_("Starting library scan, this may take a while"))
        try:
            QCoreApplication.processEvents()
            d = CheckLibraryDialog(self.gui, m.db)

            if not d.do_exec():
                info_dialog(
                    self.gui,
                    _("No problems found"),
                    _("The files in your library match the information " "in the database."),
                    show=True,
                )
        finally:
            self.gui.status_bar.clear_message()
コード例 #21
0
ファイル: add.py プロジェクト: hashken/calibre
    def add(self, books):
        if isinstance(books, basestring):
            error_dialog(
                self.pd, _("Path error"), _("The specified directory could not be processed."), det_msg=books, show=True
            )
            return self.canceled()
        if not books:
            info_dialog(self.pd, _("No books"), _("No books found"), show=True)
            return self.canceled()
        books = [[b] if isinstance(b, basestring) else b for b in books]
        restricted = set()
        for i in xrange(len(books)):
            files = books[i]
            restrictedi = set(f for f in files if not os.access(f, os.R_OK))
            if restrictedi:
                files = [f for f in files if os.access(f, os.R_OK)]
                books[i] = files
            restricted |= restrictedi
        if restrictedi:
            det_msg = u"\n".join(restrictedi)
            warning_dialog(
                self.pd,
                _("No permission"),
                _(
                    "Cannot add some files as you do not have "
                    " permission to access them. Click Show"
                    " Details to see the list of such files."
                ),
                det_msg=det_msg,
                show=True,
            )
        books = list(filter(None, books))
        if not books:
            return self.canceled()
        self.rfind = None
        from calibre.ebooks.metadata.worker import read_metadata

        self.rq = Queue()
        tasks = []
        self.ids = {}
        self.nmap = {}
        self.duplicates = []
        for i, b in enumerate(books):
            tasks.append((i, b))
            self.ids[i] = b
            self.nmap[i] = os.path.basename(b[0])
        self.worker = read_metadata(tasks, self.rq, spare_server=self.spare_server)
        self.pd.set_min(0)
        self.pd.set_max(len(self.ids))
        self.pd.value = 0
        self.db_adder = DBAdder(self, self.db, self.ids, self.nmap)
        self.db_adder.start()
        self.last_added_at = time.time()
        self.entry_count = len(self.ids)
        self.continue_updating = True
        single_shot(self.update)
コード例 #22
0
ファイル: choose_library.py プロジェクト: BobPyron/calibre
 def backup_status(self, location):
     dirty_text = 'no'
     try:
         dirty_text = \
               unicode(self.gui.library_view.model().db.dirty_queue_length())
     except:
         dirty_text = _('none')
     info_dialog(self.gui, _('Backup status'), '<p>'+
             _('Book metadata files remaining to be written: %s') % dirty_text,
             show=True)
コード例 #23
0
ファイル: search.py プロジェクト: GaryMMugford/calibre
 def count_message(action, count, show_diff=False):
     msg = _('%(action)s %(num)s occurrences of %(query)s' % dict(num=count, query=errfind, action=action))
     if show_diff and count > 0:
         d = MessageBox(MessageBox.INFO, _('Searching done'), prepare_string_for_xml(msg), parent=gui_parent, show_copy_button=False)
         d.diffb = b = d.bb.addButton(_('See what &changed'), d.bb.ActionRole)
         b.setIcon(QIcon(I('diff.png'))), d.set_details(None), b.clicked.connect(d.accept)
         b.clicked.connect(partial(show_current_diff, allow_revert=True))
         d.exec_()
     else:
         info_dialog(gui_parent, _('Searching done'), prepare_string_for_xml(msg), show=True)
コード例 #24
0
ファイル: config.py プロジェクト: AEliu/calibre
 def accept(self, *args):
     if self.shortcut_config.is_editing:
         from calibre.gui2 import info_dialog
         info_dialog(self, _('Still editing'),
                 _('You are in the middle of editing a keyboard shortcut'
                     ' first complete that, by clicking outside the '
                     ' shortcut editing box.'), show=True)
         return
     self.save_options(config())
     return QDialog.accept(self, *args)
コード例 #25
0
 def restore_confirmations(self):
     changed = 0
     for key in tuple(tprefs):
         if key.endswith('_again') and tprefs.get(key) is False:
             del tprefs[key]
             changed += 1
     msg = _('There are no disabled confirmation prompts')
     if changed:
         msg = ngettext(
             'One disabled confirmation prompt was restored', '{} disabled confirmation prompts were restored', changed).format(changed)
     info_dialog(self, _('Disabled confirmations restored'), msg, show=True)
コード例 #26
0
ファイル: plugins.py プロジェクト: hashken/calibre
    def add_plugin(self):
        info = "" if iswindows else " [.zip %s]" % _("files")
        path = choose_files(
            self,
            "add a plugin dialog",
            _("Add plugin"),
            filters=[(_("Plugins") + info, ["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?"),
                "<p>"
                + _(
                    "Installing plugins is a <b>security risk</b>. "
                    "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
            from calibre.customize.ui import config

            installed_plugins = frozenset(config["plugins"])
            try:
                plugin = add_plugin(path)
            except NameConflict as e:
                return error_dialog(self, _("Already exists"), unicode(e), show=True)
            self._plugin_model.populate()
            self._plugin_model.reset()
            self.changed_signal.emit()
            self.check_for_add_to_toolbars(plugin, previously_installed=plugin.name in installed_plugins)
            info_dialog(
                self,
                _("Success"),
                _(
                    "Plugin <b>{0}</b> successfully installed under <b>"
                    " {1} plugins</b>. You may have to restart calibre "
                    "for the plugin to take effect."
                ).format(plugin.name, plugin.type),
                show=True,
                show_copy_button=False,
            )
            idx = self._plugin_model.plugin_to_index_by_properties(plugin)
            if idx.isValid():
                self.highlight_index(idx)
        else:
            error_dialog(self, _("No valid plugin path"), _("%s is not a valid plugin path") % path).exec_()
コード例 #27
0
ファイル: choose_library.py プロジェクト: shamray/calibre
 def delete_requested(self, name, location):
     loc = location.replace('/', os.sep)
     self.stats.remove(location)
     self.build_menus()
     self.gui.iactions['Copy To Library'].build_menus()
     info_dialog(self.gui, _('Library removed'),
             _('The library %s has been removed from calibre. '
                 'The files remain on your computer, if you want '
                 'to delete them, you will have to do so manually.') % loc,
             show=True)
     if os.path.exists(loc):
         open_local_file(loc)
コード例 #28
0
ファイル: choose_library.py プロジェクト: Ralnoc/calibre
 def mark_dirty(self):
     db = self.gui.library_view.model().db
     db.dirtied(list(db.data.iterallids()))
     info_dialog(
         self.gui,
         _("Backup metadata"),
         _(
             "Metadata will be backed up while calibre is running, at the "
             "rate of approximately 1 book every three seconds."
         ),
         show=True,
     )
コード例 #29
0
ファイル: plugins.py プロジェクト: BobPyron/calibre
    def modify_plugin(self, op=''):
        index = self.plugin_view.currentIndex()
        if index.isValid():
            if not index.parent().isValid():
                name = unicode(index.data().toString())
                return error_dialog(self, _('Error'), '<p>'+
                        _('Select an actual plugin under <b>%s</b> to customize')%name,
                        show=True, show_copy_button=False)

            plugin = self._plugin_model.index_to_plugin(index)
            if op == 'toggle':
                if not plugin.can_be_disabled:
                    error_dialog(self,_('Plugin cannot be disabled'),
                                 _('The plugin: %s cannot be disabled')%plugin.name).exec_()
                    return
                if is_disabled(plugin):
                    enable_plugin(plugin)
                else:
                    disable_plugin(plugin)
                self._plugin_model.refresh_plugin(plugin)
                self.changed_signal.emit()
            if op == 'customize':
                if not plugin.is_customizable():
                    info_dialog(self, _('Plugin not customizable'),
                        _('Plugin: %s does not need customization')%plugin.name).exec_()
                    return
                self.changed_signal.emit()
                from calibre.customize import InterfaceActionBase
                if isinstance(plugin, InterfaceActionBase) and not getattr(plugin,
                        'actual_iaction_plugin_loaded', False):
                    return error_dialog(self, _('Must restart'),
                            _('You must restart calibre before you can'
                                ' configure the <b>%s</b> plugin')%plugin.name, show=True)
                if plugin.do_user_config(self.gui):
                    self._plugin_model.refresh_plugin(plugin)
            elif op == 'remove':
                if not confirm('<p>' +
                    _('Are you sure you want to remove the plugin: %s?')%
                    '<b>{0}</b>'.format(plugin.name),
                    'confirm_plugin_removal_msg', parent=self):
                    return

                msg = _('Plugin <b>{0}</b> 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 '
                         'builtin plugin. Try disabling it instead.')).exec_()
コード例 #30
0
ファイル: restore_library.py プロジェクト: MarioJC/calibre
def _show_success_msg(restorer, parent=None):
    r = restorer
    olddb = _('The old database was saved as: %s')%force_unicode(r.olddb,
            filesystem_encoding)
    if r.errors_occurred:
        warning_dialog(parent, _('Success'),
                _('Restoring the database succeeded with some warnings'
                    ' click Show details to see the details. %s')%olddb,
                det_msg=r.report, show=True)
    else:
        info_dialog(parent, _('Success'),
                _('Restoring database was successful. %s')%olddb, show=True,
                show_copy_button=False)
コード例 #31
0
ファイル: main.py プロジェクト: timotheuslin/TradSimpChinese
    def process_files(self, criteria):
        container = self.current_container  # The book being edited as a container object
        self.language = 'lang=\"' + get_language_code(criteria) + '\"'
        if criteria[0]:
            # Only convert the selected file
            name = editor_name(self.gui.central.current_editor)
            if not name or container.mime_map[name] not in OEB_DOCS:
                return info_dialog(self.gui, _('Cannot Process'),
                        _('No file open for editing or the current file is not an (x)html file.'), show=True)

            data = container.raw_data(name)
            htmlstr = self.convert_text(data, criteria)
            if htmlstr != data:
                self.filesChanged = True
                self.changed_files.append(name)
                container.open(name, 'wb').write(htmlstr)

        else:
            # Cover the entire book
            # Set metadata and Table of Contents (TOC) if language changed
            if criteria[1] != 0:
                self.filesChanged = set_metadata_toc(container, get_language_code(criteria), criteria, self.changed_files, self.converter)
            # Check for orientation change
            direction_changed = False
            if criteria[7] != 0:
                direction_changed = set_flow_direction(container, get_language_code(criteria), criteria, self.changed_files, self.converter)

            # Cover the text portion
            from calibre_plugins.chinese_text.resources.dialogs import ShowProgressDialog
            d = ShowProgressDialog(self.gui, container, OEB_DOCS, criteria, self.convert_text, _('Converting'))
            cancelled_msg = ''
            if d.wasCanceled():
                cancelled_msg = ' (cancelled)'
            self.filesChanged = self.filesChanged or (not d.clean) or direction_changed
            self.changed_files.extend(d.changed_files)
コード例 #32
0
 def _save_settings(self):
     from calibre.gui2.dialogs.confirm_delete import confirm
     message = '<p>' + _('Are you sure you want to save this setting in this library for this plugin?') + '</p>' \
               + '<p>' + _('Any settings in other libraries or stored in a JSON file in your calibre plugins folder will not be touched.') + '</p>' \
               + '<p>' + _('You must restart calibre afterwards.') + '</p>'
     if not confirm(message, self.namespace+'_save_settings', self):
         return
     ns_prefix = self._get_ns_prefix()
     key = unicode(self.keys_list.currentItem().text())
     self.db.prefs.set_namespaced(self.namespace, key,
                                  self.db.prefs.raw_to_object(self.value_text.toPlainText()))
     d = info_dialog(self, 'Settings saved',
                     '<p>' + _('All settings for this plugin in this library have been saved.') + '</p>' \
                     + '<p>' + _('Please restart calibre now.') + '</p>',
                     show_copy_button=False)
     b = d.bb.addButton(_('Restart calibre now'), d.bb.AcceptRole)
     b.setIcon(QIcon(I('lt.png')))
     d.do_restart = False
     def rf():
         d.do_restart = True
     b.clicked.connect(rf)
     d.set_details('')
     d.exec_()
     b.clicked.disconnect()
     self.close()
     if d.do_restart:
         self.gui.quit(restart=True)
コード例 #33
0
 def _clear_settings(self):
     from calibre.gui2.dialogs.confirm_delete import confirm
     message = '<p>' + _('Are you sure you want to clear your settings in this library for this plugin?') + '</p>' \
               + '<p>' + _('Any settings in other libraries or stored in a JSON file in your calibre plugins folder will not be touched.') + '</p>' \
               + '<p>' + _('You must restart calibre afterwards.') + '</p>'
     if not confirm(message, self.namespace+'_clear_settings', self):
         return
     ns_prefix = self._get_ns_prefix()
     keys = [k for k in six.iterkeys(self.db.prefs) if k.startswith(ns_prefix)]
     for k in keys:
         del self.db.prefs[k]
     self._populate_settings()
     d = info_dialog(self, 'Settings deleted',
                     '<p>' + _('All settings for this plugin in this library have been cleared.') + '</p>' \
                     + '<p>' + _('Please restart calibre now.') + '</p>',
                     show_copy_button=False)
     b = d.bb.addButton(_('Restart calibre now'), d.bb.AcceptRole)
     b.setIcon(QIcon(I('lt.png')))
     d.do_restart = False
     def rf():
         d.do_restart = True
     b.clicked.connect(rf)
     d.set_details('')
     d.exec_()
     b.clicked.disconnect()
     self.close()
     if d.do_restart:
         self.gui.quit(restart=True)
コード例 #34
0
 def find(self, query):
     idx = self._plugin_model.find(query)
     if not idx.isValid():
         return info_dialog(self, _('No matches'),
                 _('Could not find any matching plugins'), show=True,
                 show_copy_button=False)
     self.highlight_index(idx)
コード例 #35
0
ファイル: view.py プロジェクト: tokot/calibre
    def view_specific_format(self, triggered):
        rows = list(self.gui.library_view.selectionModel().selectedRows())
        if not rows or len(rows) == 0:
            d = error_dialog(self.gui, _('Cannot view'), _('No book selected'))
            d.exec_()
            return

        db = self.gui.library_view.model().db
        rows = [r.row() for r in rows]
        book_ids = [db.id(r) for r in rows]
        formats = [[x.upper() for x in db.new_api.formats(book_id)]
                   for book_id in book_ids]
        all_fmts = set([])
        for x in formats:
            if x:
                for f in x:
                    all_fmts.add(f)
        if not all_fmts:
            error_dialog(self.gui,
                         _('Format unavailable'),
                         _('Selected books have no formats'),
                         show=True)
            return
        d = ChooseFormatDialog(self.gui, _('Choose the format to view'),
                               list(sorted(all_fmts)))
        self.gui.book_converted.connect(d.book_converted)
        if d.exec_() == d.Accepted:
            formats = [[x.upper() for x in db.new_api.formats(book_id)]
                       for book_id in book_ids]
            fmt = d.format()
            orig_num = len(rows)
            rows = [
                rows[i] for i in range(len(rows))
                if formats[i] and fmt in formats[i]
            ]
            if self._view_check(len(rows)):
                for row in rows:
                    self.view_format(row, fmt)
                if len(rows) < orig_num:
                    info_dialog(
                        self.gui,
                        _('Format unavailable'),
                        _('Not all the selected books were available in'
                          ' the %s format. You should convert'
                          ' them first.') % fmt,
                        show=True)
        self.gui.book_converted.disconnect(d.book_converted)
コード例 #36
0
ファイル: add.py プロジェクト: yipeng0428/calibre
    def _files_added(self, adder, on_card=None):
        if adder.items:
            paths, infos, names = [], [], []
            for mi, cover_path, format_paths in adder.items:
                mi.cover = cover_path
                paths.append(format_paths[0]), infos.append(mi)
                names.append(ascii_filename(os.path.basename(paths[-1])))
            self.gui.upload_books(paths, names, infos, on_card=on_card)
            self.gui.status_bar.show_message(_('Uploading books to device.'),
                                             2000)
            return

        if adder.number_of_books_added > 0:
            self.refresh_gui(adder.number_of_books_added, set_current_row=0)

        if adder.merged_books:
            merged = defaultdict(list)
            for title, author in adder.merged_books:
                merged[author].append(title)
            lines = []
            for author in sorted(merged, key=sort_key):
                lines.append(author)
                for title in sorted(merged[author], key=sort_key):
                    lines.append('\t' + title)
                lines.append('')
            pm = ngettext('The following duplicate book was found.',
                          'The following {} duplicate books were found.',
                          len(adder.merged_books)).format(
                              len(adder.merged_books))
            info_dialog(
                self.gui,
                _('Merged some books'),
                pm + ' ' +
                _('Incoming book formats were processed and merged into your '
                  'calibre database according to your auto-merge '
                  'settings. Click "Show details" to see the list of merged books.'
                  ),
                det_msg='\n'.join(lines),
                show=True)

        if adder.number_of_books_added > 0 or adder.merged_books:
            # The formats of the current book could have changed if
            # automerge is enabled
            current_idx = self.gui.library_view.currentIndex()
            if current_idx.isValid():
                self.gui.library_view.model().current_changed(
                    current_idx, current_idx)
コード例 #37
0
    def main(self):
        # create a restore point
        self.boss.add_savepoint('Before: Access Aide')

        container = self.current_container

        if not container:
            return error_dialog(self.gui, 'Access Aide',
                                'No book open, please open a book first.',
                                show=True)

        if container.book_type != 'epub' or \
           container.opf_version_parsed.major not in [2, 3]:
            message = 'Access Aide supports EPUB 2 and 3, {} {} given.' \
                      .format(container.book_type.upper(),
                              container.opf_version_parsed.major)

            return error_dialog(self.gui, 'Access Aide', message, show=True)

        blacklist = ['toc.xhtml']

        # iterate over book files
        for name, media_type in list(container.mime_map.items()):

            if media_type in OEB_DOCS \
               and name not in blacklist:

                self.add_lang(container.parsed(name),
                              self.get_lang(container))
                self.add_aria(container.parsed(name))

            elif media_type in OPF_MIME:
                self.add_metadata(container)

            else:
                continue

            container.dirty(name)

        info_dialog(self.gui, 'Access Aide', self.stats_report(), show=True)

        self.lang_stat.reset()
        self.aria_stat.reset()
        self.meta_stat.reset()

        # update the editor UI
        self.boss.apply_container_update_to_gui()
コード例 #38
0
def _show_success_msg(restorer, parent=None):
    r = restorer
    olddb = _('The old database was saved as: %s') % force_unicode(
        r.olddb, filesystem_encoding)
    if r.errors_occurred:
        warning_dialog(parent,
                       _('Success'),
                       _('Restoring the database succeeded with some warnings'
                         ' click Show details to see the details. %s') % olddb,
                       det_msg=r.report,
                       show=True)
    else:
        info_dialog(parent,
                    _('Success'),
                    _('Restoring database was successful. %s') % olddb,
                    show=True,
                    show_copy_button=False)
コード例 #39
0
    def migrate_files(self):
        unique_dlg_name = PLUGIN_NAME + u"import {0} keys".format(self.key_type_name).replace(' ', '_') #takes care of automatically remembering last directory
        caption = u"Select {0} files to import".format(self.key_type_name)
        filters = [(u"{0} files".format(self.key_type_name), [self.keyfile_ext])]
        files = choose_files(self, unique_dlg_name, caption, filters, all_files=False)
        counter = 0
        skipped = 0
        if files:
            for filename in files:
                fpath = os.path.join(config_dir, filename)
                filename = os.path.basename(filename)
                new_key_name = os.path.splitext(os.path.basename(filename))[0]
                with open(fpath,'rb') as keyfile:
                    new_key_value = keyfile.read()
                if self.binary_file:
                    new_key_value = new_key_value.encode('hex')
                elif self.json_file:
                    new_key_value = json.loads(new_key_value)
                match = False
                for key in self.plugin_keys.keys():
                    if uStrCmp(new_key_name, key, True):
                        skipped += 1
                        msg = u"A key with the name <strong>{0}</strong> already exists!\nSkipping key file  <strong>{1}</strong>.\nRename the existing key and import again".format(new_key_name,filename)
                        inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION),
                                _(msg), show_copy_button=False, show=True)
                        match = True
                        break
                if not match:
                    if new_key_value in self.plugin_keys.values():
                        old_key_name = [name for name, value in self.plugin_keys.iteritems() if value == new_key_value][0]
                        skipped += 1
                        info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION),
                                            u"The key in file {0} is the same as the existing key <strong>{1}</strong> and has been skipped.".format(filename,old_key_name), show_copy_button=False, show=True)
                    else:
                        counter += 1
                        self.plugin_keys[new_key_name] = new_key_value

            msg = u""
            if counter+skipped > 1:
                if counter > 0:
                    msg += u"Imported <strong>{0:d}</strong> key {1}. ".format(counter, u"file" if counter == 1 else u"files")
                if skipped > 0:
                    msg += u"Skipped <strong>{0:d}</strong> key {1}.".format(skipped, u"file" if counter == 1 else u"files")
                inf = info_dialog(None, "{0} {1}".format(PLUGIN_NAME, PLUGIN_VERSION),
                                    _(msg), show_copy_button=False, show=True)
        return counter > 0
コード例 #40
0
ファイル: busy.py プロジェクト: MValaguz/MGrep
    def apply_diff(self, identical_msg, cache, syntax_map, changed_names,
                   renamed_names, removed_names, added_names):
        self.view.clear()
        self.apply_diff_calls = calls = []

        def add(args, kwargs):
            self.view.add_diff(*args, **kwargs)
            calls.append((args, kwargs))

        if len(changed_names) + len(renamed_names) + len(removed_names) + len(
                added_names) < 1:
            self.busy.setVisible(False)
            info_dialog(self, _('No changes found'), identical_msg, show=True)
            self.busy.setVisible(True)
            return True

        kwargs = lambda name: {
            'context': self.context,
            'beautify': self.beautify,
            'syntax': syntax_map.get(name, None)
        }

        if isinstance(changed_names, dict):
            for name, other_name in sorted(
                    changed_names.iteritems(),
                    key=lambda x: numeric_sort_key(x[0])):
                args = (name, other_name, cache.left(name),
                        cache.right(other_name))
                add(args, kwargs(name))
        else:
            for name in sorted(changed_names, key=numeric_sort_key):
                args = (name, name, cache.left(name), cache.right(name))
                add(args, kwargs(name))

        for name in sorted(added_names, key=numeric_sort_key):
            args = (_('[%s was added]') % name, name, None, cache.right(name))
            add(args, kwargs(name))

        for name in sorted(removed_names, key=numeric_sort_key):
            args = (name, _('[%s was removed]') % name, cache.left(name), None)
            add(args, kwargs(name))

        for name, new_name in sorted(renamed_names.iteritems(),
                                     key=lambda x: numeric_sort_key(x[0])):
            args = (name, new_name, None, None)
            add(args, kwargs(name))
コード例 #41
0
    def dispatcher(self):
        container = self.current_container  # The book being edited as a container object
        if not container:
            return info_dialog(self.gui, _('No book open'),
                        _('Need to have a book open first.'), show=True)
        if self.parse_current:
            name = editor_name(self.gui.central.current_editor)
            if not name or container.mime_map[name] not in OEB_DOCS:
                return info_dialog(self.gui, _('Cannot Process'),
                        _('No file open for editing or the current file is not an (x)html file.'), show=True)

        self.cleanasawhistle = True
        self.changed_files = []

        from calibre_plugins.diaps_toolbag.dialogs import RemoveDialog
        dlg = RemoveDialog(self.gui)
        if dlg.exec_():
            criteria = dlg.getCriteria()

            # Ensure any in progress editing the user is doing is present in the container
            self.boss.commit_all_editors_to_container()
            self.boss.add_savepoint(_('Before: Span Div Edit'))

            try:
                self.process_files(criteria)
            except Exception:
                # Something bad happened report the error to the user
                import traceback
                error_dialog(self.gui, _('Failed'),
                    _('Failed to process divs or spans, click "Show details" for more info'),
                    det_msg=traceback.format_exc(), show=True)
                # Revert to the saved restore point
                self.boss.revert_requested(self.boss.global_undo.previous_container)
            else:
                if not self.cleanasawhistle:
                    # Show the user what changes we have made,
                    # allowing then to revert them if necessary
                    accepted = ResultsDialog(self.gui, self.changed_files).exec_()
                    if accepted == QDialog.Accepted:
                        self.boss.show_current_diff()
                    # Update the editor UI to take into account all the changes we
                    # have made
                    self.boss.apply_container_update_to_gui()
                else:
                    info_dialog(self.gui, _('Nothing changed'),
                    '<p>{0}'.format(_('Nothing matching your criteria was found.')), show=True)
コード例 #42
0
 def find(self, query):
     if not query:
         return
     try:
         idx = self._model.find(query)
     except ParseException:
         self.search.search_done(False)
         return
     self.search.search_done(True)
     if not idx.isValid():
         info_dialog(self,
                     _('No matches'),
                     _('Could not find any shortcuts matching %s') % query,
                     show=True,
                     show_copy_button=False)
         return
     self.highlight_index(idx)
コード例 #43
0
    def add_books_from_device(self, view, paths=None):
        backloading_err = self.gui.device_manager.device.BACKLOADING_ERROR_MESSAGE
        if backloading_err is not None:
            return error_dialog(self.gui,
                                _('Add to library'),
                                backloading_err,
                                show=True)
        if paths is None:
            rows = view.selectionModel().selectedRows()
            if not rows or len(rows) == 0:
                d = error_dialog(self.gui, _('Add to library'),
                                 _('No book selected'))
                d.exec_()
                return
            paths = [p for p in view.model().paths(rows) if p is not None]
        ve = self.gui.device_manager.device.VIRTUAL_BOOK_EXTENSIONS

        def ext(x):
            ans = os.path.splitext(x)[1]
            ans = ans[1:] if len(ans) > 1 else ans
            return ans.lower()

        remove = set([p for p in paths if ext(p) in ve])
        if remove:
            paths = [p for p in paths if p not in remove]
            info_dialog(self.gui,
                        _('Not Implemented'),
                        _('The following books are virtual and cannot be added'
                          ' to the calibre library:'),
                        '\n'.join(remove),
                        show=True)
            if not paths:
                return
        if not paths or len(paths) == 0:
            d = error_dialog(self.gui, _('Add to library'),
                             _('No book files found'))
            d.exec_()
            return

        self.gui.device_manager.prepare_addable_books(
            self.Dispatcher(partial(self.books_prepared, view)), paths)
        self.bpd = ProgressDialog(_('Downloading books'),
                                  msg=_('Downloading books from device'),
                                  parent=self.gui,
                                  cancelable=False)
        QTimer.singleShot(1000, self.show_bpd)
コード例 #44
0
    def add_fonts(self):
        from calibre.utils.fonts.metadata import FontMetadata
        files = choose_files(self,
                             'add fonts to calibre',
                             _('Select font files'),
                             filters=[(_('TrueType/OpenType Fonts'),
                                       ['ttf', 'otf'])],
                             all_files=False)
        if not files:
            return
        families = set()
        for f in files:
            try:
                with open(f, 'rb') as stream:
                    fm = FontMetadata(stream)
            except:
                import traceback
                error_dialog(
                    self,
                    _('Corrupt font'),
                    _('Failed to read metadata from the font file: %s') % f,
                    det_msg=traceback.format_exc(),
                    show=True)
                return
            families.add(fm.font_family)
        families = sorted(families)

        dest = os.path.join(config_dir, 'fonts')
        for f in files:
            shutil.copyfile(f, os.path.join(dest, os.path.basename(f)))
        self.font_scanner.do_scan()
        self.m.beginResetModel()
        self.build_font_list()
        self.m.endResetModel()
        self.view.setCurrentIndex(self.m.index(0))
        if families:
            for i, val in enumerate(self.families):
                if icu_lower(val) == icu_lower(families[0]):
                    self.view.setCurrentIndex(self.m.index(i))
                    break

        info_dialog(self,
                    _('Added fonts'),
                    _('Added font families: %s') % (', '.join(families)),
                    show=True)
コード例 #45
0
 def stop_server(self):
     self.gui.content_server.threaded_exit()
     self.stopping_msg = info_dialog(
         self,
         _('Stopping'),
         _('Stopping server, this could take upto a minute, please wait...'
           ),
         show_copy_button=False)
     QTimer.singleShot(500, self.check_exited)
コード例 #46
0
    def restore_confirmations(self):
        changed = 0
        for key in tuple(tprefs):
            if key.endswith('_again') and tprefs.get(key) is False:
                del tprefs[key]
                changed += 1
            elif key.startswith('skip_ask_to_show_current_diff_for_'):
                del tprefs[key]
                changed += 1
            elif key == 'questions_to_auto_skip':
                changed += len(tprefs[key] or ())
                del tprefs[key]

        msg = _('There are no disabled confirmation prompts')
        if changed:
            msg = ngettext(
                'One disabled confirmation prompt was restored', '{} disabled confirmation prompts were restored', changed).format(changed)
        info_dialog(self, _('Disabled confirmations restored'), msg, show=True)
コード例 #47
0
ファイル: main.py プロジェクト: pombreda/calibre-1
 def check_multi_selection(self):
     if len(self.selectedItems()) > 1:
         return info_dialog(
             self,
             _('Multiple items selected'),
             _('You are trying to move multiple items at once, this is not supported. Instead use'
               ' Drag and Drop to move multiple items'),
             show=True)
     return True
コード例 #48
0
ファイル: widgets.py プロジェクト: romainsc/calibre
 def help_requested(self):
     d = info_dialog(self, _('About semantics'), _(
         'Semantics refer to additional information about specific locations in the book.'
         ' For example, you can specify that a particular location is the dedication or the preface'
         ' or the table of contents and so on.\n\nFirst choose the type of semantic information, then'
         ' choose a file and optionally a location within the file to point to.\n\nThe'
         ' semantic information will be written in the <guide> section of the opf file.'))
     d.resize(d.sizeHint())
     d.exec_()
コード例 #49
0
    def add_fonts(self):
        families = add_fonts(self)
        if not families:
            return
        self.font_scanner.do_scan()
        self.m.beginResetModel()
        self.build_font_list()
        self.m.endResetModel()
        self.view.setCurrentIndex(self.m.index(0))
        if families:
            for i, val in enumerate(self.families):
                if icu_lower(val) == icu_lower(families[0]):
                    self.view.setCurrentIndex(self.m.index(i))
                    break

        info_dialog(self, _('Added fonts'),
                _('Added font families: %s')%(
                    ', '.join(families)), show=True)
コード例 #50
0
 def toggle_content_server(self):
     if self.gui.content_server is None:
         self.gui.start_content_server()
     else:
         self.gui.content_server.threaded_exit()
         self.stopping_msg = info_dialog(self.gui, _('Stopping'),
                 _('Stopping server, this could take upto a minute, please wait...'),
                 show_copy_button=False)
         QTimer.singleShot(1000, self.check_exited)
コード例 #51
0
ファイル: plugins.py プロジェクト: kobolabs/calibre
 def add_plugin(self):
     info = '' if iswindows else ' [.zip %s]' % _('files')
     path = choose_files(self,
                         'add a plugin dialog',
                         _('Add plugin'),
                         filters=[(_('Plugins') + info, ['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?'), '<p>' + \
                 _('Installing plugins is a <b>security risk</b>. '
                 '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
         try:
             plugin = add_plugin(path)
         except NameConflict as e:
             return error_dialog(self,
                                 _('Already exists'),
                                 unicode(e),
                                 show=True)
         self._plugin_model.populate()
         self._plugin_model.reset()
         self.changed_signal.emit()
         self.check_for_add_to_toolbars(plugin)
         info_dialog(self,
                     _('Success'),
                     _('Plugin <b>{0}</b> successfully installed under <b>'
                       ' {1} plugins</b>. You may have to restart calibre '
                       'for the plugin to take effect.').format(
                           plugin.name, plugin.type),
                     show=True,
                     show_copy_button=False)
         idx = self._plugin_model.plugin_to_index_by_properties(plugin)
         if idx.isValid():
             self.highlight_index(idx)
     else:
         error_dialog(self, _('No valid plugin path'),
                      _('%s is not a valid plugin path') % path).exec_()
コード例 #52
0
ファイル: main.py プロジェクト: tletnes/EmbedComicMetadata
def iterate_over_books(
        ia,
        func,
        title,
        ptext,
        notptext,
        should_convert=None,
        convtext=_L["The following comics were converted to cbz: {}"]):
    '''
    Iterates over all selected books. For each book, it checks if it should be
    converted to cbz and then applies func to the book.
    After all books are processed, gives a completion message.
    '''
    processed = []
    not_processed = []
    converted = []

    if should_convert is None:
        should_convert = prefs["convert_cbr"]

    # iterate through the books
    for book_id in get_selected_books(ia):
        metadata = ComicMetadata(book_id, ia)

        # sanity check
        if metadata.format is None:
            not_processed.append(metadata.info)
            continue

        if should_convert and convert_to_cbz(ia, metadata):
            converted.append(metadata.info)

        if func(metadata):
            processed.append(metadata.info)
        else:
            not_processed.append(metadata.info)

    # show a completion message
    msg = ptext.format(len(processed))
    if should_convert and len(converted) > 0:
        msg += '\n' + convtext.format(lst2string(converted))
    if len(not_processed) > 0:
        msg += '\n' + notptext.format(lst2string(not_processed))
    info_dialog(ia.gui, title, msg, show=True)
コード例 #53
0
    def update_metadata(self):
        """
        Set the metadata in the files in the selected book's record to
        match the current metadata in the database.
        """
        from calibre.ebooks.metadata.meta import set_metadata
        from calibre.gui2 import error_dialog, info_dialog

        # Get currently selected books
        rows = self.gui.library_view.selectionModel().selectedRows()
        if not rows or len(rows) == 0:
            return error_dialog(self.gui,
                                "Cannot update metadata",
                                "No books selected",
                                show=True)
        # Map the rows to book ids
        ids = list(map(self.gui.library_view.model().id, rows))
        db = self.db.new_api
        for book_id in ids:
            # Get the current metadata for this book from the db
            mi = db.get_metadata(book_id, get_cover=True, cover_as_data=True)
            fmts = db.formats(book_id)
            if not fmts:
                continue
            for fmt in fmts:
                fmt = fmt.lower()
                # Get a python file object for the format. This will be either
                # an in memory file or a temporary on disk file
                ffile = db.format(book_id, fmt, as_file=True)
                ffile.seek(0)
                # Set metadata in the format
                set_metadata(ffile, mi, fmt)
                ffile.seek(0)
                # Now replace the file in the calibre library with the updated
                # file. We dont use add_format_with_hooks as the hooks were
                # already run when the file was first added to calibre.
                db.add_format(book_id, fmt, ffile, run_hooks=False)

        info_dialog(
            self,
            "Updated files",
            "Updated the metadata in the files of %d book(s)" % len(ids),
            show=True,
        )
コード例 #54
0
ファイル: boss.py プロジェクト: kmshi/calibre
    def open_book(self, path=None, edit_file=None, clear_notify_data=True):
        if self.gui.action_save.isEnabled():
            if not question_dialog(
                    self.gui, _('Unsaved changes'),
                    _('The current book has unsaved changes. If you open a new book, they will be lost'
                      ' are you sure you want to proceed?')):
                return
        if self.save_manager.has_tasks:
            return info_dialog(
                self.gui,
                _('Cannot open'),
                _('The current book is being saved, you cannot open a new book until'
                  ' the saving is completed'),
                show=True)

        if not hasattr(path, 'rpartition'):
            path = choose_files(self.gui,
                                'open-book-for-tweaking',
                                _('Choose book'),
                                [(_('Books'), [x.lower() for x in SUPPORTED])],
                                all_files=False,
                                select_only_single_file=True)
            if not path:
                return
            path = path[0]

        ext = path.rpartition('.')[-1].upper()
        if ext not in SUPPORTED:
            return error_dialog(
                self.gui,
                _('Unsupported format'),
                _('Tweaking is only supported for books in the %s formats.'
                  ' Convert your book to one of these formats first.') %
                _(' and ').join(sorted(SUPPORTED)),
                show=True)
        if not os.path.exists(path):
            return error_dialog(self.gui,
                                _('File not found'),
                                _('The file %s does not exist.') % path,
                                show=True)

        for name in tuple(editors):
            self.close_editor(name)
        self.gui.preview.clear()
        self.container_count = -1
        if self.tdir:
            shutil.rmtree(self.tdir, ignore_errors=True)
        self.tdir = PersistentTemporaryDirectory()
        self._edit_file_on_open = edit_file
        self._clear_notify_data = clear_notify_data
        self.gui.blocking_job('open_book',
                              _('Opening book, please wait...'),
                              self.book_opened,
                              get_container,
                              path,
                              tdir=self.mkdtemp())
コード例 #55
0
 def find(self, query):
     if not query:
         return
     try:
         idx = self._model.find(query)
     except ParseException:
         self.search.search_done(False)
         return
     self.search.search_done(True)
     if not idx.isValid():
         info_dialog(
             self,
             _('No matches'),
             _('Could not find any tweaks matching <i>{}</i>').format(
                 prepare_string_for_xml(query)),
             show=True,
             show_copy_button=False)
         return
     self.highlight_index(idx)
コード例 #56
0
 def _get_done(self, x, tb):
     if not self.isVisible():
         return self.reject()
     if tb is not None:
         error_dialog(self, _('Scan failed'), _(
             'Failed to scan for external resources, click "Show details" for more information.'),
                      det_msg=tb, show=True)
         self.reject()
     else:
         self.wait.stop()
         self.state = 1
         resources = x
         if not resources:
             info_dialog(self, _('No external resources found'), _(
                 'No external resources were found in this book.'), show=True)
             self.reject()
             return
         self.choose_resources.resources = resources
         self.bb.setVisible(True)
コード例 #57
0
ファイル: ui.py プロジェクト: sdockray/casanova-plugin
 def upload_metadata(self):
     ''' Upload any changes we have made locally to the Casanova metadata server '''
     row = self.get_selected_row()
     if self.gui.current_view() is self.gui.library_view:
         id = self.gui.library_view.model().id(row)
     else:
         id = self.gui.current_view().model().id(row)
     result = self.mm.commit(id)
     if isinstance(result, str):
         return info_dialog(self.gui, 'Casanova message', unicode(result), show=True)
コード例 #58
0
ファイル: search.py プロジェクト: qykth-git/calibre-debian
    def get_results(self):
        # We only want the search plugins to run
        # a maximum set amount of time before giving up.
        self.hang_check += 1
        if self.hang_check >= self.hang_time:
            self.search_pool.abort()
            self.checker.stop()
        else:
            # Stop the checker if not threads are running.
            if not self.search_pool.threads_running() and not self.search_pool.has_tasks():
                self.checker.stop()

        while self.search_pool.has_results():
            res, store_plugin = self.search_pool.get_result()
            if res:
                self.results_view.model().add_result(res, store_plugin)

        if not self.search_pool.threads_running() and not self.results_view.model().has_results():
            info_dialog(self, _('No matches'), _('Couldn\'t find any books matching your query.'), show=True, show_copy_button=False)
コード例 #59
0
 def search_clicked(self):
     search_for = icu_lower(unicode(self.search_box.text()))
     if not search_for:
         error_dialog(self, _('Find'), _('You must enter some text to search for'),
                      show=True, show_copy_button=False)
         return
     row = self.table.currentRow()
     if row < 0:
         row = 0
     rows = self.table.rowCount()
     for i in range(0, rows):
         row += 1
         if row >= rows:
             row = 0
         item = self.table.item(row, 0)
         if search_for in icu_lower(unicode(item.text())):
             self.table.setCurrentItem(item)
             return
     info_dialog(self, _('Find'), _('No tag found'), show=True, show_copy_button=False)
コード例 #60
0
    def check_library(self):
        from calibre.gui2.dialogs.check_library import CheckLibraryDialog, DBCheck
        self.gui.library_view.save_state()
        m = self.gui.library_view.model()
        m.stop_metadata_backup()
        db = m.db
        db.prefs.disable_setting = True

        d = DBCheck(self.gui, db)
        d.start()
        try:
            d.conn.close()
        except:
            pass
        d.break_cycles()
        self.gui.library_moved(db.library_path, call_close=not
                d.closed_orig_conn)
        if d.rejected:
            return
        if d.error is None:
            if not question_dialog(self.gui, _('Success'),
                    _('Found no errors in your calibre library database.'
                        ' Do you want calibre to check if the files in your '
                        ' library match the information in the database?')):
                return
        else:
            return error_dialog(self.gui, _('Failed'),
                    _('Database integrity check failed, click Show details'
                        ' for details.'), show=True, det_msg=d.error[1])

        self.gui.status_bar.show_message(
                _('Starting library scan, this may take a while'))
        try:
            QCoreApplication.processEvents()
            d = CheckLibraryDialog(self.gui, m.db)

            if not d.do_exec():
                info_dialog(self.gui, _('No problems found'),
                        _('The files in your library match the information '
                        'in the database.'), show=True)
        finally:
            self.gui.status_bar.clear_message()