2 # -*- coding: utf-8 -*-
3 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
6 __docformat__
= 'restructuredtext en'
9 import os
, struct
, time
11 from StringIO
import StringIO
13 from io
import StringIO
14 from traceback
import print_exc
16 from PyQt5
.Qt
import (Qt
, QDialog
, QPixmap
, QIcon
, QLabel
, QHBoxLayout
, QFont
, QTableWidgetItem
)
18 from calibre
.utils
.config
import config_dir
19 from calibre
.constants
import iswindows
, DEBUG
20 from calibre
import prints
21 from calibre
.gui2
import (error_dialog
, gprefs
)
22 from calibre
.gui2
.actions
import menu_action_unique_name
24 from calibre_plugins
.obok_dedrm
.__init
__ import (PLUGIN_NAME
,
25 PLUGIN_SAFE_NAME
, PLUGIN_VERSION
, PLUGIN_DESCRIPTION
)
28 plugin_icon_resources
= {}
31 from calibre
.gui2
import QVariant
35 convert_qvariant
= lambda x
: x
39 def convert_qvariant(x
):
44 return [convert_qvariant(i
) for i
in x
.toList()]
48 def debug_print(*args
):
51 BASE_TIME
= time
.time()
53 prints('DEBUG: %6.1f'%(time
.time()-BASE_TIME
), *args
)
56 debug_print("obok::utilities.py - loading translations")
59 debug_print("obok::utilities.py - exception when loading translations")
60 pass # load_translations() added in calibre 1.9
62 def format_plural(number
, possessive
=False):
64 Cosmetic ditty to provide the proper string formatting variable to handle singular/plural situations
66 :param: number: variable that represents the count/len of something
69 return '' if number
== 1 else 's'
70 return '\'s' if number
== 1 else 's\''
73 def set_plugin_icon_resources(name
, resources
):
75 Set our global store of plugin name and icon resources for sharing between
76 the InterfaceAction class which reads them and the ConfigWidget
77 if needed for use on the customization dialog for this plugin.
79 global plugin_icon_resources
, plugin_ID
81 plugin_icon_resources
= resources
83 def get_icon(icon_name
):
85 Retrieve a QIcon for the named image from the zip file if it exists,
86 or if not then from Calibre's image cache.
89 pixmap
= get_pixmap(icon_name
)
91 # Look in Calibre's cache for the icon
92 return QIcon(I(icon_name
))
97 def get_pixmap(icon_name
):
99 Retrieve a QPixmap for the named image
100 Any icons belonging to the plugin must be prefixed with 'images/'
102 if not icon_name
.startswith('images/'):
103 # We know this is definitely not an icon belonging to this plugin
105 pixmap
.load(I(icon_name
))
108 # Check to see whether the icon exists as a Calibre resource
109 # This will enable skinning if the user stores icons within a folder like:
110 # ...\AppData\Roaming\calibre\resources\images\Plugin Name\
112 local_images_dir
= get_local_images_dir(plugin_ID
)
113 local_image_path
= os
.path
.join(local_images_dir
, icon_name
.replace('images/', ''))
114 if os
.path
.exists(local_image_path
):
116 pixmap
.load(local_image_path
)
119 # As we did not find an icon elsewhere, look within our zip resources
120 if icon_name
in plugin_icon_resources
:
122 pixmap
.loadFromData(plugin_icon_resources
[icon_name
])
126 def get_local_images_dir(subfolder
=None):
128 Returns a path to the user's local resources/images folder
129 If a subfolder name parameter is specified, appends this to the path
131 images_dir
= os
.path
.join(config_dir
, 'resources/images')
133 images_dir
= os
.path
.join(images_dir
, subfolder
)
135 images_dir
= os
.path
.normpath(images_dir
)
138 def showErrorDlg(errmsg
, parent
, trcbk
=False):
140 Wrapper method for calibre's error_dialog
146 error_mess
= f
.getvalue().splitlines()
147 for line
in error_mess
:
148 error
= error
+ str(line
) + '\n'
149 errmsg
= errmsg
+ '\n\n' + error
150 return error_dialog(parent
, _(PLUGIN_NAME
+ ' v' + PLUGIN_VERSION
),
151 _(errmsg
), show
=True)
153 class SizePersistedDialog(QDialog
):
155 This dialog is a base class for any dialogs that want their size/position
156 restored when they are next opened.
158 def __init__(self
, parent
, unique_pref_name
):
159 QDialog
.__init
__(self
, parent
)
160 self
.unique_pref_name
= unique_pref_name
161 self
.geom
= gprefs
.get(unique_pref_name
, None)
162 self
.finished
.connect(self
.dialog_closing
)
164 def resize_dialog(self
):
165 if self
.geom
is None:
166 self
.resize(self
.sizeHint())
168 self
.restoreGeometry(self
.geom
)
170 def dialog_closing(self
, result
):
171 geom
= bytearray(self
.saveGeometry())
172 gprefs
[self
.unique_pref_name
] = geom
173 self
.persist_custom_prefs()
175 def persist_custom_prefs(self
):
177 Invoked when the dialog is closing. Override this function to call
178 save_custom_pref() if you have a setting you want persisted that you can
179 retrieve in your __init__() using load_custom_pref() when next opened
183 def load_custom_pref(self
, name
, default
=None):
184 return gprefs
.get(self
.unique_pref_name
+':'+name
, default
)
186 def save_custom_pref(self
, name
, value
):
187 gprefs
[self
.unique_pref_name
+':'+name
] = value
189 class ImageTitleLayout(QHBoxLayout
):
191 A reusable layout widget displaying an image followed by a title
193 def __init__(self
, parent
, icon_name
, title
):
195 :param parent: Parent gui
196 :param icon_name: Path to plugin image resource
197 :param title: String to be displayed beside the image
199 QHBoxLayout
.__init
__(self
)
200 self
.title_image_label
= QLabel(parent
)
201 self
.update_title_icon(icon_name
)
202 self
.addWidget(self
.title_image_label
)
205 title_font
.setPointSize(16)
206 shelf_label
= QLabel(title
, parent
)
207 shelf_label
.setFont(title_font
)
208 self
.addWidget(shelf_label
)
209 self
.insertStretch(-1)
211 def update_title_icon(self
, icon_name
):
212 pixmap
= get_pixmap(icon_name
)
214 error_dialog(self
.parent(), _('Restart required'),
215 _('Title image not found - you must restart Calibre before using this plugin!'), show
=True)
217 self
.title_image_label
.setPixmap(pixmap
)
218 self
.title_image_label
.setMaximumSize(32, 32)
219 self
.title_image_label
.setScaledContents(True)
222 class ReadOnlyTableWidgetItem(QTableWidgetItem
):
224 def __init__(self
, text
):
227 QTableWidgetItem
.__init
__(self
, text
, QTableWidgetItem
.UserType
)
228 self
.setFlags(Qt
.ItemIsSelectable|Qt
.ItemIsEnabled
)