Esempio n. 1
0
 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
Esempio n. 3
0
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")
Esempio n. 4
0
 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)
Esempio n. 5
0
 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)
Esempio n. 6
0
 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])
Esempio n. 7
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))
Esempio n. 8
0
    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
Esempio n. 10
0
 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)
Esempio n. 11
0
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
Esempio n. 12
0
    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
Esempio n. 13
0
    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
Esempio n. 14
0
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")
Esempio n. 15
0
        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)
Esempio n. 16
0
 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")
Esempio n. 17
0
    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)
Esempio n. 18
0
 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()
Esempio n. 19
0
    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
Esempio n. 21
0
 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)
Esempio n. 22
0
 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)
Esempio n. 23
0
    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)
Esempio n. 25
0
 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)
Esempio n. 26
0
    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()))
Esempio n. 27
0
    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)
Esempio n. 28
0
    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
Esempio n. 29
0
 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
Esempio n. 30
0
 def get_icon(self) -> QIcon:
     file_info = QFileInfo(self._file_path)
     icon_provider = QFileIconProvider()
     icon = icon_provider.icon(file_info)
     return icon
Esempio n. 31
0
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()
Esempio n. 32
0
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()
Esempio n. 33
0
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)
Esempio n. 34
0
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)
Esempio n. 35
0
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)
Esempio n. 36
0
 def icon(self, fileInfo):
     if fileInfo.isDir():
         return QIcon("folder.png")
     return QFileIconProvider.icon(self, fileInfo)
Esempio n. 37
0
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()