mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Store: Advance search for affiliate. Clean up tool tips. Add quick enable buttons in chooser. Add affiliate status in chooser.
This commit is contained in:
parent
66315cead2
commit
a46954edf9
@ -45,8 +45,9 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog):
|
|||||||
self.description_box.setText('')
|
self.description_box.setText('')
|
||||||
self.headquarters_box.setText('')
|
self.headquarters_box.setText('')
|
||||||
self.format_box.setText('')
|
self.format_box.setText('')
|
||||||
self.enabled_combo.setIndex(0)
|
self.enabled_combo.setCurrentIndex(0)
|
||||||
self.drm_combo.setIndex(0)
|
self.drm_combo.setCurrentIndex(0)
|
||||||
|
self.affiliate_combo.setCurrentIndex(0)
|
||||||
|
|
||||||
def tokens(self, raw):
|
def tokens(self, raw):
|
||||||
phrases = re.findall(r'\s*".*?"\s*', raw)
|
phrases = re.findall(r'\s*".*?"\s*', raw)
|
||||||
@ -126,6 +127,9 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog):
|
|||||||
drm = unicode(self.drm_combo.currentText()).strip()
|
drm = unicode(self.drm_combo.currentText()).strip()
|
||||||
if drm:
|
if drm:
|
||||||
ans.append('drm:' + drm)
|
ans.append('drm:' + drm)
|
||||||
|
affiliate = unicode(self.affiliate_combo.currentText()).strip()
|
||||||
|
if affiliate:
|
||||||
|
ans.append('affiliate:' + affiliate)
|
||||||
if ans:
|
if ans:
|
||||||
return ' and '.join(ans)
|
return ' and '.join(ans)
|
||||||
return ''
|
return ''
|
||||||
|
@ -226,7 +226,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0" colspan="2">
|
<item row="9" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="clear_button">
|
<widget class="QPushButton" name="clear_button">
|
||||||
@ -244,7 +244,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="8" column="1">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -335,6 +335,32 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>Affiliate:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QComboBox" name="affiliate_combo">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>true</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>false</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -23,6 +23,9 @@ class StoreChooserWidget(QWidget, Ui_Form):
|
|||||||
|
|
||||||
self.search.clicked.connect(self.do_search)
|
self.search.clicked.connect(self.do_search)
|
||||||
self.adv_search_builder.clicked.connect(self.build_adv_search)
|
self.adv_search_builder.clicked.connect(self.build_adv_search)
|
||||||
|
self.enable_all.clicked.connect(self.results_view.model().enable_all)
|
||||||
|
self.enable_none.clicked.connect(self.results_view.model().enable_none)
|
||||||
|
self.enable_invert.clicked.connect(self.results_view.model().enable_invert)
|
||||||
self.results_view.activated.connect(self.toggle_plugin)
|
self.results_view.activated.connect(self.toggle_plugin)
|
||||||
|
|
||||||
def do_search(self):
|
def do_search(self):
|
||||||
|
@ -85,26 +85,26 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Select:</string>
|
<string>Enable</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="select_all">
|
<widget class="QPushButton" name="enable_all">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>All</string>
|
<string>All</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="select_none">
|
<widget class="QPushButton" name="enable_none">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>None</string>
|
<string>None</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="select_invert">
|
<widget class="QPushButton" name="enable_invert">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Invert</string>
|
<string>Invert</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -6,7 +6,7 @@ __license__ = 'GPL 3'
|
|||||||
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
|
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from PyQt4.Qt import (Qt, QAbstractItemModel, QIcon, QVariant, QModelIndex)
|
from PyQt4.Qt import (Qt, QAbstractItemModel, QIcon, QVariant, QModelIndex, QSize)
|
||||||
|
|
||||||
from calibre.gui2 import NONE
|
from calibre.gui2 import NONE
|
||||||
from calibre.customize.ui import is_disabled, disable_plugin, enable_plugin
|
from calibre.customize.ui import is_disabled, disable_plugin, enable_plugin
|
||||||
@ -18,13 +18,15 @@ from calibre.utils.search_query_parser import SearchQueryParser
|
|||||||
|
|
||||||
class Matches(QAbstractItemModel):
|
class Matches(QAbstractItemModel):
|
||||||
|
|
||||||
HEADERS = [_('Enabled'), _('Name'), _('No DRM'), _('Headquarters'), _('Formats')]
|
HEADERS = [_('Enabled'), _('Name'), _('No DRM'), _('Headquarters'), _('Affiliate'), _('Formats')]
|
||||||
HTML_COLS = [1]
|
HTML_COLS = [1]
|
||||||
|
|
||||||
def __init__(self, plugins):
|
def __init__(self, plugins):
|
||||||
QAbstractItemModel.__init__(self)
|
QAbstractItemModel.__init__(self)
|
||||||
|
|
||||||
self.NO_DRM_ICON = QIcon(I('ok.png'))
|
self.NO_DRM_ICON = QIcon(I('ok.png'))
|
||||||
|
self.DONATE_ICON = QIcon()
|
||||||
|
self.DONATE_ICON.addFile(I('donate.png'), QSize(16, 16))
|
||||||
|
|
||||||
self.all_matches = plugins
|
self.all_matches = plugins
|
||||||
self.matches = plugins
|
self.matches = plugins
|
||||||
@ -53,6 +55,22 @@ class Matches(QAbstractItemModel):
|
|||||||
self.layoutChanged.emit()
|
self.layoutChanged.emit()
|
||||||
self.sort(self.sort_col, self.sort_order)
|
self.sort(self.sort_col, self.sort_order)
|
||||||
|
|
||||||
|
def enable_all(self):
|
||||||
|
for i in xrange(len(self.matches)):
|
||||||
|
index = self.createIndex(i, 0)
|
||||||
|
data = QVariant(True)
|
||||||
|
self.setData(index, data, Qt.CheckStateRole)
|
||||||
|
|
||||||
|
def enable_none(self):
|
||||||
|
for i in xrange(len(self.matches)):
|
||||||
|
index = self.createIndex(i, 0)
|
||||||
|
data = QVariant(False)
|
||||||
|
self.setData(index, data, Qt.CheckStateRole)
|
||||||
|
|
||||||
|
def enable_invert(self):
|
||||||
|
for i in xrange(len(self.matches)):
|
||||||
|
self.toggle_plugin(self.createIndex(i, 0))
|
||||||
|
|
||||||
def toggle_plugin(self, index):
|
def toggle_plugin(self, index):
|
||||||
new_index = self.createIndex(index.row(), 0)
|
new_index = self.createIndex(index.row(), 0)
|
||||||
data = QVariant(is_disabled(self.get_plugin(index)))
|
data = QVariant(is_disabled(self.get_plugin(index)))
|
||||||
@ -91,12 +109,15 @@ class Matches(QAbstractItemModel):
|
|||||||
return QVariant('<b>%s</b><br><i>%s</i>' % (result.name, result.description))
|
return QVariant('<b>%s</b><br><i>%s</i>' % (result.name, result.description))
|
||||||
elif col == 3:
|
elif col == 3:
|
||||||
return QVariant(result.headquarters)
|
return QVariant(result.headquarters)
|
||||||
elif col == 4:
|
elif col == 5:
|
||||||
return QVariant(', '.join(result.formats).upper())
|
return QVariant(', '.join(result.formats).upper())
|
||||||
elif role == Qt.DecorationRole:
|
elif role == Qt.DecorationRole:
|
||||||
if col == 2:
|
if col == 2:
|
||||||
if result.drm_free_only:
|
if result.drm_free_only:
|
||||||
return QVariant(self.NO_DRM_ICON)
|
return QVariant(self.NO_DRM_ICON)
|
||||||
|
if col == 4:
|
||||||
|
if result.affiliate:
|
||||||
|
return QVariant(self.DONATE_ICON)
|
||||||
elif role == Qt.CheckStateRole:
|
elif role == Qt.CheckStateRole:
|
||||||
if col == 0:
|
if col == 0:
|
||||||
if is_disabled(result):
|
if is_disabled(result):
|
||||||
@ -105,20 +126,23 @@ class Matches(QAbstractItemModel):
|
|||||||
elif role == Qt.ToolTipRole:
|
elif role == Qt.ToolTipRole:
|
||||||
if col == 0:
|
if col == 0:
|
||||||
if is_disabled(result):
|
if is_disabled(result):
|
||||||
return QVariant(_('<p>This store is currently diabled and cannot be used in other parts of calibre.</p>'))
|
return QVariant('<p>' + _('This store is currently diabled and cannot be used in other parts of calibre.') + '</p>')
|
||||||
else:
|
else:
|
||||||
return QVariant(_('<p>This store is currently enabled and can be used in other parts of calibre.</p>'))
|
return QVariant('<p>' + _('This store is currently enabled and can be used in other parts of calibre.') + '</p>')
|
||||||
elif col == 1:
|
elif col == 1:
|
||||||
return QVariant('<p>%s</p>' % result.description)
|
return QVariant('<p>%s</p>' % result.description)
|
||||||
elif col == 2:
|
elif col == 2:
|
||||||
if result.drm_free_only:
|
if result.drm_free_only:
|
||||||
return QVariant(_('<p>This store only distributes ebooks with DRM.</p>'))
|
return QVariant('<p>' + _('This store only distributes ebooks with DRM.') + '</p>')
|
||||||
else:
|
else:
|
||||||
return QVariant(_('<p>This store distributes ebooks with DRM. It may have some titles without DRM, but you will need to check on a per title basis.</p>'))
|
return QVariant('<p>' + _('This store distributes ebooks with DRM. It may have some titles without DRM, but you will need to check on a per title basis.') + '</p>')
|
||||||
elif col == 3:
|
elif col == 3:
|
||||||
return QVariant(_('<p>This store is headquartered in %s. This is a good indication of what market the store caters to. However, this does not necessarily mean that the store is limited to that market only.</p>') % result.headquarters)
|
return QVariant('<p>' + _('This store is headquartered in %s. This is a good indication of what market the store caters to. However, this does not necessarily mean that the store is limited to that market only.') % result.headquarters + '</p>')
|
||||||
elif col == 4:
|
elif col == 4:
|
||||||
return QVariant(_('<p>This store distributes ebooks in the following formats: %s</p>') % ', '.join(result.formats))
|
if result.affiliate:
|
||||||
|
return QVariant('<p>' + _('Buying from this store supports the calibre developer: %s.') % result.author + '</p>')
|
||||||
|
elif col == 5:
|
||||||
|
return QVariant('<p>' + _('This store distributes ebooks in the following formats: %s') % ', '.join(result.formats) + '</p>')
|
||||||
return NONE
|
return NONE
|
||||||
|
|
||||||
def setData(self, index, data, role):
|
def setData(self, index, data, role):
|
||||||
@ -148,6 +172,8 @@ class Matches(QAbstractItemModel):
|
|||||||
text = 'a' if getattr(match, 'drm_free_only', True) else 'b'
|
text = 'a' if getattr(match, 'drm_free_only', True) else 'b'
|
||||||
elif col == 3:
|
elif col == 3:
|
||||||
text = getattr(match, 'headquarters', '')
|
text = getattr(match, 'headquarters', '')
|
||||||
|
elif col == 4:
|
||||||
|
text = 'a' if getattr(match, 'affiliate', False) else 'b'
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def sort(self, col, order, reset=True):
|
def sort(self, col, order, reset=True):
|
||||||
@ -167,6 +193,7 @@ class SearchFilter(SearchQueryParser):
|
|||||||
|
|
||||||
USABLE_LOCATIONS = [
|
USABLE_LOCATIONS = [
|
||||||
'all',
|
'all',
|
||||||
|
'affiliate',
|
||||||
'description',
|
'description',
|
||||||
'drm',
|
'drm',
|
||||||
'enabled',
|
'enabled',
|
||||||
@ -207,6 +234,7 @@ class SearchFilter(SearchQueryParser):
|
|||||||
all_locs = set(self.USABLE_LOCATIONS) - set(['all'])
|
all_locs = set(self.USABLE_LOCATIONS) - set(['all'])
|
||||||
locations = all_locs if location == 'all' else [location]
|
locations = all_locs if location == 'all' else [location]
|
||||||
q = {
|
q = {
|
||||||
|
'affiliate': lambda x: x.affiliate,
|
||||||
'description': lambda x: x.description.lower(),
|
'description': lambda x: x.description.lower(),
|
||||||
'drm': lambda x: not x.drm_free_only,
|
'drm': lambda x: not x.drm_free_only,
|
||||||
'enabled': lambda x: not is_disabled(x),
|
'enabled': lambda x: not is_disabled(x),
|
||||||
@ -219,21 +247,21 @@ class SearchFilter(SearchQueryParser):
|
|||||||
for locvalue in locations:
|
for locvalue in locations:
|
||||||
accessor = q[locvalue]
|
accessor = q[locvalue]
|
||||||
if query == 'true':
|
if query == 'true':
|
||||||
if locvalue in ('drm', 'enabled'):
|
if locvalue in ('affiliate', 'drm', 'enabled'):
|
||||||
if accessor(sr) == True:
|
if accessor(sr) == True:
|
||||||
matches.add(sr)
|
matches.add(sr)
|
||||||
elif accessor(sr) is not None:
|
elif accessor(sr) is not None:
|
||||||
matches.add(sr)
|
matches.add(sr)
|
||||||
continue
|
continue
|
||||||
if query == 'false':
|
if query == 'false':
|
||||||
if locvalue in ('drm', 'enabled'):
|
if locvalue in ('affiliate', 'drm', 'enabled'):
|
||||||
if accessor(sr) == False:
|
if accessor(sr) == False:
|
||||||
matches.add(sr)
|
matches.add(sr)
|
||||||
elif accessor(sr) is None:
|
elif accessor(sr) is None:
|
||||||
matches.add(sr)
|
matches.add(sr)
|
||||||
continue
|
continue
|
||||||
# this is bool, so can't match below
|
# this is bool, so can't match below
|
||||||
if locvalue in ('drm', 'enabled'):
|
if locvalue in ('affiliate', 'drm', 'enabled'):
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
### Can't separate authors because comma is used for name sep and author sep
|
### Can't separate authors because comma is used for name sep and author sep
|
||||||
|
@ -45,6 +45,7 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog):
|
|||||||
self.author_box.setText('')
|
self.author_box.setText('')
|
||||||
self.price_box.setText('')
|
self.price_box.setText('')
|
||||||
self.format_box.setText('')
|
self.format_box.setText('')
|
||||||
|
self.affiliate_combo.setCurrentIndex(0)
|
||||||
|
|
||||||
def tokens(self, raw):
|
def tokens(self, raw):
|
||||||
phrases = re.findall(r'\s*".*?"\s*', raw)
|
phrases = re.findall(r'\s*".*?"\s*', raw)
|
||||||
@ -118,6 +119,9 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog):
|
|||||||
format = unicode(self.format_box.text()).strip()
|
format = unicode(self.format_box.text()).strip()
|
||||||
if format:
|
if format:
|
||||||
ans.append('format:"' + self.mc + format + '"')
|
ans.append('format:"' + self.mc + format + '"')
|
||||||
|
affiliate = unicode(self.affiliate_combo.currentText()).strip()
|
||||||
|
if affiliate:
|
||||||
|
ans.append('affiliate:' + affiliate)
|
||||||
if ans:
|
if ans:
|
||||||
return ' and '.join(ans)
|
return ' and '.join(ans)
|
||||||
return ''
|
return ''
|
||||||
|
@ -226,7 +226,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0" colspan="2">
|
<item row="7" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="clear_button">
|
<widget class="QPushButton" name="clear_button">
|
||||||
@ -244,7 +244,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="6" column="1">
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
@ -283,6 +283,32 @@
|
|||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="EnLineEdit" name="price_box"/>
|
<widget class="EnLineEdit" name="price_box"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>Affiliate:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QComboBox" name="affiliate_combo">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>true</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>false</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -121,6 +121,7 @@ class SearchThread(Thread):
|
|||||||
return
|
return
|
||||||
res.store_name = store_name
|
res.store_name = store_name
|
||||||
res.affiliate = store_plugin.base_plugin.affiliate
|
res.affiliate = store_plugin.base_plugin.affiliate
|
||||||
|
res.plugin_author = store_plugin.base_plugin.author
|
||||||
self.results.put((res, store_plugin))
|
self.results.put((res, store_plugin))
|
||||||
self.tasks.task_done()
|
self.tasks.task_done()
|
||||||
except:
|
except:
|
||||||
|
@ -200,7 +200,7 @@ class Matches(QAbstractItemModel):
|
|||||||
return QVariant('<p>%s</p>' % result.formats)
|
return QVariant('<p>%s</p>' % result.formats)
|
||||||
elif col == 5:
|
elif col == 5:
|
||||||
if result.affiliate:
|
if result.affiliate:
|
||||||
return QVariant(_('Buying from this store supports a calibre developer'))
|
return QVariant('<p>' + _('Buying from this store supports the calibre developer: %s.') % result.plugin_author + '</p>')
|
||||||
elif role == Qt.SizeHintRole:
|
elif role == Qt.SizeHintRole:
|
||||||
return QSize(64, 64)
|
return QSize(64, 64)
|
||||||
return NONE
|
return NONE
|
||||||
|
@ -102,7 +102,7 @@ class SearchDialog(QDialog, Ui_Dialog):
|
|||||||
store_list_layout.addWidget(cbox, i, 0, 1, 1)
|
store_list_layout.addWidget(cbox, i, 0, 1, 1)
|
||||||
if self.gui.istores[x].base_plugin.affiliate:
|
if self.gui.istores[x].base_plugin.affiliate:
|
||||||
iw = QLabel(self)
|
iw = QLabel(self)
|
||||||
iw.setToolTip(_('Buying from this store supports a calibre developer'))
|
iw.setToolTip('<p>' + _('Buying from this store supports the calibre developer: %s</p>') % self.gui.istores[x].base_plugin.author + '</p>')
|
||||||
iw.setPixmap(icon.pixmap(16, 16))
|
iw.setPixmap(icon.pixmap(16, 16))
|
||||||
store_list_layout.addWidget(iw, i, 1, 1, 1)
|
store_list_layout.addWidget(iw, i, 1, 1, 1)
|
||||||
self.store_checks[x] = cbox
|
self.store_checks[x] = cbox
|
||||||
|
@ -23,6 +23,7 @@ class SearchResult(object):
|
|||||||
self.drm = None
|
self.drm = None
|
||||||
self.formats = ''
|
self.formats = ''
|
||||||
self.affiliate = False
|
self.affiliate = False
|
||||||
|
self.plugin_author = ''
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.title == other.title and self.author == other.author and self.store_name == other.store_name
|
return self.title == other.title and self.author == other.author and self.store_name == other.store_name
|
||||||
|
Loading…
x
Reference in New Issue
Block a user