Remove master key
[DeDRM_tools-LCP.git] / Obok_plugin / utilities.py
blobb2f02ade09943a2f649c6276e14342564a4b61d4
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
5 __license__ = 'GPL v3'
6 __docformat__ = 'restructuredtext en'
9 import os, struct, time
10 try:
11 from StringIO import StringIO
12 except ImportError:
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)
27 plugin_ID = None
28 plugin_icon_resources = {}
30 try:
31 from calibre.gui2 import QVariant
32 del QVariant
33 except ImportError:
34 is_qt4 = False
35 convert_qvariant = lambda x: x
36 else:
37 is_qt4 = True
39 def convert_qvariant(x):
40 vt = x.type()
41 if vt == x.String:
42 return x.toString()
43 if vt == x.List:
44 return [convert_qvariant(i) for i in x.toList()]
45 return x.toPyObject()
47 BASE_TIME = None
48 def debug_print(*args):
49 global BASE_TIME
50 if BASE_TIME is None:
51 BASE_TIME = time.time()
52 if DEBUG:
53 prints('DEBUG: %6.1f'%(time.time()-BASE_TIME), *args)
55 try:
56 debug_print("obok::utilities.py - loading translations")
57 load_translations()
58 except NameError:
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):
63 '''
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
67 '''
68 if not possessive:
69 return '' if number == 1 else 's'
70 return '\'s' if number == 1 else 's\''
73 def set_plugin_icon_resources(name, resources):
74 '''
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.
78 '''
79 global plugin_icon_resources, plugin_ID
80 plugin_ID = name
81 plugin_icon_resources = resources
83 def get_icon(icon_name):
84 '''
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.
87 '''
88 if icon_name:
89 pixmap = get_pixmap(icon_name)
90 if pixmap is None:
91 # Look in Calibre's cache for the icon
92 return QIcon(I(icon_name))
93 else:
94 return QIcon(pixmap)
95 return QIcon()
97 def get_pixmap(icon_name):
98 '''
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
104 pixmap = QPixmap()
105 pixmap.load(I(icon_name))
106 return pixmap
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\
111 if plugin_ID:
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):
115 pixmap = QPixmap()
116 pixmap.load(local_image_path)
117 return pixmap
119 # As we did not find an icon elsewhere, look within our zip resources
120 if icon_name in plugin_icon_resources:
121 pixmap = QPixmap()
122 pixmap.loadFromData(plugin_icon_resources[icon_name])
123 return pixmap
124 return None
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')
132 if subfolder:
133 images_dir = os.path.join(images_dir, subfolder)
134 if iswindows:
135 images_dir = os.path.normpath(images_dir)
136 return images_dir
138 def showErrorDlg(errmsg, parent, trcbk=False):
140 Wrapper method for calibre's error_dialog
142 if trcbk:
143 error= ''
144 f=StringIO()
145 print_exc(file=f)
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())
167 else:
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
181 pass
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)
204 title_font = QFont()
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)
213 if pixmap is None:
214 error_dialog(self.parent(), _('Restart required'),
215 _('Title image not found - you must restart Calibre before using this plugin!'), show=True)
216 else:
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):
225 if text is None:
226 text = ''
227 QTableWidgetItem.__init__(self, text, QTableWidgetItem.UserType)
228 self.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)