From 903af8f4e545c0c9c7db5ae18cc296deb3c1ab50 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 12 Sep 2012 21:18:16 +0530 Subject: [PATCH] Allow the user to graphically select folders when configuring the MTP device --- src/calibre/gui2/device_drivers/mtp_config.py | 60 +++++++++++++++---- .../gui2/device_drivers/mtp_folder_browser.py | 29 +++++++-- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/calibre/gui2/device_drivers/mtp_config.py b/src/calibre/gui2/device_drivers/mtp_config.py index 7481cbf19c..0187915a4a 100644 --- a/src/calibre/gui2/device_drivers/mtp_config.py +++ b/src/calibre/gui2/device_drivers/mtp_config.py @@ -18,6 +18,7 @@ from calibre.ebooks import BOOK_EXTENSIONS from calibre.gui2 import error_dialog from calibre.gui2.dialogs.template_dialog import TemplateDialog from calibre.utils.date import parse_date +from calibre.gui2.device_drivers.mtp_folder_browser import Browser class FormatsConfig(QWidget): # {{{ @@ -117,19 +118,36 @@ class TemplateConfig(QWidget): # {{{ class SendToConfig(QWidget): # {{{ - def __init__(self, val): + def __init__(self, val, device): QWidget.__init__(self) self.t = t = QLineEdit(self) t.setText(', '.join(val or [])) t.setCursorPosition(0) - self.l = l = QVBoxLayout(self) + self.l = l = QGridLayout(self) self.setLayout(l) self.m = m = QLabel('

'+_('''A list of &folders on the device to which to send ebooks. The first one that exists will be used:''')) m.setWordWrap(True) m.setBuddy(t) - l.addWidget(m) - l.addWidget(t) + l.addWidget(m, 0, 0, 1, 2) + l.addWidget(t, 1, 0) + self.b = b = QToolButton() + l.addWidget(b, 1, 1) + b.setIcon(QIcon(I('document_open.png'))) + b.clicked.connect(self.browse) + b.setToolTip(_('Browse for a folder on the device')) + self._device = weakref.ref(device) + + @property + def device(self): + return self._device() + + def browse(self): + b = Browser(self.device.filesystem_cache, show_files=False, + parent=self) + if b.exec_() == b.Accepted: + sid, path = b.current_item + self.t.setText('/'.join(path[1:])) @property def value(self): @@ -183,8 +201,9 @@ class Rule(QWidget): remove = pyqtSignal(object) - def __init__(self, rule=None): + def __init__(self, device, rule=None): QWidget.__init__(self) + self._device = weakref.ref(device) self.l = l = QHBoxLayout() self.setLayout(l) @@ -198,6 +217,11 @@ class Rule(QWidget): self.folder = f = QLineEdit(self) f.setPlaceholderText(_('Folder on the device')) l.addWidget(f) + self.b = b = QToolButton() + l.addWidget(b) + b.setIcon(QIcon(I('document_open.png'))) + b.clicked.connect(self.browse) + b.setToolTip(_('Browse for a folder on the device')) self.rb = rb = QPushButton(QIcon(I('list_remove.png')), _('&Remove rule'), self) l.addWidget(rb) @@ -217,6 +241,17 @@ class Rule(QWidget): self.ignore = False + @property + def device(self): + return self._device() + + def browse(self): + b = Browser(self.device.filesystem_cache, show_files=False, + parent=self) + if b.exec_() == b.Accepted: + sid, path = b.current_item + self.folder.setText('/'.join(path[1:])) + def removed(self): self.remove.emit(self) @@ -232,8 +267,9 @@ class Rule(QWidget): class FormatRules(QGroupBox): - def __init__(self, rules): + def __init__(self, device, rules): QGroupBox.__init__(self, _('Format specific sending')) + self._device = weakref.ref(device) self.l = l = QVBoxLayout() self.setLayout(l) self.la = la = QLabel('

'+_( @@ -251,7 +287,7 @@ class FormatRules(QGroupBox): l.addWidget(sa) self.widgets = [] for rule in rules: - r = Rule(rule) + r = Rule(device, rule) self.widgets.append(r) w.l.addWidget(r) r.remove.connect(self.remove_rule) @@ -264,8 +300,12 @@ class FormatRules(QGroupBox): b.clicked.connect(self.add_rule) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Ignored) + @property + def device(self): + return self._device() + def add_rule(self): - r = Rule() + r = Rule(self.device) self.widgets.append(r) self.w.l.addWidget(r) r.remove.connect(self.remove_rule) @@ -319,10 +359,10 @@ class MTPConfig(QTabWidget): l = self.base.l = QGridLayout(self.base) self.base.setLayout(l) - self.rules = r = FormatRules(self.get_pref('rules')) + self.rules = r = FormatRules(self.device, self.get_pref('rules')) self.formats = FormatsConfig(set(BOOK_EXTENSIONS), self.get_pref('format_map')) - self.send_to = SendToConfig(self.get_pref('send_to')) + self.send_to = SendToConfig(self.get_pref('send_to'), self.device) self.template = TemplateConfig(self.get_pref('send_template')) self.base.la = la = QLabel(_( 'Choose the formats to send to the %s')%self.device.current_friendly_name) diff --git a/src/calibre/gui2/device_drivers/mtp_folder_browser.py b/src/calibre/gui2/device_drivers/mtp_folder_browser.py index 97b75c9de2..de9562fee7 100644 --- a/src/calibre/gui2/device_drivers/mtp_folder_browser.py +++ b/src/calibre/gui2/device_drivers/mtp_folder_browser.py @@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en' from operator import attrgetter from PyQt4.Qt import (QTabWidget, QTreeWidget, QTreeWidgetItem, Qt, QDialog, - QDialogButtonBox, QVBoxLayout, QSize) + QDialogButtonBox, QVBoxLayout, QSize, pyqtSignal) from calibre.gui2 import file_icon_provider @@ -47,17 +47,33 @@ class Storage(QTreeWidget): for child in sorted(f.files, key=attrgetter('name')): i = item(child, parent) + @property + def current_item(self): + item = self.currentItem() + if item is not None: + return (self.object_id, item.data(0, Qt.UserRole).toPyObject()) + return None + class Folders(QTabWidget): + selected = pyqtSignal() + def __init__(self, filesystem_cache, show_files=True): QTabWidget.__init__(self) self.fs = filesystem_cache for storage in self.fs.entries: w = Storage(storage, show_files) self.addTab(w, w.name) + w.doubleClicked.connect(self.selected) self.setCurrentIndex(0) + @property + def current_item(self): + w = self.currentWidget() + if w is not None: + return w.current_item + class Browser(QDialog): def __init__(self, filesystem_cache, show_files=True, parent=None): @@ -71,6 +87,11 @@ class Browser(QDialog): bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.setMinimumSize(QSize(500, 500)) + self.folders.selected.connect(self.accept) + + @property + def current_item(self): + return self.folders.current_item def browse(): from calibre.gui2 import Application @@ -87,10 +108,10 @@ def browse(): raise ValueError('No MTP device found') dev.open(cd, 'test') d = Browser(dev.filesystem_cache) - if d.exec_() == d.Accepted: - pass + d.exec_() dev.shutdown() + return d.current_item if __name__ == '__main__': - browse() + print (browse())