mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Various minor bug fixes. Fixed dragging from library to device that had been broken by a previous commit. Improved device detection code. Improved rendering of titles/authors. Version bump as there were a lot og bug fixes
This commit is contained in:
parent
695c27d229
commit
599543800c
@ -37,6 +37,6 @@ the following rule in C{/etc/udev/rules.d/90-local.rules} ::
|
|||||||
You may have to adjust the GROUP and the location of the rules file to
|
You may have to adjust the GROUP and the location of the rules file to
|
||||||
suit your distribution.
|
suit your distribution.
|
||||||
"""
|
"""
|
||||||
__version__ = "0.3.0a4"
|
__version__ = "0.3.0a5"
|
||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
@ -64,14 +64,14 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.device_view.show()
|
self.device_view.show()
|
||||||
self.library_view.hide()
|
self.library_view.hide()
|
||||||
self.book_cover.setAcceptDrops(False)
|
self.book_cover.setAcceptDrops(False)
|
||||||
self.current_view = self.device_view
|
self.device_view.resizeColumnsToContents()
|
||||||
|
self.device_view.resizeRowsToContents()
|
||||||
else:
|
else:
|
||||||
self.action_add.setEnabled(True)
|
self.action_add.setEnabled(True)
|
||||||
self.action_edit.setEnabled(True)
|
self.action_edit.setEnabled(True)
|
||||||
self.device_view.hide()
|
self.device_view.hide()
|
||||||
self.library_view.show()
|
self.library_view.show()
|
||||||
self.book_cover.setAcceptDrops(True)
|
self.book_cover.setAcceptDrops(True)
|
||||||
self.current_view = self.library_view
|
|
||||||
self.current_view.sortByColumn(3, Qt.DescendingOrder)
|
self.current_view.sortByColumn(3, Qt.DescendingOrder)
|
||||||
|
|
||||||
|
|
||||||
@ -96,29 +96,32 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
|
|
||||||
|
|
||||||
def model_modified(self):
|
def model_modified(self):
|
||||||
if self.library_view.isVisible(): view = self.library_view
|
if self.current_view.selectionModel():
|
||||||
else: view = self.device_view
|
self.current_view.selectionModel().reset()
|
||||||
view.selectionModel().reset()
|
self.current_view.resizeColumnsToContents()
|
||||||
view.resizeColumnsToContents()
|
self.current_view.resizeRowsToContents()
|
||||||
self.book_cover.hide()
|
self.book_cover.hide()
|
||||||
self.book_info.hide()
|
self.book_info.hide()
|
||||||
QCoreApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
|
QCoreApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
|
||||||
|
|
||||||
def resize_columns(self, topleft, bottomright):
|
def resize_rows_and_columns(self, topleft, bottomright):
|
||||||
if self.library_view.isVisible():
|
|
||||||
view = self.library_view
|
|
||||||
else: view = self.device_view
|
|
||||||
for c in range(topleft.column(), bottomright.column()+1):
|
for c in range(topleft.column(), bottomright.column()+1):
|
||||||
view.resizeColumnToContents(c)
|
self.current_view.resizeColumnToContents(c)
|
||||||
|
for r in range(topleft.row(), bottomright.row()+1):
|
||||||
|
self.current_view.resizeRowToContents(c)
|
||||||
|
|
||||||
def show_book(self, current, previous):
|
def show_book(self, current, previous):
|
||||||
|
if not len(self.current_view.selectedIndexes()):
|
||||||
|
return
|
||||||
if self.library_view.isVisible():
|
if self.library_view.isVisible():
|
||||||
formats, tags, comments, cover = current.model().info(current.row())
|
formats, tags, comments, cover = self.library_model\
|
||||||
|
.info(current.row())
|
||||||
data = LIBRARY_BOOK_TEMPLATE.arg(formats).arg(tags).arg(comments)
|
data = LIBRARY_BOOK_TEMPLATE.arg(formats).arg(tags).arg(comments)
|
||||||
tooltip = "To save the cover, drag it to the desktop.<br>To \
|
tooltip = "To save the cover, drag it to the desktop.<br>To \
|
||||||
change the cover drag the new cover onto this picture"
|
change the cover drag the new cover onto this picture"
|
||||||
else:
|
else:
|
||||||
title, author, size, mime, cover = current.model().info(current.row())
|
title, author, size, mime, cover = self.device_view.model()\
|
||||||
|
.info(current.row())
|
||||||
data = DEVICE_BOOK_TEMPLATE.arg(title).arg(size).arg(author).arg(mime)
|
data = DEVICE_BOOK_TEMPLATE.arg(title).arg(size).arg(author).arg(mime)
|
||||||
tooltip = "To save the cover, drag it to the desktop."
|
tooltip = "To save the cover, drag it to the desktop."
|
||||||
self.book_info.setText(data)
|
self.book_info.setText(data)
|
||||||
@ -194,7 +197,7 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
settings.setValue("add books dialog dir", \
|
settings.setValue("add books dialog dir", \
|
||||||
QVariant(os.path.dirname(x)))
|
QVariant(os.path.dirname(x)))
|
||||||
files = unicode(files.join("|||").toUtf8(), 'utf-8').split("|||")
|
files = unicode(files.join("|||").toUtf8(), 'utf-8').split("|||")
|
||||||
self.add_books(files)
|
self.add_books(files)
|
||||||
|
|
||||||
def add_books(self, files):
|
def add_books(self, files):
|
||||||
self.window.setCursor(Qt.WaitCursor)
|
self.window.setCursor(Qt.WaitCursor)
|
||||||
@ -256,7 +259,8 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.library_view.model().update_cover(self.library_view\
|
self.library_view.model().update_cover(self.library_view\
|
||||||
.currentIndex(), pix)
|
.currentIndex(), pix)
|
||||||
self.book_cover.setPixmap(pix)
|
self.book_cover.setPixmap(pix)
|
||||||
except Exception, e: Error("Unable to change cover", e)
|
except Exception, e:
|
||||||
|
Error("Unable to change cover", e)
|
||||||
|
|
||||||
def upload_books(self, to, files, ids):
|
def upload_books(self, to, files, ids):
|
||||||
oncard = False if to == "reader" else True
|
oncard = False if to == "reader" else True
|
||||||
@ -268,8 +272,10 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
model = self.card_model if oncard else self.reader_model
|
model = self.card_model if oncard else self.reader_model
|
||||||
model.sort(col, order)
|
model.sort(col, order)
|
||||||
if self.device_view.isVisible() and self.device_view.model()\
|
if self.device_view.isVisible() and self.device_view.model()\
|
||||||
== model: self.search.clear()
|
== model:
|
||||||
else: model.search("")
|
self.search.clear()
|
||||||
|
else:
|
||||||
|
model.search("")
|
||||||
|
|
||||||
def sync_lists():
|
def sync_lists():
|
||||||
self.status("Syncing media list to device main memory")
|
self.status("Syncing media list to device main memory")
|
||||||
@ -299,7 +305,8 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
str(_buffer.buffer()))
|
str(_buffer.buffer()))
|
||||||
ename = info["title"]
|
ename = info["title"]
|
||||||
for f in files:
|
for f in files:
|
||||||
if re.match("......_"+str(_id)+"_", os.path.basename(f)):
|
if re.match("libprs500_\S+_......_" + \
|
||||||
|
str(_id) + "_", os.path.basename(f)):
|
||||||
formats.append(f)
|
formats.append(f)
|
||||||
_file = None
|
_file = None
|
||||||
try:
|
try:
|
||||||
@ -358,6 +365,14 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.window.setCursor(Qt.ArrowCursor)
|
self.window.setCursor(Qt.ArrowCursor)
|
||||||
self.update_availabe_space()
|
self.update_availabe_space()
|
||||||
|
|
||||||
|
@apply
|
||||||
|
def current_view():
|
||||||
|
doc = """ The currently visible view """
|
||||||
|
def fget(self):
|
||||||
|
return self.library_view if self.library_view.isVisible() \
|
||||||
|
else self.device_view
|
||||||
|
return property(doc=doc, fget=fget)
|
||||||
|
|
||||||
def __init__(self, window, log_packets):
|
def __init__(self, window, log_packets):
|
||||||
QObject.__init__(self)
|
QObject.__init__(self)
|
||||||
Ui_MainWindow.__init__(self)
|
Ui_MainWindow.__init__(self)
|
||||||
@ -373,25 +388,26 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.library_model = LibraryBooksModel(window)
|
self.library_model = LibraryBooksModel(window)
|
||||||
self.library_model.set_data(LibraryDatabase(str(self.database_path)))
|
self.library_model.set_data(LibraryDatabase(str(self.database_path)))
|
||||||
self.library_view.setModel(self.library_model)
|
self.library_view.setModel(self.library_model)
|
||||||
self.current_view = self.library_view
|
|
||||||
QObject.connect(self.library_model, SIGNAL("layoutChanged()"), \
|
QObject.connect(self.library_model, SIGNAL("layoutChanged()"), \
|
||||||
self.library_view.resizeRowsToContents)
|
self.library_view.resizeRowsToContents)
|
||||||
QObject.connect(self.library_view.selectionModel(), \
|
QObject.connect(self.library_view.selectionModel(), \
|
||||||
SIGNAL("currentChanged(QModelIndex, QModelIndex)"), self.show_book)
|
SIGNAL("currentChanged(QModelIndex, QModelIndex)"), self.show_book)
|
||||||
QObject.connect(self.search, SIGNAL("textChanged(QString)"), \
|
QObject.connect(self.search, SIGNAL("textChanged(QString)"), \
|
||||||
self.library_model.search)
|
self.library_model.search)
|
||||||
QObject.connect(self.library_model, SIGNAL("sorted()"), self.model_modified)
|
QObject.connect(self.library_model, SIGNAL("sorted()"), \
|
||||||
|
self.model_modified)
|
||||||
QObject.connect(self.library_model, SIGNAL("searched()"), \
|
QObject.connect(self.library_model, SIGNAL("searched()"), \
|
||||||
self.model_modified)
|
self.model_modified)
|
||||||
QObject.connect(self.library_model, SIGNAL("deleted()"), \
|
QObject.connect(self.library_model, SIGNAL("deleted()"), \
|
||||||
self.model_modified)
|
self.model_modified)
|
||||||
QObject.connect(self.library_model, \
|
QObject.connect(self.library_model, \
|
||||||
SIGNAL("dataChanged(QModelIndex, QModelIndex)"), self.resize_columns)
|
SIGNAL("dataChanged(QModelIndex, QModelIndex)"), \
|
||||||
|
self.resize_rows_and_columns)
|
||||||
QObject.connect(self.library_view, \
|
QObject.connect(self.library_view, \
|
||||||
SIGNAL('books_dropped'), self.add_books)
|
SIGNAL('books_dropped'), self.add_books)
|
||||||
QObject.connect(self.library_model, \
|
QObject.connect(self.library_model, \
|
||||||
SIGNAL('formats_added'), self.formats_added)
|
SIGNAL('formats_added'), self.formats_added)
|
||||||
self.library_view.resizeColumnsToContents()
|
self.library_view.sortByColumn(3, Qt.DescendingOrder)
|
||||||
|
|
||||||
# Create Device tree
|
# Create Device tree
|
||||||
model = DeviceModel(self.device_tree)
|
model = DeviceModel(self.device_tree)
|
||||||
@ -417,8 +433,9 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
QObject.connect(model, SIGNAL("sorted()"), self.model_modified)
|
QObject.connect(model, SIGNAL("sorted()"), self.model_modified)
|
||||||
QObject.connect(model, SIGNAL("searched()"), self.model_modified)
|
QObject.connect(model, SIGNAL("searched()"), self.model_modified)
|
||||||
QObject.connect(model, SIGNAL("deleted()"), self.model_modified)
|
QObject.connect(model, SIGNAL("deleted()"), self.model_modified)
|
||||||
QObject.connect(model, SIGNAL("dataChanged(QModelIndex, QModelIndex)")\
|
QObject.connect(model, \
|
||||||
, self.resize_columns)
|
SIGNAL("dataChanged(QModelIndex, QModelIndex)"), \
|
||||||
|
self.resize_rows_and_columns)
|
||||||
|
|
||||||
# Setup book display
|
# Setup book display
|
||||||
self.book_cover.hide()
|
self.book_cover.hide()
|
||||||
@ -441,17 +458,23 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.show_device(False)
|
self.show_device(False)
|
||||||
self.df_template = self.df.text()
|
self.df_template = self.df.text()
|
||||||
self.df.setText(self.df_template.arg("").arg("").arg(""))
|
self.df.setText(self.df_template.arg("").arg("").arg(""))
|
||||||
window.show()
|
window.show()
|
||||||
|
self.library_view.resizeColumnsToContents()
|
||||||
|
self.library_view.resizeRowsToContents()
|
||||||
|
|
||||||
|
|
||||||
def device_removed(self):
|
def device_removed(self):
|
||||||
""" @todo: only reset stuff if library is not shown """
|
""" @todo: only reset stuff if library is not shown """
|
||||||
self.df.setText(self.df_template.arg("").arg("").arg(""))
|
self.df.setText(self.df_template.arg("").arg("").arg(""))
|
||||||
self.device_tree.hide_reader(True)
|
self.device_tree.hide_reader(True)
|
||||||
self.device_tree.hide_card(True)
|
self.device_tree.hide_card(True)
|
||||||
self.book_cover.hide()
|
self.device_tree.selectionModel().reset()
|
||||||
self.book_info.hide()
|
if self.device_view.isVisible():
|
||||||
self.device_view.hide()
|
self.device_view.hide()
|
||||||
self.library_view.show()
|
self.library_view.selectionModel().reset()
|
||||||
|
self.library_view.show()
|
||||||
|
self.book_cover.hide()
|
||||||
|
self.book_info.hide()
|
||||||
|
|
||||||
def progress(self, val):
|
def progress(self, val):
|
||||||
if val < 0:
|
if val < 0:
|
||||||
@ -471,12 +494,12 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.status("Connecting to device")
|
self.status("Connecting to device")
|
||||||
try:
|
try:
|
||||||
info = self.dev.get_device_information(end_session=False)
|
info = self.dev.get_device_information(end_session=False)
|
||||||
except DeviceBusy, e:
|
except DeviceBusy, err:
|
||||||
qFatal(str(e))
|
qFatal(str(err))
|
||||||
except DeviceError:
|
except DeviceError, err:
|
||||||
self.dev.reconnect()
|
self.dev.reconnect()
|
||||||
self.detector.connection_failed()
|
self.thread().msleep(100)
|
||||||
return
|
return self.establish_connection()
|
||||||
except ProtocolError, e:
|
except ProtocolError, e:
|
||||||
traceback.print_exc(e)
|
traceback.print_exc(e)
|
||||||
qFatal("Unable to connect to device. Please try unplugging and"+\
|
qFatal("Unable to connect to device. Please try unplugging and"+\
|
||||||
@ -522,10 +545,6 @@ class DeviceConnectDetector(QObject):
|
|||||||
self.emit(SIGNAL("device_removed()"))
|
self.emit(SIGNAL("device_removed()"))
|
||||||
self.is_connected = False
|
self.is_connected = False
|
||||||
|
|
||||||
def connection_failed(self):
|
|
||||||
# TODO: Do something intelligent if we're using HAL
|
|
||||||
self.is_connected = False
|
|
||||||
|
|
||||||
def udi_is_device(self, udi):
|
def udi_is_device(self, udi):
|
||||||
ans = False
|
ans = False
|
||||||
try:
|
try:
|
||||||
|
@ -156,14 +156,17 @@ class FileDragAndDrop(object):
|
|||||||
return self.drag_object_from_files(files), self._dragged_files
|
return self.drag_object_from_files(files), self._dragged_files
|
||||||
|
|
||||||
|
|
||||||
class TableView(FileDragAndDrop, QTableView):
|
class TableView(FileDragAndDrop, QTableView):
|
||||||
|
wrapper = textwrap.TextWrapper(width=20)
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
FileDragAndDrop.__init__(self, QTableView)
|
FileDragAndDrop.__init__(self, QTableView)
|
||||||
QTableView.__init__(self, parent)
|
QTableView.__init__(self, parent)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def wrap(cls, s, width=20):
|
def wrap(cls, s, width=20):
|
||||||
return textwrap.fill(s, width)
|
cls.wrapper.width = 20
|
||||||
|
return cls.wrapper.fill(s)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def human_readable(cls, size):
|
def human_readable(cls, size):
|
||||||
@ -452,7 +455,7 @@ class LibraryBooksModel(QAbstractTableModel):
|
|||||||
row = index.row()
|
row = index.row()
|
||||||
_id = self._data[row]["id"]
|
_id = self._data[row]["id"]
|
||||||
col = index.column()
|
col = index.column()
|
||||||
val = unicode(value.toString().toUtf8(), 'utf-8')
|
val = unicode(value.toString().toUtf8(), 'utf-8').strip()
|
||||||
if col == 0:
|
if col == 0:
|
||||||
col = "title"
|
col = "title"
|
||||||
elif col == 1:
|
elif col == 1:
|
||||||
@ -567,7 +570,9 @@ class LibraryBooksModel(QAbstractTableModel):
|
|||||||
elif col == 1:
|
elif col == 1:
|
||||||
au = row["authors"]
|
au = row["authors"]
|
||||||
if au:
|
if au:
|
||||||
text = TableView.wrap(re.sub("&", "\n", au), width=25)
|
au = au.split("&")
|
||||||
|
jau = [ TableView.wrap(a, width=25).strip() for a in au ]
|
||||||
|
text = "\n".join(jau)
|
||||||
elif col == 2:
|
elif col == 2:
|
||||||
text = TableView.human_readable(row["size"])
|
text = TableView.human_readable(row["size"])
|
||||||
elif col == 3:
|
elif col == 3:
|
||||||
@ -575,7 +580,8 @@ class LibraryBooksModel(QAbstractTableModel):
|
|||||||
time.strptime(row["date"], self.TIME_READ_FMT))
|
time.strptime(row["date"], self.TIME_READ_FMT))
|
||||||
elif col == 5:
|
elif col == 5:
|
||||||
pub = row["publisher"]
|
pub = row["publisher"]
|
||||||
if pub: text = TableView.wrap(pub, 20)
|
if pub:
|
||||||
|
text = TableView.wrap(pub, 20)
|
||||||
if text == None:
|
if text == None:
|
||||||
text = "Unknown"
|
text = "Unknown"
|
||||||
return QVariant(text)
|
return QVariant(text)
|
||||||
@ -689,8 +695,11 @@ class DeviceBooksModel(QAbstractTableModel):
|
|||||||
book = self._data[row]
|
book = self._data[row]
|
||||||
if col == 0:
|
if col == 0:
|
||||||
text = TableView.wrap(book.title, width=40)
|
text = TableView.wrap(book.title, width=40)
|
||||||
elif col == 1:
|
elif col == 1:
|
||||||
text = re.sub("&\s*", "\n", book.author)
|
au = book.author
|
||||||
|
au = au.split("&")
|
||||||
|
jau = [ TableView.wrap(a, width=25).strip() for a in au ]
|
||||||
|
text = "\n".join(jau)
|
||||||
elif col == 2:
|
elif col == 2:
|
||||||
text = TableView.human_readable(book.size)
|
text = TableView.human_readable(book.size)
|
||||||
elif col == 3:
|
elif col == 3:
|
||||||
@ -784,7 +793,8 @@ class DeviceModel(QAbstractListModel):
|
|||||||
self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), \
|
self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), \
|
||||||
self.index(1), self.index(2))
|
self.index(1), self.index(2))
|
||||||
|
|
||||||
def rowCount(self, parent): return 3
|
def rowCount(self, parent):
|
||||||
|
return 3
|
||||||
|
|
||||||
def update_free_space(self, reader, card):
|
def update_free_space(self, reader, card):
|
||||||
self.memory_free = reader
|
self.memory_free = reader
|
||||||
|
Loading…
x
Reference in New Issue
Block a user