From e25696f16c8bbdc2362bf285337f65322c33eda9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 24 Apr 2014 14:09:49 +0530 Subject: [PATCH] More QVariant porting --- setup/qt5-migrate.py | 1 + src/calibre/gui2/library/delegates.py | 44 ++++++++++---------- src/calibre/gui2/library/views.py | 6 +-- src/calibre/gui2/metadata/config.py | 8 ++-- src/calibre/gui2/metadata/pdf_covers.py | 4 +- src/calibre/gui2/metadata/single_download.py | 42 +++++++++---------- src/calibre/gui2/tag_browser/view.py | 14 +++---- src/calibre/gui2/wizard/__init__.py | 20 ++++----- 8 files changed, 70 insertions(+), 69 deletions(-) diff --git a/setup/qt5-migrate.py b/setup/qt5-migrate.py index 97462d8958..9fe8a1cc30 100644 --- a/setup/qt5-migrate.py +++ b/setup/qt5-migrate.py @@ -54,6 +54,7 @@ def detect_qvariant(): 'src/calibre/utils/serve_coffee.py': {'toString()'}, 'src/calibre/gui2/job_indicator.py': {'toPoint'}, 'src/calibre/ebooks/pdf/render/engine.py': {'toRect'}, + 'src/calibre/gui2/wizard/send_email.py': {'NONE'}, } for path in all_py_files(): if os.path.basename(path) in { diff --git a/src/calibre/gui2/library/delegates.py b/src/calibre/gui2/library/delegates.py index 3d53eb9624..7b2685e392 100644 --- a/src/calibre/gui2/library/delegates.py +++ b/src/calibre/gui2/library/delegates.py @@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en' import sys from PyQt5.Qt import (Qt, QApplication, QStyle, QIcon, QDoubleSpinBox, QStyleOptionViewItem, - QVariant, QSpinBox, QStyledItemDelegate, QComboBox, QTextDocument, QSize, + QSpinBox, QStyledItemDelegate, QComboBox, QTextDocument, QSize, QAbstractTextDocumentLayout, QFont, QFontInfo, QDate, QDateTimeEdit, QDateTime) from calibre.gui2 import UNDEFINED_QDATETIME, error_dialog, rating_font @@ -79,7 +79,7 @@ class RatingDelegate(QStyledItemDelegate): # {{{ return sb def displayText(self, value, locale): - r = value.toInt()[0] + r = int(value) if r < 0 or r > 5: r = 0 return u'\u2605'*r @@ -107,7 +107,7 @@ class DateDelegate(QStyledItemDelegate): # {{{ self.format = default_format def displayText(self, val, locale): - d = qt_to_dt(val.toDateTime()) + d = qt_to_dt(val) if is_date_undefined(d): return '' return format_date(d, self.format) @@ -126,7 +126,7 @@ class PubDateDelegate(QStyledItemDelegate): # {{{ self.format = 'MMM yyyy' def displayText(self, val, locale): - d = qt_to_dt(val.toDateTime()) + d = qt_to_dt(val) if is_date_undefined(d): return '' return format_date(d, self.format) @@ -135,7 +135,7 @@ class PubDateDelegate(QStyledItemDelegate): # {{{ return DateTimeEdit(parent, self.format) def setEditorData(self, editor, index): - val = index.data(Qt.EditRole).toDate() + val = index.data(Qt.EditRole) if is_date_undefined(val): val = QDate(2000, 1, 1) editor.setDate(val) @@ -166,14 +166,14 @@ class TextDelegate(QStyledItemDelegate): # {{{ return editor def setEditorData(self, editor, index): - ct = unicode(index.data(Qt.DisplayRole).toString()) + ct = unicode(index.data(Qt.DisplayRole) or '') editor.setText(ct) editor.selectAll() def setModelData(self, editor, model, index): if isinstance(editor, EditWithComplete): val = editor.lineEdit().text() - model.setData(index, QVariant(val), Qt.EditRole) + model.setData(index, (val), Qt.EditRole) else: QStyledItemDelegate.setModelData(self, editor, model, index) @@ -208,14 +208,14 @@ class CompleteDelegate(QStyledItemDelegate): # {{{ return editor def setEditorData(self, editor, index): - ct = unicode(index.data(Qt.DisplayRole).toString()) + ct = unicode(index.data(Qt.DisplayRole) or '') editor.setText(ct) editor.selectAll() def setModelData(self, editor, model, index): if isinstance(editor, EditWithComplete): val = editor.lineEdit().text() - model.setData(index, QVariant(val), Qt.EditRole) + model.setData(index, (val), Qt.EditRole) else: QStyledItemDelegate.setModelData(self, editor, model, index) # }}} @@ -228,12 +228,12 @@ class LanguagesDelegate(QStyledItemDelegate): # {{{ return editor def setEditorData(self, editor, index): - ct = unicode(index.data(Qt.DisplayRole).toString()) + ct = unicode(index.data(Qt.DisplayRole) or '') editor.show_initial_value(ct) def setModelData(self, editor, model, index): val = ','.join(editor.lang_codes) - model.setData(index, QVariant(val), Qt.EditRole) + model.setData(index, (val), Qt.EditRole) # }}} class CcDateDelegate(QStyledItemDelegate): # {{{ @@ -250,7 +250,7 @@ class CcDateDelegate(QStyledItemDelegate): # {{{ self.format = format def displayText(self, val, locale): - d = qt_to_dt(val.toDateTime()) + d = qt_to_dt(val) if is_date_undefined(d): return '' return format_date(d, self.format) @@ -271,7 +271,7 @@ class CcDateDelegate(QStyledItemDelegate): # {{{ val = editor.dateTime() if is_date_undefined(val): val = None - model.setData(index, QVariant(val), Qt.EditRole) + model.setData(index, (val), Qt.EditRole) # }}} @@ -291,13 +291,13 @@ class CcTextDelegate(QStyledItemDelegate): # {{{ return editor def setEditorData(self, editor, index): - ct = unicode(index.data(Qt.DisplayRole).toString()) + ct = unicode(index.data(Qt.DisplayRole) or '') editor.setText(ct) editor.selectAll() def setModelData(self, editor, model, index): val = editor.text() - model.setData(index, QVariant(val), Qt.EditRole) + model.setData(index, (val), Qt.EditRole) # }}} class CcNumberDelegate(QStyledItemDelegate): # {{{ @@ -324,7 +324,7 @@ class CcNumberDelegate(QStyledItemDelegate): # {{{ val = editor.value() if val == editor.minimum(): val = None - model.setData(index, QVariant(val), Qt.EditRole) + model.setData(index, (val), Qt.EditRole) def setEditorData(self, editor, index): m = index.model() @@ -353,7 +353,7 @@ class CcEnumDelegate(QStyledItemDelegate): # {{{ val = unicode(editor.currentText()) if not val: val = None - model.setData(index, QVariant(val), Qt.EditRole) + model.setData(index, (val), Qt.EditRole) def setEditorData(self, editor, index): m = index.model() @@ -401,11 +401,11 @@ class CcCommentsDelegate(QStyledItemDelegate): # {{{ editor = CommentsDialog(parent, text, column_name=m.custom_columns[col]['name']) d = editor.exec_() if d: - m.setData(index, QVariant(editor.textbox.html), Qt.EditRole) + m.setData(index, (editor.textbox.html), Qt.EditRole) return None def setModelData(self, editor, model, index): - model.setData(index, QVariant(editor.textbox.html), Qt.EditRole) + model.setData(index, (editor.textbox.html), Qt.EditRole) # }}} class DelegateCB(QComboBox): # {{{ @@ -439,7 +439,7 @@ class CcBoolDelegate(QStyledItemDelegate): # {{{ def setModelData(self, editor, model, index): val = {0:True, 1:False, 2:None}[editor.currentIndex()] - model.setData(index, QVariant(val), Qt.EditRole) + model.setData(index, (val), Qt.EditRole) def setEditorData(self, editor, index): m = index.model() @@ -484,7 +484,7 @@ class CcTemplateDelegate(QStyledItemDelegate): # {{{ editor.textbox.setTabStopWidth(20) d = editor.exec_() if d: - m.setData(index, QVariant(editor.rule[1]), Qt.EditRole) + m.setData(index, (editor.rule[1]), Qt.EditRole) return None def setModelData(self, editor, model, index): @@ -495,7 +495,7 @@ class CcTemplateDelegate(QStyledItemDelegate): # {{{ error_dialog(self.parent(), _('Invalid template'), '

'+_('The template %s is invalid:')%val + '
'+str(err), show=True) - model.setData(index, QVariant(val), Qt.EditRole) + model.setData(index, (val), Qt.EditRole) def setEditorData(self, editor, index): m = index.model() diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index cfe948f527..6b32967b97 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -51,7 +51,7 @@ class HeaderView(QHeaderView): # {{{ opt.orientation = self.orientation() opt.textAlignment = Qt.AlignHCenter | Qt.AlignVCenter model = self.parent().model() - opt.text = model.headerData(logical_index, opt.orientation, Qt.DisplayRole).toString() + opt.text = unicode(model.headerData(logical_index, opt.orientation, Qt.DisplayRole) or '') if self.isSortIndicatorShown() and self.sortIndicatorSection() == logical_index: opt.sortIndicator = QStyleOptionHeader.SortDown if self.sortIndicatorOrder() == Qt.AscendingOrder else QStyleOptionHeader.SortUp opt.text = opt.fontMetrics.elidedText(opt.text, Qt.ElideRight, rect.width() - 4) @@ -294,7 +294,7 @@ class BooksView(QTableView): # {{{ if idx > -1 and idx < len(self.column_map): col = self.column_map[idx] name = unicode(self.model().headerData(idx, Qt.Horizontal, - Qt.DisplayRole).toString()) + Qt.DisplayRole) or '') self.column_header_context_menu = QMenu(self) if col != 'ondevice': self.column_header_context_menu.addAction(_('Hide column %s') % @@ -352,7 +352,7 @@ class BooksView(QTableView): # {{{ for col in hidden_cols: hidx = self.column_map.index(col) name = unicode(self.model().headerData(hidx, Qt.Horizontal, - Qt.DisplayRole).toString()) + Qt.DisplayRole) or '') m.addAction(name, partial(self.column_header_context_handler, action='show', column=col)) diff --git a/src/calibre/gui2/metadata/config.py b/src/calibre/gui2/metadata/config.py index 794156251a..340f23f271 100644 --- a/src/calibre/gui2/metadata/config.py +++ b/src/calibre/gui2/metadata/config.py @@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en' import textwrap from PyQt5.Qt import (QWidget, QGridLayout, QGroupBox, QListView, Qt, QSpinBox, - QDoubleSpinBox, QCheckBox, QLineEdit, QComboBox, QLabel, QVariant) + QDoubleSpinBox, QCheckBox, QLineEdit, QComboBox, QLabel) from calibre.gui2.preferences.metadata_sources import FieldsModel as FM @@ -98,8 +98,8 @@ class ConfigWidget(QWidget): elif opt.type == 'choices': widget = QComboBox(self) for key, label in opt.choices.iteritems(): - widget.addItem(label, QVariant(key)) - idx = widget.findData(QVariant(val)) + widget.addItem(label, (key)) + idx = widget.findData((val)) widget.setCurrentIndex(idx) widget.opt = opt widget.setToolTip(textwrap.fill(opt.desc)) @@ -127,7 +127,7 @@ class ConfigWidget(QWidget): val = w.isChecked() elif isinstance(w, QComboBox): idx = w.currentIndex() - val = unicode(w.itemData(idx).toString()) + val = unicode(w.itemData(idx) or '') self.plugin.prefs[w.opt.name] = val diff --git a/src/calibre/gui2/metadata/pdf_covers.py b/src/calibre/gui2/metadata/pdf_covers.py index 839e157197..d48c0181e3 100644 --- a/src/calibre/gui2/metadata/pdf_covers.py +++ b/src/calibre/gui2/metadata/pdf_covers.py @@ -62,9 +62,9 @@ class PDFCovers(QDialog): @property def cover_path(self): for item in self.covers.selectedItems(): - return unicode(item.data(Qt.UserRole).toString()) + return unicode(item.data(Qt.UserRole) or '') if self.covers.count() > 0: - return unicode(self.covers.item(0).data(Qt.UserRole).toString()) + return unicode(self.covers.item(0).data(Qt.UserRole) or '') def cleanup(self): try: diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py index 5dec1de049..ae950f53a7 100644 --- a/src/calibre/gui2/metadata/single_download.py +++ b/src/calibre/gui2/metadata/single_download.py @@ -20,7 +20,7 @@ from PyQt5.Qt import ( QStyledItemDelegate, QTextDocument, QRectF, QIcon, Qt, QApplication, QDialog, QVBoxLayout, QLabel, QDialogButtonBox, QStyle, QStackedWidget, QWidget, QTableView, QGridLayout, QFontInfo, QPalette, QTimer, pyqtSignal, - QAbstractTableModel, QVariant, QSize, QListView, QPixmap, QModelIndex, + QAbstractTableModel, QSize, QListView, QPixmap, QModelIndex, QUrl, QAbstractListModel, QColor, QRect, QTextBrowser, QStringListModel, QMenu, QCursor) from PyQt5.QtWebKitWidgets import QWebView @@ -30,7 +30,7 @@ from calibre.utils.logging import GUILog as Log from calibre.ebooks.metadata.sources.identify import urls_from_identifiers from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.opf2 import OPF -from calibre.gui2 import error_dialog, NONE, rating_font, gprefs +from calibre.gui2 import error_dialog, rating_font, gprefs from calibre.utils.date import (utcnow, fromordinal, format_date, UNDEFINED_DATE, as_utc) from calibre.library.comments import comments_to_html @@ -57,7 +57,7 @@ class RichTextDelegate(QStyledItemDelegate): # {{{ c = p.color(group, p.HighlightedText) c = 'rgb(%d, %d, %d)'%c.getRgb()[:3] doc.setDefaultStyleSheet(' * { color: %s }'%c) - doc.setHtml(index.data().toString()) + doc.setHtml(index.data() or '') return doc def sizeHint(self, option, index): @@ -131,7 +131,7 @@ class CoverDelegate(QStyledItemDelegate): # {{{ def paint(self, painter, option, index): QStyledItemDelegate.paint(self, painter, option, index) style = QApplication.style() - waiting = self.timer.isActive() and index.data(Qt.UserRole).toBool() + waiting = self.timer.isActive() and bool(index.data(Qt.UserRole)) if waiting: rect = QRect(0, 0, self.spinner_width, self.spinner_width) rect.moveCenter(option.rect.center()) @@ -154,7 +154,7 @@ class ResultsModel(QAbstractTableModel): # {{{ def __init__(self, results, parent=None): QAbstractTableModel.__init__(self, parent) self.results = results - self.yes_icon = QVariant(QIcon(I('ok.png'))) + self.yes_icon = (QIcon(I('ok.png'))) def rowCount(self, parent=None): return len(self.results) @@ -165,10 +165,10 @@ class ResultsModel(QAbstractTableModel): # {{{ def headerData(self, section, orientation, role): if orientation == Qt.Horizontal and role == Qt.DisplayRole: try: - return QVariant(self.COLUMNS[section]) + return (self.COLUMNS[section]) except: - return NONE - return NONE + return None + return None def data_as_text(self, book, col): if col == 0: @@ -187,12 +187,12 @@ class ResultsModel(QAbstractTableModel): # {{{ try: book = self.results[row] except: - return NONE + return None if role == Qt.DisplayRole and col not in self.ICON_COLS: res = self.data_as_text(book, col) if res: - return QVariant(res) - return NONE + return (res) + return None elif role == Qt.DecorationRole and col in self.ICON_COLS: if col == 3 and getattr(book, 'has_cached_cover_url', False): return self.yes_icon @@ -201,13 +201,13 @@ class ResultsModel(QAbstractTableModel): # {{{ elif role == Qt.UserRole: return book elif role == Qt.ToolTipRole and col == 3: - return QVariant( + return ( _('The has cover indication is not fully\n' 'reliable. Sometimes results marked as not\n' 'having a cover will find a cover in the download\n' 'cover stage, and vice versa.')) - return NONE + return None def sort(self, col, order=Qt.AscendingOrder): key = lambda x: x @@ -336,7 +336,7 @@ class Comments(QWebView): # {{{ def link_clicked(self, url): from calibre.gui2 import open_url - if unicode(url.toString()).startswith('http://'): + if unicode(url.toString(QUrl.None)).startswith('http://'): open_url(url) def turnoff_scrollbar(self, *args): @@ -655,7 +655,7 @@ class CoversModel(QAbstractListModel): # {{{ self.plugin_map = {} for i, plugin in enumerate(metadata_plugins(['cover'])): self.covers.append((plugin.name+'\n'+_('Searching...'), - QVariant(self.blank), None, True)) + (self.blank), None, True)) self.plugin_map[plugin] = [i+1] if do_reset: @@ -663,10 +663,10 @@ class CoversModel(QAbstractListModel): # {{{ def get_item(self, src, pmap, waiting=False): sz = '%dx%d'%(pmap.width(), pmap.height()) - text = QVariant(src + '\n' + sz) + text = (src + '\n' + sz) scaled = pmap.scaled(150, 200, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) - return (text, QVariant(scaled), pmap, waiting) + return (text, (scaled), pmap, waiting) def rowCount(self, parent=None): return len(self.covers) @@ -675,14 +675,14 @@ class CoversModel(QAbstractListModel): # {{{ try: text, pmap, cover, waiting = self.covers[index.row()] except: - return NONE + return None if role == Qt.DecorationRole: return pmap if role == Qt.DisplayRole: return text if role == Qt.UserRole: return waiting - return NONE + return None def plugin_for_index(self, index): row = index.row() if hasattr(index, 'row') else index @@ -821,7 +821,7 @@ class CoversView(QListView): # {{{ def show_context_menu(self, point): idx = self.currentIndex() - if idx and idx.isValid() and not idx.data(Qt.UserRole).toPyObject(): + if idx and idx.isValid() and not idx.data(Qt.UserRole): m = QMenu() m.addAction(QIcon(I('view.png')), _('View this cover at full size'), self.show_cover) m.addAction(QIcon(I('edit-copy.png')), _('Copy this cover to clipboard'), self.copy_cover) @@ -834,7 +834,7 @@ class CoversView(QListView): # {{{ pmap = self.model().cc if pmap is not None: from calibre.gui2.viewer.image_popup import ImageView - d = ImageView(self, pmap, unicode(idx.data(Qt.DisplayRole).toString()), geom_name='metadata_download_cover_popup_geom') + d = ImageView(self, pmap, unicode(idx.data(Qt.DisplayRole) or ''), geom_name='metadata_download_cover_popup_geom') d(use_exec=True) def copy_cover(self): diff --git a/src/calibre/gui2/tag_browser/view.py b/src/calibre/gui2/tag_browser/view.py index 8171bde2fa..f7a0fee2d9 100644 --- a/src/calibre/gui2/tag_browser/view.py +++ b/src/calibre/gui2/tag_browser/view.py @@ -29,7 +29,7 @@ class TagDelegate(QStyledItemDelegate): # {{{ self.old_look = gprefs['tag_browser_old_look'] def paint(self, painter, option, index): - item = index.data(Qt.UserRole).toPyObject() + item = index.data(Qt.UserRole) QStyledItemDelegate.paint(self, painter, option, index) widget = self.parent() style = QApplication.style() if widget is None else widget.style() @@ -246,7 +246,7 @@ class TagsView(QTreeView): # {{{ QTreeView.mouseMoveEvent(self, event) return md = self._model.mimeData([dex]) - pixmap = dex.data(Qt.DecorationRole).toPyObject().pixmap(25, 25) + pixmap = dex.data(Qt.DecorationRole).pixmap(25, 25) drag = QDrag(self) drag.setPixmap(pixmap) drag.setMimeData(md) @@ -408,7 +408,7 @@ class TagsView(QTreeView): # {{{ self.context_menu = QMenu(self) if index.isValid(): - item = index.data(Qt.UserRole).toPyObject() + item = index.data(Qt.UserRole) tag = None if item.type == TagTreeItem.TAG: @@ -421,7 +421,7 @@ class TagsView(QTreeView): # {{{ if not item.category_key.startswith('@'): while item.parent != self._model.root_item: item = item.parent - category = unicode(item.name.toString()) + category = unicode(item.name or '') key = item.category_key # Verify that we are working with a field that we know something about if key not in self.db.field_metadata: @@ -626,7 +626,7 @@ class TagsView(QTreeView): # {{{ if not index.isValid(): return src_is_tb = event.mimeData().hasFormat('application/calibre+from_tag_browser') - item = index.data(Qt.UserRole).toPyObject() + item = index.data(Qt.UserRole) if item.type == TagTreeItem.ROOT: return flags = self._model.flags(index) @@ -662,7 +662,7 @@ class TagsView(QTreeView): # {{{ self.model().clear_state() def is_visible(self, idx): - item = idx.data(Qt.UserRole).toPyObject() + item = idx.data(Qt.UserRole) if getattr(item, 'type', None) == TagTreeItem.TAG: idx = idx.parent() return self.isExpanded(idx) @@ -711,7 +711,7 @@ class TagsView(QTreeView): # {{{ def show_item_at_index(self, idx, box=False, position=QTreeView.PositionAtCenter): - if idx.isValid() and idx.data(Qt.UserRole).toPyObject() is not self._model.root_item: + if idx.isValid() and idx.data(Qt.UserRole) is not self._model.root_item: self.expand_parent(idx) self.setCurrentIndex(idx) self.scrollTo(idx, position) diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py index c529e9a8b9..81733e9fb7 100644 --- a/src/calibre/gui2/wizard/__init__.py +++ b/src/calibre/gui2/wizard/__init__.py @@ -12,7 +12,7 @@ from contextlib import closing from PyQt5.Qt import (QWizard, QWizardPage, QPixmap, Qt, QAbstractListModel, - QVariant, QItemSelectionModel, QObject, QTimer, pyqtSignal, QItemSelection) + QItemSelectionModel, QObject, QTimer, pyqtSignal, QItemSelection) from calibre import __appname__, patheq from calibre.library.move import MoveLibrary from calibre.constants import (filesystem_encoding, iswindows, plugins, @@ -26,7 +26,7 @@ from calibre.gui2.wizard.stanza_ui import Ui_WizardPage as StanzaUI from calibre.gui2 import min_available_height, available_width from calibre.utils.config import dynamic, prefs -from calibre.gui2 import NONE, choose_dir, error_dialog +from calibre.gui2 import choose_dir, error_dialog from calibre.gui2.dialogs.progress import ProgressDialog if iswindows: @@ -387,10 +387,10 @@ class ManufacturerModel(QAbstractListModel): def data(self, index, role): if role == Qt.DisplayRole: - return QVariant(self.manufacturers[index.row()]) + return (self.manufacturers[index.row()]) if role == Qt.UserRole: return self.manufacturers[index.row()] - return NONE + return None def index_of(self, man): for i, x in enumerate(self.manufacturers): @@ -411,10 +411,10 @@ class DeviceModel(QAbstractListModel): def data(self, index, role): if role == Qt.DisplayRole: - return QVariant(self.devices[index.row()].name) + return (self.devices[index.row()].name) if role == Qt.UserRole: return self.devices[index.row()] - return NONE + return None def index_of(self, dev): for i, device in enumerate(self.devices): @@ -702,19 +702,19 @@ class LibraryPage(QWizardPage, LibraryUI): return 'English' return get_language(l) - self.language.addItem(get_esc_lang(lang), QVariant(lang)) + self.language.addItem(get_esc_lang(lang), (lang)) items = [(l, get_esc_lang(l)) for l in available_translations() if l != lang] if lang != 'en': items.append(('en', get_esc_lang('en'))) items.sort(cmp=lambda x, y: cmp(x[1], y[1])) for item in items: - self.language.addItem(item[1], QVariant(item[0])) + self.language.addItem(item[1], (item[0])) self.language.blockSignals(False) - prefs['language'] = str(self.language.itemData(self.language.currentIndex()).toString()) + prefs['language'] = str(self.language.itemData(self.language.currentIndex()) or '') def change_language(self, idx): - prefs['language'] = str(self.language.itemData(self.language.currentIndex()).toString()) + prefs['language'] = str(self.language.itemData(self.language.currentIndex()) or '') import __builtin__ __builtin__.__dict__['_'] = lambda(x): x from calibre.utils.localization import set_translators