diff --git a/manual/gui.rst b/manual/gui.rst index ab7a9dce22..e8088e96b4 100644 --- a/manual/gui.rst +++ b/manual/gui.rst @@ -782,3 +782,5 @@ calibre has several keyboard shortcuts to save you time and mouse movement. Thes - Re-apply the current sort * - :kbd:`Ctrl+Q` - Quit calibre + * - :kbd:`X` + - Toggle autoscroll of the book list diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 2eed4e46cc..900ef33a4c 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -970,6 +970,12 @@ class ActionOpenFolder(InterfaceActionBase): ' calibre library') +class ActionAutoscrollBooks(InterfaceActionBase): + name = 'Autoscroll Books' + actual_plugin = 'calibre.gui2.actions.auto_scroll:AutoscrollBooksAction' + description = _('Auto scroll through the list of books') + + class ActionSendToDevice(InterfaceActionBase): name = 'Send To Device' actual_plugin = 'calibre.gui2.actions.device:SendToDeviceAction' @@ -1115,7 +1121,7 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog, ActionCopyToLibrary, ActionTweakEpub, ActionUnpackBook, ActionNextMatch, ActionStore, ActionPluginUpdater, ActionPickRandom, ActionEditToC, ActionSortBy, ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionTagMapper, ActionAuthorMapper, - ActionVirtualLibrary, ActionBrowseAnnotations, ActionTemplateFunctions] + ActionVirtualLibrary, ActionBrowseAnnotations, ActionTemplateFunctions, ActionAutoscrollBooks] # }}} diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index 5b9243a7b7..a1f4d0e239 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -2219,7 +2219,7 @@ class Cache(object): for book in self._search(expr, virtual_fields=virtual_fields): c[book].append(lib) except Exception as e: - c[book].append(_('[Error in virtual library {0}: {1}]').format(lib, str(e))) + c[book].append(_('[Error in Virtual library {0}: {1}]').format(lib, str(e))) self.vls_for_books_cache = {b:tuple(sorted(libs, key=sort_key)) for b, libs in c.items()} if not book_ids: book_ids = self._all_book_ids() diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 3fdce7dc2f..55f92f505f 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -124,7 +124,8 @@ def create_defs(): 'Edit Metadata', 'Send To Device', 'Save To Disk', 'Connect Share', 'Copy To Library', None, 'Convert Books', 'View', 'Open Folder', 'Show Book Details', - 'Similar Books', 'Tweak ePub', None, 'Remove Books', + 'Similar Books', 'Tweak ePub', None, 'Remove Books', None, + 'Autoscroll Books' ) defs['show_splash_screen'] = True @@ -198,6 +199,7 @@ def create_defs(): defs['browse_annots_restrict_to_type'] = None defs['browse_annots_use_stemmer'] = True defs['annots_export_format'] = 'txt' + defs['books_autoscroll_time'] = 2.0 create_defs() diff --git a/src/calibre/gui2/actions/auto_scroll.py b/src/calibre/gui2/actions/auto_scroll.py new file mode 100644 index 0000000000..0ba0e63566 --- /dev/null +++ b/src/calibre/gui2/actions/auto_scroll.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +# License: GPLv3 Copyright: 2015, Kovid Goyal + + +from calibre.gui2.actions import InterfaceAction + + +class AutoscrollBooksAction(InterfaceAction): + + name = 'Autoscroll Books' + action_spec = (_('Auto scroll through the book list'), 'auto-scroll.png', + _('Auto scroll through the book list, particularly useful with the cover browser open'), _('X')) + dont_add_to = frozenset(('context-menu-device', 'menubar-device')) + action_type = 'current' + + def genesis(self): + self.qaction.triggered.connect(self.gui.toggle_auto_scroll) + + def location_selected(self, loc): + enabled = loc == 'library' + self.qaction.setEnabled(enabled) + self.menuless_qaction.setEnabled(enabled) diff --git a/src/calibre/gui2/cover_flow.py b/src/calibre/gui2/cover_flow.py index d713dacb26..ad7cc3d6b7 100644 --- a/src/calibre/gui2/cover_flow.py +++ b/src/calibre/gui2/cover_flow.py @@ -9,15 +9,19 @@ __docformat__ = 'restructuredtext en' Module to implement the Cover Flow feature ''' -import sys, os, time +import os +import sys +import time +from qt.core import ( + QAction, QApplication, QDialog, QFont, QImage, QItemSelectionModel, + QKeySequence, QLabel, QSize, QSizePolicy, QStackedLayout, Qt, QTimer, pyqtSignal +) -from qt.core import (QImage, QSizePolicy, QTimer, QDialog, Qt, QSize, QAction, - QStackedLayout, QLabel, pyqtSignal, QKeySequence, QFont, QApplication, QItemSelectionModel) - -from calibre.ebooks.metadata import rating_to_stars from calibre.constants import islinux -from calibre.gui2 import (config, available_height, available_width, gprefs, - rating_font) +from calibre.ebooks.metadata import rating_to_stars +from calibre.gui2 import ( + available_height, available_width, config, gprefs, rating_font +) from calibre_extensions import pictureflow @@ -190,6 +194,12 @@ class CoverFlow(pictureflow.PictureFlow): if not gprefs['cover_browser_reflections']: self.setShowReflections(False) + def one_auto_scroll(self): + if self.currentSlide() >= self.count() - 1: + self.setCurrentSlide(0) + else: + self.showNext() + def set_subtitle_font(self, for_ratings=True): if for_ratings: self.setSubtitleFont(QFont(rating_font())) @@ -295,6 +305,28 @@ class CoverFlowMixin(object): def __init__(self, *args, **kwargs): pass + def one_auto_scroll(self): + cb_visible = self.cover_flow is not None and self.cb_splitter.button.isChecked() + if cb_visible: + self.cover_flow.one_auto_scroll() + else: + self.library_view.show_next_book() + + def toggle_auto_scroll(self): + if not hasattr(self, 'auto_scroll_timer'): + self.auto_scroll_timer = t = QTimer(self) + t.timeout.connect(self.one_auto_scroll) + if self.auto_scroll_timer.isActive(): + self.auto_scroll_timer.stop() + else: + self.one_auto_scroll() + self.auto_scroll_timer.start(int(1000 * gprefs['books_autoscroll_time'])) + + def update_auto_scroll_timeout(self): + if hasattr(self, 'auto_scroll_timer') and self.auto_scroll_timer.isActive(): + self.auto_scroll_timer.stop() + self.toggle_auto_scroll() + def init_cover_flow_mixin(self): self.cover_flow = None self.cf_last_updated_at = None diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index f18d8412a3..6bc5c4c862 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -1290,6 +1290,14 @@ class BooksView(QTableView): # {{{ self.set_current_row(row, select=False) break + def show_next_book(self): + ci = self.currentIndex() + if not ci.isValid(): + self.set_current_row() + return + n = (ci.row() + 1) % self.model().rowCount(QModelIndex()) + self.set_current_row(n) + @property def next_id(self): ''' diff --git a/src/calibre/gui2/pictureflow/pictureflow.cpp b/src/calibre/gui2/pictureflow/pictureflow.cpp index 4aa0c29a04..1069e9108f 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.cpp +++ b/src/calibre/gui2/pictureflow/pictureflow.cpp @@ -1518,6 +1518,7 @@ void PictureFlow::timerEvent(QTimerEvent* event) void PictureFlow::dataChanged() { d->dataChanged(); } void PictureFlow::emitcurrentChanged(int index) { emit currentChanged(index); } +int PictureFlow::count() const { return d->slideCount(); } int FlowImages::count() { return 0; } QImage FlowImages::image(int index) { Q_UNUSED(index); return QImage(); } diff --git a/src/calibre/gui2/pictureflow/pictureflow.h b/src/calibre/gui2/pictureflow/pictureflow.h index 9aeb9652ab..f144cabb24 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.h +++ b/src/calibre/gui2/pictureflow/pictureflow.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -* (C) Copyright 2007 Trolltech ASA +* (C) Copyright 2007 Trolltech ASA * All rights reserved. ** * This is version of the Pictureflow animated image show widget modified by Trolltech ASA. @@ -77,15 +77,15 @@ signals: class PictureFlowPrivate; /*! - Class PictureFlow implements an image show widget with animation effect - like Apple's CoverFlow (in iTunes and iPod). Images are arranged in form - of slides, one main slide is shown at the center with few slides on - the left and right sides of the center slide. When the next or previous - slide is brought to the front, the whole slides flow to the right or - the right with smooth animation effect; until the new slide is finally + Class PictureFlow implements an image show widget with animation effect + like Apple's CoverFlow (in iTunes and iPod). Images are arranged in form + of slides, one main slide is shown at the center with few slides on + the left and right sides of the center slide. When the next or previous + slide is brought to the front, the whole slides flow to the right or + the right with smooth animation effect; until the new slide is finally placed at the center. - */ + */ class PictureFlow : public QWidget { Q_OBJECT @@ -98,7 +98,7 @@ Q_OBJECT public: /*! Creates a new PictureFlow widget. - */ + */ PictureFlow(QWidget* parent = 0, int queueLength = 3); /*! @@ -110,42 +110,44 @@ public: Set the images to be displayed by this widget. */ void setImages(FlowImages *images); - + + int count() const; + /*! Returns the dimension of each slide (in pixels). - */ + */ QSize slideSize() const; /*! Sets the dimension of each slide (in pixels). Do not use this method directly instead use resize which automatically sets an appropriate slide size. - */ + */ void setSlideSize(QSize size); /*! Returns whether aspect ration is preserved when scaling images - */ + */ bool preserveAspectRatio() const; /*! Whether to preserve aspect ration when scaling images - */ + */ void setPreserveAspectRatio(bool preserve); /*! Turn the reflections on/off. - */ + */ void setShowReflections(bool show); bool showReflections() const; /*! Returns the font used to render subtitles - */ + */ QFont subtitleFont() const; /*! Sets the font used to render subtitles - */ + */ void setSubtitleFont(QFont font); @@ -158,20 +160,20 @@ public: Returns QImage of specified slide. This function will be called only whenever necessary, e.g. the 100th slide will not be retrived when only the first few slides are visible. - */ + */ virtual QImage slide(int index) const; /*! Returns the index of slide currently shown in the middle of the viewport. - */ + */ int currentSlide() const; public slots: /*! - Sets slide to be shown in the middle of the viewport. No animation + Sets slide to be shown in the middle of the viewport. No animation effect will be produced, unlike using showSlide. - */ + */ void setCurrentSlide(int index); /*! @@ -194,12 +196,12 @@ public slots: Go to specified slide using animation effect. */ void showSlide(int index); - + /*! Clear all caches and redraw */ void dataChanged(); - + void emitcurrentChanged(int index); signals: @@ -221,4 +223,3 @@ private: qreal device_pixel_ratio() const; qreal last_device_pixel_ratio; }; - diff --git a/src/calibre/gui2/pictureflow/pictureflow.sip b/src/calibre/gui2/pictureflow/pictureflow.sip index 91e6c30e04..ca1108ad37 100644 --- a/src/calibre/gui2/pictureflow/pictureflow.sip +++ b/src/calibre/gui2/pictureflow/pictureflow.sip @@ -35,6 +35,7 @@ public : PictureFlow(QWidget *parent /TransferThis/ = 0, int queueLength = 3); void setImages(FlowImages *images); + int count(); QSize slideSize() const; diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index 9f89128ea4..d57a1708a2 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -425,6 +425,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): r('cover_grid_show_title', gprefs) r('tag_browser_show_counts', gprefs) r('tag_browser_item_padding', gprefs) + r('books_autoscroll_time', gprefs) r('qv_respects_vls', gprefs) r('qv_dclick_changes_column', gprefs) @@ -806,6 +807,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): getattr(gui, view + '_view').set_row_header_visibility() gui.library_view.refresh_row_sizing() gui.grid_view.refresh_settings() + gui.update_auto_scroll_timeout() qv = get_quickview_action_plugin() if qv: qv.refill_quickview() diff --git a/src/calibre/gui2/preferences/look_feel.ui b/src/calibre/gui2/preferences/look_feel.ui index 71c6c61794..6a8d6f4e0c 100644 --- a/src/calibre/gui2/preferences/look_feel.ui +++ b/src/calibre/gui2/preferences/look_feel.ui @@ -1251,6 +1251,32 @@ them to all have the same width and height + + + + Show ne&xt cover during auto scroll after: + + + opt_books_autoscroll_time + + + + + + + seconds + + + 1 + + + 1.000000000000000 + + + 100000.000000000000000 + + +