diff --git a/src/calibre/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index a8e2239105..9b56509351 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -83,8 +83,6 @@ class Device(DeviceConfig, DevicePlugin): ''' FDI_LUNS = {'lun0':0, 'lun1':1, 'lun2':2} FDI_BCD_TEMPLATE = '' - FDI_LUNS = {'lun0':0, 'lun1':1, 'lun2':2} - def reset(self, key='-1', log_packets=False, report_progress=None) : self._main_prefix = self._card_a_prefix = self._card_b_prefix = None diff --git a/src/calibre/ebooks/conversion/cli.py b/src/calibre/ebooks/conversion/cli.py index 4529f060ad..73e1a1e523 100644 --- a/src/calibre/ebooks/conversion/cli.py +++ b/src/calibre/ebooks/conversion/cli.py @@ -211,7 +211,6 @@ def main(args=sys.argv): OptionRecommendation.HIGH) \ for n in parser.options_iter() if n.dest] - print recommendations plumber.merge_ui_recommendations(recommendations) plumber.run() diff --git a/src/calibre/ebooks/pdb/output.py b/src/calibre/ebooks/pdb/output.py index 2095b64ab2..edf047442a 100644 --- a/src/calibre/ebooks/pdb/output.py +++ b/src/calibre/ebooks/pdb/output.py @@ -6,8 +6,9 @@ __docformat__ = 'restructuredtext en' import os -from calibre.customize.conversion import OutputFormatPlugin -from calibre.ebooks.pdb import PDBError, get_writer +from calibre.customize.conversion import OutputFormatPlugin, \ + OptionRecommendation +from calibre.ebooks.pdb import PDBError, get_writer, FORMAT_WRITERS class PDBOutput(OutputFormatPlugin): @@ -15,20 +16,25 @@ class PDBOutput(OutputFormatPlugin): author = 'John Schember' file_type = 'pdb' + options = set([ + OptionRecommendation(name='format', recommended_value='doc', + level=OptionRecommendation.LOW, + short_switch='f', choices=FORMAT_WRITERS.keys(), + help=_('Format to use inside the pdb container. Choices are: ' + '%s' % FORMAT_WRITERS.keys())), + ]) + def convert(self, oeb_book, output_path, input_plugin, opts, log): close = False if not hasattr(output_path, 'write'): - # Determine the format to write based upon the sub extension - format = os.path.splitext(os.path.splitext(output_path)[0])[1][1:] close = True if not os.path.exists(os.path.dirname(output_path)) and os.path.dirname(output_path) != '': os.makedirs(os.path.dirname(output_path)) out_stream = open(output_path, 'wb') else: - format = os.path.splitext(os.path.splitext(output_path.name)[0])[1][1:] out_stream = output_path - Writer = get_writer(format) + Writer = get_writer(opts.format) if Writer is None: raise PDBError('No writer avaliable for format %s.' % format) diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py index 948cf4f3af..bd99864dbd 100644 --- a/src/calibre/gui2/add.py +++ b/src/calibre/gui2/add.py @@ -7,7 +7,7 @@ from PyQt4.Qt import QThread, SIGNAL, QMutex, QWaitCondition, Qt from calibre.gui2.dialogs.progress import ProgressDialog from calibre.constants import preferred_encoding -from calibre.gui2.widgets import WarningDialog +from calibre.gui2 import warning_dialog class Add(QThread): @@ -113,13 +113,13 @@ class AddFiles(Add): def process_duplicates(self): if self.duplicates: - files = _('

Books with the same title as the following already ' - 'exist in the database. Add them anyway?

', parent=self._parent) + files += mi.title+'\n' + d = warning_dialog(_('Duplicates found!'), + _('Books with the same title as the following already ' + 'exist in the database. Add them anyway?'), + files, parent=self._parent) if d.exec_() == d.Accepted: num = self.db.add_books(*self.duplicates, **dict(add_duplicates=True))[1] @@ -221,19 +221,19 @@ class AddRecursive(Add): def process_duplicates(self): if self.duplicates: - files = _('

Books with the same title as the following already ' - 'exist in the database. Add them anyway?

', parent=self._parent) + files += title+'\n' + d = warning_dialog(_('Duplicates found!'), + _('Books with the same title as the following already ' + 'exist in the database. Add them anyway?'), + files, parent=self._parent) if d.exec_() == d.Accepted: for mi, formats in self.duplicates: self.db.import_book(mi, formats, notify=False) self.number_of_books_added += 1 - \ No newline at end of file + diff --git a/src/calibre/gui2/convert/bulk.py b/src/calibre/gui2/convert/bulk.py new file mode 100644 index 0000000000..d6d03c9aec --- /dev/null +++ b/src/calibre/gui2/convert/bulk.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- + +__license__ = 'GPL 3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +import sys + +from PyQt4.Qt import QString, SIGNAL + +from calibre.gui2.convert.single import Config, sort_formats_by_preference, \ + GroupModel +from calibre.customize.ui import available_output_formats +from calibre.gui2 import ResizableDialog +from calibre.gui2.convert.look_and_feel import LookAndFeelWidget +from calibre.gui2.convert.page_setup import PageSetupWidget +from calibre.gui2.convert import GuiRecommendations +from calibre.ebooks.conversion.plumber import Plumber, OUTPUT_FORMAT_PREFERENCES +from calibre.utils.logging import Log + +class BulkConfig(Config): + + def __init__(self, parent, db, preferred_output_format=None): + ResizableDialog.__init__(self, parent) + + self.setup_output_formats(db, preferred_output_format) + self.db = db + + self.setup_pipeline() + + self.input_formats.hide() + + self.connect(self.output_formats, SIGNAL('currentIndexChanged(QString)'), + self.setup_pipeline) + self.connect(self.groups, SIGNAL('activated(QModelIndex)'), + self.show_pane) + self.connect(self.groups, SIGNAL('clicked(QModelIndex)'), + self.show_pane) + self.connect(self.groups, SIGNAL('entered(QModelIndex)'), + self.show_group_help) + self.groups.setMouseTracking(True) + + + def setup_pipeline(self, *args): + oidx = self.groups.currentIndex().row() + output_format = self.output_format + + input_path = 'dummy.epub' + output_path = 'dummy.'+output_format + log = Log() + log.outputs = [] + self.plumber = Plumber(input_path, output_path, log) + + def widget_factory(cls): + return cls(self.stack, self.plumber.get_option_by_name, + self.plumber.get_option_help, self.db) + + self.setWindowTitle(_('Bulk Convert')) + lf = widget_factory(LookAndFeelWidget) + ps = widget_factory(PageSetupWidget) + + output_widget = None + name = 'calibre.gui2.convert.%s' % self.plumber.output_plugin.name.lower().replace(' ', '_') + try: + __import__(name) + output_widget = sys.modules[name] + pw = output_widget.PluginWidget + pw.ICON = ':/images/back.svg' + pw.HELP = _('Options specific to the output format.') + output_widget = widget_factory(pw) + except ImportError: + pass + + while True: + c = self.stack.currentWidget() + if not c: break + self.stack.removeWidget(c) + + widgets = [lf, ps] + if output_widget is not None: + widgets.append(output_widget) + for w in widgets: + self.stack.addWidget(w) + self.connect(w, SIGNAL('set_help(PyQt_PyObject)'), + self.help.setPlainText) + + self._groups_model = GroupModel(widgets) + self.groups.setModel(self._groups_model) + + idx = oidx if -1 < oidx < self._groups_model.rowCount() else 0 + self.groups.setCurrentIndex(self._groups_model.index(idx)) + + + def setup_output_formats(self, db, preferred_output_format): + available_formats = '' + available_formats = set([x.lower() for x in + available_formats.split(',')]) + output_formats = sorted(available_output_formats()) + output_formats.remove('oeb') + preferred_output_format = preferred_output_format if \ + preferred_output_format in output_formats else \ + sort_formats_by_preference(output_formats, + OUTPUT_FORMAT_PREFERENCES)[0] + self.output_formats.addItems(list(map(QString, [x.upper() for x in + output_formats]))) + self.output_formats.setCurrentIndex(output_formats.index(preferred_output_format)) + + def accept(self): + recs = GuiRecommendations() + for w in self._groups_model.widgets: + x = w.commit(save_defaults=False) + recs.update(x) + self._recommendations = recs + ResizableDialog.accept(self) + + diff --git a/src/calibre/gui2/convert/gui_conversion.py b/src/calibre/gui2/convert/gui_conversion.py index 1d41b4ec29..8f25acb7be 100644 --- a/src/calibre/gui2/convert/gui_conversion.py +++ b/src/calibre/gui2/convert/gui_conversion.py @@ -4,8 +4,6 @@ __license__ = 'GPL 3' __copyright__ = '2009, John Schember ' __docformat__ = 'restructuredtext en' -import logging - from calibre.ebooks.conversion.plumber import Plumber from calibre.utils.logging import Log diff --git a/src/calibre/gui2/convert/pdb_output.py b/src/calibre/gui2/convert/pdb_output.py new file mode 100644 index 0000000000..db52db8f46 --- /dev/null +++ b/src/calibre/gui2/convert/pdb_output.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +__license__ = 'GPL 3' +__copyright__ = '2009, John Schember ' +__docformat__ = 'restructuredtext en' + +from calibre.gui2.convert.pdb_output_ui import Ui_Form +from calibre.gui2.convert import Widget +from calibre.ebooks.pdb import FORMAT_WRITERS +from calibre.gui2.widgets import BasicComboModel + +format_model = None + +class PluginWidget(Widget, Ui_Form): + + TITLE = _('PDB Output') + + def __init__(self, parent, get_option, get_help, db=None, book_id=None): + Widget.__init__(self, parent, 'pdb_output', ['format']) + self.db, self.book_id = db, book_id + self.initialize_options(get_option, get_help, db, book_id) + + global format_model + if format_model is None: + format_model = BasicComboModel(FORMAT_WRITERS.keys()) + self.format_model = format_model + self.opt_format.setModel(self.format_model) + diff --git a/src/calibre/gui2/convert/pdb_output.ui b/src/calibre/gui2/convert/pdb_output.ui new file mode 100644 index 0000000000..5f21031233 --- /dev/null +++ b/src/calibre/gui2/convert/pdb_output.ui @@ -0,0 +1,44 @@ + + + Form + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Format: + + + + + + + + + + Qt::Vertical + + + + 148 + 246 + + + + + + + + + diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 1c990f7e8b..cf04e18ae6 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -21,18 +21,12 @@ from calibre.gui2 import config, error_dialog, Dispatcher, dynamic, \ pixmap_to_data, warning_dialog, \ info_dialog from calibre.ebooks.metadata import authors_to_string -from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog from calibre import sanitize_file_name, preferred_encoding from calibre.utils.filenames import ascii_filename from calibre.devices.errors import FreeSpaceError from calibre.utils.smtp import compose_mail, sendmail, extract_email_address, \ config as email_config -def warning(title, msg, details, parent): - from calibre.gui2.widgets import WarningDialog - WarningDialog(title, msg, details, parent).exec_() - - class DeviceJob(Job): def __init__(self, func, *args, **kwargs): @@ -530,13 +524,13 @@ class DeviceGUI(object): good.append(title) if errors: errors = '\n'.join([ - '
  • %s
    %s
    %s
  • ' % - (title, e, tb.replace('\n', '
    ')) for \ + '%s\n\n%s\n%s\n' % + (title, e, tb) for \ title, e, tb in errors ]) - ConversionErrorDialog(self, _('Failed to email books'), - '

    '+_('Failed to email the following books:')+\ - '

      %s
    '%errors, + error_dialog(self, _('Failed to email books'), + _('Failed to email the following books:'), + '%s'%errors, show=True) else: self.status_bar.showMessage(_('Sent by email:') + ', '.join(good), diff --git a/src/calibre/gui2/dialogs/warning.ui b/src/calibre/gui2/dialogs/warning.ui deleted file mode 100644 index 11c2e95cad..0000000000 --- a/src/calibre/gui2/dialogs/warning.ui +++ /dev/null @@ -1,113 +0,0 @@ - - Dialog - - - - 0 - 0 - 727 - 432 - - - - Dialog - - - - :/images/dialog_warning.svg:/images/dialog_warning.svg - - - - - - TextLabel - - - true - - - - - - - - - - - - - - :/images/dialog_warning.svg - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - Dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 97e4c24d53..6bea660294 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -24,7 +24,7 @@ from calibre.gui2 import APP_UID, warning_dialog, choose_files, error_dialog, \ max_available_height, config, info_dialog, \ available_width, GetMetadata from calibre.gui2.cover_flow import CoverFlow, DatabaseImages, pictureflowerror -from calibre.gui2.widgets import ProgressIndicator, WarningDialog +from calibre.gui2.widgets import ProgressIndicator from calibre.gui2.dialogs.scheduler import Scheduler from calibre.gui2.update import CheckForUpdates from calibre.gui2.dialogs.progress import ProgressDialog @@ -36,8 +36,8 @@ from calibre.gui2.jobs2 import JobManager from calibre.gui2.dialogs.metadata_single import MetadataSingleDialog from calibre.gui2.dialogs.metadata_bulk import MetadataBulkDialog from calibre.gui2.dialogs.jobs import JobsDialog -from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog -from calibre.gui2.tools import convert_single_ebook, fetch_scheduled_recipe +from calibre.gui2.tools import convert_single_ebook, convert_bulk_ebook, \ + fetch_scheduled_recipe from calibre.gui2.dialogs.config import ConfigDialog from calibre.gui2.dialogs.search import SearchDialog from calibre.gui2.dialogs.choose_format import ChooseFormatDialog @@ -89,7 +89,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.persistent_files = [] self.metadata_dialogs = [] self.default_thumbnail = None - self.device_error_dialog = ConversionErrorDialog(self, + self.device_error_dialog = error_dialog(self, _('Error'), _('Error communicating with device'), ' ') self.device_error_dialog.setModal(Qt.NonModal) self.tb_wrapper = textwrap.TextWrapper(width=40) @@ -865,16 +865,16 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): db = self.library_view.model().refresh_ids( x.updated, cr) if x.failures: - details = ['
  • %s: %s
  • '%(title, reason) for title, + details = ['%s: %s'%(title, reason) for title, reason in x.failures.values()] - details = '

      %s

    '%(''.join(details)) - WarningDialog(_('Failed to download some metadata'), + details = '%s\n'%('\n'.join(details)) + warning_dialog(_('Failed to download some metadata'), _('Failed to download metadata for the following:'), details, self).exec_() else: err = _('Failed to download metadata:')+\ '
    '+x.tb+'
    ' - ConversionErrorDialog(self, _('Error'), err, + error_dialog(self, _('Error'), err, show=True) @@ -1047,28 +1047,27 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): d = error_dialog(self, _('Cannot convert'), _('No books selected')) d.exec_() - return [], [] + return None return [self.library_view.model().db.id(r) for r in rows] def convert_bulk(self, checked): - r = self.get_books_for_conversion() - if r is None: - return - comics, others = r - - res = convert_bulk_ebooks(self, - self.library_view.model().db, comics, others) - if res is None: - return - jobs, changed = res + row_ids = self.get_books_for_conversion() + if row_ids is None: return + previous = self.library_view.currentIndex() + rows = [x.row() for x in \ + self.library_view.selectionModel().selectedRows()] + jobs, changed, bad = convert_bulk_ebook(self, + self.library_view.model().db, row_ids) for func, args, desc, fmt, id, temp_files in jobs: - job = self.job_manager.run_job(Dispatcher(self.book_converted), + if id not in bad: + job = self.job_manager.run_job(Dispatcher(self.book_converted), func, args=args, description=desc) - self.conversion_jobs[job] = (temp_files, fmt, id) + self.conversion_jobs[job] = (temp_files, fmt, id) if changed: - self.library_view.model().resort(reset=False) - self.library_view.model().research() + self.library_view.model().refresh_rows(rows) + current = self.library_view.currentIndex() + self.library_view.model().current_changed(current, previous) def convert_single(self, checked): row_ids = self.get_books_for_conversion() @@ -1431,7 +1430,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): return if isinstance(job.exception, JobKilled): return - ConversionErrorDialog(self, _('Conversion Error'), job.gui_text(), + error_dialog(self, _('Conversion Error'), job.gui_text(), show=True) diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index a8407df767..ceeee60ab5 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -16,6 +16,7 @@ from calibre.gui2 import warning_dialog from calibre.gui2.convert import load_specifics from calibre.gui2.convert.single import NoSupportedInputFormats from calibre.gui2.convert.single import Config as SingleConfig +from calibre.gui2.convert.bulk import BulkConfig def convert_single_ebook(parent, db, book_ids, auto_conversion=False, out_format=None): changed = False @@ -71,109 +72,59 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, out_format return jobs, changed, bad -def convert_bulk_ebooks(*args): - pass - #(fmt, parent, db, comics, others): - if others: - d = get_dialog(fmt)(parent, db) - if d.exec_() != QDialog.Accepted: - others, user_mi = [], None - else: - opts = d.opts - opts.verbose = 2 - user_mi = d.user_mi - if comics: - comic_opts = ComicConf.get_bulk_conversion_options(parent) - if not comic_opts: - comics = [] - bad_rows = [] +def convert_bulk_ebook(parent, db, book_ids): + changed = False jobs = [] - total = sum(map(len, (others, comics))) + bad = [] + + total = len(book_ids) if total == 0: - return - parent.status_bar.showMessage(_('Starting Bulk conversion of %d books')%total, 2000) + return None, None, None + parent.status_bar.showMessage(_('Starting conversion of %d books') % total, 2000) - for i, row in enumerate(others+comics): - row_id = db.id(row) - if row in others: - data = None - for _fmt in EPUB_PREFERRED_SOURCE_FORMATS: - try: - data = db.format(row, _fmt.upper()) - if data is not None: - break - except: - continue - if data is None: - bad_rows.append(row) - continue - options = opts.copy() - mi = db.get_metadata(row) - if user_mi is not None: - if user_mi.series_index == 1: - user_mi.series_index = None - mi.smart_update(user_mi) - db.set_metadata(db.id(row), mi) - opf = OPFCreator(os.getcwdu(), mi) - opf_file = PersistentTemporaryFile('.opf') - opf.render(opf_file) - opf_file.close() - pt = PersistentTemporaryFile('.'+_fmt.lower()) - pt.write(data) - pt.close() - of = PersistentTemporaryFile('.'+fmt) - of.close() - cover = db.cover(row) - cf = None - if cover: - cf = PersistentTemporaryFile('.jpeg') - cf.write(cover) - cf.close() - options.cover = cf.name - options.output = of.name - options.from_opf = opf_file.name - args = [options, pt.name] - desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) - temp_files = [cf] if cf is not None else [] - temp_files.extend([opf_file, pt, of]) - jobs.append(('any2'+fmt, args, desc, fmt.upper(), row_id, temp_files)) - else: - options = comic_opts.copy() - mi = db.get_metadata(row) - if mi.title: - options.title = mi.title - if mi.authors: - options.author = ','.join(mi.authors) - data = None - for _fmt in ['cbz', 'cbr']: - try: - data = db.format(row, _fmt.upper()) - if data is not None: - break - except: - continue + d = BulkConfig(parent, db) + if d.exec_() != QDialog.Accepted: + return jobs, changed, bad - pt = PersistentTemporaryFile('.'+_fmt.lower()) - pt.write(data) - pt.close() - of = PersistentTemporaryFile('.'+fmt) - of.close() - setattr(options, 'output', of.name) - options.verbose = 1 - args = [pt.name, options] - desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) - jobs.append(('comic2'+fmt, args, desc, fmt.upper(), row_id, [pt, of])) + output_format = d.output_format + recs = cPickle.loads(d.recommendations) - if bad_rows: + for i, book_id in enumerate(book_ids): + temp_files = [] + + try: + d = SingleConfig(parent, db, book_id, None, output_format) + d.accept() + + mi = db.get_metadata(book_id, True) + in_file = db.format_abspath(book_id, d.input_format, True) + + out_file = PersistentTemporaryFile('.' + output_format) + out_file.write(output_format) + out_file.close() + + desc = _('Convert book %d of %d (%s)') % (i + 1, total, repr(mi.title)) + + args = [in_file, out_file.name, recs] + temp_files = [out_file] + jobs.append(('gui_convert', args, desc, d.output_format.upper(), book_id, temp_files)) + + changed = True + except NoSupportedInputFormats: + bad.append(book_id) + + if bad != []: res = [] - for row in bad_rows: - title = db.title(row) - res.append('
  • %s
  • '%title) + for id in bad: + title = db.title(id, True) + res.append('%s'%title) - msg = _('

    Could not convert %d of %d books, because no suitable source format was found.

      %s
    ')%(len(res), total, '\n'.join(res)) - warning_dialog(parent, _('Could not convert some books'), msg).exec_() + msg = '%s' % '\n'.join(res) + warning_dialog(parent, _('Could not convert some books'), + _('Could not convert %d of %d books, because no suitable source format was found.' % (len(res), total)), + msg).exec_() - return jobs, False + return jobs, changed, bad def _fetch_news(data, fmt): pt = PersistentTemporaryFile(suffix='_feeds2%s.%s'%(fmt.lower(), fmt.lower())) diff --git a/src/calibre/gui2/widgets.py b/src/calibre/gui2/widgets.py index 7f3487f035..db36daa784 100644 --- a/src/calibre/gui2/widgets.py +++ b/src/calibre/gui2/widgets.py @@ -19,7 +19,6 @@ from calibre import fit_image from calibre.utils.fontconfig import find_font_families from calibre.ebooks.metadata.meta import metadata_from_filename from calibre.utils.config import prefs -from calibre.gui2.dialogs.warning_ui import Ui_Dialog as Ui_WarningDialog class ProgressIndicator(QWidget): @@ -56,16 +55,6 @@ class ProgressIndicator(QWidget): self.movie.setPaused(True) self.setVisible(False) - -class WarningDialog(QDialog, Ui_WarningDialog): - - def __init__(self, title, msg, details, parent=None): - QDialog.__init__(self, parent) - self.setupUi(self) - self.setWindowTitle(title) - self.msg.setText(msg) - self.details.setText(details) - class FilenamePattern(QWidget, Ui_Form): def __init__(self, parent): @@ -305,6 +294,31 @@ class FontFamilyModel(QAbstractListModel): def index_of(self, family): return self.families.index(family.strip()) +class BasicComboModel(QAbstractListModel): + + def __init__(self, items, *args): + QAbstractListModel.__init__(self, *args) + self.items = [i for i in items] + self.items.sort() + + def rowCount(self, *args): + return len(self.items) + + def data(self, index, role): + try: + item = self.items[index.row()] + except: + traceback.print_exc() + return NONE + if role == Qt.DisplayRole: + return QVariant(item) + if role == Qt.FontRole: + return QVariant(QFont(item)) + return NONE + + def index_of(self, item): + return self.items.index(item.strip()) + class BasicListItem(QListWidgetItem):