mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Allow auto scrolling through the list of books by pressing the X key. The speed of scrolling can be controlled in Preferences->Look & feel->Cover browser. Useful to have a "slideshow" of book covers
Fixes #1917634 [[Enhancement] Add slideshow capability to cover browser](https://bugs.launchpad.net/calibre/+bug/1917634)
This commit is contained in:
parent
095515b6e8
commit
75333c2b54
@ -782,3 +782,5 @@ calibre has several keyboard shortcuts to save you time and mouse movement. Thes
|
|||||||
- Re-apply the current sort
|
- Re-apply the current sort
|
||||||
* - :kbd:`Ctrl+Q`
|
* - :kbd:`Ctrl+Q`
|
||||||
- Quit calibre
|
- Quit calibre
|
||||||
|
* - :kbd:`X`
|
||||||
|
- Toggle autoscroll of the book list
|
||||||
|
@ -970,6 +970,12 @@ class ActionOpenFolder(InterfaceActionBase):
|
|||||||
' calibre library')
|
' 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):
|
class ActionSendToDevice(InterfaceActionBase):
|
||||||
name = 'Send To Device'
|
name = 'Send To Device'
|
||||||
actual_plugin = 'calibre.gui2.actions.device:SendToDeviceAction'
|
actual_plugin = 'calibre.gui2.actions.device:SendToDeviceAction'
|
||||||
@ -1115,7 +1121,7 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
|
|||||||
ActionCopyToLibrary, ActionTweakEpub, ActionUnpackBook, ActionNextMatch, ActionStore,
|
ActionCopyToLibrary, ActionTweakEpub, ActionUnpackBook, ActionNextMatch, ActionStore,
|
||||||
ActionPluginUpdater, ActionPickRandom, ActionEditToC, ActionSortBy,
|
ActionPluginUpdater, ActionPickRandom, ActionEditToC, ActionSortBy,
|
||||||
ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionTagMapper, ActionAuthorMapper,
|
ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionTagMapper, ActionAuthorMapper,
|
||||||
ActionVirtualLibrary, ActionBrowseAnnotations, ActionTemplateFunctions]
|
ActionVirtualLibrary, ActionBrowseAnnotations, ActionTemplateFunctions, ActionAutoscrollBooks]
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -2219,7 +2219,7 @@ class Cache(object):
|
|||||||
for book in self._search(expr, virtual_fields=virtual_fields):
|
for book in self._search(expr, virtual_fields=virtual_fields):
|
||||||
c[book].append(lib)
|
c[book].append(lib)
|
||||||
except Exception as e:
|
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()}
|
self.vls_for_books_cache = {b:tuple(sorted(libs, key=sort_key)) for b, libs in c.items()}
|
||||||
if not book_ids:
|
if not book_ids:
|
||||||
book_ids = self._all_book_ids()
|
book_ids = self._all_book_ids()
|
||||||
|
@ -124,7 +124,8 @@ def create_defs():
|
|||||||
'Edit Metadata', 'Send To Device', 'Save To Disk',
|
'Edit Metadata', 'Send To Device', 'Save To Disk',
|
||||||
'Connect Share', 'Copy To Library', None,
|
'Connect Share', 'Copy To Library', None,
|
||||||
'Convert Books', 'View', 'Open Folder', 'Show Book Details',
|
'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
|
defs['show_splash_screen'] = True
|
||||||
@ -198,6 +199,7 @@ def create_defs():
|
|||||||
defs['browse_annots_restrict_to_type'] = None
|
defs['browse_annots_restrict_to_type'] = None
|
||||||
defs['browse_annots_use_stemmer'] = True
|
defs['browse_annots_use_stemmer'] = True
|
||||||
defs['annots_export_format'] = 'txt'
|
defs['annots_export_format'] = 'txt'
|
||||||
|
defs['books_autoscroll_time'] = 2.0
|
||||||
|
|
||||||
|
|
||||||
create_defs()
|
create_defs()
|
||||||
|
23
src/calibre/gui2/actions/auto_scroll.py
Normal file
23
src/calibre/gui2/actions/auto_scroll.py
Normal file
@ -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 <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
@ -9,15 +9,19 @@ __docformat__ = 'restructuredtext en'
|
|||||||
Module to implement the Cover Flow feature
|
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.constants import islinux
|
||||||
from calibre.gui2 import (config, available_height, available_width, gprefs,
|
from calibre.ebooks.metadata import rating_to_stars
|
||||||
rating_font)
|
from calibre.gui2 import (
|
||||||
|
available_height, available_width, config, gprefs, rating_font
|
||||||
|
)
|
||||||
from calibre_extensions import pictureflow
|
from calibre_extensions import pictureflow
|
||||||
|
|
||||||
|
|
||||||
@ -190,6 +194,12 @@ class CoverFlow(pictureflow.PictureFlow):
|
|||||||
if not gprefs['cover_browser_reflections']:
|
if not gprefs['cover_browser_reflections']:
|
||||||
self.setShowReflections(False)
|
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):
|
def set_subtitle_font(self, for_ratings=True):
|
||||||
if for_ratings:
|
if for_ratings:
|
||||||
self.setSubtitleFont(QFont(rating_font()))
|
self.setSubtitleFont(QFont(rating_font()))
|
||||||
@ -295,6 +305,28 @@ class CoverFlowMixin(object):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
pass
|
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):
|
def init_cover_flow_mixin(self):
|
||||||
self.cover_flow = None
|
self.cover_flow = None
|
||||||
self.cf_last_updated_at = None
|
self.cf_last_updated_at = None
|
||||||
|
@ -1290,6 +1290,14 @@ class BooksView(QTableView): # {{{
|
|||||||
self.set_current_row(row, select=False)
|
self.set_current_row(row, select=False)
|
||||||
break
|
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
|
@property
|
||||||
def next_id(self):
|
def next_id(self):
|
||||||
'''
|
'''
|
||||||
|
@ -1518,6 +1518,7 @@ void PictureFlow::timerEvent(QTimerEvent* event)
|
|||||||
|
|
||||||
void PictureFlow::dataChanged() { d->dataChanged(); }
|
void PictureFlow::dataChanged() { d->dataChanged(); }
|
||||||
void PictureFlow::emitcurrentChanged(int index) { emit currentChanged(index); }
|
void PictureFlow::emitcurrentChanged(int index) { emit currentChanged(index); }
|
||||||
|
int PictureFlow::count() const { return d->slideCount(); }
|
||||||
|
|
||||||
int FlowImages::count() { return 0; }
|
int FlowImages::count() { return 0; }
|
||||||
QImage FlowImages::image(int index) { Q_UNUSED(index); return QImage(); }
|
QImage FlowImages::image(int index) { Q_UNUSED(index); return QImage(); }
|
||||||
|
@ -111,6 +111,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setImages(FlowImages *images);
|
void setImages(FlowImages *images);
|
||||||
|
|
||||||
|
int count() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns the dimension of each slide (in pixels).
|
Returns the dimension of each slide (in pixels).
|
||||||
*/
|
*/
|
||||||
@ -221,4 +223,3 @@ private:
|
|||||||
qreal device_pixel_ratio() const;
|
qreal device_pixel_ratio() const;
|
||||||
qreal last_device_pixel_ratio;
|
qreal last_device_pixel_ratio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ public :
|
|||||||
PictureFlow(QWidget *parent /TransferThis/ = 0, int queueLength = 3);
|
PictureFlow(QWidget *parent /TransferThis/ = 0, int queueLength = 3);
|
||||||
|
|
||||||
void setImages(FlowImages *images);
|
void setImages(FlowImages *images);
|
||||||
|
int count();
|
||||||
|
|
||||||
QSize slideSize() const;
|
QSize slideSize() const;
|
||||||
|
|
||||||
|
@ -425,6 +425,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
r('cover_grid_show_title', gprefs)
|
r('cover_grid_show_title', gprefs)
|
||||||
r('tag_browser_show_counts', gprefs)
|
r('tag_browser_show_counts', gprefs)
|
||||||
r('tag_browser_item_padding', gprefs)
|
r('tag_browser_item_padding', gprefs)
|
||||||
|
r('books_autoscroll_time', gprefs)
|
||||||
|
|
||||||
r('qv_respects_vls', gprefs)
|
r('qv_respects_vls', gprefs)
|
||||||
r('qv_dclick_changes_column', gprefs)
|
r('qv_dclick_changes_column', gprefs)
|
||||||
@ -806,6 +807,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
getattr(gui, view + '_view').set_row_header_visibility()
|
getattr(gui, view + '_view').set_row_header_visibility()
|
||||||
gui.library_view.refresh_row_sizing()
|
gui.library_view.refresh_row_sizing()
|
||||||
gui.grid_view.refresh_settings()
|
gui.grid_view.refresh_settings()
|
||||||
|
gui.update_auto_scroll_timeout()
|
||||||
qv = get_quickview_action_plugin()
|
qv = get_quickview_action_plugin()
|
||||||
if qv:
|
if qv:
|
||||||
qv.refill_quickview()
|
qv.refill_quickview()
|
||||||
|
@ -1251,6 +1251,32 @@ them to all have the same width and height</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<widget class="QLabel" name="label_26">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show ne&xt cover during auto scroll after:</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>opt_books_autoscroll_time</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="1">
|
||||||
|
<widget class="QDoubleSpinBox" name="opt_books_autoscroll_time">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> seconds</string>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>1.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>100000.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="quickview_tab">
|
<widget class="QWidget" name="quickview_tab">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user