%PDF- %PDF-
Direktori : /lib/calibre/calibre/gui2/device_drivers/ |
Current File : //lib/calibre/calibre/gui2/device_drivers/mtp_folder_browser.py |
#!/usr/bin/env python3 __license__ = 'GPL v3' __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' __docformat__ = 'restructuredtext en' from operator import attrgetter from qt.core import (QTabWidget, QTreeWidget, QTreeWidgetItem, Qt, QDialog, QDialogButtonBox, QVBoxLayout, QSize, pyqtSignal, QIcon, QLabel) from calibre.gui2 import file_icon_provider def browser_item(f, parent): name = f.name if not f.is_folder: name += ' [%s]'%f.last_mod_string ans = QTreeWidgetItem(parent, [name]) ans.setData(0, Qt.ItemDataRole.UserRole, f.full_path) if f.is_folder: ext = 'dir' else: ext = f.name.rpartition('.')[-1] ans.setData(0, Qt.ItemDataRole.DecorationRole, file_icon_provider().icon_from_ext(ext)) return ans class Storage(QTreeWidget): def __init__(self, storage, show_files=False, item_func=browser_item): QTreeWidget.__init__(self) self.item_func = item_func self.show_files = show_files self.create_children(storage, self) self.name = storage.name self.object_id = storage.persistent_id self.setMinimumHeight(350) self.setHeaderHidden(True) self.storage = storage def create_children(self, f, parent): for child in sorted(f.folders, key=attrgetter('name')): i = self.item_func(child, parent) self.create_children(child, i) if self.show_files: for child in sorted(f.files, key=attrgetter('name')): i = self.item_func(child, parent) @property def current_item(self): item = self.currentItem() if item is not None: return (self.object_id, item.data(0, Qt.ItemDataRole.UserRole)) 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): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.folders = cw = Folders(filesystem_cache, show_files=show_files) l.addWidget(cw) bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok|QDialogButtonBox.StandardButton.Cancel) l.addWidget(bb) bb.accepted.connect(self.accept) bb.rejected.connect(self.reject) self.setMinimumSize(QSize(500, 500)) self.folders.selected.connect(self.accept) self.setWindowTitle(_('Choose folder on device')) self.setWindowIcon(QIcon(I('devices/tablet.png'))) @property def current_item(self): return self.folders.current_item class IgnoredFolders(QDialog): def __init__(self, dev, ignored_folders=None, parent=None): QDialog.__init__(self, parent) self.l = l = QVBoxLayout() self.setLayout(l) self.la = la = QLabel('<p>'+ _('<b>Scanned folders:</b>') + ' ' + _('You can select which folders calibre will ' 'scan when searching this device for books.')) la.setWordWrap(True) l.addWidget(la) self.tabs = QTabWidget(self) l.addWidget(self.tabs) self.widgets = [] for storage in dev.filesystem_cache.entries: self.dev = dev w = Storage(storage, item_func=self.create_item) del self.dev self.tabs.addTab(w, storage.name) self.widgets.append(w) w.itemChanged.connect(self.item_changed) self.la2 = la = QLabel(_( 'If you a select a previously unselected folder, any sub-folders' ' will not be visible until you restart calibre.')) l.addWidget(la) la.setWordWrap(True) self.bb = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.sab = self.bb.addButton(_('Select &all'), QDialogButtonBox.ButtonRole.ActionRole) self.sab.clicked.connect(self.select_all) self.snb = self.bb.addButton(_('Select &none'), QDialogButtonBox.ButtonRole.ActionRole) self.snb.clicked.connect(self.select_none) l.addWidget(self.bb) self.setWindowTitle(_('Choose folders to scan')) self.setWindowIcon(QIcon(I('devices/tablet.png'))) self.resize(600, 500) def item_changed(self, item, column): w = item.treeWidget() root = w.invisibleRootItem() w.itemChanged.disconnect(self.item_changed) try: if item.checkState(0) == Qt.CheckState.Checked: # Ensure that the parents of this item are checked p = item.parent() while p is not None and p is not root: p.setCheckState(0, Qt.CheckState.Checked) p = p.parent() # Set the state of all descendants to the same state as this item for child in self.iterchildren(item): child.setCheckState(0, item.checkState(0)) finally: w.itemChanged.connect(self.item_changed) def iterchildren(self, node): ' Iterate over all descendants of node ' for i in range(node.childCount()): child = node.child(i) yield child yield from self.iterchildren(child) def create_item(self, f, parent): name = f.name ans = QTreeWidgetItem(parent, [name]) ans.setData(0, Qt.ItemDataRole.UserRole, '/'.join(f.full_path[1:])) ans.setFlags(Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsEnabled) ans.setCheckState(0, Qt.CheckState.Unchecked if self.dev.is_folder_ignored(f.storage_id, f.full_path[1:]) else Qt.CheckState.Checked) ans.setData(0, Qt.ItemDataRole.DecorationRole, file_icon_provider().icon_from_ext('dir')) return ans def select_all(self): w = self.tabs.currentWidget() for i in range(w.invisibleRootItem().childCount()): c = w.invisibleRootItem().child(i) c.setCheckState(0, Qt.CheckState.Checked) def select_none(self): w = self.tabs.currentWidget() for i in range(w.invisibleRootItem().childCount()): c = w.invisibleRootItem().child(i) c.setCheckState(0, Qt.CheckState.Unchecked) @property def ignored_folders(self): ans = {} for w in self.widgets: folders = set() for node in self.iterchildren(w.invisibleRootItem()): if node.checkState(0) == Qt.CheckState.Checked: continue path = str(node.data(0, Qt.ItemDataRole.UserRole) or '') parent = path.rpartition('/')[0] if '/' not in path or icu_lower(parent) not in folders: folders.add(icu_lower(path)) ans[str(w.storage.storage_id)] = list(folders) return ans def setup_device(): from calibre.devices.mtp.driver import MTP_DEVICE from calibre.devices.scanner import DeviceScanner s = DeviceScanner() s.scan() dev = MTP_DEVICE(None) dev.startup() cd = dev.detect_managed_devices(s.devices) if cd is None: raise ValueError('No MTP device found') dev.open(cd, 'test') return dev def browse(): from calibre.gui2 import Application app = Application([]) app dev = setup_device() d = Browser(dev.filesystem_cache) d.exec() dev.shutdown() return d.current_item def ignored_folders(): from calibre.gui2 import Application app = Application([]) app dev = setup_device() d = IgnoredFolders(dev) d.exec() dev.shutdown() return d.ignored_folders if __name__ == '__main__': print(browse()) # print ('Ignored:', ignored_folders())