diff --git a/src/calibre/gui2/icon_theme.py b/src/calibre/gui2/icon_theme.py index 5760bcce10..710bbad3bc 100644 --- a/src/calibre/gui2/icon_theme.py +++ b/src/calibre/gui2/icon_theme.py @@ -15,12 +15,12 @@ from threading import Thread from PyQt5.Qt import ( QImageReader, QFormLayout, QVBoxLayout, QSplitter, QGroupBox, QListWidget, QLineEdit, QSpinBox, QTextEdit, QSize, QListWidgetItem, QIcon, QImage, - QCursor, pyqtSignal, QStackedLayout, QWidget, QLabel, Qt, QComboBox, - QPixmap, QGridLayout, QStyledItemDelegate, QModelIndex, QApplication, - QStaticText, QStyle, QPen + pyqtSignal, QStackedLayout, QWidget, QLabel, Qt, QComboBox, QPixmap, + QGridLayout, QStyledItemDelegate, QModelIndex, QApplication, QStaticText, + QStyle, QPen ) -from calibre import walk, fit_image +from calibre import walk, fit_image, human_readable from calibre.constants import cache_dir, config_dir from calibre.customize.ui import interface_actions from calibre.gui2 import must_use_qt, gprefs, choose_dir, error_dialog, choose_save_file, question_dialog @@ -415,13 +415,15 @@ class Delegate(QStyledItemDelegate): bottom = option.rect.bottom() - 2 painter.drawLine(0, bottom, option.rect.right(), bottom) if 'static-text' not in theme: - theme['static-text'] = QStaticText( + theme['static-text'] = QStaticText(_( '''

{title}

-

by {author} with {number} icons

+

by {author} with {number} icons [{size}]

{description}

+

Version: {version}

'''.format(title=theme.get('title', _('Unknown')), author=theme.get('author', _('Unknown')), - number=theme.get('number', 0), description=theme.get('description', ''))) + number=theme.get('number', 0), description=theme.get('description', ''), + size=human_readable(theme.get('compressed-size', 0)), version=theme.get('version', 1)))) painter.drawStaticText(COVER_SIZE[0] + self.SPACING, option.rect.top() + self.SPACING, theme['static-text']) painter.restore() @@ -457,11 +459,12 @@ class ChooseTheme(Dialog): self.current_theme = json.loads(I('icon-theme.json', data=True))['title'] except Exception: self.current_theme = None - self.changed = False Dialog.__init__(self, _('Choose an icon theme'), 'choose-icon-theme-dialog', parent) self.themes_downloaded.connect(self.show_themes, type=Qt.QueuedConnection) self.cover_downloaded.connect(self.set_cover, type=Qt.QueuedConnection) self.keep_downloading = True + self.commit_changes = None + self.new_theme_title = None def sizeHint(self): desktop = QApplication.instance().desktop() @@ -603,8 +606,7 @@ class ChooseTheme(Dialog): 'Are you sure you want to remove the %s icon theme' ' and return to the stock icons?') % self.current_theme): return - self.changed = True - remove_icon_theme() + self.commit_changes = remove_icon_theme Dialog.accept(self) def accept(self): @@ -614,7 +616,7 @@ class ChooseTheme(Dialog): theme = self.theme_list.currentItem().data(Qt.UserRole) url = BASE_URL + theme['icons-url'] size = theme['compressed-size'] - theme = {k:theme.get(k, '') for k in 'name title'.split()} + theme = {k:theme.get(k, '') for k in 'name title version'.split()} self.keep_downloading = True d = DownloadProgress(self, size) d.canceled_signal.connect(lambda : setattr(self, 'keep_downloading', False)) @@ -626,7 +628,7 @@ class ChooseTheme(Dialog): try: response = get_https_resource_securely(url, get_response=True) while self.keep_downloading: - raw = response.read(100) + raw = response.read(1024) if not raw: break buf.write(raw) @@ -647,23 +649,17 @@ class ChooseTheme(Dialog): 'Failed to download icon theme, click "Show Details" for more information.'), show=True, det_msg=self.downloaded_theme) if ret == d.Rejected or not self.keep_downloading or d.canceled or self.downloaded_theme is None: return - self.changed = True - with BusyCursor(): - self.downloaded_theme.seek(0) - f = decompress(self.downloaded_theme) + dt = self.downloaded_theme + def commit_changes(): + dt.seek(0) + f = decompress(dt) f.seek(0) remove_icon_theme() install_icon_theme(theme, f) + self.commit_changes = commit_changes + self.new_theme_title = theme['title'] return Dialog.accept(self) -class BusyCursor(object): - - def __enter__(self): - QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) - - def __exit__(self, *args): - QApplication.restoreOverrideCursor() - # }}} def remove_icon_theme(): @@ -709,5 +705,7 @@ if __name__ == '__main__': from calibre.gui2 import Application app = Application([]) # create_theme('.') - ChooseTheme().exec_() + d = ChooseTheme() + if d.exec_() == d.Accepted and d.commit_changes is not None: + d.commit_changes() del app diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index 5e2bc3b45d..308877e0c0 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -5,12 +5,14 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' +import json + from threading import Thread from functools import partial from PyQt5.Qt import ( QApplication, QFont, QFontInfo, QFontDialog, QColorDialog, QPainter, - QAbstractListModel, Qt, QIcon, QKeySequence, QColor, pyqtSignal, + QAbstractListModel, Qt, QIcon, QKeySequence, QColor, pyqtSignal, QCursor, QWidget, QSizePolicy, QBrush, QPixmap, QSize, QPushButton, QVBoxLayout) from calibre import human_readable @@ -25,6 +27,14 @@ from calibre.gui2.book_details import get_field_list from calibre.gui2.preferences.coloring import EditRules from calibre.gui2.library.alternate_views import auto_height, CM_TO_INCH +class BusyCursor(object): + + def __enter__(self): + QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) + + def __exit__(self, *args): + QApplication.restoreOverrideCursor() + class DisplayedFields(QAbstractListModel): # {{{ def __init__(self, db, parent=None): @@ -136,6 +146,13 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): r = self.register + try: + self.icon_theme_title = json.loads(I('icon-theme.json', data=True))['name'] + except Exception: + self.icon_theme_title = _('Default icons') + self.icon_theme.setText(_('Icon theme: %s') % self.icon_theme_title) + self.commit_icon_theme = None + self.icon_theme_button.clicked.connect(self.choose_icon_theme) r('gui_layout', config, restart_required=True, choices=[(_('Wide'), 'wide'), (_('Narrow'), 'narrow')]) r('ui_style', gprefs, restart_required=True, choices=[(_('System default'), 'system'), (_('Calibre style'), 'calibre')]) @@ -207,8 +224,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): choices = set([k for k in db.field_metadata.all_field_keys() if (db.field_metadata[k]['is_category'] and (db.field_metadata[k]['datatype'] in ['text', 'series', 'enumeration']) and - not db.field_metadata[k]['display'].get('is_names', False)) - or + not db.field_metadata[k]['display'].get('is_names', False)) or (db.field_metadata[k]['datatype'] in ['composite'] and db.field_metadata[k]['display'].get('make_category', False))]) choices -= set(['authors', 'publisher', 'formats', 'news', 'identifiers']) @@ -281,6 +297,15 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.opt_cover_grid_width.valueChanged.connect(self.update_aspect_ratio) self.opt_cover_grid_height.valueChanged.connect(self.update_aspect_ratio) + def choose_icon_theme(self): + from calibre.gui2.icon_theme import ChooseTheme + d = ChooseTheme(self) + if d.exec_() == d.Accepted: + self.commit_icon_theme = d.commit_changes + self.icon_theme_title = d.new_theme_title or _('Default icons') + self.icon_theme.setText(_('Icon theme: %s') % self.icon_theme_title) + self.changed_signal.emit() + @property def current_cover_size(self): cval = self.opt_cover_grid_height.value() @@ -448,20 +473,24 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.changed_signal.emit() def commit(self, *args): - rr = ConfigWidgetBase.commit(self, *args) - if self.current_font != self.initial_font: - gprefs['font'] = (self.current_font[:4] if self.current_font else - None) - gprefs['font_stretch'] = (self.current_font[4] if self.current_font - is not None else QFont.Unstretched) - QApplication.setFont(self.font_display.font()) - rr = True - self.display_model.commit() - self.edit_rules.commit(self.gui.current_db.prefs) - self.icon_rules.commit(self.gui.current_db.prefs) - self.grid_rules.commit(self.gui.current_db.prefs) - gprefs['cover_grid_color'] = tuple(self.cg_bg_widget.bcol.getRgb())[:3] - gprefs['cover_grid_texture'] = self.cg_bg_widget.btex + with BusyCursor(): + rr = ConfigWidgetBase.commit(self, *args) + if self.current_font != self.initial_font: + gprefs['font'] = (self.current_font[:4] if self.current_font else + None) + gprefs['font_stretch'] = (self.current_font[4] if self.current_font + is not None else QFont.Unstretched) + QApplication.setFont(self.font_display.font()) + rr = True + self.display_model.commit() + self.edit_rules.commit(self.gui.current_db.prefs) + self.icon_rules.commit(self.gui.current_db.prefs) + self.grid_rules.commit(self.gui.current_db.prefs) + gprefs['cover_grid_color'] = tuple(self.cg_bg_widget.bcol.getRgb())[:3] + gprefs['cover_grid_texture'] = self.cg_bg_widget.btex + if self.commit_icon_theme is not None: + self.commit_icon_theme() + rr = True return rr def refresh_gui(self, gui): diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index f83dde019a..a65cdaaa19 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -28,125 +28,27 @@ Main Interface - - - - QComboBox::AdjustToMinimumContentsLengthWithIcon - - - 20 - - - - - - - Enable system &tray icon (needs restart) - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + - User Interface &layout (needs restart): + E&xtra spacing to add between rows in the book list (can be negative): - opt_gui_layout + opt_book_list_extra_row_spacing - - - - - 250 - 16777215 - + + + + px - - QComboBox::AdjustToMinimumContentsLengthWithIcon - - - 20 + + -20 - - - - Disable all animations. Useful if you have a slow/old computer. - - - Disable &animations - - - - - - - Disable &notifications in system tray - - - - - - - Show &splash screen at startup - - - - - - - - - Interface font: - - - font_display - - - - - - - true - - - - - - - - - Change &font (needs restart) - - - - - - - User interface &style (needs restart): - - - opt_ui_style - - - - + &Toolbar @@ -181,7 +83,60 @@ - + + + + + + + Change &font (needs restart) + + + + + + + + 250 + 16777215 + + + + QComboBox::AdjustToMinimumContentsLengthWithIcon + + + 20 + + + + + + + Show &tooltips in the book list + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Enable system &tray icon (needs restart) + + + + Choose &language (requires restart): @@ -191,33 +146,92 @@ - - + + + + + + Interface font: + + + font_display + + + + + + + true + + + + + + + + + + + - + - Show &tooltips in the book list + Disable &notifications in system tray - - + + + + QComboBox::AdjustToMinimumContentsLengthWithIcon + + + 20 + + + + + - Extra &spacing to add between rows in the book list (can be negative): + &User Interface layout (needs restart): - opt_book_list_extra_row_spacing + opt_gui_layout - - - - px + + + + User interface style (&needs restart): - - -20 + + opt_ui_style + + + + + + + Disable all animations. Useful if you have a slow/old computer. + + + Disable &animations + + + + + + + Show &splash screen at startup + + + + + + + Change &icon theme (needs restart) @@ -274,7 +288,7 @@ - &Field to show under the covers: + Field to show &under the covers: opt_field_under_covers_in_grid @@ -468,7 +482,7 @@ A value of zero means calculate automatically. - &Size of the emblems (if any) shown next to the covers: + Size of the emblems (if any) shown &next to the covers: opt_emblem_size @@ -757,7 +771,7 @@ A value of zero means calculate automatically. - Default author link template: + Default author &link template: opt_default_author_link @@ -804,7 +818,7 @@ Manage Authors. You can use the values {author} and - &Collapse when more items than: + Co&llapse when more items than: opt_tags_browser_collapse_at @@ -825,7 +839,7 @@ up into subcategories. If the partition method is set to disable, this value is - Categories not to partition: + Categories &not to partition: opt_tag_browser_dont_collapse