(o);
+ if (sp != 0) {
+ s = sp->create(name);
+ if (s != 0) {
+ s->setObjectName(name);
+ QApplication::setStyle(s);
+ ret = 1;
+ }
+ }
+ }
+ return ret;
+}
diff --git a/src/calibre/gui2/progress_indicator/QProgressIndicator.h b/src/calibre/gui2/progress_indicator/QProgressIndicator.h
index c2098ffe64..0fd82a99f5 100644
--- a/src/calibre/gui2/progress_indicator/QProgressIndicator.h
+++ b/src/calibre/gui2/progress_indicator/QProgressIndicator.h
@@ -91,3 +91,12 @@ private:
QColor m_color;
};
+/* Utility function that can be used to load a QStyle from a Qt plugin. This is
+ * here so that there is no need to create a separate PyQt plugin just for this
+ * simple functionality.
+ * \param path The full path to the DLL containing the plugin
+ * \param name The name of the style plugin to load
+ * \return 1 if succeeds 0 otherwise. The objectName of the loaded style is set to name
+ */
+int load_style(QString &path, QString &name);
+
diff --git a/src/calibre/gui2/progress_indicator/QProgressIndicator.sip b/src/calibre/gui2/progress_indicator/QProgressIndicator.sip
index 3db47d668a..03c6dacdd6 100644
--- a/src/calibre/gui2/progress_indicator/QProgressIndicator.sip
+++ b/src/calibre/gui2/progress_indicator/QProgressIndicator.sip
@@ -6,6 +6,10 @@
%Import QtCore/QtCoremod.sip
%Import QtGui/QtGuimod.sip
+%ModuleHeaderCode
+int load_style(QString &path, QString &name);
+%End
+
class QProgressIndicator : QWidget {
%TypeHeaderCode
@@ -50,3 +54,6 @@ protected:
virtual void paintEvent(QPaintEvent * event);
};
+
+int load_style(QString &path, QString &name);
+
diff --git a/src/calibre/gui2/tag_browser/model.py b/src/calibre/gui2/tag_browser/model.py
index e08245f4cf..95d58d2cb6 100644
--- a/src/calibre/gui2/tag_browser/model.py
+++ b/src/calibre/gui2/tag_browser/model.py
@@ -418,21 +418,24 @@ class TagsModel(QAbstractItemModel): # {{{
chardict[c][1] = idx
# sort the ranges to facilitate detecting overlap
- ranges = sorted([(v[0], v[1], c) for c,v in chardict.items()])
-
- # Create a list of 'first letters' to use for each item in
- # the category. The list is generated using the ranges. Overlaps
- # are filled with the character that first occurs.
- cl_list = list(repeat(None, len(data[key])))
- for t in ranges:
- start = t[0]
- c = t[2]
- if cl_list[start] is None:
- nc = c
- else:
- nc = cl_list[start]
- for i in range(start, t[1]+1):
- cl_list[i] = nc
+ if len(chardict) == 1 and ' ' in chardict:
+ # The category could not be partitioned.
+ collapse_model = 'disable'
+ else:
+ ranges = sorted([(v[0], v[1], c) for c,v in chardict.items()])
+ # Create a list of 'first letters' to use for each item in
+ # the category. The list is generated using the ranges. Overlaps
+ # are filled with the character that first occurs.
+ cl_list = list(repeat(None, len(data[key])))
+ for t in ranges:
+ start = t[0]
+ c = t[2]
+ if cl_list[start] is None:
+ nc = c
+ else:
+ nc = cl_list[start]
+ for i in range(start, t[1]+1):
+ cl_list[i] = nc
for idx,tag in enumerate(data[key]):
if clear_rating:
@@ -448,13 +451,19 @@ class TagsModel(QAbstractItemModel): # {{{
else:
d['last'] = data[key][cat_len-1]
name = eval_formatter.safe_format(collapse_template,
- d, 'TAG_VIEW', None)
- sub_cat = self.create_node(parent=category, data = name,
+ d, '##TAG_VIEW##', None)
+ if name.startswith('##TAG_VIEW##'):
+ # Formatter threw an exception. Don't create subnode
+ node_parent = category
+ else:
+ sub_cat = self.create_node(parent=category, data = name,
tooltip = None, temporary=True,
category_icon = category_node.icon,
category_key=category_node.category_key,
icon_map=self.icon_state_map)
- sub_cat.tag.is_searchable = False
+ sub_cat.tag.is_searchable = False
+ sub_cat.is_gst = is_gst
+ node_parent = sub_cat
else: # by 'first letter'
cl = cl_list[idx]
if cl != collapse_letter:
@@ -465,8 +474,8 @@ class TagsModel(QAbstractItemModel): # {{{
tooltip = None, temporary=True,
category_key=category_node.category_key,
icon_map=self.icon_state_map)
- sub_cat.is_gst = is_gst
- node_parent = sub_cat
+ sub_cat.is_gst = is_gst
+ node_parent = sub_cat
else:
node_parent = category
@@ -1178,13 +1187,16 @@ class TagsModel(QAbstractItemModel): # {{{
for subnode in tag_item.children:
if subnode.tag.sort:
letters_seen[subnode.tag.sort[0]] = True
- charclass = ''.join(letters_seen)
- if k == 'author_sort':
- expr = r'%s:"~(^[%s])|(&\s*[%s])"'%(k, charclass, charclass)
- elif k == 'series':
- expr = r'series_sort:"~^[%s]"'%(charclass)
+ if letters_seen:
+ charclass = ''.join(letters_seen)
+ if k == 'author_sort':
+ expr = r'%s:"~(^[%s])|(&\s*[%s])"'%(k, charclass, charclass)
+ elif k == 'series':
+ expr = r'series_sort:"~^[%s]"'%(charclass)
+ else:
+ expr = r'%s:"~^[%s]"'%(k, charclass)
else:
- expr = r'%s:"~^[%s]"'%(k, charclass)
+ expr = r'%s:false'%(k)
if node_searches[tag_item.tag.state] == 'true':
ans.append(expr)
else:
diff --git a/src/calibre/gui2/tag_browser/ui.py b/src/calibre/gui2/tag_browser/ui.py
index 5a760639fb..913ff8f4a6 100644
--- a/src/calibre/gui2/tag_browser/ui.py
+++ b/src/calibre/gui2/tag_browser/ui.py
@@ -388,7 +388,7 @@ class TagBrowserWidget(QWidget): # {{{
type=Qt.QueuedConnection)
parent.alter_tb = l = QPushButton(parent)
- l.setText(_('&Alter Tag Browser'))
+ l.setText(_('Alter Tag Browser'))
l.setIcon(QIcon(I('tags.png')))
l.m = QMenu()
l.setMenu(l.m)
diff --git a/src/calibre/gui2/tag_browser/view.py b/src/calibre/gui2/tag_browser/view.py
index 57d7e54c56..2669298c4e 100644
--- a/src/calibre/gui2/tag_browser/view.py
+++ b/src/calibre/gui2/tag_browser/view.py
@@ -117,6 +117,7 @@ class TagsView(QTreeView): # {{{
QTreeView::item:hover {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
border: 1px solid #bfcde4;
+ border-radius: 6px;
}
''')
diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py
index d07e9516fd..84204027c9 100644
--- a/src/calibre/gui2/viewer/documentview.py
+++ b/src/calibre/gui2/viewer/documentview.py
@@ -649,7 +649,7 @@ class DocumentView(QWebView): # {{{
def current_page_image(self, overlap=-1):
if overlap < 0:
overlap = self.height()
- img = QImage(self.width(), overlap, QImage.Format_ARGB32)
+ img = QImage(self.width(), overlap, QImage.Format_ARGB32_Premultiplied)
painter = QPainter(img)
self.document.mainFrame().render(painter, QRegion(0, 0, self.width(), overlap))
painter.end()
diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py
index 0ce6c3d48b..ee0d3bd361 100644
--- a/src/calibre/gui2/viewer/main.py
+++ b/src/calibre/gui2/viewer/main.py
@@ -28,6 +28,7 @@ from calibre.customize.ui import available_input_formats
from calibre.gui2.viewer.dictionary import Lookup
from calibre import as_unicode, force_unicode, isbytestring
from calibre.ptempfile import reset_base_dir
+from calibre.utils.zipfile import BadZipfile
vprefs = JSONConfig('viewer')
@@ -37,6 +38,11 @@ class Worker(Thread):
try:
Thread.run(self)
self.exception = self.traceback = None
+ except BadZipfile:
+ self.exception = _(
+ 'This ebook is corrupted and cannot be opened. If you '
+ 'downloaded it from somewhere, try downloading it again.')
+ self.traceback = ''
except Exception as err:
self.exception = err
self.traceback = traceback.format_exc()
diff --git a/src/calibre/gui2/viewer/toc.py b/src/calibre/gui2/viewer/toc.py
index 327a5363cf..f8add78ed6 100644
--- a/src/calibre/gui2/viewer/toc.py
+++ b/src/calibre/gui2/viewer/toc.py
@@ -32,6 +32,7 @@ class TOCView(QTreeView):
QTreeView::item:hover {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
border: 1px solid #bfcde4;
+ border-radius: 6px;
}
QHeaderView::section {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
@@ -69,7 +70,11 @@ class TOCItem(QStandardItem):
if si == self.abspath:
spos = i
break
- am = getattr(spine[i], 'anchor_map', {})
+ try:
+ am = getattr(spine[i], 'anchor_map', {})
+ except UnboundLocalError:
+ # Spine was empty?
+ am = {}
frag = self.fragment if (self.fragment and self.fragment in am) else None
self.starts_at = spos
self.start_anchor = frag
diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py
index 7f50c13e41..ef756a226a 100644
--- a/src/calibre/gui2/wizard/__init__.py
+++ b/src/calibre/gui2/wizard/__init__.py
@@ -418,9 +418,17 @@ class KindlePage(QWizardPage, KindleUI):
def initializePage(self):
opts = smtp_prefs().parse()
- for x in opts.accounts.keys():
+ accs = []
+ has_default = False
+ for x, ac in opts.accounts.iteritems():
+ default = ac[2]
if x.strip().endswith('@kindle.com'):
- self.to_address.setText(x)
+ accs.append((x, default))
+ if default: has_default = True
+ if has_default:
+ accs = [x for x in accs if x[1]]
+ if accs:
+ self.to_address.setText(accs[0])
def x():
t = unicode(self.to_address.text())
if t.strip():
diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py
index eb53cadb34..89241dc601 100644
--- a/src/calibre/library/cli.py
+++ b/src/calibre/library/cli.py
@@ -40,7 +40,7 @@ def write_dirtied(db):
def get_parser(usage):
parser = OptionParser(usage)
- go = parser.add_option_group('GLOBAL OPTIONS')
+ go = parser.add_option_group(_('GLOBAL OPTIONS'))
go.add_option('--library-path', '--with-library', default=None, help=_('Path to the calibre library. Default is to use the path stored in the settings.'))
return parser
diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot
index 307c7c47c6..21c895d0e2 100644
--- a/src/calibre/translations/calibre.pot
+++ b/src/calibre/translations/calibre.pot
@@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: calibre 0.8.54\n"
-"POT-Creation-Date: 2012-05-31 07:22+IST\n"
-"PO-Revision-Date: 2012-05-31 07:22+IST\n"
+"POT-Creation-Date: 2012-06-01 23:16+IST\n"
+"PO-Revision-Date: 2012-06-01 23:16+IST\n"
"Last-Translator: Automatically generated\n"
"Language-Team: LANGUAGE\n"
"MIME-Version: 1.0\n"
@@ -142,8 +142,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/manipulate/split.py:82
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/writer.py:116
#: /home/kovid/work/calibre/src/calibre/ebooks/pdf/writer.py:117
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:418
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:426
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:419
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:427
#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:166
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:397
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:400
@@ -173,7 +173,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:84
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:245
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:264
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:390
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:389
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single_download.py:172
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single_download.py:176
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:204
@@ -245,8 +245,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:20
#: /home/kovid/work/calibre/src/calibre/gui2/actions/preferences.py:28
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:197
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:287
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:309
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:288
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:310
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:206
msgid "Preferences"
msgstr ""
@@ -1014,8 +1014,8 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:1092
#: /home/kovid/work/calibre/src/calibre/gui2/actions/fetch_news.py:73
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:469
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1163
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1165
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1164
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:1166
#: /home/kovid/work/calibre/src/calibre/library/database2.py:346
#: /home/kovid/work/calibre/src/calibre/library/database2.py:359
#: /home/kovid/work/calibre/src/calibre/library/database2.py:3165
@@ -3072,7 +3072,7 @@ msgid "Producer"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/book/base.py:773
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:941
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:937
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/metadata_sources.py:157
#: /home/kovid/work/calibre/src/calibre/library/field_metadata.py:245
msgid "Comments"
@@ -3218,7 +3218,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/opf2.py:1434
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1273
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:953
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:949
#: /home/kovid/work/calibre/src/calibre/gui2/store/search/models.py:41
msgid "Cover"
msgstr ""
@@ -3355,7 +3355,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/base.py:1275
#: /home/kovid/work/calibre/src/calibre/ebooks/oeb/transforms/htmltoc.py:15
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main_ui.py:199
-#: /home/kovid/work/calibre/src/calibre/gui2/viewer/toc.py:154
+#: /home/kovid/work/calibre/src/calibre/gui2/viewer/toc.py:159
msgid "Table of Contents"
msgstr ""
@@ -3657,144 +3657,144 @@ msgstr ""
msgid "Table of Contents:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:120
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:121
msgid "Send file to storage card instead of main memory by default"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:122
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:123
msgid "Confirm before deleting"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:124
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:125
msgid "Main window geometry"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:126
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:127
msgid "Notify when a new version is available"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:128
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:129
msgid "Use Roman numerals for series number"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:130
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:131
msgid "Sort tags list by name, popularity, or rating"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:132
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:133
msgid "Match tags by any or all."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:134
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:135
msgid "Number of covers to show in the cover browsing mode"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:136
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:137
msgid "Defaults for conversion to LRF"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:138
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:139
msgid "Options for the LRF ebook viewer"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:142
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:143
msgid "Formats that are viewed using the internal viewer"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:144
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:145
msgid "Columns to be displayed in the book list"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:145
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:146
msgid "Automatically launch content server on application startup"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:146
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:147
msgid "Oldest news kept in database"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:147
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:148
msgid "Show system tray icon"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:149
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:150
msgid "Upload downloaded news to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:151
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:152
msgid "Delete news books from library after uploading to device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:153
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:154
msgid "Show the cover flow in a separate window instead of in the main calibre window"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:155
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:156
msgid "Disable notifications from the system tray icon"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:157
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:158
msgid "Default action to perform when send to device button is clicked"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:162
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:163
msgid "Start searching as you type. If this is disabled then search will only take place when the Enter or Return key is pressed."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:165
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:166
msgid "When searching, show all books with search results highlighted instead of showing only the matches. You can use the N or F3 keys to go to the next match."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:190
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:191
msgid "Maximum number of simultaneous conversion/news download jobs. This number is twice the actual value for historical reasons."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:193
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:194
msgid "Download social metadata (tags/rating/etc.)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:195
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:196
msgid "Overwrite author and title with new metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:197
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:198
msgid "Automatically download the cover, if available"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:199
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:200
msgid "Limit max simultaneous jobs to number of CPUs"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:201
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:202
msgid "The layout of the user interface. Wide has the book details panel on the right and narrow has it at the bottom."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:205
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:206
msgid "Show the average rating per item indication in the tag browser"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:207
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:208
msgid "Disable UI animations"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:212
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:213
msgid "tag browser categories not to display"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:266
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:267
msgid "WARNING:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:276
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:277
msgid "ERROR:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:288
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:289
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:258
msgid "Show this confirmation again"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:537
+#: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:539
msgid "Choose Files"
msgstr ""
@@ -3908,7 +3908,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:178
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:242
#: /home/kovid/work/calibre/src/calibre/gui2/actions/edit_metadata.py:279
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:91
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:80
msgid "No books selected"
msgstr ""
@@ -3974,7 +3974,7 @@ msgid "Add to library"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/add.py:380
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:136
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:137
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:87
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:106
#: /home/kovid/work/calibre/src/calibre/gui2/actions/store.py:115
@@ -4278,7 +4278,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:496
#: /home/kovid/work/calibre/src/calibre/gui2/actions/choose_library.py:501
#: /home/kovid/work/calibre/src/calibre/gui2/actions/copy_to_library.py:224
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:100
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:89
#: /home/kovid/work/calibre/src/calibre/gui2/library/views.py:960
msgid "Not allowed"
msgstr ""
@@ -4449,68 +4449,68 @@ msgstr ""
msgid "Remove matching books from device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:133
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:134
msgid "Cannot delete"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:146
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:147
msgid "Choose formats to be deleted"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:164
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:165
msgid "Choose formats not to be deleted.Note that this will never remove all formats from a book."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:191
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:192
msgid "All formats for the selected books will be deleted from your library.
The book metadata will be kept. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:211
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:212
msgid "Cannot delete books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:212
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:213
msgid "No device is connected"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:222
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:223
msgid "Main memory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:223
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:224
#: /home/kovid/work/calibre/src/calibre/gui2/device.py:527
#: /home/kovid/work/calibre/src/calibre/gui2/device.py:536
msgid "Storage Card A"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:224
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:225
#: /home/kovid/work/calibre/src/calibre/gui2/device.py:529
#: /home/kovid/work/calibre/src/calibre/gui2/device.py:538
msgid "Storage Card B"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:229
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:230
msgid "No books to delete"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:230
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:231
msgid "None of the selected books are on the device"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:247
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:340
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:248
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:341
msgid "Deleting books from device."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:295
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:296
msgid "Some of the selected books are on the attached device. Where do you want the selected files deleted from?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:307
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:308
msgid "The selected books will be permanently deleted and the files removed from your calibre library. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:332
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/delete.py:333
msgid "The selected books will be permanently deleted from your device. Are you sure?"
msgstr ""
@@ -4833,60 +4833,65 @@ msgstr ""
msgid "Restart"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:24
-msgid "Save single format to disk..."
-msgstr ""
-
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:39
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:20
msgid "S"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:39
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:20
msgid "Save to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:48
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:29
msgid "Save to disk in a single directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:50
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:68
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:31
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:48
#, python-format
msgid "Save only %s format to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:54
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:71
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:35
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:51
#, python-format
msgid "Save only %s format to disk in a single directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:90
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:38
+msgid "Save single format to disk..."
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:60
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:79
msgid "Cannot save to disk"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:93
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:63
+msgid "Choose format to save to disk"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:82
msgid "Choose destination directory"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:101
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:90
msgid "You are trying to save files into the calibre library. This can cause corruption of your library. Save to disk is meant to export files from your calibre library elsewhere."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:132
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:121
msgid "Error while saving"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:133
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:122
msgid "There was an error while saving."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:140
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:141
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:129
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:130
msgid "Could not save some books"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:142
+#: /home/kovid/work/calibre/src/calibre/gui2/actions/save_to_disk.py:131
msgid "Click the show details button to see which ones."
msgstr ""
@@ -5066,7 +5071,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/actions/tweak_epub.py:105
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/comments_dialog.py:25
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/template_dialog.py:242
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:233
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:234
#: /usr/src/qt-everywhere-opensource-src-4.8.0/src/gui/widgets/qdialogbuttonbox.cpp:667
msgid "&Cancel"
msgstr ""
@@ -5576,7 +5581,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/conversion_ui.py:54
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/custom_columns_ui.py:81
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/email_ui.py:65
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:222
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:229
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/metadata_sources_ui.py:21
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/misc_ui.py:21
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/plugboard_ui.py:113
@@ -8112,13 +8117,13 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/device_category_editor.py:86
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:186
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:897
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:898
msgid "Item is blank"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/device_category_editor.py:87
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/tag_list_editor.py:187
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:898
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:899
msgid "An item cannot be set to nothing. Delete it instead."
msgstr ""
@@ -8241,17 +8246,17 @@ msgid "Copy to author"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog.py:313
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:947
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:948
msgid "Invalid author name"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog.py:314
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:948
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:949
msgid "Author names cannot contain & characters."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/edit_authors_dialog_ui.py:88
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:137
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:136
msgid "Manage authors"
msgstr ""
@@ -8392,7 +8397,7 @@ msgid "Standard metadata"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk.py:62
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:922
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:919
msgid "Custom metadata"
msgstr ""
@@ -8546,7 +8551,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:561
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:562
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:191
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:190
msgid "Open Tag Editor"
msgstr ""
@@ -8683,13 +8688,13 @@ msgid "Set from &ebook file(s)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:608
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:561
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:727
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:560
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:725
msgid "&Basic metadata"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_bulk_ui.py:609
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:568
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:567
msgid "&Custom metadata"
msgstr ""
@@ -9694,7 +9699,7 @@ msgstr ""
msgid "There are %(count)d book(s) with the %(fmt)s format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/select_formats.py:54
+#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/select_formats.py:55
msgid "Choose formats"
msgstr ""
@@ -10302,7 +10307,7 @@ msgid "Regular expression (?P)"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:108
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:276
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:284
msgid "Cover Browser"
msgstr ""
@@ -10311,7 +10316,7 @@ msgid "Shift+Alt+B"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:127
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:271
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:279
msgid "Tag Browser"
msgstr ""
@@ -10335,7 +10340,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:215
#: /home/kovid/work/calibre/src/calibre/gui2/init.py:226
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:247
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:255
msgid "Book Details"
msgstr ""
@@ -10613,7 +10618,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:786
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:1398
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:312
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:313
msgid "The lookup/search name is \"{0}\""
msgstr ""
@@ -10625,7 +10630,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/library/models.py:875
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:103
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:279
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:441
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:440
msgid "Permission denied"
msgstr ""
@@ -10922,7 +10927,7 @@ msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:104
#: /home/kovid/work/calibre/src/calibre/gui2/metadata/basic_widgets.py:280
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:442
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:441
#, python-format
msgid "Could not open %s. Is it being used by another program?"
msgstr ""
@@ -11209,117 +11214,117 @@ msgstr ""
msgid "Previous"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:118
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:117
msgid ""
"Automatically create the title sort entry based on the current title entry.\n"
"Using this button to create title sort will change title sort from red to green."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:129
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:128
msgid "Automatically create the author sort entry based on the current author entry. Using this button to create author sort will change author sort from red to green. There is a menu of functions available under this button. Click and hold on the button to see it."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:135
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:134
msgid "Set author sort from author"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:136
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:135
msgid "Set author from author sort"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:139
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:138
msgid "Copy author to author sort"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:141
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:140
msgid "Copy author sort to author"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:152
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:151
msgid "Swap the author and title"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:158
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:157
msgid "Manage authors. Use to rename authors and correct individual author's sort values"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:165
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:164
msgid "Clear series"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:200
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:199
msgid "Clear Ids"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:204
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:203
msgid "Paste the contents of the clipboard into the identifiers box prefixed with isbn:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:217
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:216
msgid "&Download metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:229
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:228
msgid "Configure download metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:233
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:232
msgid "Change how calibre downloads metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:295
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:294
#, python-format
msgid " [%(num)d of %(tot)d]"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:326
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:333
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:325
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:332
msgid "Could not read cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:327
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:326
#, python-format
msgid "Could not read cover from %s format"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:334
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:333
#, python-format
msgid "The cover in the %s format is invalid"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:509
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:514
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:508
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:513
#, python-format
msgid "Save changes and edit the metadata of %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:611
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:816
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:610
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:813
msgid "Change cover"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:670
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:668
msgid "Co&mments"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:710
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:857
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:708
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:854
msgid "&Metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:715
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:713
msgid "&Cover and formats"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:785
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:783
msgid "C&ustom metadata"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:797
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:794
msgid "&Comments"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:863
+#: /home/kovid/work/calibre/src/calibre/gui2/metadata/single.py:860
msgid "Basic metadata"
msgstr ""
@@ -12309,127 +12314,139 @@ msgstr ""
msgid "Wide"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:134
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:105
+msgid "Calibre style"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:105
+msgid "System default"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:142
msgid "Off"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:134
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:142
msgid "Small"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:135
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:143
msgid "Large"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:135
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:143
msgid "Medium"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:138
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:146
msgid "Always"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:138
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:146
msgid "If there is enough room"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:139
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:147
msgid "Never"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:142
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:497
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:150
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:511
msgid "By first letter"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:142
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:150
msgid "Disabled"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:143
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:151
msgid "Partitioned"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:176
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:184
msgid "Column coloring"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:182
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel.py:190
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts.py:132
#: /home/kovid/work/calibre/src/calibre/gui2/shortcuts.py:223
#: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:227
msgid " or "
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:223
-msgid "User Interface &layout (needs restart):"
-msgstr ""
-
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:224
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:230
msgid "Choose &language (requires restart):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:225
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:231
msgid "Enable system &tray icon (needs restart)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:226
-msgid "Disable all animations. Useful if you have a slow/old computer."
-msgstr ""
-
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:227
-msgid "Disable &animations"
-msgstr ""
-
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:228
-msgid "Disable ¬ifications in system tray"
-msgstr ""
-
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:229
-msgid "Show &splash screen at startup"
-msgstr ""
-
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:230
-msgid "&Toolbar"
-msgstr ""
-
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:231
-msgid "&Icon size:"
-msgstr ""
-
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:232
-msgid "Show &text under icons:"
+msgid "User Interface &layout (needs restart):"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:233
-msgid "Interface font:"
+msgid "Disable all animations. Useful if you have a slow/old computer."
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:234
-msgid "Change &font (needs restart)"
+msgid "Disable &animations"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:235
-msgid "Main Interface"
+msgid "Disable ¬ifications in system tray"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:236
-msgid "Select displayed metadata"
+msgid "Show &splash screen at startup"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:237
-msgid "Move up"
+msgid "&Toolbar"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:238
-msgid "Move down"
+msgid "&Icon size:"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:239
-msgid "Default author link template:"
+msgid "Show &text under icons:"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:240
+msgid "Interface font:"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:241
+msgid "Change &font (needs restart)"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:242
+msgid "User interface &style (needs restart):"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:243
+msgid "Main Interface"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:244
+msgid "Select displayed metadata"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:245
+msgid "Move up"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:246
+msgid "Move down"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:247
+msgid "Default author link template:"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:248
msgid ""
"Enter a template to be used to create a link for\n"
"an author in the books information dialog. This template will\n"
@@ -12438,19 +12455,19 @@ msgid ""
"{author_sort}, and any template function."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:245
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:253
msgid "Use &Roman numerals for series"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:246
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:254
msgid "Note that comments will always be displayed at the end, regardless of the position you assign here."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:248
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:256
msgid "Tags browser category &partitioning method:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:249
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:257
msgid ""
"Choose how tag browser subcategories are displayed when\n"
"there are more items than the limit. Select by first\n"
@@ -12459,21 +12476,21 @@ msgid ""
"if you never want subcategories"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:254
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:262
msgid "&Collapse when more items than:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:255
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:263
msgid ""
"If a Tag Browser category has more than this number of items, it is divided\n"
"up into subcategories. If the partition method is set to disable, this value is ignored."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:257
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:265
msgid "Categories not to partition:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:258
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:266
msgid ""
"A comma-separated list of categories that are not to\n"
"be partitioned even if the number of items is larger than\n"
@@ -12482,15 +12499,15 @@ msgid ""
"a few top-level elements."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:263
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:271
msgid "Show &average ratings in the tags browser"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:264
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:272
msgid "Categories with &hierarchical items:"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:265
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:273
msgid ""
"A comma-separated list of categories in which items containing\n"
"periods are displayed in the tag browser trees. For example, if\n"
@@ -12500,58 +12517,58 @@ msgid ""
"then the tags will be displayed each on their own line."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:272
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:280
msgid "Show cover &browser in a separate window (needs restart)"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:273
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:281
msgid "&Number of covers to show in browse mode (needs restart):"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:274
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:282
msgid "When showing cover browser in separate window, show it &fullscreen"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:275
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/look_feel_ui.py:283
#, python-format
msgid "You can press the %s keys to toggle full screen mode."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:230
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:231
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/tweaks_ui.py:123
msgid "&Apply"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:237
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:238
msgid "Restore &defaults"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:238
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:239
msgid "Save changes"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:239
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:240
msgid "Cancel and return to overview"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:295
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:296
msgid "Restoring to defaults not supported for"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:331
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:332
msgid "Some of the changes you made require a restart. Please restart calibre as soon as possible."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:334
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:335
msgid "The changes you have made require calibre be restarted immediately. You will not be allowed to set any more preferences, until you restart."
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:339
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:340
#: /home/kovid/work/calibre/src/calibre/gui2/preferences/server.py:134
msgid "Restart needed"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:341
+#: /home/kovid/work/calibre/src/calibre/gui2/preferences/main.py:342
msgid "Restart calibre now"
msgstr ""
@@ -13967,44 +13984,44 @@ msgstr ""
msgid "%p%"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:307
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:308
msgid "The grouped search term name is \"{0}\""
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:734
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:735
msgid "Changing the authors for several books can take a while. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:739
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:740
msgid "Changing the metadata for that many books can take a while. Are you sure?"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:826
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:827
#: /home/kovid/work/calibre/src/calibre/library/database2.py:469
msgid "Searches"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:903
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:923
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:932
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:904
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:924
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:933
msgid "Rename user category"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:904
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:905
msgid "You cannot use periods in the name when renaming user categories"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:924
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:933
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:925
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:934
#, python-format
msgid "The name %s is already used"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:952
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:953
msgid "Duplicate search name"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:953
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/model.py:954
#, python-format
msgid "The saved search name %s is already used."
msgstr ""
@@ -14026,13 +14043,13 @@ msgid "Manage Tags"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:57
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:480
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:484
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:494
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:498
msgid "Manage User Categories"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:59
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:472
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:486
msgid "Manage Saved Searches"
msgstr ""
@@ -14121,7 +14138,7 @@ msgid "No More Matches.
Click Find again to go to first match"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:391
-msgid "&Alter Tag Browser"
+msgid "Alter Tag Browser"
msgstr ""
#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/ui.py:397
@@ -14169,110 +14186,110 @@ msgstr ""
msgid "All of these category_managers are available by right-clicking on items in the tag browser above"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:353
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:392
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:422
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:367
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:406
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:436
#, python-format
msgid "Rename %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:359
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:373
#, python-format
msgid "Delete %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:363
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:377
#, python-format
msgid "Edit sort for %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:366
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:380
#, python-format
msgid "Edit link for %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:373
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:387
#, python-format
msgid "Add %s to user category"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:386
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:400
#, python-format
msgid "Children of %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:396
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:410
#, python-format
msgid "Delete search %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:401
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:415
#, python-format
msgid "Remove %(item)s from category %(cat)s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:409
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:423
#, python-format
msgid "Search for %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:414
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:428
#, python-format
msgid "Search for everything but %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:426
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:440
#, python-format
msgid "Add sub-category to %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:430
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:444
#, python-format
msgid "Delete user category %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:435
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:449
#, python-format
msgid "Hide category %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:439
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:453
msgid "Show category"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:449
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:463
#, python-format
msgid "Search for books in category %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:455
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:469
#, python-format
msgid "Search for books not in category %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:464
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:469
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:478
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:483
#, python-format
msgid "Manage %s"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:491
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:505
msgid "Show all categories"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:494
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:508
msgid "Change sub-categorization scheme"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:495
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:509
msgid "Disable"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:499
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:513
msgid "Partition"
msgstr ""
-#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:514
+#: /home/kovid/work/calibre/src/calibre/gui2/tag_browser/view.py:528
msgid "First letter is usable only when sorting by name"
msgstr ""
@@ -15748,6 +15765,10 @@ msgstr ""
msgid "Folders raising exception"
msgstr ""
+#: /home/kovid/work/calibre/src/calibre/library/cli.py:43
+msgid "GLOBAL OPTIONS"
+msgstr ""
+
#: /home/kovid/work/calibre/src/calibre/library/cli.py:44
msgid "Path to the calibre library. Default is to use the path stored in the settings."
msgstr ""
@@ -16672,6 +16693,18 @@ msgstr ""
msgid "Whenever you pass arguments to %prog that have spaces in them, enclose the arguments in quotation marks."
msgstr ""
+#: /home/kovid/work/calibre/src/calibre/utils/config.py:94
+msgid "Options"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/utils/config.py:95
+msgid "show this help message and exit"
+msgstr ""
+
+#: /home/kovid/work/calibre/src/calibre/utils/config.py:96
+msgid "show program's version number and exit"
+msgstr ""
+
#: /home/kovid/work/calibre/src/calibre/utils/config_base.py:377
msgid "Path to the database in which books are stored"
msgstr ""
diff --git a/src/calibre/utils/config.py b/src/calibre/utils/config.py
index b5b8b566ba..65e59afbeb 100644
--- a/src/calibre/utils/config.py
+++ b/src/calibre/utils/config.py
@@ -89,6 +89,11 @@ class OptionParser(_OptionParser):
formatter=CustomHelpFormatter(),
conflict_handler=conflict_handler, **kwds)
self.gui_mode = gui_mode
+ if False:
+ # Translatable string from optparse
+ _("Options")
+ _("show this help message and exit")
+ _("show program's version number and exit")
def error(self, msg):
if self.gui_mode:
diff --git a/src/calibre/utils/ipc/simple_worker.py b/src/calibre/utils/ipc/simple_worker.py
index fceb04cbfe..5a89b91461 100644
--- a/src/calibre/utils/ipc/simple_worker.py
+++ b/src/calibre/utils/ipc/simple_worker.py
@@ -186,7 +186,13 @@ def main():
args = conn.recv()
try:
mod, func, args, kwargs = args
- mod = importlib.import_module(mod)
+ try:
+ mod = importlib.import_module(mod)
+ except ImportError:
+ # Load plugins incase fork_job() is being used in a plugin
+ import calibre.customize.ui as u
+ u
+ mod = importlib.import_module(mod)
func = getattr(mod, func)
res = {'result':func(*args, **kwargs)}
except:
diff --git a/src/qtcurve/AUTHORS b/src/qtcurve/AUTHORS
new file mode 100644
index 0000000000..5f68aed5b4
--- /dev/null
+++ b/src/qtcurve/AUTHORS
@@ -0,0 +1 @@
+Craig Drummond
diff --git a/src/qtcurve/COPYING b/src/qtcurve/COPYING
new file mode 100644
index 0000000000..d60c31a97a
--- /dev/null
+++ b/src/qtcurve/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/src/qtcurve/common/check_on.png b/src/qtcurve/common/check_on.png
new file mode 100644
index 0000000000..472578e47d
Binary files /dev/null and b/src/qtcurve/common/check_on.png differ
diff --git a/src/qtcurve/common/check_x_on.png b/src/qtcurve/common/check_x_on.png
new file mode 100644
index 0000000000..1be26e1a40
Binary files /dev/null and b/src/qtcurve/common/check_x_on.png differ
diff --git a/src/qtcurve/common/colorutils.c b/src/qtcurve/common/colorutils.c
new file mode 100644
index 0000000000..52b2183208
--- /dev/null
+++ b/src/qtcurve/common/colorutils.c
@@ -0,0 +1,342 @@
+/*
+ This file is taken from kcolorspaces.cpp and kcolorutils.cpp from kdelibs
+The code has been modified to work with QColor (Qt3 &Qt4) and GdkColor
+*/
+
+/* This file is part of the KDE project
+ * Copyright (C) 2007 Matthew Woehlke
+ * Copyright (C) 2007 Olaf Schmidt
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "config.h"
+#include "common.h"
+
+#ifdef __cplusplus
+#include
+#endif
+
+#if !(defined QT_VERSION && (QT_VERSION >= 0x040000) && !defined QTC_QT_ONLY)
+
+#include
+
+#if defined _WIN32 && defined QT_VERSION && (QT_VERSION >= 0x040000)
+#include
+#include
+#include
+
+static int isnan(double x)
+{
+ return _isnan(x);
+}
+#endif
+
+#ifdef __cplusplus
+static inline int qtcLimit(double c)
+{
+ return c < 0.0 ? 0 : (c > 255.0 ? 255 : (int)c);
+}
+#else
+static inline int qtcLimit(double c)
+{
+ return c < 0.0
+ ? 0
+ : c > 65535.0
+ ? 65535
+ : (int)c;
+}
+#endif
+
+#ifdef __cplusplus
+#if defined QT_VERSION && (QT_VERSION >= 0x040000)
+#define FLOAT_COLOR(VAL, COL) (VAL).COL##F()
+#define TO_COLOR(R, G, B) QColor::fromRgbF(R, G, B)
+#else
+#define FLOAT_COLOR(VAL, COL) ((double)(((VAL).COL()*1.0)/255.0))
+#define TO_COLOR(R, G, B) QColor(qtcLimit(R*255.0), qtcLimit(G*255.0), qtcLimit(B*255.0))
+#endif
+#else
+#define inline
+#define FLOAT_COLOR(VAL, COL) ((double)(((VAL).COL*1.0)/65535.0))
+static GdkColor qtcGdkColor(double r, double g, double b)
+{
+ GdkColor col;
+
+ col.red=qtcLimit(r*65535);
+ col.green=qtcLimit(g*65535);
+ col.blue=qtcLimit(b*65535);
+
+ return col;
+}
+
+#define TO_COLOR(R, G, B) qtcGdkColor(R, G, B)
+#endif
+
+static inline double ColorUtils_normalize(double a)
+{
+ return (a < 1.0 ? (a > 0.0 ? a : 0.0) : 1.0);
+}
+
+static inline double ColorUtils_wrap(double a)
+{
+ static double d = 1.0;
+ double r = fmod(a, d);
+ return (r < 0.0 ? d + r : (r > 0.0 ? r : 0.0));
+}
+
+#define HCY_REC 709 // use 709 for now
+#if HCY_REC == 601
+static const double yc[3] = { 0.299, 0.587, 0.114 };
+#elif HCY_REC == 709
+static const double yc[3] = {0.2126, 0.7152, 0.0722};
+#else // use Qt values
+static const double yc[3] = { 0.34375, 0.5, 0.15625 };
+#endif
+
+static inline double ColorUtils_HCY_gamma(double n)
+{
+ return pow(ColorUtils_normalize(n), 2.2);
+}
+
+static inline double ColorUtils_HCY_igamma(double n)
+{
+ return pow(ColorUtils_normalize(n), 1.0/2.2);
+}
+
+static inline double ColorUtils_HCY_lumag(double r, double g, double b)
+{
+ return r*yc[0] + g*yc[1] + b*yc[2];
+}
+
+typedef struct
+{
+ double h, c, y;
+} ColorUtils_HCY;
+
+// static ColorUtils_HCY ColorUtils_HCY_fromValues(double h_, double c_, double y_/*, double a_*/)
+// {
+// h = h_;
+// c = c_;
+// y = y_;
+// // a = a_;
+// }
+
+static ColorUtils_HCY ColorUtils_HCY_fromColor(const color *color)
+{
+ ColorUtils_HCY hcy;
+ double r = ColorUtils_HCY_gamma(FLOAT_COLOR(*color, red));
+ double g = ColorUtils_HCY_gamma(FLOAT_COLOR(*color, green));
+ double b = ColorUtils_HCY_gamma(FLOAT_COLOR(*color, blue));
+// a = color.alphaF();
+
+ // luma component
+ hcy.y = ColorUtils_HCY_lumag(r, g, b);
+
+ // hue component
+ double p = MAX(MAX(r, g), b);
+ double n = MIN(MIN(r, g), b);
+ double d = 6.0 * (p - n);
+ if (n == p)
+ hcy.h = 0.0;
+ else if (r == p)
+ hcy.h = ((g - b) / d);
+ else if (g == p)
+ hcy.h = ((b - r) / d) + (1.0 / 3.0);
+ else
+ hcy.h = ((r - g) / d) + (2.0 / 3.0);
+
+ // chroma component
+ if (0.0 == hcy.y || 1.0 == hcy.y)
+ hcy.c = 0.0;
+ else
+ hcy.c = MAX( (hcy.y - n) / hcy.y, (p - hcy.y) / (1 - hcy.y) );
+ return hcy;
+}
+
+static color ColorUtils_HCY_toColor(ColorUtils_HCY *hcy)
+{
+ // start with sane component values
+ double _h = ColorUtils_wrap(hcy->h);
+ double _c = ColorUtils_normalize(hcy->c);
+ double _y = ColorUtils_normalize(hcy->y);
+
+ // calculate some needed variables
+ double _hs = _h * 6.0, th, tm;
+ if (_hs < 1.0) {
+ th = _hs;
+ tm = yc[0] + yc[1] * th;
+ }
+ else if (_hs < 2.0) {
+ th = 2.0 - _hs;
+ tm = yc[1] + yc[0] * th;
+ }
+ else if (_hs < 3.0) {
+ th = _hs - 2.0;
+ tm = yc[1] + yc[2] * th;
+ }
+ else if (_hs < 4.0) {
+ th = 4.0 - _hs;
+ tm = yc[2] + yc[1] * th;
+ }
+ else if (_hs < 5.0) {
+ th = _hs - 4.0;
+ tm = yc[2] + yc[0] * th;
+ }
+ else {
+ th = 6.0 - _hs;
+ tm = yc[0] + yc[2] * th;
+ }
+
+ // calculate RGB channels in sorted order
+ double tn, to, tp;
+ if (tm >= _y) {
+ tp = _y + _y * _c * (1.0 - tm) / tm;
+ to = _y + _y * _c * (th - tm) / tm;
+ tn = _y - (_y * _c);
+ }
+ else {
+ tp = _y + (1.0 - _y) * _c;
+ to = _y + (1.0 - _y) * _c * (th - tm) / (1.0 - tm);
+ tn = _y - (1.0 - _y) * _c * tm / (1.0 - tm);
+ }
+
+ // return RGB channels in appropriate order
+ if (_hs < 1.0)
+ return TO_COLOR(ColorUtils_HCY_igamma(tp), ColorUtils_HCY_igamma(to), ColorUtils_HCY_igamma(tn));
+ else if (_hs < 2.0)
+ return TO_COLOR(ColorUtils_HCY_igamma(to), ColorUtils_HCY_igamma(tp), ColorUtils_HCY_igamma(tn));
+ else if (_hs < 3.0)
+ return TO_COLOR(ColorUtils_HCY_igamma(tn), ColorUtils_HCY_igamma(tp), ColorUtils_HCY_igamma(to));
+ else if (_hs < 4.0)
+ return TO_COLOR(ColorUtils_HCY_igamma(tn), ColorUtils_HCY_igamma(to), ColorUtils_HCY_igamma(tp));
+ else if (_hs < 5.0)
+ return TO_COLOR(ColorUtils_HCY_igamma(to), ColorUtils_HCY_igamma(tn), ColorUtils_HCY_igamma(tp));
+ else
+ return TO_COLOR(ColorUtils_HCY_igamma(tp), ColorUtils_HCY_igamma(tn), ColorUtils_HCY_igamma(to));
+}
+
+// #ifndef __cplusplus
+static inline double ColorUtils_HCY_luma(const color *color)
+{
+ return ColorUtils_HCY_lumag(ColorUtils_HCY_gamma(FLOAT_COLOR(*color, red)),
+ ColorUtils_HCY_gamma(FLOAT_COLOR(*color, green)),
+ ColorUtils_HCY_gamma(FLOAT_COLOR(*color, blue)));
+}
+
+static inline double ColorUtils_mixQreal(double a, double b, double bias)
+{
+ return a + (b - a) * bias;
+}
+
+double ColorUtils_luma(const color *color)
+{
+ return ColorUtils_HCY_luma(color);
+}
+
+static double ColorUtils_contrastRatio(const color *c1, const color *c2)
+{
+ double y1 = ColorUtils_luma(c1), y2 = ColorUtils_luma(c2);
+ if (y1 > y2)
+ return (y1 + 0.05) / (y2 + 0.05);
+ else
+ return (y2 + 0.05) / (y1 + 0.05);
+}
+
+color ColorUtils_lighten(const color *color, double ky, double kc)
+{
+ ColorUtils_HCY c=ColorUtils_HCY_fromColor(color);
+
+ c.y = 1.0 - ColorUtils_normalize((1.0 - c.y) * (1.0 - ky));
+ c.c = 1.0 - ColorUtils_normalize((1.0 - c.c) * kc);
+ return ColorUtils_HCY_toColor(&c);
+}
+
+color ColorUtils_darken(const color *color, double ky, double kc)
+{
+ ColorUtils_HCY c=ColorUtils_HCY_fromColor(color);
+ c.y = ColorUtils_normalize(c.y * (1.0 - ky));
+ c.c = ColorUtils_normalize(c.c * kc);
+ return ColorUtils_HCY_toColor(&c);
+}
+
+color ColorUtils_shade(const color *color, double ky, double kc)
+{
+ ColorUtils_HCY c=ColorUtils_HCY_fromColor(color);
+ c.y = ColorUtils_normalize(c.y + ky);
+ c.c = ColorUtils_normalize(c.c + kc);
+ return ColorUtils_HCY_toColor(&c);
+}
+
+color ColorUtils_mix(const color *c1, const color *c2, double bias);
+
+static color ColorUtils_tintHelper(const color *base, const color *col, double amount)
+{
+ color mixed=ColorUtils_mix(base, col, pow(amount, 0.3));
+ ColorUtils_HCY c=ColorUtils_HCY_fromColor(&mixed);
+ c.y = ColorUtils_mixQreal(ColorUtils_luma(base), c.y, amount);
+
+ return ColorUtils_HCY_toColor(&c);
+}
+
+color ColorUtils_tint(const color *base, const color *col, double amount)
+{
+ if (amount <= 0.0) return *base;
+ if (amount >= 1.0) return *col;
+ if (isnan(amount)) return *base;
+
+ double ri = ColorUtils_contrastRatio(base, col);
+ double rg = 1.0 + ((ri + 1.0) * amount * amount * amount);
+ double u = 1.0, l = 0.0;
+ color result;
+ int i;
+ for (i = 12 ; i ; --i) {
+ double a = 0.5 * (l+u);
+ result = ColorUtils_tintHelper(base, col, a);
+ double ra = ColorUtils_contrastRatio(base, &result);
+ if (ra > rg)
+ u = a;
+ else
+ l = a;
+ }
+ return result;
+}
+
+color ColorUtils_mix(const color *c1, const color *c2, double bias)
+{
+ if (bias <= 0.0) return *c1;
+ if (bias >= 1.0) return *c2;
+ if (isnan(bias)) return *c1;
+
+ {
+ double r = ColorUtils_mixQreal(FLOAT_COLOR(*c1, red), FLOAT_COLOR(*c2, red), bias);
+ double g = ColorUtils_mixQreal(FLOAT_COLOR(*c1, green), FLOAT_COLOR(*c2, green), bias);
+ double b = ColorUtils_mixQreal(FLOAT_COLOR(*c1, blue), FLOAT_COLOR(*c2, blue), bias);
+ /*double a = ColorUtils_mixQreal(FLOAT_COLOR(*c1, alpha), FLOAT_COLOR(*c2, alpha), bias);*/
+
+ return TO_COLOR(r, g, b);
+ }
+}
+
+// #endif
+/* Added!!! */
+// static color ColorUtils_shade_qtc(const color *color, double k)
+// {
+// ColorUtils_HCY c=ColorUtils_HCY_fromColor(color);
+// c.y = ColorUtils_normalize(c.y * (k>1.0 ? (k*1.1) : (k<1.0 ? (k*0.9) : k)));
+// return ColorUtils_HCY_toColor(&c);
+// }
+
+#endif // !(defined QT_VERSION && (QT_VERSION >= 0x040000) && !defined QTC_QT_ONLY)
diff --git a/src/qtcurve/common/colorutils.h b/src/qtcurve/common/colorutils.h
new file mode 100644
index 0000000000..6bcecdd30f
--- /dev/null
+++ b/src/qtcurve/common/colorutils.h
@@ -0,0 +1,11 @@
+#ifndef QTC_COLOR_UTILS_H
+#define QTC_COLOR_UTILS_H
+
+extern color ColorUtils_lighten(const color *color, double ky, double kc);
+extern color ColorUtils_darken(const color *color, double ky, double kc);
+extern color ColorUtils_shade(const color *color, double ky, double kc);
+extern color ColorUtils_tint(const color *base, const color *col, double amount);
+extern color ColorUtils_mix(const color *c1, const color *c2, double bias);
+extern double ColorUtils_luma(const color *color);
+
+#endif
diff --git a/src/qtcurve/common/common.c b/src/qtcurve/common/common.c
new file mode 100644
index 0000000000..b09e5848bd
--- /dev/null
+++ b/src/qtcurve/common/common.c
@@ -0,0 +1,728 @@
+#include
+#include
+#include
+#include "common.h"
+#include "colorutils.h"
+
+#ifdef __cplusplus
+#include
+#else
+#include
+#endif
+
+/* Taken from rgb->hsl routines taken from KColor
+ Copyright 2007 Matthew Woehlke
+*/
+static inline double normalize(double a)
+{
+ return (a < 0.0 ? 0.0 : a > 1.0 ? 1.0 : a);
+}
+
+static inline double mix(double a, double b, double k)
+{
+ return a + ( ( b - a ) * k );
+}
+
+static inline double wrap(double a, double d)
+{
+ register double r = fmod( a, d );
+ return ( r < 0.0 ? d + r : ( r > 0.0 ? r : 0.0 ) );
+}
+
+static inline double h2c(double h, double m1, double m2)
+{
+ h = wrap( h, 6.0 );
+
+ if ( h < 1.0 )
+ return mix( m1, m2, h );
+ if ( h < 3.0 )
+ return m2;
+ if ( h < 4.0 )
+ return mix( m1, m2, 4.0 - h );
+ return m1;
+}
+
+static inline void rgbToHsl(double r, double g, double b, double *h, double *s, double *l)
+{
+ double min=MIN(MIN(r, g), b),
+ max=MAX(MAX(r, g), b);
+
+ *l = 0.5 * (max + min);
+ *s = 0.0;
+ *h = 0.0;
+
+ if (max != min)
+ {
+ double delta = max - min;
+
+ if ( *l <= 0.5 )
+ *s = delta / ( max + min );
+ else
+ *s = delta / ( 2.0 - max - min );
+
+ if ( r == max )
+ *h = ( g - b ) / delta;
+ else if ( g == max )
+ *h = 2.0 + ( b - r ) / delta;
+ else if ( b == max )
+ *h = 4.0 + ( r - g ) / delta;
+
+ *h /= 6.0;
+ if ( *h < 0.0 )
+ (*h) += 1.0;
+ }
+}
+
+static inline void hslToRgb(double h, double s, double l, double *r, double *g, double *b)
+{
+ double m1, m2;
+
+ // TODO h2rgb( h, r, g, b );
+ h *= 6.0;
+
+ if ( l <= 0.5 )
+ m2 = l * ( 1.0 + s );
+ else
+ m2 = l + s * ( 1.0 - l );
+ m1 = 2.0 * l - m2;
+
+ *r = h2c( h + 2.0, m1, m2 );
+ *g = h2c( h, m1, m2 );
+ *b = h2c( h - 2.0, m1, m2 );
+}
+
+void qtcRgbToHsv(double r, double g, double b, double *h, double *s, double *v)
+{
+ double min=MIN(MIN(r, g), b),
+ max=MAX(MAX(r, g), b),
+ delta=max - min;
+
+ *v=max;
+ if(max != 0)
+ *s=delta / max;
+ else
+ *s=0;
+
+ if (*s==0.0)
+ *h = 0.0;
+ else
+ {
+ if(r == max)
+ *h=(g - b) / delta; /* between yellow & magenta */
+ else if(g == max)
+ *h=2 + (b - r) / delta; /* between cyan & yellow */
+ else if(b == max)
+ *h=4 + (r - g) / delta; /* between magenta & cyan */
+ *h *= 60; /* degrees */
+ if(*h < 0)
+ *h += 360;
+ }
+}
+
+void qtcHsvToRgb(double *r, double *g, double *b, double h, double s, double v)
+{
+ if(0==s)
+ *r=*g=*b=v;
+ else
+ {
+ int i;
+ double f,
+ p;
+
+ h /= 60; /* sector 0 to 5 */
+ i=(int)floor(h);
+ f=h - i; /* factorial part of h */
+ p=v * (1 - s);
+ switch(i)
+ {
+ case 0:
+ *r=v;
+ *g=v * (1 - s * (1 - f));
+ *b=p;
+ break;
+ case 1:
+ *r=v * (1 - s * f);
+ *g=v;
+ *b=p;
+ break;
+ case 2:
+ *r=p;
+ *g=v;
+ *b=v * (1 - s * (1 - f));
+ break;
+ case 3:
+ *r=p;
+ *g=v * (1 - s * f);
+ *b=v;
+ break;
+ case 4:
+ *r=v * (1 - s * (1 - f));
+ *g=p;
+ *b=v;
+ break;
+ /* case 5: */
+ default:
+ *r=v;
+ *g=p;
+ *b=v * (1 - s * f);
+ break;
+ }
+ }
+}
+
+#ifdef __cplusplus
+static inline int qtcLimit(double c)
+{
+ return c < 0.0 ? 0 : (c > 255.0 ? 255 : (int)c);
+}
+#else
+static inline int qtcLimit(double c)
+{
+ return c < 0.0
+ ? 0
+ : c > 65535.0
+ ? 65535
+ : (int)c;
+}
+#endif
+
+#ifdef __cplusplus
+void qtcShade(const Options *opts, const color &ca, color *cb, double k)
+#else
+void qtcShade(const Options *opts, const color *ca, color *cb, double k)
+#endif
+{
+ if(qtcEqual(k, 1.0))
+ {
+#ifdef __cplusplus
+ *cb=ca;
+#else
+ cb->red = ca->red;
+ cb->green = ca->green;
+ cb->blue = ca->blue;
+#endif
+ }
+ else
+ switch(opts->shading)
+ {
+ case SHADING_SIMPLE:
+ {
+ #ifdef __cplusplus
+ int v=(int)(255.0*(k-1.0));
+
+ cb->setRgb(qtcLimit(ca.red()+v), qtcLimit(ca.green()+v), qtcLimit(ca.blue()+v));
+ #else
+ double v=65535.0*(k-1.0);
+
+ cb->red = qtcLimit(ca->red+v);
+ cb->green = qtcLimit(ca->green+v);
+ cb->blue = qtcLimit(ca->blue+v);
+ #endif
+ break;
+ }
+ case SHADING_HSL:
+ {
+ #ifdef __cplusplus
+ double r(ca.red()/255.0),
+ g(ca.green()/255.0),
+ b(ca.blue()/255.0);
+ #else
+ double r=ca->red/65535.0,
+ g=ca->green/65535.0,
+ b=ca->blue/65535.0;
+ #endif
+ double h, s, l;
+
+ rgbToHsl(r, g, b, &h, &s, &l);
+ l=normalize(l*k);
+ s=normalize(s*k);
+ hslToRgb(h, s, l, &r, &g, &b);
+ #ifdef __cplusplus
+ cb->setRgb(qtcLimit(r*255.0), qtcLimit(g*255.0), qtcLimit(b*255.0));
+ #else
+ cb->red=qtcLimit(r*65535.0);
+ cb->green=qtcLimit(g*65535.0);
+ cb->blue=qtcLimit(b*65535.0);
+ #endif
+ break;
+ }
+ case SHADING_HSV:
+ {
+ #ifdef __cplusplus
+ double r(ca.red()/255.0),
+ g(ca.green()/255.0),
+ b(ca.blue()/255.0);
+ #else
+ double r=ca->red/65535.0,
+ g=ca->green/65535.0,
+ b=ca->blue/65535.0;
+ #endif
+ double h, s, v;
+
+ qtcRgbToHsv(r, g, b, &h, &s, &v);
+
+ v*=k;
+ if (v > 1.0)
+ {
+ s -= v - 1.0;
+ if (s < 0)
+ s = 0;
+ v = 1.0;
+ }
+ qtcHsvToRgb(&r, &g, &b, h, s, v);
+ #ifdef __cplusplus
+ cb->setRgb(qtcLimit(r*255.0), qtcLimit(g*255.0), qtcLimit(b*255.0));
+ #else
+ cb->red=qtcLimit(r*65535.0);
+ cb->green=qtcLimit(g*65535.0);
+ cb->blue=qtcLimit(b*65535.0);
+ #endif
+ break;
+ }
+ case SHADING_HCY:
+ {
+ #define HCY_FACTOR 0.15
+ #if defined QT_VERSION && (QT_VERSION >= 0x040000) && !defined QTC_QT_ONLY
+ if(k>1.0)
+ *cb=KColorUtils::lighten(ca, (k*(1+HCY_FACTOR))-1.0, 1.0);
+ else
+ *cb=KColorUtils::darken(ca, 1.0-(k*(1-HCY_FACTOR)), 1.0);
+ #elif defined __cplusplus
+ if(k>1.0)
+ *cb=ColorUtils_lighten(&ca, (k*(1+HCY_FACTOR))-1.0, 1.0);
+ else
+ *cb=ColorUtils_darken(&ca, 1.0-(k*(1-HCY_FACTOR)), 1.0);
+ #else
+ if(k>1.0)
+ *cb=ColorUtils_lighten(ca, (k*(1+HCY_FACTOR))-1.0, 1.0);
+ else
+ *cb=ColorUtils_darken(ca, 1.0-(k*(1-HCY_FACTOR)), 1.0);
+ #endif
+ }
+ }
+#if defined __cplusplus && defined QT_VERSION && (QT_VERSION >= 0x040000)
+ cb->setAlpha(ca.alpha());
+#endif
+#ifndef __cplusplus
+ cb->pixel = ca->pixel;
+#endif
+}
+
+static unsigned char checkBounds(int num)
+{
+ return num < 0 ? 0 :
+ num > 255 ? 255 :
+ num;
+}
+
+void qtcAdjustPix(unsigned char *data, int numChannels, int w, int h, int stride, int ro, int go, int bo, double shade)
+{
+ int width=w*numChannels,
+ offset=0,
+ row,
+ r=(int)((ro*shade)+0.5),
+ g=(int)((go*shade)+0.5),
+ b=(int)((bo*shade)+0.5);
+
+ for(row=0; rowborder=border;
+#ifndef __cplusplus
+ grad->numStops=numStops;
+ grad->stops=malloc(sizeof(GradientStop) * numStops);
+#endif
+ va_start(ap, numStops);
+ for(i=0; istops.insert(GradientStop(pos, val));
+#else
+ grad->stops[i].pos=pos;
+ grad->stops[i].val=val;
+ grad->stops[i].alpha=1.0;
+#endif
+ }
+ va_end(ap);
+}
+
+const Gradient * qtcGetGradient(EAppearance app, const Options *opts)
+{
+ if(IS_CUSTOM(app))
+ {
+#ifdef __cplusplus
+ GradientCont::const_iterator grad(opts->customGradient.find(app));
+
+ if(grad!=opts->customGradient.end())
+ return &((*grad).second);
+#else
+ Gradient *grad=opts->customGradient[app-APPEARANCE_CUSTOM1];
+
+ if(grad)
+ return grad;
+#endif
+ app=APPEARANCE_RAISED;
+ }
+
+ {
+ static Gradient stdGradients[NUM_STD_APP];
+ static bool init=false;
+
+ if(!init)
+ {
+ qtcSetupGradient(&stdGradients[APPEARANCE_FLAT-APPEARANCE_FLAT], GB_3D,2,0.0,1.0,1.0,1.0);
+ qtcSetupGradient(&stdGradients[APPEARANCE_RAISED-APPEARANCE_FLAT], GB_3D_FULL,2,0.0,1.0,1.0,1.0);
+ qtcSetupGradient(&stdGradients[APPEARANCE_DULL_GLASS-APPEARANCE_FLAT], GB_LIGHT,4,0.0,1.05,0.499,0.984,0.5,0.928,1.0,1.0);
+ qtcSetupGradient(&stdGradients[APPEARANCE_SHINY_GLASS-APPEARANCE_FLAT], GB_LIGHT,4,0.0,1.2,0.499,0.984,0.5,0.9,1.0,1.06);
+ qtcSetupGradient(&stdGradients[APPEARANCE_AGUA-APPEARANCE_FLAT], GB_SHINE, 2,0.0,0.6,1.0,1.1);
+ qtcSetupGradient(&stdGradients[APPEARANCE_SOFT_GRADIENT-APPEARANCE_FLAT], GB_3D,2,0.0,1.04,1.0,0.98);
+ qtcSetupGradient(&stdGradients[APPEARANCE_GRADIENT-APPEARANCE_FLAT], GB_3D,2,0.0,1.1,1.0,0.94);
+ qtcSetupGradient(&stdGradients[APPEARANCE_HARSH_GRADIENT-APPEARANCE_FLAT], GB_3D,2,0.0,1.3,1.0,0.925);
+ qtcSetupGradient(&stdGradients[APPEARANCE_INVERTED-APPEARANCE_FLAT], GB_3D,2,0.0,0.93,1.0,1.04);
+ qtcSetupGradient(&stdGradients[APPEARANCE_DARK_INVERTED-APPEARANCE_FLAT], GB_NONE,3,0.0,0.8,0.7,0.95,1.0,1.0);
+ qtcSetupGradient(&stdGradients[APPEARANCE_SPLIT_GRADIENT-APPEARANCE_FLAT], GB_3D,4,0.0,1.06,0.499,1.004,0.5,0.986,1.0,0.92);
+ qtcSetupGradient(&stdGradients[APPEARANCE_BEVELLED-APPEARANCE_FLAT], GB_3D,4,0.0,1.05,0.1,1.02,0.9,0.985,1.0,0.94);
+ qtcSetupGradient(&stdGradients[APPEARANCE_LV_BEVELLED-APPEARANCE_FLAT], GB_3D,3,0.0,1.00,0.85,1.0,1.0,0.90);
+ qtcSetupGradient(&stdGradients[APPEARANCE_AGUA_MOD-APPEARANCE_FLAT], GB_NONE,3,0.0,1.5,0.49,0.85,1.0,1.3);
+ qtcSetupGradient(&stdGradients[APPEARANCE_LV_AGUA-APPEARANCE_FLAT], GB_NONE,4,0.0,0.98,0.35,0.95,0.4,0.93,1.0,1.15);
+ init=true;
+ }
+
+ return &stdGradients[app-APPEARANCE_FLAT];
+ }
+
+ return 0L; /* Will never happen! */
+}
+
+#ifdef __cplusplus
+EAppearance qtcWidgetApp(EWidget w, const Options *opts, bool active)
+#else
+EAppearance qtcWidgetApp(EWidget w, const Options *opts)
+#endif
+{
+ switch(w)
+ {
+ case WIDGET_SB_BGND:
+ return opts->sbarBgndAppearance;
+ case WIDGET_LISTVIEW_HEADER:
+ return opts->lvAppearance;
+ case WIDGET_SB_BUTTON:
+ case WIDGET_SLIDER:
+ case WIDGET_SB_SLIDER:
+ return opts->sliderAppearance;
+ case WIDGET_FILLED_SLIDER_TROUGH:
+ return opts->sliderFill;
+ case WIDGET_TAB_TOP:
+ case WIDGET_TAB_BOT:
+ return opts->tabAppearance;
+ case WIDGET_MENU_ITEM:
+ return opts->menuitemAppearance;
+ case WIDGET_PROGRESSBAR:
+#ifndef __cplusplus
+ case WIDGET_ENTRY_PROGRESSBAR:
+#endif
+ return opts->progressAppearance;
+ case WIDGET_PBAR_TROUGH:
+ return opts->progressGrooveAppearance;
+ case WIDGET_SELECTION:
+ return opts->selectionAppearance;
+#ifdef __cplusplus
+ case WIDGET_DOCK_WIDGET_TITLE:
+ return opts->dwtAppearance;
+ case WIDGET_MDI_WINDOW:
+ case WIDGET_MDI_WINDOW_TITLE:
+ return active ? opts->titlebarAppearance : opts->inactiveTitlebarAppearance;
+ case WIDGET_MDI_WINDOW_BUTTON:
+ return opts->titlebarButtonAppearance;
+ case WIDGET_DIAL:
+ return IS_FLAT(opts->appearance) ? APPEARANCE_RAISED : APPEARANCE_SOFT_GRADIENT;
+#endif
+ case WIDGET_TROUGH:
+ case WIDGET_SLIDER_TROUGH:
+ return opts->grooveAppearance;
+#ifndef __cplusplus
+ case WIDGET_SPIN_UP:
+ case WIDGET_SPIN_DOWN:
+#endif
+ case WIDGET_SPIN:
+ return MODIFY_AGUA(opts->appearance);
+ case WIDGET_TOOLBAR_BUTTON:
+ return APPEARANCE_NONE==opts->tbarBtnAppearance ? opts->appearance : opts->tbarBtnAppearance;
+ default:
+ break;
+ }
+
+ return opts->appearance;
+};
+
+#if !defined __cplusplus || (defined QT_VERSION && (QT_VERSION >= 0x040000))
+
+#define CAN_EXTRA_ROUND(MOD) \
+ (IS_EXTRA_ROUND_WIDGET(widget) && \
+ (IS_SLIDER(widget) || WIDGET_TROUGH==widget || \
+ ( ( (w>(MIN_ROUND_EXTRA_SIZE(widget)+MOD)) || (WIDGET_NO_ETCH_BTN==widget || WIDGET_MENU_BUTTON==widget) ) &&\
+ (h>(MIN_ROUND_EXTRA_SIZE(widget)+MOD)))))
+#define CAN_FULL_ROUND(MOD) (w>(MIN_ROUND_FULL_SIZE+MOD) && h>(MIN_ROUND_FULL_SIZE+MOD))
+
+// **NOTE** MUST KEEP IN SYNC WITH getRadius/RADIUS_ETCH !!!
+ERound qtcGetWidgetRound(const Options *opts, int w, int h, EWidget widget)
+{
+ ERound r=opts->round;
+
+ if( ((WIDGET_PBAR_TROUGH==widget || WIDGET_PROGRESSBAR==widget) && (opts->square&SQUARE_PROGRESS)) ||
+ (WIDGET_ENTRY==widget && (opts->square&SQUARE_ENTRY)) ||
+ (WIDGET_SCROLLVIEW==widget && (opts->square&SQUARE_SCROLLVIEW)) )
+ return ROUND_NONE;
+
+ if((WIDGET_CHECKBOX==widget || WIDGET_FOCUS==widget) && ROUND_NONE!=r)
+ r=ROUND_SLIGHT;
+
+#if defined __cplusplus && (defined QT_VERSION && (QT_VERSION >= 0x040000))
+ if((WIDGET_MDI_WINDOW_BUTTON==widget && (opts->titlebarButtons&TITLEBAR_BUTTON_ROUND)) ||
+ WIDGET_RADIO_BUTTON==widget || WIDGET_DIAL==widget)
+ return ROUND_MAX;
+#endif
+#ifndef __cplusplus
+ if(WIDGET_RADIO_BUTTON==widget)
+ return ROUND_MAX;
+#endif
+
+#if !defined __cplusplus || (defined QT_VERSION && (QT_VERSION >= 0x040000))
+ if(WIDGET_SLIDER==widget &&
+ (SLIDER_ROUND==opts->sliderStyle || SLIDER_ROUND_ROTATED==opts->sliderStyle || SLIDER_CIRCULAR==opts->sliderStyle))
+ return ROUND_MAX;
+#endif
+
+ switch(r)
+ {
+ case ROUND_MAX:
+ if(IS_SLIDER(widget) || WIDGET_TROUGH==widget ||
+ (w>(MIN_ROUND_MAX_WIDTH+2) && h>(MIN_ROUND_MAX_HEIGHT+2) && IS_MAX_ROUND_WIDGET(widget)))
+ return ROUND_MAX;
+ case ROUND_EXTRA:
+ if(CAN_EXTRA_ROUND(2))
+ return ROUND_EXTRA;
+ case ROUND_FULL:
+ if(CAN_FULL_ROUND(2))
+ return ROUND_FULL;
+ case ROUND_SLIGHT:
+ return ROUND_SLIGHT;
+ case ROUND_NONE:
+ return ROUND_NONE;
+ }
+
+ return ROUND_NONE;
+}
+
+double qtcGetRadius(const Options *opts, int w, int h, EWidget widget, ERadius rad)
+{
+ ERound r=opts->round;
+
+ if((WIDGET_CHECKBOX==widget || WIDGET_FOCUS==widget) && ROUND_NONE!=r)
+ r=ROUND_SLIGHT;
+
+ if( ((WIDGET_PBAR_TROUGH==widget || WIDGET_PROGRESSBAR==widget) && (opts->square&SQUARE_PROGRESS)) ||
+ (WIDGET_ENTRY==widget && (opts->square&SQUARE_ENTRY)) ||
+ (WIDGET_SCROLLVIEW==widget && (opts->square&SQUARE_SCROLLVIEW)) )
+ return 0.0;
+
+#if defined __cplusplus && (defined QT_VERSION && (QT_VERSION >= 0x040000))
+ if((WIDGET_MDI_WINDOW_BUTTON==widget && (opts->titlebarButtons&TITLEBAR_BUTTON_ROUND)) ||
+ WIDGET_RADIO_BUTTON==widget || WIDGET_DIAL==widget)
+ return (w>h ? h : w)/2.0;
+#endif
+#ifndef __cplusplus
+ if(WIDGET_RADIO_BUTTON==widget)
+ return (w>h ? h : w)/2.0;
+#endif
+
+#if !defined __cplusplus || (defined QT_VERSION && (QT_VERSION >= 0x040000))
+ if(WIDGET_SLIDER==widget &&
+ (SLIDER_ROUND==opts->sliderStyle || SLIDER_ROUND_ROTATED==opts->sliderStyle || SLIDER_CIRCULAR==opts->sliderStyle))
+ return (w>h ? h : w)/2.0;
+#endif
+
+ if(RADIUS_EXTERNAL==rad && !opts->fillProgress && (WIDGET_PROGRESSBAR==widget
+#ifndef __cplusplus
+ || WIDGET_ENTRY_PROGRESSBAR==widget
+#endif
+ ))
+ rad=RADIUS_INTERNAL;
+
+ switch(rad)
+ {
+ case RADIUS_SELECTION:
+ switch(r)
+ {
+ case ROUND_MAX:
+ case ROUND_EXTRA:
+ if(/* (WIDGET_RUBBER_BAND==widget && w>14 && h>14) || */(w>48 && h>48))
+ return 6.0;
+ case ROUND_FULL:
+// if( /*(WIDGET_RUBBER_BAND==widget && w>11 && h>11) || */(w>48 && h>48))
+// return 3.0;
+ if(w>MIN_ROUND_FULL_SIZE && h>MIN_ROUND_FULL_SIZE)
+ return 3.0;
+ case ROUND_SLIGHT:
+ return 2.0;
+ case ROUND_NONE:
+ return 0;
+ }
+ case RADIUS_INTERNAL:
+ switch(r)
+ {
+ case ROUND_MAX:
+ if(IS_SLIDER(widget) || WIDGET_TROUGH==widget)
+ {
+ double r=((w>h ? h : w)-(WIDGET_SLIDER==widget ? 1 : 0))/2.0;
+ return r>MAX_RADIUS_INTERNAL ? MAX_RADIUS_INTERNAL : r;
+ }
+ if(w>(MIN_ROUND_MAX_WIDTH-2) && h>(MIN_ROUND_MAX_HEIGHT-2) && IS_MAX_ROUND_WIDGET(widget))
+ {
+ double r=((w>h ? h : w)-2.0)/2.0;
+ return r>9.5 ? 9.5 : r;
+ }
+ case ROUND_EXTRA:
+ if(CAN_EXTRA_ROUND(-2))
+ return EXTRA_INNER_RADIUS;
+ case ROUND_FULL:
+ if(CAN_FULL_ROUND(-2))
+ return FULL_INNER_RADIUS;
+ case ROUND_SLIGHT:
+ return SLIGHT_INNER_RADIUS;
+ case ROUND_NONE:
+ return 0;
+ }
+ case RADIUS_EXTERNAL:
+ switch(r)
+ {
+ case ROUND_MAX:
+ if(IS_SLIDER(widget) || WIDGET_TROUGH==widget)
+ {
+ double r=((w>h ? h : w)-(WIDGET_SLIDER==widget ? 1 : 0))/2.0;
+ return r>MAX_RADIUS_EXTERNAL ? MAX_RADIUS_EXTERNAL : r;
+ }
+ if(w>MIN_ROUND_MAX_WIDTH && h>MIN_ROUND_MAX_HEIGHT && IS_MAX_ROUND_WIDGET(widget))
+ {
+ double r=((w>h ? h : w)-2.0)/2.0;
+ return r>10.5 ? 10.5 : r;
+ }
+ case ROUND_EXTRA:
+ if(CAN_EXTRA_ROUND(0))
+ return EXTRA_OUTER_RADIUS;
+ case ROUND_FULL:
+ if(CAN_FULL_ROUND(0))
+ return FULL_OUTER_RADIUS;
+ case ROUND_SLIGHT:
+ return SLIGHT_OUTER_RADIUS;
+ case ROUND_NONE:
+ return 0;
+ }
+ case RADIUS_ETCH:
+ // **NOTE** MUST KEEP IN SYNC WITH getWidgetRound !!!
+ switch(r)
+ {
+ case ROUND_MAX:
+ if(IS_SLIDER(widget) || WIDGET_TROUGH==widget)
+ {
+ double r=((w>h ? h : w)-(WIDGET_SLIDER==widget ? 1 : 0))/2.0;
+ return r>MAX_RADIUS_EXTERNAL ? MAX_RADIUS_EXTERNAL : r;
+ }
+ if(w>(MIN_ROUND_MAX_WIDTH+2) && h>(MIN_ROUND_MAX_HEIGHT+2) && IS_MAX_ROUND_WIDGET(widget))
+ {
+ double r=((w>h ? h : w)-2.0)/2.0;
+ return r>11.5 ? 11.5 : r;
+ }
+ case ROUND_EXTRA:
+ if(CAN_FULL_ROUND(2))
+ return EXTRA_ETCH_RADIUS;
+ case ROUND_FULL:
+ if(w>(MIN_ROUND_FULL_SIZE+2) && h>(MIN_ROUND_FULL_SIZE+2))
+ return FULL_ETCH_RADIUS;
+ case ROUND_SLIGHT:
+ return SLIGHT_ETCH_RADIUS;
+ case ROUND_NONE:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+double qtcRingAlpha[3]={0.125, 0.125, 0.5};
+
+void qtcCalcRingAlphas(const color *bgnd)
+{
+#ifdef __cplusplus
+ double r=bgnd->red()/255.0,
+ g=bgnd->green()/255.0,
+ b=bgnd->blue()/255.0,
+#else
+ double r=bgnd->red/65535.0,
+ g=bgnd->green/65535.0,
+ b=bgnd->blue/65535.0,
+#endif
+ h=0,
+ s=0,
+ v=0;
+ qtcRgbToHsv(r, g, b, &h, &s, &v);
+ qtcRingAlpha[0]=v*0.26;
+ qtcRingAlpha[1]=v*0.14;
+ qtcRingAlpha[2]=v*0.55;
+}
+
+double qtcShineAlpha(const color *bgnd)
+{
+#ifdef __cplusplus
+ double r=bgnd->red()/255.0,
+ g=bgnd->green()/255.0,
+ b=bgnd->blue()/255.0,
+#else
+ double r=bgnd->red/65535.0,
+ g=bgnd->green/65535.0,
+ b=bgnd->blue/65535.0,
+#endif
+ h=0,
+ s=0,
+ v=0;
+ qtcRgbToHsv(r, g, b, &h, &s, &v);
+ return v*0.8;
+}
+
+#endif // !defined __cplusplus || (defined QT_VERSION && (QT_VERSION >= 0x040000))
diff --git a/src/qtcurve/common/common.h b/src/qtcurve/common/common.h
new file mode 100644
index 0000000000..7d5ed7e181
--- /dev/null
+++ b/src/qtcurve/common/common.h
@@ -0,0 +1,1383 @@
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+/*
+ QtCurve (C) Craig Drummond, 2003 - 2010 craig.p.drummond@gmail.com
+
+ ----
+
+ This program is free software; you can redistr ibute it and/or
+ modify it under the terms of the GNU General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#define MAKE_VERSION(a, b) (((a) << 16) | ((b) << 8))
+#define MAKE_VERSION3(a, b, c) (((a) << 16) | ((b) << 8) | (c))
+
+/*
+ The following #define disables the rounding when scrollbar type==none.
+#define SIMPLE_SCROLLBARS
+*/
+
+/*
+ The following #define controls whether a scrollbar's slider should overlap
+ the scrollbar buttons when at min/max. This removes the thick looking line
+ between the slider and the buttons.
+*/
+#define INCREASE_SB_SLIDER
+
+typedef enum
+{
+ SHADING_SIMPLE=0,
+ SHADING_HSL=1,
+ SHADING_HSV=2,
+ SHADING_HCY=3
+} EShading;
+
+#ifdef __cplusplus
+#include
+#include
+#include