def __init__(self, name, conn, path, is_dir, size): super(RemoteFileSystemNode, self).__init__(name) self._name = name self._conn = conn self.path = path self._is_dir = is_dir self._populated = not is_dir self._show_hidden_files = False self.size_item = QStandardItem(sizeof_fmt(size) if not is_dir else '') icon_provider = QFileIconProvider() if is_dir: self.setData(True, RemoteFileSystem.ExpandableRole) self.setIcon(icon_provider.icon(QFileIconProvider.Folder)) else: self.setIcon(icon_provider.icon(QFileIconProvider.File))
def __init__(self, fileInfo, _parent = None): """Initializes data for the model.""" self._noteFile = QFileInfo(fileInfo) q = QFileIconProvider() self._icon = q.icon(self._noteFile) self._parent = _parent
def getShortcutIcon(shortcut): if shortcut["icon"]: icon = QIcon(shortcut["icon"]) if not icon.isNull(): return icon iconProvider = QFileIconProvider() if shortcut["path"] == COMPUTER_PATH: return QIcon(":/images/user-home.png") elif shortcut["path"] == DOCUMENTS_PATH: documentsIcon = iconProvider.icon( QFileInfo( QStandardPaths.writableLocation( QStandardPaths.DocumentsLocation))) if documentsIcon.isNull(): return QIcon(":/images/folder-documents.png") else: return documentsIcon elif shortcut["path"] == MUSIC_PATH: musicIcon = iconProvider.icon( QFileInfo( QStandardPaths.writableLocation(QStandardPaths.MusicLocation))) if musicIcon.isNull(): return QIcon(":/images/folder-sound.png") else: return musicIcon elif shortcut["path"] == PICTURES_PATH: picturesIcon = iconProvider.icon( QFileInfo( QStandardPaths.writableLocation( QStandardPaths.PicturesLocation))) if picturesIcon.isNull(): return QIcon(":/images/folder-image.png") else: return picturesIcon else: url = QUrl.fromUserInput(shortcut["path"]) if url.scheme() == "file": if os.path.exists(shortcut["path"]): icon = iconProvider.icon(QFileInfo(url.toLocalFile())) if not icon.isNull(): return icon return QIcon(":/images/unknown.png") else: return QIcon(":/images/httpurl.png") return QIcon(":/images/unknown.png")
def setFileIcon(self, path): "每当txtPath的值改变时,就设置快捷方式的图标" fi = QFileInfo(path) if not fi.exists(): self.shortcutIcon = QIcon(":/images/unknown.png") else: ip = QFileIconProvider() self.shortcutIcon = ip.icon(fi) self.btnFace.setIcon(self.shortcutIcon)
def parseLocalFile(self, parent, name, path): if name[0] == '.': return tmp = QTreeWidgetItem(parent) fileInfo = QFileInfo(path) fileIcon = QFileIconProvider() icon = QIcon(fileIcon.icon(fileInfo)) tmp.setIcon(0, QIcon(icon)) tmp.setText(0, name) tmp.setText(1, os.path.split(path)[0])
def CreateTree(self, dirs, root, path): for i in dirs: path_new = path + '/' + i if os.path.isdir(path_new): fileInfo = QFileInfo(path_new) fileIcon = QFileIconProvider() icon = QIcon(fileIcon.icon(fileInfo)) child = QTreeWidgetItem(root) child.setText(0, i) child.setIcon(0, QIcon(icon)) dirs_new = file_name(path_new) self.CreateTree(dirs_new, child, path_new) else: fileInfo = QFileInfo(path_new) fileIcon = QFileIconProvider() icon = QIcon(fileIcon.icon(fileInfo)) child = QTreeWidgetItem(root) child.setText(0, i) child.setIcon(0, QIcon(icon))
def Update(self, file): # TODO: wtf is this? iconprovider = QFileIconProvider() fileinfo = QFileInfo(str(file)) icon = iconprovider.icon(fileinfo) iconsize = QSize(self.x, self.y) self.widget = QLabel() self.widget.setPixmap(icon.pixmap(iconsize))
def fromPath(cls, path): # type: (str) -> ImportItem """ Create a `ImportItem` from a local file system path. """ iconprovider = QFileIconProvider() basename = os.path.basename(path) item = cls() item.setText(basename) item.setToolTip(path) finfo = QFileInfo(path) if finfo.exists(): item.setIcon(iconprovider.icon(finfo)) else: item.setIcon(iconprovider.icon(QFileIconProvider.File)) item.setData(path, ImportItem.PathRole) if not os.path.isfile(path): item.setEnabled(False) item.setToolTip(item.toolTip() + " (missing from filesystem)") return item
def add_item(row, column, item): self.tableWidget_6.setItem( row, column, QtWidgets.QTableWidgetItem(str(item))) self.tableWidget_6.item(row, column).setTextAlignment( Qt.AlignHCenter | Qt.AlignVCenter) if column == 1: file_info = QFileInfo(str(item)) iconProvider = QFileIconProvider() icon = iconProvider.icon(file_info) self.tableWidget_6.item(row, column).setIcon(icon) self.tableWidget_6.item(row, column).setTextAlignment( Qt.AlignLeft | Qt.AlignVCenter)
def icon_types(_file, icon: bool = False): file_type = os.path.splitext(os.path.split(_file)[1])[1].strip(".") ## set image/video icon if file_type in json.load(open(base_dir + "api/icons.json")).get("image"): return QIcon(_file) ## Default System Icons else: fileInfo = QFileInfo(_file) iconProvider = QFileIconProvider() icon = iconProvider.icon(fileInfo) return icon
def _assign_icon(filename, is_dir): if filename.endswith("py"): # py and mpy icon = Icons().tree_python else: iconProvider = QFileIconProvider() if is_dir: fileInfo = iconProvider.Folder else: fileInfo = QFileInfo(filename) icon = iconProvider.icon(fileInfo) return icon
def getShortcutIcon(shortcut): if shortcut["icon"]: icon = QIcon(shortcut["icon"]) if not icon.isNull(): return icon iconProvider = QFileIconProvider() if shortcut["path"] == COMPUTER_PATH: return QIcon(":/images/user-home.png") elif shortcut["path"] == DOCUMENTS_PATH: documentsIcon = iconProvider.icon(QFileInfo(QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation))) if documentsIcon.isNull(): return QIcon(":/images/folder-documents.png") else: return documentsIcon elif shortcut["path"] == MUSIC_PATH: musicIcon = iconProvider.icon(QFileInfo(QStandardPaths.writableLocation(QStandardPaths.MusicLocation))) if musicIcon.isNull(): return QIcon(":/images/folder-sound.png") else: return musicIcon elif shortcut["path"] == PICTURES_PATH: picturesIcon = iconProvider.icon(QFileInfo(QStandardPaths.writableLocation(QStandardPaths.PicturesLocation))) if picturesIcon.isNull(): return QIcon(":/images/folder-image.png") else: return picturesIcon else: url = QUrl.fromUserInput(shortcut["path"]) if url.scheme() == "file": if os.path.exists(shortcut["path"]): icon = iconProvider.icon(QFileInfo(url.toLocalFile())) if not icon.isNull(): return icon return QIcon(":/images/unknown.png") else: return QIcon(":/images/httpurl.png") return QIcon(":/images/unknown.png")
def data(self, index, role=None): """return the data of the table for different roles""" row = index.row() if (row < 0 or row >= len(self.fileList)): return col = index.column() file = self.fileList[row] if role == Qt.UserRole: # use the UserRole to check if item is dir if file["isDir"]: return True return False if role == Qt.DisplayRole: # the text that is shown if col == 0: return file["name"] if col == 1: return file["path"] if col == 2: return file["fileSize"] if col == 3: return file["lastChange"] if role == Qt.DecorationRole: # the icon in the first column if col == 0: fip = QFileIconProvider() if file["isDir"]: ico = fip.icon(QFileIconProvider.Folder) # type: QIcon return ico.pixmap(20, 20) ico = fip.icon(QFileIconProvider.File) # type: QIcon return ico.pixmap(20, 20) if role == Qt.BackgroundColorRole: # make stripes if row % 2 == 0: return QColor(Qt.white) return QColor(Qt.lightGray).lighter(120)
def check_icon_path(self, item): if item["type"] in (2, 4): if not os.path.exists(item["ico"]): save_path = get_file_realpath( os.path.join("data/image/sysico", os.path.splitext(item["url"])[1][1:] + ".ico")) print("save_path:" + save_path) provider = QFileIconProvider() fi = QFileInfo(item["url"]) icon = provider.icon(fi) icon.pixmap(48).save(save_path) item["ico"] = save_path if item["type"] == 1: if not os.path.exists(item["ico"]): item["ico"] = get_file_realpath("data/image/firefox64.png")
def add_file(self, file_objects, clear=True): if clear: self.listview.clear() if not file_objects: item = QListWidgetItem("No files has the selected tag") item.setFlags(Qt.NoItemFlags) self.listview.addItem(item) for object in file_objects: item = QListWidgetItem(object.file_name) item.setData(Qt.UserRole, object) fileinfo = QFileInfo(object.file_path + "/" + object.file_name) iconprovider = QFileIconProvider() icon = iconprovider.icon(fileinfo) item.setIcon(icon) self.listview.addItem(item)
def set_tree(self): self.tree.clear() path = read_line(configure_file, 1)[:-1] print("+" * 10 + path) dirs = file_name(path) print(dirs) fileInfo = QFileInfo(path) fileIcon = QFileIconProvider() icon = QIcon(fileIcon.icon(fileInfo)) root = QTreeWidgetItem(self.tree) root.setText(0, path.split('/')[-1]) root.setIcon(0, QIcon(icon)) self.CreateTree(dirs, root, path) self.tree.expandAll() # self.setCentralWidget(self.tree) # self.tree.clicked.connect(self.onTreeClicked) QApplication.processEvents()
def open_files_clicked(self): files = QFileDialog.getOpenFileNames( self, self.tr("Select files"), "", "PDF file (*.pdf) ;; All files (*.*)")[0] provider = QFileIconProvider() self.list_widget.clear() for file_path in files: file = QFileInfo(file_path) item = QListWidgetItem() item.setText(file.baseName()) item.setData(Qt.UserRole, file_path) item.setIcon(provider.icon(file)) self.list_widget.addItem(item) self.label_find.setText( self.tr("Schedules: ") + str(self.list_widget.count()))
def __init__(self, dirPath): """Initialize data for the model.""" self._notebookDir = QFileInfo(dirPath) #store path to the notebook as a 'QFileInfo' for added flexibility q = QFileIconProvider() #objec used to create model display icon self._icon = q.icon(self._notebookDir) #create model display icon self._notes = [] #initialize empty list of notes notebookPath = self._notebookDir.absoluteFilePath() #get the absolute path to the notebook #load all the notes inside this notebook for item in sorted(os.listdir(notebookPath)): #for every item in the notebook itemPath = os.path.join(notebookPath, item) #get absolute path to the item if os.path.isfile(itemPath): #if the item is a file/note self._notes.append( QuarkNoteModel(itemPath, self) ) #append a new note to the notes list
def parseLocalDir(self, parent, name, path): tmp = QTreeWidgetItem(parent) fileInfo = QFileInfo(path) fileIcon = QFileIconProvider() icon = QIcon(fileIcon.icon(fileInfo)) tmp.setIcon(0, QIcon(icon)) tmp.setText(0, name) tmp.setText(1, path) new = QTreeWidgetItem(tmp) new.setText(0, "<NEW DIR>") new.setText(1, path) for item in os.listdir(path): item_path = os.path.join(path, item) if os.path.isdir(item_path): self.parseLocalDir(parent=tmp, name=item, path=item_path) if os.path.isfile(item_path): self.parseLocalFile(parent=tmp, name=item, path=item_path)
def changeFileIcon(self): "用户点击了更换图标按钮。" filename, selectedFilter = QFileDialog.getOpenFileName(self, self.windowTitle()) if not filename: return image = QImage(filename) if not image.isNull(): self.shortcutIcon = QIcon(QPixmap.fromImage(image)) else: ip = QFileIconProvider() shortcutIcon = ip.icon(QFileInfo(filename)) if shortcutIcon.isNull(): QMessageBox.information(self, self.tr("更换图标"), self.tr("您选择的文件不包含任何可以使用的图标。")) return self.shortcutIcon = shortcutIcon self.iconPath = filename self.btnFace.setIcon(self.shortcutIcon)
def insertFiles(self, files): self.listfiles.clear() if len(files) == 0: return self.__storeFilePath(files[0]) fileInfo = QFileInfo(files[0]) fileIcon = QFileIconProvider() icon = QIcon(fileIcon.icon(fileInfo)) #获取文件图标 for index, item in enumerate(files): name = os.path.basename(item) value = QListWidgetItem(icon, name) self.listfiles.insertItem(index, value)
def keyReleaseEvent(self,event): key = event.key() if event.modifiers()== Qt.ControlModifier and key == Qt.Key_V : clipboard = QApplication.clipboard() mimeData = clipboard.mimeData() if mimeData.hasText(): print("准备粘贴:" + clipboard.text()) path = clipboard.text() item = {} if not path.startswith("file") : item = self.dl_launch_item_detail.get_url_info(path) item["session_id"] = self.cur_session["id"] item["id"] = app_data.insert_launch_item(item) self.add_launch_item(item) return path = path.replace("file:///","") if os.name == "posix" : path = "/" + path provider = QFileIconProvider() fi = QFileInfo(path) icon = provider.icon(fi) # t = icon.pixmap().toImage().text() save_path = join(config_dir ,"data/image/sysico",splitext(path)[0]+".ico") print("save_path:" + save_path) icon.pixmap(48).save(save_path) t = icon.name() t1 = icon.themeName() t2 = icon.themeSearchPaths() print("icon path:" + t+"," + t1,t2) if not icon.isNull() : item["ico"] = save_path item["name"] = basename(path) item["url"] = path item["type"] = 2 if not self.cur_session["id"]: QMessageBox.information(self, "新桌面", "新桌面需重启后才能添加启动项") return item["session_id"] = self.cur_session["id"] print("add other launch item:" ,item) item["id"] = app_data.insert_launch_item(item) print(item) self.add_launch_item(item)
def changeFileIcon(self): "用户点击了更换图标按钮。" filename, selectedFilter = QFileDialog.getOpenFileName( self, self.windowTitle()) if not filename: return image = QImage(filename) if not image.isNull(): self.shortcutIcon = QIcon(QPixmap.fromImage(image)) else: ip = QFileIconProvider() shortcutIcon = ip.icon(QFileInfo(filename)) if shortcutIcon.isNull(): QMessageBox.information(self, self.tr("更换图标"), self.tr("您选择的文件不包含任何可以使用的图标。")) return self.shortcutIcon = shortcutIcon self.iconPath = filename self.btnFace.setIcon(self.shortcutIcon)
def open_folder_clicked(self): path = QFileDialog.getExistingDirectory(self, self.tr("Select folder")) provider = QFileIconProvider() self.list_widget.clear() for dir_path, dir_names, file_names in os.walk(path): for file_name in file_names: if file_name.endswith(".pdf"): item = QListWidgetItem() item.setText(file_name[0:-4]) item.setData(Qt.UserRole, dir_path + os.sep + file_name) item.setIcon( provider.icon(QFileInfo(dir_path + os.sep + file_name))) self.list_widget.addItem(item) self.label_find.setText( self.tr("Schedules: ") + str(self.list_widget.count()))
def update(self): # Update files. self._ui.project_tree.clear() items = [] icon_provider = QFileIconProvider() for cur_file in self.project.files: file_info = QFileInfo(cur_file) item = QTreeWidgetItem(None, [ os.path.relpath(cur_file, self.project.proj_dir), "N/A", ]) item.setData(0, Qt.UserRole, Project.file_to_idb(cur_file)) item.setIcon(0, icon_provider.icon(file_info)) items.append(item) self._ui.project_tree.insertTopLevelItems(0, items) # Update other stuff. self._ui.project_path.setText(self.project.proj_dir)
def add_item_on_file_table(cls, package): """ 像指定表格对象添加指定的特定格式数据数据 """ for index, file_obj in enumerate(package.data.listdir): file_obj = Dict(file_obj) # 插入空行 package.widget.insertRow(index) # =============文件图标 item0 = QTableWidgetItem() item0.setText(file_obj.name) provider = QFileIconProvider() item0.setIcon( provider.icon( QFileInfo( ICO.FILE_TYPE_ICO.get(file_obj.type, "ico/txt.txt")))) # f_t_widget.setRowHeight(index, 20) package.widget.setItem(index, 0, item0) # =============文件大小 item3 = QTableWidgetItem() # item3.setFont(self.fileInfoWidget.global_row_font) item3.setText(file_obj.size) package.widget.setItem(index, 1, item3) # =============文件类型 item2 = QTableWidgetItem() # item2.setFont(self.fileInfoWidget.global_row_font) # fileType = provider.type(QFileInfo(abs_file_path)) item2.setText(file_obj.type) package.widget.setItem(index, 2, item2) # ============最后修改时间 item1 = QTableWidgetItem() # item1.setFont(self.fileInfoWidget.global_row_font) # mtime = os.path.getmtime(abs_file_path) item1.setText(file_obj.last_time) package.widget.setItem(index, 3, item1) return True
def addTab(self, path: str): """ Creates new tab and adds it to the horizontal layout :param path: path to file being displayed :return: returns the new tab that was open """ logging.info(path) file_info = QFileInfo(path) # Add new tab and save index index = super().addTab(file_info.fileName()) # Set tab data and tooltip self.setTabData(index, path) self.setTabToolTip(index, path) # Set tab icon icon_provider = QFileIconProvider() self.setTabIcon(index, icon_provider.icon(file_info)) # Update the current index to the new tab self.blockSignals(True) self.setCurrentIndex(index) self.blockSignals(False) # add tab to the dict holding open tabs self.open_tabs[path] = index
def get_icon(self) -> QIcon: file_info = QFileInfo(self._file_path) icon_provider = QFileIconProvider() icon = icon_provider.icon(file_info) return icon
class DownloadManager(QDialog, Ui_DownloadManager): """ Class implementing the download manager. @signal downloadsCountChanged() emitted to indicate a change of the count of download items """ RemoveNever = 0 RemoveExit = 1 RemoveSuccessFullDownload = 2 UpdateTimerTimeout = 1000 downloadsCountChanged = pyqtSignal() def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(DownloadManager, self).__init__(parent) self.setupUi(self) self.setWindowFlags(Qt.Window) self.__winTaskbarButton = None self.__saveTimer = AutoSaver(self, self.save) self.__model = DownloadModel(self) self.__manager = WebBrowserWindow.networkManager() self.__iconProvider = None self.__downloads = [] self.__downloadDirectory = "" self.__loaded = False self.__rowHeightMultiplier = 1.1 self.setDownloadDirectory(Preferences.getUI("DownloadPath")) self.downloadsView.setShowGrid(False) self.downloadsView.verticalHeader().hide() self.downloadsView.horizontalHeader().hide() self.downloadsView.setAlternatingRowColors(True) self.downloadsView.horizontalHeader().setStretchLastSection(True) self.downloadsView.setModel(self.__model) self.downloadsView.setContextMenuPolicy(Qt.CustomContextMenu) self.downloadsView.customContextMenuRequested.connect( self.__customContextMenuRequested) self.__clearShortcut = QShortcut(QKeySequence("Ctrl+L"), self) self.__clearShortcut.activated.connect(self.on_cleanupButton_clicked) self.__load() self.__updateTimer = QBasicTimer() def __customContextMenuRequested(self, pos): """ Private slot to handle the context menu request for the bookmarks tree. @param pos position the context menu was requested (QPoint) """ menu = QMenu() selectedRowsCount = len( self.downloadsView.selectionModel().selectedRows()) if selectedRowsCount == 1: row = self.downloadsView.selectionModel().selectedRows()[0].row() itm = self.__downloads[row] if itm.downloadedSuccessfully(): menu.addAction(UI.PixmapCache.getIcon("open.png"), self.tr("Open"), self.__contextMenuOpen) elif itm.downloading(): menu.addAction(UI.PixmapCache.getIcon("stopLoading.png"), self.tr("Cancel"), self.__contextMenuCancel) menu.addSeparator() menu.addAction(self.tr("Open Containing Folder"), self.__contextMenuOpenFolder) menu.addSeparator() menu.addAction(self.tr("Go to Download Page"), self.__contextMenuGotoPage) menu.addAction(self.tr("Copy Download Link"), self.__contextMenuCopyLink) menu.addSeparator() menu.addAction(self.tr("Select All"), self.__contextMenuSelectAll) if (selectedRowsCount > 1 or (selectedRowsCount == 1 and not self.__downloads[self.downloadsView.selectionModel( ).selectedRows()[0].row()].downloading())): menu.addSeparator() menu.addAction(self.tr("Remove From List"), self.__contextMenuRemoveSelected) menu.exec_(QCursor.pos()) def shutdown(self): """ Public method to stop the download manager. """ self.save() self.close() def activeDownloadsCount(self): """ Public method to get the number of active downloads. @return number of active downloads (integer) """ count = 0 for download in self.__downloads: if download.downloading(): count += 1 return count def allowQuit(self): """ Public method to check, if it is ok to quit. @return flag indicating allowance to quit (boolean) """ if self.activeDownloadsCount() > 0: res = E5MessageBox.yesNo( self, self.tr(""), self.tr( """There are %n downloads in progress.\n""" """Do you want to quit anyway?""", "", self.activeDownloadsCount()), icon=E5MessageBox.Warning) if not res: self.show() return False self.close() return True def __testWebBrowserView(self, view, url): """ Private method to test a web browser view against an URL. @param view reference to the web browser view to be tested @type WebBrowserView @param url URL to test against @type QUrl @return flag indicating, that the view is the one for the URL @rtype bool """ if view.tabWidget().count() < 2: return False page = view.page() if page.history().count() != 0: return False if (not page.url().isEmpty() and page.url().host() == url.host()): return True requestedUrl = page.requestedUrl() if requestedUrl.isEmpty(): requestedUrl = QUrl(view.tabWidget().urlBarForView(view).text()) return requestedUrl.isEmpty() or requestedUrl.host() == url.host() def __closeDownloadTab(self, url): """ Private method to close an empty tab, that was opened only for loading the download URL. @param url download URL @type QUrl """ if self.__testWebBrowserView( WebBrowserWindow.getWindow().currentBrowser(), url): WebBrowserWindow.getWindow().closeCurrentBrowser() return for window in WebBrowserWindow.mainWindows(): for browser in window.browsers(): if self.__testWebBrowserView(browser, url): window.closeBrowser(browser) return def download(self, downloadItem): """ Public method to download a file. @param downloadItem reference to the download object containing the download data. @type QWebEngineDownloadItem """ url = downloadItem.url() if url.isEmpty(): return self.__closeDownloadTab(url) # Safe Browsing from WebBrowser.SafeBrowsing.SafeBrowsingManager import ( SafeBrowsingManager) if SafeBrowsingManager.isEnabled(): threatLists = ( WebBrowserWindow.safeBrowsingManager().lookupUrl(url)[0]) if threatLists: threatMessages = (WebBrowserWindow.safeBrowsingManager(). getThreatMessages(threatLists)) res = E5MessageBox.warning( WebBrowserWindow.getWindow(), self.tr("Suspicuous URL detected"), self.tr("<p>The URL <b>{0}</b> was found in the Safe" " Browsing database.</p>{1}").format( url.toString(), "".join(threatMessages)), E5MessageBox.StandardButtons(E5MessageBox.Abort | E5MessageBox.Ignore), E5MessageBox.Abort) if res == E5MessageBox.Abort: downloadItem.cancel() return window = WebBrowserWindow.getWindow() if window: pageUrl = window.currentBrowser().url() else: pageUrl = QUrl() from .DownloadItem import DownloadItem itm = DownloadItem(downloadItem=downloadItem, pageUrl=pageUrl, parent=self) self.__addItem(itm) if Preferences.getWebBrowser("DownloadManagerAutoOpen"): self.show() else: self.__startUpdateTimer() def show(self): """ Public slot to show the download manager dialog. """ self.__startUpdateTimer() super(DownloadManager, self).show() self.activateWindow() self.raise_() def __addItem(self, itm, append=False): """ Private method to add a download to the list of downloads. @param itm reference to the download item @type DownloadItem @param append flag indicating to append the item @type bool """ itm.statusChanged.connect(lambda: self.__updateRow(itm)) itm.downloadFinished.connect(self.__finished) # insert at top of window if append: row = self.downloadsCount() else: row = 0 self.__model.beginInsertRows(QModelIndex(), row, row) if append: self.__downloads.append(itm) else: self.__downloads.insert(0, itm) self.__model.endInsertRows() self.downloadsView.setIndexWidget(self.__model.index(row, 0), itm) icon = self.style().standardIcon(QStyle.SP_FileIcon) itm.setIcon(icon) self.downloadsView.setRowHeight( row, itm.sizeHint().height() * self.__rowHeightMultiplier) # just in case the download finished before the constructor returned self.__updateRow(itm) self.changeOccurred() self.downloadsCountChanged.emit() def __updateRow(self, itm): """ Private slot to update a download item. @param itm reference to the download item @type DownloadItem """ if itm not in self.__downloads: return row = self.__downloads.index(itm) if self.__iconProvider is None: self.__iconProvider = QFileIconProvider() icon = self.__iconProvider.icon(QFileInfo(itm.fileName())) if icon.isNull(): icon = self.style().standardIcon(QStyle.SP_FileIcon) itm.setIcon(icon) self.downloadsView.setRowHeight( row, itm.minimumSizeHint().height() * self.__rowHeightMultiplier) remove = False if (itm.downloadedSuccessfully() and self.removePolicy() == DownloadManager.RemoveSuccessFullDownload): remove = True if remove: self.__model.removeRow(row) self.cleanupButton.setEnabled( (self.downloadsCount() - self.activeDownloadsCount()) > 0) # record the change self.changeOccurred() def removePolicy(self): """ Public method to get the remove policy. @return remove policy (integer) """ return Preferences.getWebBrowser("DownloadManagerRemovePolicy") def setRemovePolicy(self, policy): """ Public method to set the remove policy. @param policy policy to be set (DownloadManager.RemoveExit, DownloadManager.RemoveNever, DownloadManager.RemoveSuccessFullDownload) """ assert policy in (DownloadManager.RemoveExit, DownloadManager.RemoveNever, DownloadManager.RemoveSuccessFullDownload) if policy == self.removePolicy(): return Preferences.setWebBrowser("DownloadManagerRemovePolicy", self.policy) def save(self): """ Public method to save the download settings. """ if not self.__loaded: return Preferences.setWebBrowser("DownloadManagerSize", self.size()) Preferences.setWebBrowser("DownloadManagerPosition", self.pos()) if self.removePolicy() == DownloadManager.RemoveExit: return from WebBrowser.WebBrowserWindow import WebBrowserWindow if WebBrowserWindow.isPrivate(): return downloads = [] for download in self.__downloads: downloads.append(download.getData()) Preferences.setWebBrowser("DownloadManagerDownloads", downloads) def __load(self): """ Private method to load the download settings. """ if self.__loaded: return size = Preferences.getWebBrowser("DownloadManagerSize") if size.isValid(): self.resize(size) pos = Preferences.getWebBrowser("DownloadManagerPosition") self.move(pos) from WebBrowser.WebBrowserWindow import WebBrowserWindow if not WebBrowserWindow.isPrivate(): downloads = Preferences.getWebBrowser("DownloadManagerDownloads") for download in downloads: if (not download["URL"].isEmpty() and bool(download["Location"])): from .DownloadItem import DownloadItem itm = DownloadItem(parent=self) itm.setData(download) self.__addItem(itm, append=True) self.cleanupButton.setEnabled( (self.downloadsCount() - self.activeDownloadsCount()) > 0) self.__loaded = True self.downloadsCountChanged.emit() def closeEvent(self, evt): """ Protected event handler for the close event. @param evt reference to the close event @type QCloseEvent """ self.save() def cleanup(self): """ Public slot to cleanup the downloads. """ self.on_cleanupButton_clicked() @pyqtSlot() def on_cleanupButton_clicked(self): """ Private slot to cleanup the downloads. """ if self.downloadsCount() == 0: return self.__model.removeRows(0, self.downloadsCount()) if (self.downloadsCount() == 0 and self.__iconProvider is not None): self.__iconProvider = None self.changeOccurred() self.downloadsCountChanged.emit() def __finished(self, success): """ Private slot to handle a finished download. @param success flag indicating a successful download @type bool """ if self.isVisible(): QApplication.alert(self) self.downloadsCountChanged.emit() if self.activeDownloadsCount() == 0: # all active downloads are done if success and e5App().activeWindow() is not self: if WebBrowserWindow.notificationsEnabled(): WebBrowserWindow.showNotification( UI.PixmapCache.getPixmap("downloads48.png"), self.tr("Downloads finished"), self.tr("All files have been downloaded.")) if not Preferences.getWebBrowser("DownloadManagerAutoClose"): self.raise_() self.activateWindow() self.__stopUpdateTimer() self.infoLabel.clear() self.setWindowTitle(self.tr("Download Manager")) if Globals.isWindowsPlatform(): self.__taskbarButton().progress().hide() if Preferences.getWebBrowser("DownloadManagerAutoClose"): self.close() def setDownloadDirectory(self, directory): """ Public method to set the current download directory. @param directory current download directory (string) """ self.__downloadDirectory = directory if self.__downloadDirectory != "": self.__downloadDirectory += "/" def downloadDirectory(self): """ Public method to get the current download directory. @return current download directory (string) """ return self.__downloadDirectory def downloadsCount(self): """ Public method to get the number of downloads. @return number of downloads @rtype int """ return len(self.__downloads) def downloads(self): """ Public method to get a reference to the downloads. @return reference to the downloads (list of DownloadItem) """ return self.__downloads def changeOccurred(self): """ Public method to signal a change. """ self.__saveTimer.changeOccurred() def __taskbarButton(self): """ Private method to get a reference to the task bar button (Windows only). @return reference to the task bar button @rtype QWinTaskbarButton or None """ if Globals.isWindowsPlatform(): from PyQt5.QtWinExtras import QWinTaskbarButton if self.__winTaskbarButton is None: window = WebBrowserWindow.mainWindow() self.__winTaskbarButton = QWinTaskbarButton( window.windowHandle()) self.__winTaskbarButton.progress().setRange(0, 100) return self.__winTaskbarButton def timerEvent(self, evt): """ Protected event handler for timer events. @param evt reference to the timer event @type QTimerEvent """ if evt.timerId() == self.__updateTimer.timerId(): if self.activeDownloadsCount() == 0: self.__stopUpdateTimer() self.infoLabel.clear() self.setWindowTitle(self.tr("Download Manager")) if Globals.isWindowsPlatform(): self.__taskbarButton().progress().hide() else: progresses = [] for itm in self.__downloads: if (itm is None or itm.downloadCanceled() or not itm.downloading()): continue progresses.append( (itm.downloadProgress(), itm.remainingTime(), itm.currentSpeed())) if not progresses: return remaining = 0 progress = 0 speed = 0.0 for progressData in progresses: if progressData[1] > remaining: remaining = progressData[1] progress += progressData[0] speed += progressData[2] progress = progress / len(progresses) if self.isVisible(): self.infoLabel.setText( self.tr("{0}% of %n file(s) ({1}) {2}", "", len(progresses)).format( progress, speedString(speed), timeString(remaining), )) self.setWindowTitle(self.tr("{0}% - Download Manager")) if Globals.isWindowsPlatform(): self.__taskbarButton().progress().show() self.__taskbarButton().progress().setValue(progress) super(DownloadManager, self).timerEvent(evt) def __startUpdateTimer(self): """ Private slot to start the update timer. """ if self.activeDownloadsCount() and not self.__updateTimer.isActive(): self.__updateTimer.start(DownloadManager.UpdateTimerTimeout, self) def __stopUpdateTimer(self): """ Private slot to stop the update timer. """ self.__updateTimer.stop() ########################################################################### ## Context menu related methods below ########################################################################### def __currentItem(self): """ Private method to get a reference to the current item. @return reference to the current item (DownloadItem) """ index = self.downloadsView.currentIndex() if index and index.isValid(): row = index.row() return self.__downloads[row] return None def __contextMenuOpen(self): """ Private method to open the downloaded file. """ itm = self.__currentItem() if itm is not None: itm.openFile() def __contextMenuOpenFolder(self): """ Private method to open the folder containing the downloaded file. """ itm = self.__currentItem() if itm is not None: itm.openFolder() def __contextMenuCancel(self): """ Private method to cancel the current download. """ itm = self.__currentItem() if itm is not None: itm.cancelDownload() def __contextMenuGotoPage(self): """ Private method to open the download page. """ itm = self.__currentItem() if itm is not None: url = itm.getPageUrl() WebBrowserWindow.mainWindow().openUrl(url, "") def __contextMenuCopyLink(self): """ Private method to copy the download link to the clipboard. """ itm = self.__currentItem() if itm is not None: url = itm.getPageUrl().toDisplayString(QUrl.FullyDecoded) QApplication.clipboard().setText(url) def __contextMenuSelectAll(self): """ Private method to select all downloads. """ self.downloadsView.selectAll() def __contextMenuRemoveSelected(self): """ Private method to remove the selected downloads from the list. """ self.downloadsView.removeSelected()
class DownloadManager(QDialog, Ui_DownloadManager): """ Class implementing the download manager. """ RemoveNever = 0 RemoveExit = 1 RemoveSuccessFullDownload = 2 def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(DownloadManager, self).__init__(parent) self.setupUi(self) self.__saveTimer = AutoSaver(self, self.save) self.__model = DownloadModel(self) self.__manager = Helpviewer.HelpWindow.HelpWindow\ .networkAccessManager() self.__iconProvider = None self.__downloads = [] self.__downloadDirectory = "" self.__loaded = False self.setDownloadDirectory(Preferences.getUI("DownloadPath")) self.downloadsView.setShowGrid(False) self.downloadsView.verticalHeader().hide() self.downloadsView.horizontalHeader().hide() self.downloadsView.setAlternatingRowColors(True) self.downloadsView.horizontalHeader().setStretchLastSection(True) self.downloadsView.setModel(self.__model) self.downloadsView.setContextMenuPolicy(Qt.CustomContextMenu) self.downloadsView.customContextMenuRequested.connect( self.__customContextMenuRequested) self.__load() def __customContextMenuRequested(self, pos): """ Private slot to handle the context menu request for the bookmarks tree. @param pos position the context menu was requested (QPoint) """ menu = QMenu() selectedRowsCount = len( self.downloadsView.selectionModel().selectedRows()) if selectedRowsCount == 1: row = self.downloadsView.selectionModel().selectedRows()[0].row() itm = self.__downloads[row] if itm.downloadCanceled(): menu.addAction( UI.PixmapCache.getIcon("restart.png"), self.tr("Retry"), self.__contextMenuRetry) else: if itm.downloadedSuccessfully(): menu.addAction( UI.PixmapCache.getIcon("open.png"), self.tr("Open"), self.__contextMenuOpen) elif itm.downloading(): menu.addAction( UI.PixmapCache.getIcon("stopLoading.png"), self.tr("Cancel"), self.__contextMenuCancel) menu.addSeparator() menu.addAction( self.tr("Open Containing Folder"), self.__contextMenuOpenFolder) menu.addSeparator() menu.addAction( self.tr("Go to Download Page"), self.__contextMenuGotoPage) menu.addAction( self.tr("Copy Download Link"), self.__contextMenuCopyLink) menu.addSeparator() menu.addAction(self.tr("Select All"), self.__contextMenuSelectAll) if selectedRowsCount > 1 or \ (selectedRowsCount == 1 and not self.__downloads[ self.downloadsView.selectionModel().selectedRows()[0].row()] .downloading()): menu.addSeparator() menu.addAction( self.tr("Remove From List"), self.__contextMenuRemoveSelected) menu.exec_(QCursor.pos()) def shutdown(self): """ Public method to stop the download manager. """ self.__saveTimer.changeOccurred() self.__saveTimer.saveIfNeccessary() self.close() def activeDownloads(self): """ Public method to get the number of active downloads. @return number of active downloads (integer) """ count = 0 for download in self.__downloads: if download.downloading(): count += 1 return count def allowQuit(self): """ Public method to check, if it is ok to quit. @return flag indicating allowance to quit (boolean) """ if self.activeDownloads() > 0: res = E5MessageBox.yesNo( self, self.tr(""), self.tr("""There are %n downloads in progress.\n""" """Do you want to quit anyway?""", "", self.activeDownloads()), icon=E5MessageBox.Warning) if not res: self.show() return False return True def download(self, requestOrUrl, requestFileName=False, mainWindow=None): """ Public method to download a file. @param requestOrUrl reference to a request object (QNetworkRequest) or a URL to be downloaded (QUrl) @keyparam requestFileName flag indicating to ask for the download file name (boolean) @keyparam mainWindow reference to the main window (HelpWindow) """ request = QNetworkRequest(requestOrUrl) if request.url().isEmpty(): return self.handleUnsupportedContent( self.__manager.get(request), requestFileName=requestFileName, download=True, mainWindow=mainWindow) def handleUnsupportedContent(self, reply, requestFileName=False, webPage=None, download=False, mainWindow=None): """ Public method to handle unsupported content by downloading the referenced resource. @param reply reference to the reply object (QNetworkReply) @keyparam requestFileName indicating to ask for a filename (boolean) @keyparam webPage reference to the web page (HelpWebPage) @keyparam download flag indicating a download request (boolean) @keyparam mainWindow reference to the main window (HelpWindow) """ if reply is None or reply.url().isEmpty(): return size = reply.header(QNetworkRequest.ContentLengthHeader) if size == 0: return from .DownloadItem import DownloadItem itm = DownloadItem( reply=reply, requestFilename=requestFileName, webPage=webPage, download=download, parent=self, mainWindow=mainWindow) self.__addItem(itm) if itm.canceledFileSelect(): return if not self.isVisible(): self.show() self.activateWindow() self.raise_() def __addItem(self, itm): """ Private method to add a download to the list of downloads. @param itm reference to the download item (DownloadItem) """ itm.statusChanged.connect(self.__updateRow) itm.downloadFinished.connect(self.__finished) row = len(self.__downloads) self.__model.beginInsertRows(QModelIndex(), row, row) self.__downloads.append(itm) self.__model.endInsertRows() self.downloadsView.setIndexWidget(self.__model.index(row, 0), itm) icon = self.style().standardIcon(QStyle.SP_FileIcon) itm.setIcon(icon) self.downloadsView.setRowHeight(row, itm.sizeHint().height() * 1.5) # just in case the download finished before the constructor returned self.__updateRow(itm) self.changeOccurred() self.__updateActiveItemCount() def __updateRow(self, itm=None): """ Private slot to update a download item. @param itm reference to the download item (DownloadItem) """ if itm is None: itm = self.sender() if itm not in self.__downloads: return row = self.__downloads.index(itm) if self.__iconProvider is None: self.__iconProvider = QFileIconProvider() icon = self.__iconProvider.icon(QFileInfo(itm.fileName())) if icon.isNull(): icon = self.style().standardIcon(QStyle.SP_FileIcon) itm.setIcon(icon) oldHeight = self.downloadsView.rowHeight(row) self.downloadsView.setRowHeight( row, max(oldHeight, itm.minimumSizeHint().height() * 1.5)) remove = False globalSettings = QWebSettings.globalSettings() if not itm.downloading() and \ globalSettings.testAttribute(QWebSettings.PrivateBrowsingEnabled): remove = True if itm.downloadedSuccessfully() and \ self.removePolicy() == DownloadManager.RemoveSuccessFullDownload: remove = True if remove: self.__model.removeRow(row) self.cleanupButton.setEnabled( (len(self.__downloads) - self.activeDownloads()) > 0) # record the change self.changeOccurred() def removePolicy(self): """ Public method to get the remove policy. @return remove policy (integer) """ return Preferences.getHelp("DownloadManagerRemovePolicy") def setRemovePolicy(self, policy): """ Public method to set the remove policy. @param policy policy to be set (DownloadManager.RemoveExit, DownloadManager.RemoveNever, DownloadManager.RemoveSuccessFullDownload) """ assert policy in (DownloadManager.RemoveExit, DownloadManager.RemoveNever, DownloadManager.RemoveSuccessFullDownload) if policy == self.removePolicy(): return Preferences.setHelp("DownloadManagerRemovePolicy", self.policy) def save(self): """ Public method to save the download settings. """ if not self.__loaded: return Preferences.setHelp("DownloadManagerSize", self.size()) Preferences.setHelp("DownloadManagerPosition", self.pos()) if self.removePolicy() == DownloadManager.RemoveExit: return downloads = [] for download in self.__downloads: downloads.append(download.getData()) Preferences.setHelp("DownloadManagerDownloads", downloads) def __load(self): """ Private method to load the download settings. """ if self.__loaded: return size = Preferences.getHelp("DownloadManagerSize") if size.isValid(): self.resize(size) pos = Preferences.getHelp("DownloadManagerPosition") self.move(pos) downloads = Preferences.getHelp("DownloadManagerDownloads") for download in downloads: if not download[0].isEmpty() and \ download[1] != "": from .DownloadItem import DownloadItem itm = DownloadItem(parent=self) itm.setData(download) self.__addItem(itm) self.cleanupButton.setEnabled( (len(self.__downloads) - self.activeDownloads()) > 0) self.__loaded = True self.__updateActiveItemCount() def cleanup(self): """ Public slot to cleanup the downloads. """ self.on_cleanupButton_clicked() @pyqtSlot() def on_cleanupButton_clicked(self): """ Private slot cleanup the downloads. """ if len(self.__downloads) == 0: return self.__model.removeRows(0, len(self.__downloads)) if len(self.__downloads) == 0 and \ self.__iconProvider is not None: self.__iconProvider = None self.changeOccurred() self.__updateActiveItemCount() def __updateItemCount(self): """ Private method to update the count label. """ count = len(self.__downloads) self.countLabel.setText(self.tr("%n Download(s)", "", count)) def __updateActiveItemCount(self): """ Private method to update the window title. """ count = self.activeDownloads() if count > 0: self.setWindowTitle( self.tr("Downloading %n file(s)", "", count)) else: self.setWindowTitle(self.tr("Downloads")) def __finished(self): """ Private slot to handle a finished download. """ self.__updateActiveItemCount() if self.isVisible(): QApplication.alert(self) def setDownloadDirectory(self, directory): """ Public method to set the current download directory. @param directory current download directory (string) """ self.__downloadDirectory = directory if self.__downloadDirectory != "": self.__downloadDirectory += "/" def downloadDirectory(self): """ Public method to get the current download directory. @return current download directory (string) """ return self.__downloadDirectory def count(self): """ Public method to get the number of downloads. @return number of downloads (integer) """ return len(self.__downloads) def downloads(self): """ Public method to get a reference to the downloads. @return reference to the downloads (list of DownloadItem) """ return self.__downloads def changeOccurred(self): """ Public method to signal a change. """ self.__saveTimer.changeOccurred() self.__updateItemCount() ########################################################################### ## Context menu related methods below ########################################################################### def __currentItem(self): """ Private method to get a reference to the current item. @return reference to the current item (DownloadItem) """ index = self.downloadsView.currentIndex() if index and index.isValid(): row = index.row() return self.__downloads[row] return None def __contextMenuRetry(self): """ Private method to retry of the download. """ itm = self.__currentItem() if itm is not None: itm.retry() def __contextMenuOpen(self): """ Private method to open the downloaded file. """ itm = self.__currentItem() if itm is not None: itm.openFile() def __contextMenuOpenFolder(self): """ Private method to open the folder containing the downloaded file. """ itm = self.__currentItem() if itm is not None: itm.openFolder() def __contextMenuCancel(self): """ Private method to cancel the current download. """ itm = self.__currentItem() if itm is not None: itm.cancelDownload() def __contextMenuGotoPage(self): """ Private method to open the download page. """ itm = self.__currentItem() if itm is not None: url = itm.getPageUrl() Helpviewer.HelpWindow.HelpWindow.mainWindow().openUrl(url, "") def __contextMenuCopyLink(self): """ Private method to copy the download link to the clipboard. """ itm = self.__currentItem() if itm is not None: url = itm.getPageUrl().toString() QApplication.clipboard().setText(url) def __contextMenuSelectAll(self): """ Private method to select all downloads. """ self.downloadsView.selectAll() def __contextMenuRemoveSelected(self): """ Private method to remove the selected downloads from the list. """ self.downloadsView.removeSelected()
class Model(QAbstractItemModel): def __init__(self, rows, columns, parent = None): super(Model, self).__init__(parent) self.services = QIcon(images_dir + '/services.png') self.rc = rows self.cc = columns self.tree = [Node() for node in range(rows)] self.iconProvider = QFileIconProvider() def index(self, row, column, parent): if row < self.rc and row >= 0 and column < self.cc and column >= 0: parentNode = parent.internalPointer() childNode = self.node(row, parentNode) if childNode is not None: return self.createIndex(row, column, childNode) return QModelIndex() def parent(self, child): if isinstance(child, QModelIndex): # parent of QModelIndex child if child.isValid(): childNode = child.internalPointer() parentNode = self.parent(childNode) if parentNode: return self.createIndex(self.row(parentNode), 0, parentNode) return QModelIndex() else: # parent of Node if child: return child.parent def rowCount(self, parent): if parent.isValid() and parent.column() != 0: return 0 return self.rc def columnCount(self, parent): return self.cc def data(self, index, role): if not index.isValid(): return None elif role == Qt.DisplayRole: return "Item %d:%s" % (index.row(), index.column()) elif role == Qt.DecorationRole: if index.column() == 0: return self.iconProvider.icon(QFileIconProvider.Folder) return self.iconProvider.icon(QFileIconProvider.File) return None def headerData(self, section, orientation, role): if role == Qt.DisplayRole: return str(section) if role == Qt.DecorationRole: return self.services return super(Model, self).headerData(section, orientation, role) def hasChildren(self, parent): if parent.isValid() and parent.column() != 0: return False return self.rc > 0 and self.cc > 0 def flags(self, index): if not index.isValid(): return 0 return Qt.ItemIsDragEnabled | super(Model, self).flags(index) def node(self, row, parent): if parent and not parent.children: parent.children = [Node(parent) for node in range(self.rc)] if parent: return parent.children[row] else: return self.tree[row] def row(self, node): if node.parent: return node.parent.children.index(node) else: return self.tree.index(node)
class HDF5ItemModel(QtCore.QAbstractItemModel): """This model takes its data from an HDF5 Group for display in a tree. It loads the file as the tree is expanded for speed - in the future it might implement sanity checks to abort loading very long folders. """ def __init__(self, data_group, res, extended_selection): """Init the class Args: data_group (HDF5 grup): HDF5 group res (qt resolution): size of the app extended_selection (bool): allow multiple selection """ super().__init__() self.root_item = None self.data_group = data_group self.iconProvider = QFileIconProvider() self.res = res self.extended_selection = extended_selection _data_group = None @property def data_group(self, new_data_group): if self.root_item is not None: del self.root_item self._data_group = new_data_group self.root_item = HDF5TreeItem(new_data_group.file, None, new_data_group.name, 0) @data_group.setter def data_group(self, new_data_group): """Set the data group represented by the model.""" if self.root_item is not None: del self.root_item self._data_group = new_data_group self.root_item = HDF5TreeItem(new_data_group.file, None, new_data_group.name, 0) def _index_to_item(self, index): '''return the HDF5Item for a given index. Args: index (int): index of the item Returns: HDF5item: corresponding item ''' if index.isValid(): return index.internalPointer() else: return self.root_item def index(self, row, column, parent_index): """Return the index of the <row>th child of parent. Args: row (int): row index column (int): column index parent_index (QtCore.QModelIndex): Parent """ try: parent = self._index_to_item(parent_index) return self.createIndex(row, column, parent.children[row]) except: return QtCore.QModelIndex() def parent(self, index=None): """Find the index of the parent of the item at a given index.""" try: parent = self._index_to_item(index).parent return self.createIndex(parent.row, 0, parent) except: # Something went wrong with finding the parent so return an invalid index return QtCore.QModelIndex() def flags(self, index): """Return flags telling Qt what to do with the item""" return QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled def data(self, index, role): """The data represented by this item.""" if not index.isValid(): return None if role == QtCore.Qt.DisplayRole: item = self._index_to_item(index) # If the dataset is one number we print the value in the name # if item.parent.basename == 'targets': try: value = item.data_file[item.name][()] if not isinstance(value, np.ndarray): return "{:10s}".format( item.basename) + '\tvalue : %1.3e' % value else: if value.shape == (1, ): return "{:10s}".format( item.basename) + '\tvalue : %1.3e' % value else: dims = ' x '.join(map(lambda x: str(x), value.shape)) return "{:10s}".format( item.basename) + '\tsize : ' + dims except Exception as ex: pass # for the rest just the values return self._index_to_item(index).basename elif role == Qt.DecorationRole: if self._index_to_item(index)._has_children: return self.iconProvider.icon(QFileIconProvider.Folder) else: return self.iconProvider.icon(QFileIconProvider.File) else: return None def headerData(self, section, orientation, role=None): """Return the header names - an empty string here!""" return [""] def rowCount(self, index): """The number of rows exposed by the model""" try: item = self._index_to_item(index) assert item.has_children return len(item.children) except: # if it doesn't have keys, assume there are no children. return 0 def hasChildren(self, index): """Whether or not this object has children""" return self._index_to_item(index).has_children def columnCount(self, index=None, *args, **kwargs): """Return the number of columns""" return 1 def refresh_tree(self): """Reload the HDF5 tree, resetting the model This causes all cached HDF5 tree information to be deleted, and any views using this model will automatically reload. """ self.beginResetModel() self.root_item.purge_children() self.endResetModel() def selected_h5item_from_view(self, treeview): """Given a treeview object, return the selection, as an HDF5 object, or a work-alike for multiple selection. If one item is selected, we will return the HDF5 group or dataset that is selected. If multiple items are selected, we will return a dummy HDF5 group containing all selected items. """ items = [ self._index_to_item(index) for index in treeview.selectedIndexes() ] if len(items) == 1: return items[0].h5item elif len(items) > 1: return DummyHDF5Group({item.name: item.h5item for item in items}) else: return None def set_up_treeview(self, treeview): """Correctly configure a QTreeView to use this model. This will set the HDF5ItemModel as the tree's model (data source), and in the future may set up context menus, etc. as appropriate.""" # Make the tree view use this object as its model treeview.setModel(self) treeview.setAlternatingRowColors(True) treeview.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked | QtWidgets.QAbstractItemView.SelectedClicked) treeview.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems) # Set up a callback to allow us to customise the context menu treeview.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) treeview.customContextMenuRequested.connect( functools.partial(self.context_menu, treeview)) # set the selection Mode if self.extended_selection: treeview.setSelectionMode( QtWidgets.QAbstractItemView.ExtendedSelection)
class Model(QAbstractItemModel): def __init__(self, rows, columns, parent=None): super(Model, self).__init__(parent) self.services = QIcon(images_dir + "/services.png") self.rc = rows self.cc = columns self.tree = [Node() for node in range(rows)] self.iconProvider = QFileIconProvider() def index(self, row, column, parent): if row < self.rc and row >= 0 and column < self.cc and column >= 0: parentNode = parent.internalPointer() childNode = self.node(row, parentNode) if childNode is not None: return self.createIndex(row, column, childNode) return QModelIndex() def parent(self, child): if isinstance(child, QModelIndex): # parent of QModelIndex child if child.isValid(): childNode = child.internalPointer() parentNode = self.parent(childNode) if parentNode: return self.createIndex(self.row(parentNode), 0, parentNode) return QModelIndex() else: # parent of Node if child: return child.parent def rowCount(self, parent): if parent.isValid() and parent.column() != 0: return 0 return self.rc def columnCount(self, parent): return self.cc def data(self, index, role): if not index.isValid(): return None elif role == Qt.DisplayRole: return "Item %d:%s" % (index.row(), index.column()) elif role == Qt.DecorationRole: if index.column() == 0: return self.iconProvider.icon(QFileIconProvider.Folder) return self.iconProvider.icon(QFileIconProvider.File) return None def headerData(self, section, orientation, role): if role == Qt.DisplayRole: return str(section) if role == Qt.DecorationRole: return self.services return super(Model, self).headerData(section, orientation, role) def hasChildren(self, parent): if parent.isValid() and parent.column() != 0: return False return self.rc > 0 and self.cc > 0 def flags(self, index): if not index.isValid(): return 0 return Qt.ItemIsDragEnabled | super(Model, self).flags(index) def node(self, row, parent): if parent and not parent.children: parent.children = [Node(parent) for node in range(self.rc)] if parent: return parent.children[row] else: return self.tree[row] def row(self, node): if node.parent: return node.parent.children.index(node) else: return self.tree.index(node)
def icon(self, fileInfo): if fileInfo.isDir(): return QIcon("folder.png") return QFileIconProvider.icon(self, fileInfo)
class DownloadManager(QDialog, Ui_DownloadManager): """ Class implementing the download manager. """ RemoveNever = 0 RemoveExit = 1 RemoveSuccessFullDownload = 2 def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(DownloadManager, self).__init__(parent) self.setupUi(self) self.setWindowFlags(Qt.Window) self.__saveTimer = AutoSaver(self, self.save) self.__model = DownloadModel(self) self.__manager = Helpviewer.HelpWindow.HelpWindow\ .networkAccessManager() self.__iconProvider = None self.__downloads = [] self.__downloadDirectory = "" self.__loaded = False self.setDownloadDirectory(Preferences.getUI("DownloadPath")) self.downloadsView.setShowGrid(False) self.downloadsView.verticalHeader().hide() self.downloadsView.horizontalHeader().hide() self.downloadsView.setAlternatingRowColors(True) self.downloadsView.horizontalHeader().setStretchLastSection(True) self.downloadsView.setModel(self.__model) self.downloadsView.setContextMenuPolicy(Qt.CustomContextMenu) self.downloadsView.customContextMenuRequested.connect( self.__customContextMenuRequested) self.__load() def __customContextMenuRequested(self, pos): """ Private slot to handle the context menu request for the bookmarks tree. @param pos position the context menu was requested (QPoint) """ menu = QMenu() selectedRowsCount = len( self.downloadsView.selectionModel().selectedRows()) if selectedRowsCount == 1: row = self.downloadsView.selectionModel().selectedRows()[0].row() itm = self.__downloads[row] if itm.downloadCanceled(): menu.addAction(UI.PixmapCache.getIcon("restart.png"), self.tr("Retry"), self.__contextMenuRetry) else: if itm.downloadedSuccessfully(): menu.addAction(UI.PixmapCache.getIcon("open.png"), self.tr("Open"), self.__contextMenuOpen) elif itm.downloading(): menu.addAction(UI.PixmapCache.getIcon("stopLoading.png"), self.tr("Cancel"), self.__contextMenuCancel) menu.addSeparator() menu.addAction(self.tr("Open Containing Folder"), self.__contextMenuOpenFolder) menu.addSeparator() menu.addAction(self.tr("Go to Download Page"), self.__contextMenuGotoPage) menu.addAction(self.tr("Copy Download Link"), self.__contextMenuCopyLink) menu.addSeparator() menu.addAction(self.tr("Select All"), self.__contextMenuSelectAll) if selectedRowsCount > 1 or \ (selectedRowsCount == 1 and not self.__downloads[ self.downloadsView.selectionModel().selectedRows()[0].row()] .downloading()): menu.addSeparator() menu.addAction(self.tr("Remove From List"), self.__contextMenuRemoveSelected) menu.exec_(QCursor.pos()) def shutdown(self): """ Public method to stop the download manager. """ self.__saveTimer.changeOccurred() self.__saveTimer.saveIfNeccessary() self.close() def activeDownloads(self): """ Public method to get the number of active downloads. @return number of active downloads (integer) """ count = 0 for download in self.__downloads: if download.downloading(): count += 1 return count def allowQuit(self): """ Public method to check, if it is ok to quit. @return flag indicating allowance to quit (boolean) """ if self.activeDownloads() > 0: res = E5MessageBox.yesNo( self, self.tr(""), self.tr( """There are %n downloads in progress.\n""" """Do you want to quit anyway?""", "", self.activeDownloads()), icon=E5MessageBox.Warning) if not res: self.show() return False return True def download(self, requestOrUrl, requestFileName=False, mainWindow=None): """ Public method to download a file. @param requestOrUrl reference to a request object (QNetworkRequest) or a URL to be downloaded (QUrl) @keyparam requestFileName flag indicating to ask for the download file name (boolean) @keyparam mainWindow reference to the main window (HelpWindow) """ request = QNetworkRequest(requestOrUrl) if request.url().isEmpty(): return self.handleUnsupportedContent(self.__manager.get(request), requestFileName=requestFileName, download=True, mainWindow=mainWindow) def handleUnsupportedContent(self, reply, requestFileName=False, webPage=None, download=False, mainWindow=None): """ Public method to handle unsupported content by downloading the referenced resource. @param reply reference to the reply object (QNetworkReply) @keyparam requestFileName indicating to ask for a filename (boolean) @keyparam webPage reference to the web page (HelpWebPage) @keyparam download flag indicating a download request (boolean) @keyparam mainWindow reference to the main window (HelpWindow) """ if reply is None or reply.url().isEmpty(): return size = reply.header(QNetworkRequest.ContentLengthHeader) if size == 0: return from .DownloadItem import DownloadItem itm = DownloadItem(reply=reply, requestFilename=requestFileName, webPage=webPage, download=download, parent=self, mainWindow=mainWindow) self.__addItem(itm) if itm.canceledFileSelect(): return if not self.isVisible(): self.show() self.activateWindow() self.raise_() def __addItem(self, itm): """ Private method to add a download to the list of downloads. @param itm reference to the download item (DownloadItem) """ itm.statusChanged.connect(self.__updateRow) itm.downloadFinished.connect(self.__finished) row = len(self.__downloads) self.__model.beginInsertRows(QModelIndex(), row, row) self.__downloads.append(itm) self.__model.endInsertRows() self.downloadsView.setIndexWidget(self.__model.index(row, 0), itm) icon = self.style().standardIcon(QStyle.SP_FileIcon) itm.setIcon(icon) self.downloadsView.setRowHeight(row, itm.sizeHint().height() * 1.5) # just in case the download finished before the constructor returned self.__updateRow(itm) self.changeOccurred() self.__updateActiveItemCount() def __updateRow(self, itm=None): """ Private slot to update a download item. @param itm reference to the download item (DownloadItem) """ if itm is None: itm = self.sender() if itm not in self.__downloads: return row = self.__downloads.index(itm) if self.__iconProvider is None: self.__iconProvider = QFileIconProvider() icon = self.__iconProvider.icon(QFileInfo(itm.fileName())) if icon.isNull(): icon = self.style().standardIcon(QStyle.SP_FileIcon) itm.setIcon(icon) oldHeight = self.downloadsView.rowHeight(row) self.downloadsView.setRowHeight( row, max(oldHeight, itm.minimumSizeHint().height() * 1.5)) remove = False globalSettings = QWebSettings.globalSettings() if not itm.downloading() and \ globalSettings.testAttribute(QWebSettings.PrivateBrowsingEnabled): remove = True if itm.downloadedSuccessfully() and \ self.removePolicy() == DownloadManager.RemoveSuccessFullDownload: remove = True if remove: self.__model.removeRow(row) self.cleanupButton.setEnabled( (len(self.__downloads) - self.activeDownloads()) > 0) # record the change self.changeOccurred() def removePolicy(self): """ Public method to get the remove policy. @return remove policy (integer) """ return Preferences.getHelp("DownloadManagerRemovePolicy") def setRemovePolicy(self, policy): """ Public method to set the remove policy. @param policy policy to be set (DownloadManager.RemoveExit, DownloadManager.RemoveNever, DownloadManager.RemoveSuccessFullDownload) """ assert policy in (DownloadManager.RemoveExit, DownloadManager.RemoveNever, DownloadManager.RemoveSuccessFullDownload) if policy == self.removePolicy(): return Preferences.setHelp("DownloadManagerRemovePolicy", self.policy) def save(self): """ Public method to save the download settings. """ if not self.__loaded: return Preferences.setHelp("DownloadManagerSize", self.size()) Preferences.setHelp("DownloadManagerPosition", self.pos()) if self.removePolicy() == DownloadManager.RemoveExit: return downloads = [] for download in self.__downloads: downloads.append(download.getData()) Preferences.setHelp("DownloadManagerDownloads", downloads) def __load(self): """ Private method to load the download settings. """ if self.__loaded: return size = Preferences.getHelp("DownloadManagerSize") if size.isValid(): self.resize(size) pos = Preferences.getHelp("DownloadManagerPosition") self.move(pos) downloads = Preferences.getHelp("DownloadManagerDownloads") for download in downloads: if not download[0].isEmpty() and \ download[1] != "": from .DownloadItem import DownloadItem itm = DownloadItem(parent=self) itm.setData(download) self.__addItem(itm) self.cleanupButton.setEnabled( (len(self.__downloads) - self.activeDownloads()) > 0) self.__loaded = True self.__updateActiveItemCount() def cleanup(self): """ Public slot to cleanup the downloads. """ self.on_cleanupButton_clicked() @pyqtSlot() def on_cleanupButton_clicked(self): """ Private slot cleanup the downloads. """ if len(self.__downloads) == 0: return self.__model.removeRows(0, len(self.__downloads)) if len(self.__downloads) == 0 and \ self.__iconProvider is not None: self.__iconProvider = None self.changeOccurred() self.__updateActiveItemCount() def __updateItemCount(self): """ Private method to update the count label. """ count = len(self.__downloads) self.countLabel.setText(self.tr("%n Download(s)", "", count)) def __updateActiveItemCount(self): """ Private method to update the window title. """ count = self.activeDownloads() if count > 0: self.setWindowTitle(self.tr("Downloading %n file(s)", "", count)) else: self.setWindowTitle(self.tr("Downloads")) def __finished(self): """ Private slot to handle a finished download. """ self.__updateActiveItemCount() if self.isVisible(): QApplication.alert(self) def setDownloadDirectory(self, directory): """ Public method to set the current download directory. @param directory current download directory (string) """ self.__downloadDirectory = directory if self.__downloadDirectory != "": self.__downloadDirectory += "/" def downloadDirectory(self): """ Public method to get the current download directory. @return current download directory (string) """ return self.__downloadDirectory def count(self): """ Public method to get the number of downloads. @return number of downloads (integer) """ return len(self.__downloads) def downloads(self): """ Public method to get a reference to the downloads. @return reference to the downloads (list of DownloadItem) """ return self.__downloads def changeOccurred(self): """ Public method to signal a change. """ self.__saveTimer.changeOccurred() self.__updateItemCount() ########################################################################### ## Context menu related methods below ########################################################################### def __currentItem(self): """ Private method to get a reference to the current item. @return reference to the current item (DownloadItem) """ index = self.downloadsView.currentIndex() if index and index.isValid(): row = index.row() return self.__downloads[row] return None def __contextMenuRetry(self): """ Private method to retry of the download. """ itm = self.__currentItem() if itm is not None: itm.retry() def __contextMenuOpen(self): """ Private method to open the downloaded file. """ itm = self.__currentItem() if itm is not None: itm.openFile() def __contextMenuOpenFolder(self): """ Private method to open the folder containing the downloaded file. """ itm = self.__currentItem() if itm is not None: itm.openFolder() def __contextMenuCancel(self): """ Private method to cancel the current download. """ itm = self.__currentItem() if itm is not None: itm.cancelDownload() def __contextMenuGotoPage(self): """ Private method to open the download page. """ itm = self.__currentItem() if itm is not None: url = itm.getPageUrl() Helpviewer.HelpWindow.HelpWindow.mainWindow().openUrl(url, "") def __contextMenuCopyLink(self): """ Private method to copy the download link to the clipboard. """ itm = self.__currentItem() if itm is not None: url = itm.getPageUrl().toString() QApplication.clipboard().setText(url) def __contextMenuSelectAll(self): """ Private method to select all downloads. """ self.downloadsView.selectAll() def __contextMenuRemoveSelected(self): """ Private method to remove the selected downloads from the list. """ self.downloadsView.removeSelected()