mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
MobileRead store dialog to display avaliable books.
This commit is contained in:
parent
98921e4bfa
commit
ad306d8f67
@ -14,15 +14,18 @@ from threading import RLock
|
||||
|
||||
from lxml import html
|
||||
|
||||
from PyQt4.Qt import QUrl
|
||||
from PyQt4.Qt import Qt, QUrl, QDialog, QAbstractItemModel, QModelIndex, QVariant, \
|
||||
pyqtSignal
|
||||
|
||||
from calibre import browser
|
||||
from calibre.gui2 import open_url
|
||||
from calibre.gui2 import open_url, NONE
|
||||
from calibre.gui2.store import StorePlugin
|
||||
from calibre.gui2.store.basic_config import BasicStoreConfig
|
||||
from calibre.gui2.store.mobileread_store_dialog_ui import Ui_Dialog
|
||||
from calibre.gui2.store.search_result import SearchResult
|
||||
from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
||||
from calibre.utils.config import DynamicConfig
|
||||
from calibre.utils.icu import sort_key
|
||||
|
||||
class MobileReadStore(BasicStoreConfig, StorePlugin):
|
||||
|
||||
@ -37,10 +40,15 @@ class MobileReadStore(BasicStoreConfig, StorePlugin):
|
||||
if external or settings.get(self.name + '_open_external', False):
|
||||
open_url(QUrl(detail_item if detail_item else url))
|
||||
else:
|
||||
d = WebStoreDialog(self.gui, url, parent, detail_item)
|
||||
d.setWindowTitle(self.name)
|
||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
||||
d = d.exec_()
|
||||
if detail_item:
|
||||
d = WebStoreDialog(self.gui, url, parent, detail_item)
|
||||
d.setWindowTitle(self.name)
|
||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
||||
d.exec_()
|
||||
else:
|
||||
d = MobeReadStoreDialog(self, parent)
|
||||
d.setWindowTitle(self.name)
|
||||
d.exec_()
|
||||
|
||||
def search(self, query, max_results=10, timeout=60):
|
||||
books = self.get_book_list(timeout=timeout)
|
||||
@ -123,3 +131,173 @@ class BookRef(SearchResult):
|
||||
SearchResult.__init__(self)
|
||||
|
||||
self.format = ''
|
||||
|
||||
|
||||
class MobeReadStoreDialog(QDialog, Ui_Dialog):
|
||||
|
||||
def __init__(self, plugin, *args):
|
||||
QDialog.__init__(self, *args)
|
||||
self.setupUi(self)
|
||||
|
||||
self.plugin = plugin
|
||||
|
||||
self.model = BooksModel()
|
||||
self.results_view.setModel(self.model)
|
||||
self.results_view.model().set_books(self.plugin.get_book_list())
|
||||
self.total.setText('%s' % self.model.rowCount())
|
||||
|
||||
self.results_view.activated.connect(self.open_store)
|
||||
self.search_query.textChanged.connect(self.model.set_filter)
|
||||
self.results_view.model().total_changed.connect(self.total.setText)
|
||||
self.finished.connect(self.dialog_closed)
|
||||
|
||||
self.restore_state()
|
||||
|
||||
def open_store(self, index):
|
||||
result = self.results_view.model().get_book(index)
|
||||
if result:
|
||||
self.plugin.open(self, result.detail_item)
|
||||
|
||||
def restore_state(self):
|
||||
geometry = self.plugin.config['store_mobileread_dialog_geometry']
|
||||
if geometry:
|
||||
self.restoreGeometry(geometry)
|
||||
|
||||
results_cwidth = self.plugin.config['store_mobileread_dialog_results_view_column_width']
|
||||
if results_cwidth:
|
||||
for i, x in enumerate(results_cwidth):
|
||||
if i >= self.results_view.model().columnCount():
|
||||
break
|
||||
self.results_view.setColumnWidth(i, x)
|
||||
else:
|
||||
for i in xrange(self.results_view.model().columnCount()):
|
||||
self.results_view.resizeColumnToContents(i)
|
||||
|
||||
self.results_view.model().sort_col = self.plugin.config.get('store_mobileread_dialog_sort_col', 0)
|
||||
self.results_view.model().sort_order = self.plugin.config.get('store_mobileread_dialog_sort_order', Qt.AscendingOrder)
|
||||
self.results_view.model().sort(self.results_view.model().sort_col, self.results_view.model().sort_order)
|
||||
|
||||
def save_state(self):
|
||||
self.plugin.config['store_mobileread_dialog_geometry'] = self.saveGeometry()
|
||||
self.plugin.config['store_mobileread_dialog_results_view_column_width'] = [self.results_view.columnWidth(i) for i in range(self.model.columnCount())]
|
||||
self.plugin.config['store_mobileread_dialog_sort_col'] = self.results_view.model().sort_col
|
||||
self.plugin.config['store_mobileread_dialog_sort_order'] = self.results_view.model().sort_order
|
||||
|
||||
def dialog_closed(self, result):
|
||||
self.save_state()
|
||||
|
||||
|
||||
class BooksModel(QAbstractItemModel):
|
||||
|
||||
total_changed = pyqtSignal(unicode)
|
||||
|
||||
HEADERS = [_('Title'), _('Author(s)'), _('Format')]
|
||||
|
||||
def __init__(self):
|
||||
QAbstractItemModel.__init__(self)
|
||||
self.books = []
|
||||
self.all_books = []
|
||||
self.filter = ''
|
||||
self.sort_col = 0
|
||||
self.sort_order = Qt.AscendingOrder
|
||||
|
||||
def set_books(self, books):
|
||||
self.books = books
|
||||
self.all_books = books
|
||||
|
||||
self.sort(self.sort_col, self.sort_order)
|
||||
|
||||
def get_book(self, index):
|
||||
row = index.row()
|
||||
if row < len(self.books):
|
||||
return self.books[row]
|
||||
else:
|
||||
return None
|
||||
|
||||
def set_filter(self, filter):
|
||||
#self.layoutAboutToBeChanged.emit()
|
||||
self.beginResetModel()
|
||||
|
||||
self.filter = unicode(filter)
|
||||
self.books = []
|
||||
if self.filter:
|
||||
for b in self.all_books:
|
||||
test = '%s %s %s' % (b.title, b.author, b.format)
|
||||
test = test.lower()
|
||||
include = True
|
||||
for item in self.filter.split(' '):
|
||||
item = item.lower()
|
||||
if item not in test:
|
||||
include = False
|
||||
break
|
||||
if include:
|
||||
self.books.append(b)
|
||||
else:
|
||||
self.books = self.all_books
|
||||
|
||||
self.sort(self.sort_col, self.sort_order, reset=False)
|
||||
self.total_changed.emit('%s' % self.rowCount())
|
||||
|
||||
self.endResetModel()
|
||||
#self.layoutChanged.emit()
|
||||
|
||||
def index(self, row, column, parent=QModelIndex()):
|
||||
return self.createIndex(row, column)
|
||||
|
||||
def parent(self, index):
|
||||
if not index.isValid() or index.internalId() == 0:
|
||||
return QModelIndex()
|
||||
return self.createIndex(0, 0)
|
||||
|
||||
def rowCount(self, *args):
|
||||
return len(self.books)
|
||||
|
||||
def columnCount(self, *args):
|
||||
return len(self.HEADERS)
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
if role != Qt.DisplayRole:
|
||||
return NONE
|
||||
text = ''
|
||||
if orientation == Qt.Horizontal:
|
||||
if section < len(self.HEADERS):
|
||||
text = self.HEADERS[section]
|
||||
return QVariant(text)
|
||||
else:
|
||||
return QVariant(section+1)
|
||||
|
||||
def data(self, index, role):
|
||||
row, col = index.row(), index.column()
|
||||
result = self.books[row]
|
||||
if role == Qt.DisplayRole:
|
||||
if col == 0:
|
||||
return QVariant(result.title)
|
||||
elif col == 1:
|
||||
return QVariant(result.author)
|
||||
elif col == 2:
|
||||
return QVariant(result.format)
|
||||
return NONE
|
||||
|
||||
def data_as_text(self, result, col):
|
||||
text = ''
|
||||
if col == 0:
|
||||
text = result.title
|
||||
elif col == 1:
|
||||
text = result.author
|
||||
elif col == 2:
|
||||
text = result.format
|
||||
return text
|
||||
|
||||
def sort(self, col, order, reset=True):
|
||||
self.sort_col = col
|
||||
self.sort_order = order
|
||||
|
||||
if not self.books:
|
||||
return
|
||||
descending = order == Qt.DescendingOrder
|
||||
self.books.sort(None,
|
||||
lambda x: sort_key(unicode(self.data_as_text(x, col))),
|
||||
descending)
|
||||
if reset:
|
||||
self.reset()
|
||||
|
||||
|
112
src/calibre/gui2/store/mobileread_store_dialog.ui
Normal file
112
src/calibre/gui2/store/mobileread_store_dialog.ui
Normal file
@ -0,0 +1,112 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>691</width>
|
||||
<height>614</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Search:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="search_query"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="results_view">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerCascadingSectionResizes">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Books:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="total">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>308</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="close_button">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>close_button</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Dialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>440</x>
|
||||
<y>432</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>245</x>
|
||||
<y>230</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Loading…
x
Reference in New Issue
Block a user