diff --git a/imgsrc/vl.svg b/imgsrc/vl.svg
new file mode 100644
index 0000000000..2ece55e698
--- /dev/null
+++ b/imgsrc/vl.svg
@@ -0,0 +1,746 @@
+
+
+
+
diff --git a/resources/images/vl.png b/resources/images/vl.png
new file mode 100644
index 0000000000..14e3735f06
Binary files /dev/null and b/resources/images/vl.png differ
diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py
index d38f570be5..ea220c15f7 100644
--- a/src/calibre/customize/builtins.py
+++ b/src/calibre/customize/builtins.py
@@ -1037,6 +1037,12 @@ class ActionMarkBooks(InterfaceActionBase):
description = _('Temporarily mark books')
+class ActionVirtualLibrary(InterfaceActionBase):
+ name = 'Virtual Library'
+ actual_plugin = 'calibre.gui2.actions.virtual_library:VirtualLibraryAction'
+ description = _('Change the current Virtual library')
+
+
class ActionStore(InterfaceActionBase):
name = 'Store'
author = 'John Schember'
@@ -1070,7 +1076,8 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
ActionAddToLibrary, ActionEditCollections, ActionMatchBooks, ActionChooseLibrary,
ActionCopyToLibrary, ActionTweakEpub, ActionUnpackBook, ActionNextMatch, ActionStore,
ActionPluginUpdater, ActionPickRandom, ActionEditToC, ActionSortBy,
- ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionTagMapper]
+ ActionMarkBooks, ActionEmbed, ActionTemplateTester, ActionTagMapper,
+ ActionVirtualLibrary]
# }}}
diff --git a/src/calibre/gui2/actions/virtual_library.py b/src/calibre/gui2/actions/virtual_library.py
new file mode 100644
index 0000000000..20655563a6
--- /dev/null
+++ b/src/calibre/gui2/actions/virtual_library.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python2
+# vim:fileencoding=utf-8
+# License: GPLv3 Copyright: 2018, Kovid Goyal
+
+from __future__ import absolute_import, division, print_function, unicode_literals
+
+from PyQt5.Qt import QToolButton
+
+from calibre.gui2.actions import InterfaceAction
+
+
+class VirtualLibraryAction(InterfaceAction):
+
+ name = 'Virtual library'
+ action_spec = (
+ _('Virtual library'), 'vl.png', _('Change the current Virtual library'),
+ None
+ )
+ action_type = 'current'
+ action_add_menu = True
+ popup_type = QToolButton.InstantPopup
+ dont_add_to = frozenset(['context-menu-device', 'menubar-device'])
+
+ def genesis(self):
+ self.menu = m = self.qaction.menu()
+ m.aboutToShow.connect(self.about_to_show_menu)
+
+ def about_to_show_menu(self):
+ self.gui.build_virtual_library_menu(self.menu, add_tabs_action=False)
diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py
index 54afd6ca60..095118904a 100644
--- a/src/calibre/gui2/layout.py
+++ b/src/calibre/gui2/layout.py
@@ -184,7 +184,7 @@ class SearchBar(QFrame): # {{{
x.setPopupMode(x.InstantPopup)
x.setText(_('Virtual library'))
x.setAutoRaise(True)
- x.setIcon(QIcon(I('lt.png')))
+ x.setIcon(QIcon(I('vl.png')))
x.setObjectName("virtual_library")
x.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
l.addWidget(x)
diff --git a/src/calibre/gui2/search_restriction_mixin.py b/src/calibre/gui2/search_restriction_mixin.py
index 8566194500..3385409cc8 100644
--- a/src/calibre/gui2/search_restriction_mixin.py
+++ b/src/calibre/gui2/search_restriction_mixin.py
@@ -366,8 +366,7 @@ class SearchRestrictionMixin(object):
self.apply_virtual_library(cd.library_name)
self.rebuild_vl_tabs()
- def virtual_library_menu_about_to_show(self):
- m = self.virtual_library_menu
+ def build_virtual_library_menu(self, m, add_tabs_action=True):
m.clear()
a = m.addAction(_('Create Virtual library'))
@@ -381,10 +380,11 @@ class SearchRestrictionMixin(object):
self.build_virtual_library_list(a, self.remove_vl_triggered)
m.addMenu(a)
- if gprefs['show_vl_tabs']:
- m.addAction(_('Hide virtual library tabs'), self.vl_tabs.disable_bar)
- else:
- m.addAction(_('Show virtual libraries as tabs'), self.vl_tabs.enable_bar)
+ if add_tabs_action:
+ if gprefs['show_vl_tabs']:
+ m.addAction(_('Hide virtual library tabs'), self.vl_tabs.disable_bar)
+ else:
+ m.addAction(_('Show virtual libraries as tabs'), self.vl_tabs.enable_bar)
m.addSeparator()
@@ -422,6 +422,9 @@ class SearchRestrictionMixin(object):
a = m.addAction(self.checked if vl == current_lib else self.empty, vl.replace('&', '&&'))
a.triggered.connect(partial(self.apply_virtual_library, library=vl))
+ def virtual_library_menu_about_to_show(self):
+ self.build_virtual_library_menu(self.virtual_library_menu)
+
def rebuild_vl_tabs(self):
self.vl_tabs.rebuild()