def SaveTools(self): try: if os.path.isfile(self.filepath): QFile.remove(self.file) self.file.open(QIODevice.WriteOnly) datastream = QDataStream(self.file) count = self.MyToolsBars.topLevelItemCount() datastream.writeUInt32(count) for i in range(0, count): item = self.MyToolsBars.topLevelItem(i) item.write(datastream) self.bar = None self.CreateToolBar(item) self.save_item(item, datastream) self.hasChanged = False self.file.close() # We restore the list of Qgis tools. state = self.saveWidgetState(self.ToolBars) self.PopulateQgisTools() self.loadWidgetState(self.ToolBars, state) self.iface.messageBar().pushMessage("Info: ", "Save correctly.", level=QGis.Info, duration=3) self.rename_btn.setEnabled(False) self.delete_btn.setEnabled(False) self.restore = {} except Exception: self.iface.messageBar().pushMessage("Error: ", "Error save tools ", level=QGis.Critical, duration=3) return
def removeScript(self, script): """ Public method to remove a script. @param script script to be removed (GreaseMonkeyScript) @return flag indicating success (boolean) """ if not script: return False from .GreaseMonkeyScript import GreaseMonkeyScript if script.startAt() == GreaseMonkeyScript.DocumentStart: try: self.__startScripts.remove(script) except ValueError: pass else: try: self.__endScripts.remove(script) except ValueError: pass fullName = script.fullName() if fullName in self.__disabledScripts: self.__disabledScripts.remove(fullName) QFile.remove(script.fileName()) self.scriptsChanged.emit() return True
def _copy_lib_file(cls, file_name, dir_name, dst_file_name=None): """ Copy a library file to a directory and return the full pathname of the copy. """ # Note that we use the Qt file operations to support the possibility # that pyqtdeploy itself has been deployed as a single executable. if dst_file_name is None: dst_file_name = file_name s_file_name = cls._get_lib_file_name(file_name) else: s_file_name = file_name d_file_name = dir_name + '/' + dst_file_name # Make sure the destination doesn't exist. QFile.remove(d_file_name) if not QFile.copy(s_file_name, d_file_name): raise UserException("Unable to copy file {0}".format(file_name)) # The file will be read-only if it was embedded. QFile.setPermissions(d_file_name, QFileDevice.ReadOwner | QFileDevice.WriteOwner) return d_file_name
def removeEngine(self, name): """ Public method to remove an engine. @param name name of the engine (string) """ if len(self.__engines) <= 1: return if name not in self.__engines: return engine = self.__engines[name] for keyword in [ k for k in self.__keywords if self.__keywords[k] == engine ]: del self.__keywords[keyword] del self.__engines[name] file_ = QDir(self.enginesDirectory()).filePath( self.generateEngineFileName(name)) QFile.remove(file_) if name == self.__current: self.setCurrentEngineName(list(self.__engines.keys())[0]) self.changed.emit()
def __finished(self): """ Private slot to handle the download finished. """ self.__finishedDownloading = True if not self.__startedSaving: return noError = self.__reply.error() == QNetworkReply.NoError self.progressBar.setVisible(False) if not self.__isFtpDownload: self.stopButton.setEnabled(False) self.stopButton.setVisible(False) self.pauseButton.setEnabled(False) self.pauseButton.setVisible(False) self.openButton.setEnabled(noError) self.openButton.setVisible(noError) self.__output.close() if QFile.exists(self.__fileName): QFile.remove(self.__fileName) self.__output.rename(self.__fileName) self.__updateInfoLabel() self.__state = DownloadItem.DownloadSuccessful self.statusChanged.emit() self.downloadFinished.emit() if self.__autoOpen: self.__open()
def removeItem(self, deleteFile: bool): """ Remove a char item from the presentation Args: deleteFile (bool) : whether to delete the file of the char item """ # find the selected item charItem = self.selectedItem() # remove the item from the presentation charItem.setParentItem(None) # rearrange the items self.insertionIndex = -1 for charItem in self.childItems(): self.insertionIndex += 1 self.positionChar(charItem) # reset the selected index self.selectedItemIndex = -1 # delete the character file if requested if deleteFile == QMessageBox.Yes: fh = QFile(charItem.filename) fh.remove()
def downloadFile(self): self.url = QUrl(self.urlLineEdit.text()) fileInfo = QFileInfo(self.url.path()) fileName = fileInfo.fileName() if not fileName: fileName = 'index.html' if QFile.exists(fileName): ret = QMessageBox.question(self, "HTTP", "There already exists a file called %s in the current " "directory. Overwrite?" % fileName, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.No: return QFile.remove(fileName) self.outFile = QFile(fileName) if not self.outFile.open(QIODevice.WriteOnly): QMessageBox.information(self, "HTTP", "Unable to save the file %s: %s." % (fileName, self.outFile.errorString())) self.outFile = None return self.progressDialog.setWindowTitle("HTTP") self.progressDialog.setLabelText("Downloading %s." % fileName) self.downloadButton.setEnabled(False) self.httpRequestAborted = False self.startRequest(self.url)
def removeSubscription(self, subscription, emitSignal=True): """ Public method to remove an AdBlock subscription. @param subscription AdBlock subscription to be removed (AdBlockSubscription) @param emitSignal flag indicating to send a signal (boolean) """ if subscription is None: return if subscription.url().toString().startswith( (self.__defaultSubscriptionUrlString, self.__customSubscriptionUrlString)): return try: self.__subscriptions.remove(subscription) rulesFileName = subscription.rulesFileName() QFile.remove(rulesFileName) requiresSubscriptions = self.getRequiresSubscriptions(subscription) for requiresSubscription in requiresSubscriptions: self.removeSubscription(requiresSubscription, False) if emitSignal: self.rulesChanged.emit() except ValueError: pass
def __loadRules(self): """ Private method to load the rules of the subscription. """ fileName = self.rulesFileName() f = QFile(fileName) if f.exists(): if not f.open(QIODevice.ReadOnly): E5MessageBox.warning( None, self.tr("Load subscription rules"), self.tr( """Unable to open adblock file '{0}' for reading."""). format(fileName)) else: textStream = QTextStream(f) header = textStream.readLine(1024) if not header.startswith("[Adblock"): E5MessageBox.warning( None, self.tr("Load subscription rules"), self.tr("""AdBlock file '{0}' does not start""" """ with [Adblock.""").format(fileName)) f.close() f.remove() self.__lastUpdate = QDateTime() else: from .AdBlockRule import AdBlockRule self.__updatePeriod = 0 self.__remoteModified = QDateTime() self.__rules = [] self.__rules.append(AdBlockRule(header, self)) while not textStream.atEnd(): line = textStream.readLine() self.__rules.append(AdBlockRule(line, self)) expires = self.__expiresRe.search(line) if expires: period, kind = expires.groups() if kind: # hours self.__updatePeriod = int(period) else: # days self.__updatePeriod = int(period) * 24 remoteModified = self.__remoteModifiedRe.search(line) if remoteModified: day, month, year, time, hour, minute = \ remoteModified.groups() self.__remoteModified.setDate( QDate(int(year), self.__monthNameToNumber[month], int(day))) if time: self.__remoteModified.setTime( QTime(int(hour), int(minute))) self.__populateCache() self.changed.emit() elif not fileName.endswith("_custom"): self.__lastUpdate = QDateTime() self.checkForUpdate()
def removeEngine(self, name): """ Public method to remove an engine. @param name name of the engine (string) """ if len(self.__engines) <= 1: return if name not in self.__engines: return engine = self.__engines[name] for keyword in [k for k in self.__keywords if self.__keywords[k] == engine]: del self.__keywords[keyword] del self.__engines[name] file_ = QDir(self.enginesDirectory()).filePath( self.generateEngineFileName(name)) QFile.remove(file_) if name == self.__current: self.setCurrentEngineName(list(self.__engines.keys())[0]) self.changed.emit()
def downloadV2raycore(self, url=False): if (url): self.downloadURL = url fileInfo = QFileInfo(self.downloadURL.path()) self.fileName = fileName = fileInfo.fileName() if not fileName: fileName = "v2ray.zip" if QFile.exists(fileName): QFile.remove(fileName) self.outFile = QFile(fileName) if not self.outFile.open(QIODevice.WriteOnly): if (self.silentInstall == False): self.msgBox.information( QDialog().move(self.fly), self.translate("updateV2ray", "Download {}").format(fileName), self.translate("updateV2ray", "Unable to save the file {}: {}.").format( fileName, self.outFile.errorString())) self.outFile = None return self.httpRequestAborted = False if (self.silentInstall == False): self.progressDialog = QProgressDialog() self.progressDialog.setLabelText( self.translate("updateV2ray", "v2ray-core is downloading...")) self.progressDialog.canceled.connect(self.cancelDownload) self.startRequest(self.downloadURL)
async def setupQrCodesFolder(self, ipfsop, profile, model, files): """ Import the sample QR codes to the corresponding folder Needs rewrite .. """ for name, qrFile in sampleQrCodes(): await ipfsop.sleep() if qrFile.exists(): path = self.app.tempDir.filePath(name) if qrFile.copy(path): tmpFile = QFile(path) entry = await ipfsop.addPath(path) await ipfsop.sleep() if not entry: tmpFile.remove() continue exists = await ipfsop.filesLookupHash( model.itemQrCodes.path, entry['Hash']) await ipfsop.sleep() if not exists: await files.linkEntryNoMetadata( entry, model.itemQrCodes.path, entry['Name']) tmpFile.remove() self.qrInitialized = True
def saveTextdata(self, filePath, data): outFile = QFileInfo(filePath) fileName = outFile.fileName() if QFile.exists(fileName): QFile.remove(fileName) outFile = QFile(outFile.absoluteFilePath()) outFile.open(QIODevice.WriteOnly | QIODevice.Text) if outFile.error() != outFile.NoError: self.msgBox.information( QDialog().move(self.fly), "{}".format(fileName), self.translate("openV2rayJSONFile", "Unable to open the file {}: {}.").format( fileName, outFile.errorString())) outFile = None return False outFile.write(codecs.encode(data, "utf-8")) if outFile.error() != outFile.NoError: self.msgBox.information( QDialog().move(self.fly), "{}".format(fileName), self.translate("openV2rayJSONFile", "Unable to save the file {}: {}.").format( fileName, outFile.errorString())) outFile = None return False outFile.close()
def saveV2raycoreJSONFile(self): JSONData = {} JSONData["preferences"] = copy.deepcopy(self.preferences) JSONData["update"] = copy.deepcopy(self.update) JSONData["configFiles"] = copy.deepcopy(self.configFiles) outFile = QFileInfo(self.v2rayshellConfigFileName) fileName = outFile.fileName() if QFile.exists(fileName): QFile.remove(fileName) outFile = QFile(fileName) outFile.open(QIODevice.WriteOnly | QIODevice.Text) if outFile.error() != outFile.NoError: self.msgBox.information(QDialog().move(self.fly), "{}".format(fileName), self.translate("bridgetreasureChest", "Unable to open the file {}: {}.").format(fileName, outFile.errorString())) outFile = None return False outFile.write(codecs.encode(json.dumps(JSONData, indent = 4, sort_keys = False), "utf-8")) if outFile.error() != outFile.NoError: self.msgBox.information(QDialog().move(self.fly), "{}".format(fileName), self.translate("bridgetreasureChest", "Unable to save the file {}: {}.").format(fileName, outFile.errorString())) outFile = None return False outFile.close()
def removeScript(self, script, removeFile=True): """ Public method to remove a script. @param script script to be removed (GreaseMonkeyScript) @param removeFile flag indicating to remove the script file as well (bool) @return flag indicating success (boolean) """ if not script: return False try: self.__scripts.remove(script) except ValueError: pass fullName = script.fullName() collection = WebBrowserWindow.webProfile().scripts() collection.remove(collection.findScript(fullName)) if fullName in self.__disabledScripts: self.__disabledScripts.remove(fullName) if removeFile: QFile.remove(script.fileName()) del script self.scriptsChanged.emit() return True
def _copy_lib_file(cls, file_name, dir_name, dst_file_name=None): """ Copy a library file to a directory and return the full pathname of the copy. """ # Note that we use the Qt file operations to support the possibility # that pyqtdeploy itself has been deployed as a single executable. if dst_file_name is None: dst_file_name = file_name s_file_name = cls._get_lib_file_name(file_name) else: s_file_name = file_name d_file_name = dir_name + '/' + dst_file_name # Make sure the destination doesn't exist. QFile.remove(d_file_name) if not QFile.copy(s_file_name, d_file_name): raise UserException("Unable to copy file {0}".format(file_name)) # The file will be read-only if it was embedded. QFile.setPermissions(d_file_name, QFileDevice.ReadOwner|QFileDevice.WriteOwner) return d_file_name
def _copy_file(self, uid: str = "", source_path: str = "", dest_path: str = ""): self._current_uid = uid source_file = QFile(source_path) dest_file = QFile(dest_path) if not source_file.open(QFile.ReadOnly): self.copy_error.emit(uid, FileCopier.CannotOpenSourceFile) return dest_file_info = QFileInfo(dest_file) dest_dir = dest_file_info.absoluteDir() if not dest_dir.exists(): if not dest_dir.mkpath(dest_dir.absolutePath()): self.copy_error.emit(uid, FileCopier.CannotCreateDestinationDirectory) return if not dest_file.open(QFile.WriteOnly): ic(dest_path, dest_file.errorString()) self.copy_error.emit(uid, FileCopier.CannotOpenDestinationFile) return progress: int = 0 total: int = source_file.size() error: int = FileCopier.NoError while True: if self._cancel_current: self._cancel_current = False self.copy_cancelled.emit(uid) break data: Union[bytes, int] = source_file.read(_COPY_BLOCK_SIZE) if isinstance(data, int): assert data == -1 error = FileCopier.CannotReadSourceFile break data_len = len(data) if data_len == 0: self.copy_progress.emit(uid, progress, total) break if data_len != dest_file.write(data): error = FileCopier.CannotWriteDestinationFile break progress += data_len self.copy_progress.emit(uid, progress, total) qApp.processEvents() source_file.close() dest_file.close() if error != FileCopier.NoError: dest_file.remove() self.copy_error.emit(uid, error) else: dest_file.setPermissions(source_file.permissions()) self.copy_complete.emit(uid)
def checkdownloadFileExists(self, downloadPath): if (not downloadPath or not downloadPath): return False filePath = QUrl(downloadPath) fileInfo = QFileInfo(filePath.path()) fileName = fileInfo.fileName() if QFile.exists(fileName): QFile.remove(fileName) return True
def savebugReportText(self, save=False): if save: outFile = QFileInfo(self.translate("bugReport", "bugReport.txt")) fileName = outFile.fileName() if QFile.exists(fileName): QFile.remove(fileName) outFile = QFile(fileName) outFile.open(QIODevice.WriteOnly | QIODevice.Text) outFile.write(codecs.encode(save, "utf-8"))
def __downloadRepositoryFileDone(self): """ Private method called after the repository file was downloaded. """ reply = self.sender() if reply in self.__replies: self.__replies.remove(reply) if reply.error() != QNetworkReply.NoError: E5MessageBox.warning( None, self.tr("Error downloading file"), self.tr( """<p>Could not download the requested file""" """ from {0}.</p><p>Error: {1}</p>""" ).format(Preferences.getUI("PluginRepositoryUrl6"), reply.errorString()) ) return ioDevice = QFile(self.pluginRepositoryFile + ".tmp") ioDevice.open(QIODevice.WriteOnly) ioDevice.write(reply.readAll()) ioDevice.close() if QFile.exists(self.pluginRepositoryFile): QFile.remove(self.pluginRepositoryFile) ioDevice.rename(self.pluginRepositoryFile) if os.path.exists(self.pluginRepositoryFile): f = QFile(self.pluginRepositoryFile) if f.open(QIODevice.ReadOnly): # save current URL url = Preferences.getUI("PluginRepositoryUrl6") # read the repository file from E5XML.PluginRepositoryReader import PluginRepositoryReader reader = PluginRepositoryReader(f, self.checkPluginEntry) reader.readXML() if url != Preferences.getUI("PluginRepositoryUrl6"): # redo if it is a redirect self.checkPluginUpdatesAvailable() return if self.__updateAvailable: res = E5MessageBox.information( None, self.tr("New plugin versions available"), self.tr("<p>There are new plug-ins or plug-in" " updates available. Use the plug-in" " repository dialog to get them.</p>"), E5MessageBox.StandardButtons( E5MessageBox.Ignore | E5MessageBox.Open), E5MessageBox.Open) if res == E5MessageBox.Open: self.__ui.showPluginsAvailable()
def delete_csl_style(self, style_identifier: str) -> None: """Deletes a csl style""" # Remove style path styles = self.get_setting_value("Render/Csl_styles") style_path = styles[style_identifier]["path"] QFile.remove(style_path) # Remove style from Settings manager styles.pop(style_identifier) self.set_setting_value("Render/Csl_styles", styles)
def joinVideos(self, joinlist: list, filename: str) -> None: listfile = os.path.normpath( os.path.join(os.path.dirname(joinlist[0]), '.vidcutter.list')) fobj = open(listfile, 'w') for file in joinlist: fobj.write('file \'%s\'\n' % file.replace("'", "\\'")) fobj.close() self.videoService.join(listfile, filename) QFile.remove(listfile) for file in joinlist: if os.path.isfile(file): QFile.remove(file)
def __downloadFileDone(self): """ Private method called, after the file has been downloaded from the internet. """ self.__updateButton.setEnabled(True) self.__downloadCancelButton.setEnabled(False) self.__onlineStateChanged( self.__networkConfigurationManager.isOnline()) ok = True reply = self.sender() if reply in self.__replies: self.__replies.remove(reply) if reply.error() != QNetworkReply.NoError: ok = False if not self.__downloadCancelled: E5MessageBox.warning( self, self.tr("Error downloading file"), self.tr( """<p>Could not download the requested file""" """ from {0}.</p><p>Error: {1}</p>""" ).format(self.__downloadURL, reply.errorString()) ) self.downloadProgress.setValue(0) self.__downloadURL = None self.__downloadIODevice.remove() self.__downloadIODevice = None if self.repositoryList.topLevelItemCount(): if self.repositoryList.currentItem() is None: self.repositoryList.setCurrentItem( self.repositoryList.topLevelItem(0)) else: self.__downloadButton.setEnabled( len(self.__selectedItems())) self.__downloadInstallButton.setEnabled( len(self.__selectedItems())) reply.deleteLater() return self.__downloadIODevice.open(QIODevice.WriteOnly) self.__downloadIODevice.write(reply.readAll()) self.__downloadIODevice.close() if QFile.exists(self.__downloadFileName): QFile.remove(self.__downloadFileName) self.__downloadIODevice.rename(self.__downloadFileName) self.__downloadIODevice = None self.__downloadURL = None reply.deleteLater() if self.__doneMethod is not None: self.__doneMethod(ok, self.__downloadFileName)
def redo(self): redo = QFile(self.redoFilename) if redo.exists(): dest = QFile(self.filename) if dest.exists(): dest.remove() QFile.copy(self.redoFilename, self.filename) self.editor.load() else: QFile.copy(self.filename, self.undoFilename) self.editor.save() QFile.copy(self.filename, self.redoFilename)
def __rulesDownloaded(self): """ Private slot to deal with the downloaded rules. """ reply = self.sender() response = reply.readAll() reply.close() self.__downloading = None if reply.error() != QNetworkReply.NoError: if not self.__defaultSubscription: # don't show error if we try to load the default E5MessageBox.warning( None, self.tr("Downloading subscription rules"), self.tr( """<p>Subscription rules could not be""" """ downloaded.</p><p>Error: {0}</p>""") .format(reply.errorString())) else: # reset after first download attempt self.__defaultSubscription = False return if response.isEmpty(): E5MessageBox.warning( None, self.tr("Downloading subscription rules"), self.tr("""Got empty subscription rules.""")) return fileName = self.rulesFileName() QFile.remove(fileName) f = QFile(fileName) if not f.open(QIODevice.ReadWrite): E5MessageBox.warning( None, self.tr("Downloading subscription rules"), self.tr( """Unable to open adblock file '{0}' for writing.""") .file(fileName)) return f.write(response) f.close() self.__lastUpdate = QDateTime.currentDateTime() if self.__validateCheckSum(fileName): self.__loadRules() else: QFile.remove(fileName) self.__downloading = None reply.deleteLater()
def exportHistory(self): result = QFileDialog.getSaveFileName( parent=None, caption="Экспорт истории", directory='../ExportedHistories/', filter='Файлы настроек (*.conf)\nВсе файлы (*)', options=QFileDialog.DontUseNativeDialog)[0] if QFile.exists(result): QFile.remove(result) self.dataHistory = QSettings(result, QSettings.IniFormat) for i in self.history: self.dataHistory.setValue(str(i), self.history[i]) self.dataHistory = QSettings(self.pathDataHistory, QSettings.IniFormat)
def mpegtsJoin(self, inputs: list, output: str) -> bool: result = False try: self.checkDiskSpace(output) outfiles = list() video_bsf, audio_bsf = self.getBSF(inputs[0]) # 1. transcode to mpeg transport streams for file in inputs: name, _ = os.path.splitext(file) outfile = '%s.ts' % name outfiles.append(outfile) if os.path.isfile(outfile): os.remove(outfile) args = '-i "%s" -c copy -map 0 %s -f mpegts -v 16 "%s"' % ( file, video_bsf, outfile) if not self.cmdExec(self.backend, args): return result # 2. losslessly concatenate at the file level if len(outfiles): if os.path.isfile(output): os.remove(output) args = '-i "concat:%s" -c copy %s -v 16 "%s"' % ( '|'.join(map(str, outfiles)), audio_bsf, QDir.fromNativeSeparators(output)) result = self.cmdExec(self.backend, args) # 3. cleanup mpegts files [QFile.remove(file) for file in outfiles] except: self.logger.exception('Exception in VideoService.mpegtsJoin()', exc_info=True) result = False return result
def configure(self): data = "database_name: " + self.dbName.text() data += "\ndatabase_username: "******"\ndatabase_password: "******"\ndatabase_hostname: " + self.hostname.text() data += "\ndatabase_port: " + self.port.text() f = QFile("config/database.config") f.remove("config/database.config") if f.open(QIODevice.ReadWrite | QIODevice.Text): stream = QTextStream(f) stream << data f.close() self.close()
def copy_dir_recursive(from_dir, to_dir, replace_on_conflict=False): dir = QDir() dir.setPath(from_dir) from_dir += QDir.separator() to_dir += QDir.separator() if not os.path.exists(to_dir): os.makedirs(to_dir) for file_ in dir.entryList(QDir.Files): from_ = from_dir + file_ to_ = to_dir + file_ if os.path.exists(to_): if replace_on_conflict: if not QFile.remove(to): return False else: continue if not QFile.copy(from_, to_): return False for dir_ in dir.entryList(QDir.Dirs | QDir.NoDotAndDotDot): from_ = from_dir + dir_ to_ = to_dir + dir_ if not os.path.exists(to_): os.makedirs(to_) if not copy_dir_recursive(from_, to_, replace_on_conflict): return False return True
def __rulesDownloaded(self): """ Private slot to deal with the downloaded rules. """ reply = self.sender() response = reply.readAll() reply.close() self.__downloading = None if reply.error() != QNetworkReply.NoError: if not self.__defaultSubscription: # don't show error if we try to load the default E5MessageBox.warning( None, self.tr("Downloading subscription rules"), self.tr("""<p>Subscription rules could not be""" """ downloaded.</p><p>Error: {0}</p>""").format( reply.errorString())) else: # reset after first download attempt self.__defaultSubscription = False return if response.isEmpty(): E5MessageBox.warning(None, self.tr("Downloading subscription rules"), self.tr("""Got empty subscription rules.""")) return fileName = self.rulesFileName() QFile.remove(fileName) f = QFile(fileName) if not f.open(QIODevice.ReadWrite): E5MessageBox.warning( None, self.tr("Downloading subscription rules"), self.tr("""Unable to open adblock file '{0}' for writing."""). file(fileName)) return f.write(response) f.close() self.__lastUpdate = QDateTime.currentDateTime() if self.__validateCheckSum(fileName): self.__loadRules() else: QFile.remove(fileName) self.__downloading = None reply.deleteLater()
def removeFromDriveByUrl(self, url, actionType="removeSongByUrl"): ''' remove song from Drive by url ''' df = QFile(url) flag = df.remove() if flag: self.removeFromDatabaseByUrl(url, actionType)
def cutVideo(self) -> bool: self.setCursor(Qt.BusyCursor) clips = len(self.clipTimes) filename, filelist = '', [] source = self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile() _, sourceext = os.path.splitext(source) if clips > 0: self.finalFilename, _ = QFileDialog.getSaveFileName( self.parent, 'Save video', source, 'Video files (*%s)' % sourceext) if self.finalFilename != '': self.saveAction.setDisabled(True) self.showProgress(clips) file, ext = os.path.splitext(self.finalFilename) index = 1 self.progress.setLabelText('Cutting video clips...') qApp.processEvents() for clip in self.clipTimes: duration = self.deltaToQTime(clip[0].msecsTo( clip[1])).toString(self.timeformat) filename = '%s_%s%s' % (file, '{0:0>2}'.format(index), ext) filelist.append(filename) self.videoService.cut(source, filename, clip[0].toString(self.timeformat), duration) index += 1 if len(filelist) > 1: self.joinVideos(filelist, self.finalFilename) else: QFile.remove(self.finalFilename) QFile.rename(filename, self.finalFilename) self.unsetCursor() self.progress.setLabelText('Complete...') qApp.processEvents() self.saveAction.setEnabled(True) self.progress.close() self.progress.deleteLater() self.complete() self.saveAction.setEnabled(True) self.unsetCursor() self.saveAction.setDisabled(True) return True self.unsetCursor() self.saveAction.setDisabled(True) return False
def deleteFile(self): index = self.selectionModel().currentIndex() path = self.model.filePath(index) if path: fileInfo = QFileInfo(path) if fileInfo.isFile(): if not self.ask_dialog( "Do you wan't to delete the selected file?"): return file = QFile(path) file.remove() elif fileInfo.isDir(): if not self.ask_dialog( "Do you wan't to delete the selected directory?"): return directory = QDir(path) directory.removeRecursively()
def copyFile(source, dest, overwrite=False): if os.path.exists(dest): if overwrite or abs(QFileInfo(source).lastModified().secsTo(QFileInfo(dest).lastModified())) > 5: # use secsTo for different file systems if DEBUG_MODE: qDebug("Existing file removed: %s (%s, %s)" % (dest, str(QFileInfo(source).lastModified()), str(QFileInfo(dest).lastModified()))) QFile.remove(dest) else: if DEBUG_MODE: qDebug("File already exists: %s" % dest) return False ret = QFile.copy(source, dest) if DEBUG_MODE: if ret: qDebug("File copied: %s to %s" % (source, dest)) else: qDebug("Failed to copy file: %s to %s" % (source, dest)) return ret
def copy_dir_recursive(from_dir, to_dir, replace_on_conflict=False): dir = QDir() dir.setPath(from_dir) from_dir += QDir.separator() to_dir += QDir.separator() if not os.path.exists(to_dir): os.makedirs(to_dir) for file_ in dir.entryList(QDir.Files): from_ = from_dir + file_ to_ = to_dir + file_ if str(to_).endswith(".src"): to_ = str(to_).replace(".src", "") if os.path.exists(to_): if replace_on_conflict: if not QFile.remove(to_): return False else: continue if not QFile.copy(from_, to_): return False for dir_ in dir.entryList(QDir.Dirs | QDir.NoDotAndDotDot): from_ = from_dir + dir_ to_ = to_dir + dir_ if not os.path.exists(to_): os.makedirs(to_) if not copy_dir_recursive(from_, to_, replace_on_conflict): return False return True
class HttpWindow(QDialog): def __init__(self, parent=None): super(HttpWindow, self).__init__(parent) self.url = QUrl() self.qnam = QNetworkAccessManager() self.reply = None self.outFile = None self.httpGetId = 0 self.httpRequestAborted = False self.urlLineEdit = QLineEdit('https://www.qt.io') urlLabel = QLabel("&URL:") urlLabel.setBuddy(self.urlLineEdit) self.statusLabel = QLabel( "Please enter the URL of a file you want to download.") self.statusLabel.setWordWrap(True) self.downloadButton = QPushButton("Download") self.downloadButton.setDefault(True) self.quitButton = QPushButton("Quit") self.quitButton.setAutoDefault(False) buttonBox = QDialogButtonBox() buttonBox.addButton(self.downloadButton, QDialogButtonBox.ActionRole) buttonBox.addButton(self.quitButton, QDialogButtonBox.RejectRole) self.progressDialog = QProgressDialog(self) self.urlLineEdit.textChanged.connect(self.enableDownloadButton) self.qnam.authenticationRequired.connect( self.slotAuthenticationRequired) self.qnam.sslErrors.connect(self.sslErrors) self.progressDialog.canceled.connect(self.cancelDownload) self.downloadButton.clicked.connect(self.downloadFile) self.quitButton.clicked.connect(self.close) topLayout = QHBoxLayout() topLayout.addWidget(urlLabel) topLayout.addWidget(self.urlLineEdit) mainLayout = QVBoxLayout() mainLayout.addLayout(topLayout) mainLayout.addWidget(self.statusLabel) mainLayout.addWidget(buttonBox) self.setLayout(mainLayout) self.setWindowTitle("HTTP") self.urlLineEdit.setFocus() def startRequest(self, url): self.reply = self.qnam.get(QNetworkRequest(url)) self.reply.finished.connect(self.httpFinished) self.reply.readyRead.connect(self.httpReadyRead) self.reply.downloadProgress.connect(self.updateDataReadProgress) def downloadFile(self): self.url = QUrl(self.urlLineEdit.text()) fileInfo = QFileInfo(self.url.path()) fileName = fileInfo.fileName() if not fileName: fileName = 'index.html' if QFile.exists(fileName): ret = QMessageBox.question(self, "HTTP", "There already exists a file called %s in the current " "directory. Overwrite?" % fileName, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if ret == QMessageBox.No: return QFile.remove(fileName) self.outFile = QFile(fileName) if not self.outFile.open(QIODevice.WriteOnly): QMessageBox.information(self, "HTTP", "Unable to save the file %s: %s." % (fileName, self.outFile.errorString())) self.outFile = None return self.progressDialog.setWindowTitle("HTTP") self.progressDialog.setLabelText("Downloading %s." % fileName) self.downloadButton.setEnabled(False) self.httpRequestAborted = False self.startRequest(self.url) def cancelDownload(self): self.statusLabel.setText("Download canceled.") self.httpRequestAborted = True if self.reply is not None: self.reply.abort() self.downloadButton.setEnabled(True) def httpFinished(self): if self.httpRequestAborted: if self.outFile is not None: self.outFile.close() self.outFile.remove() self.outFile = None self.reply.deleteLater() self.reply = None self.progressDialog.hide() return self.progressDialog.hide() self.outFile.flush() self.outFile.close() redirectionTarget = self.reply.attribute(QNetworkRequest.RedirectionTargetAttribute) if self.reply.error(): self.outFile.remove() QMessageBox.information(self, "HTTP", "Download failed: %s." % self.reply.errorString()) self.downloadButton.setEnabled(True) elif redirectionTarget is not None: newUrl = self.url.resolved(redirectionTarget) ret = QMessageBox.question(self, "HTTP", "Redirect to %s?" % newUrl.toString(), QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.Yes: self.url = newUrl self.reply.deleteLater() self.reply = None self.outFile.open(QIODevice.WriteOnly) self.outFile.resize(0) self.startRequest(self.url) return else: fileName = QFileInfo(QUrl(self.urlLineEdit.text()).path()).fileName() self.statusLabel.setText("Downloaded %s to %s." % (fileName, QDir.currentPath())) self.downloadButton.setEnabled(True) self.reply.deleteLater() self.reply = None self.outFile = None def httpReadyRead(self): if self.outFile is not None: self.outFile.write(self.reply.readAll()) def updateDataReadProgress(self, bytesRead, totalBytes): if self.httpRequestAborted: return self.progressDialog.setMaximum(totalBytes) self.progressDialog.setValue(bytesRead) def enableDownloadButton(self): self.downloadButton.setEnabled(self.urlLineEdit.text() != '') def slotAuthenticationRequired(self, authenticator): import os from PyQt5 import uic ui = os.path.join(os.path.dirname(__file__), 'authenticationdialog.ui') dlg = uic.loadUi(ui) dlg.adjustSize() dlg.siteDescription.setText("%s at %s" % (authenticator.realm(), self.url.host())) dlg.userEdit.setText(self.url.userName()) dlg.passwordEdit.setText(self.url.password()) if dlg.exec_() == QDialog.Accepted: authenticator.setUser(dlg.userEdit.text()) authenticator.setPassword(dlg.passwordEdit.text()) def sslErrors(self, reply, errors): errorString = ", ".join([str(error.errorString()) for error in errors]) ret = QMessageBox.warning(self, "HTTP Example", "One or more SSL errors has occurred: %s" % errorString, QMessageBox.Ignore | QMessageBox.Abort) if ret == QMessageBox.Ignore: self.reply.ignoreSslErrors()
def build(self, opt, nr_resources, build_dir=None, clean=False): """ Build the project in a given directory. Raise a UserException if there is an error. """ project = self._project # Create a temporary directory which will be removed automatically when # this function's objects are garbage collected. temp_dir = QTemporaryDir() if not temp_dir.isValid(): raise UserException( "There was an error creating a temporary directory") # Get the names of the required Python modules, extension modules and # libraries. metadata = get_python_metadata(project.python_target_version) required_modules, required_libraries = project.get_stdlib_requirements( include_hidden=True) required_py = {} required_ext = {} for name in required_modules.keys(): module = metadata[name] if module.source is None: required_py[name] = module elif not module.core: required_ext[name] = module # Initialise and check we have the information we need. if len(required_py) != 0 or len(required_ext) != 0: if project.python_source_dir == '': raise UserException( "The name of the Python source directory has not been " "specified") if project.get_executable_basename() == '': raise UserException("The name of the application has not been " "specified and cannot be inferred") if project.application_script == '': if project.application_entry_point == '': raise UserException("Either the application script name or " "the entry point must be specified") elif len(project.application_entry_point.split(':')) != 2: raise UserException("An entry point must be a module name and " "a callable separated by a colon.") elif project.application_entry_point != '': raise UserException("Either the application script name or the " "entry point must be specified but not both") # Get the name of the build directory. if build_dir is None: build_dir = project.build_dir if build_dir == '': build_dir = '.' build_dir = project.path_from_user(build_dir) # Remove any build directory if required. if clean: native_build_dir = QDir.toNativeSeparators(build_dir) self._message_handler.progress_message( "Cleaning {0}".format(native_build_dir)) shutil.rmtree(native_build_dir, ignore_errors=True) # Now start the build. self._create_directory(build_dir) # Create the job file and writer. job_filename = QDir.toNativeSeparators(temp_dir.path() + '/jobs.csv') job_file = open(job_filename, 'w', newline='') job_writer = csv.writer(job_file) # Freeze the bootstrap. py_major, py_minor, py_patch = project.python_target_version py_version = (py_major << 16) + (py_minor << 8) + py_patch bootstrap_src = get_embedded_file_for_version(py_version, __file__, 'lib', 'bootstrap') bootstrap = self._copy_lib_file(bootstrap_src, temp_dir.path(), dst_file_name='bootstrap.py') self._freeze(job_writer, build_dir + '/frozen_bootstrap.h', bootstrap, 'pyqtdeploy_bootstrap', as_c=True) # Freeze any main application script. if project.application_script != '': self._freeze(job_writer, build_dir + '/frozen_main.h', project.path_from_user(project.application_script), 'pyqtdeploy_main', as_c=True) # Create the pyqtdeploy module version file. version_f = self._create_file(build_dir + '/pyqtdeploy_version.h') version_f.write( '#define PYQTDEPLOY_HEXVERSION %s\n' % hex( PYQTDEPLOY_HEXVERSION)) version_f.close() # Generate the application resource. resource_names = self._generate_resource(build_dir + '/resources', required_py, job_writer, nr_resources) # Write the .pro file. self._write_qmake(build_dir, required_ext, required_libraries, job_writer, opt, resource_names) # Run the freeze jobs. job_file.close() # The odd naming of Python source files is to prevent them from being # frozen if we deploy ourself. freeze = self._copy_lib_file(self._get_lib_file_name('freeze.python'), temp_dir.path(), dst_file_name='freeze.py') self._run_freeze(freeze, job_filename, opt) # Remove the contents of the temporary directory. QFile.remove(freeze) QFile.remove(bootstrap) QFile.remove(job_filename)
def deleteStamp(self, stamp): self.mStampsByName.remove(stamp.name()) QFile.remove(stampFilePath(stamp.fileName()))
class PluginRepositoryWidget(QWidget, Ui_PluginRepositoryDialog): """ Class implementing a dialog showing the available plugins. @signal closeAndInstall() emitted when the Close & Install button is pressed """ closeAndInstall = pyqtSignal() DescrRole = Qt.UserRole UrlRole = Qt.UserRole + 1 FilenameRole = Qt.UserRole + 2 AuthorRole = Qt.UserRole + 3 PluginStatusUpToDate = 0 PluginStatusNew = 1 PluginStatusLocalUpdate = 2 PluginStatusRemoteUpdate = 3 def __init__(self, parent=None, external=False): """ Constructor @param parent parent of this dialog (QWidget) @param external flag indicating an instatiation as a main window (boolean) """ super(PluginRepositoryWidget, self).__init__(parent) self.setupUi(self) self.__updateButton = self.buttonBox.addButton( self.tr("Update"), QDialogButtonBox.ActionRole) self.__downloadButton = self.buttonBox.addButton( self.tr("Download"), QDialogButtonBox.ActionRole) self.__downloadButton.setEnabled(False) self.__downloadInstallButton = self.buttonBox.addButton( self.tr("Download && Install"), QDialogButtonBox.ActionRole) self.__downloadInstallButton.setEnabled(False) self.__downloadCancelButton = self.buttonBox.addButton( self.tr("Cancel"), QDialogButtonBox.ActionRole) self.__installButton = \ self.buttonBox.addButton(self.tr("Close && Install"), QDialogButtonBox.ActionRole) self.__downloadCancelButton.setEnabled(False) self.__installButton.setEnabled(False) self.repositoryUrlEdit.setText( Preferences.getUI("PluginRepositoryUrl6")) self.repositoryList.headerItem().setText( self.repositoryList.columnCount(), "") self.repositoryList.header().setSortIndicator(0, Qt.AscendingOrder) self.__pluginContextMenu = QMenu(self) self.__hideAct = self.__pluginContextMenu.addAction( self.tr("Hide"), self.__hidePlugin) self.__hideSelectedAct = self.__pluginContextMenu.addAction( self.tr("Hide Selected"), self.__hideSelectedPlugins) self.__pluginContextMenu.addSeparator() self.__showAllAct = self.__pluginContextMenu.addAction( self.tr("Show All"), self.__showAllPlugins) self.__pluginContextMenu.addSeparator() self.__pluginContextMenu.addAction( self.tr("Cleanup Downloads"), self.__cleanupDownloads) self.pluginRepositoryFile = \ os.path.join(Utilities.getConfigDir(), "PluginRepository") self.__external = external # attributes for the network objects self.__networkManager = QNetworkAccessManager(self) self.__networkManager.proxyAuthenticationRequired.connect( proxyAuthenticationRequired) if SSL_AVAILABLE: self.__sslErrorHandler = E5SslErrorHandler(self) self.__networkManager.sslErrors.connect(self.__sslErrors) self.__replies = [] self.__networkConfigurationManager = QNetworkConfigurationManager(self) self.__onlineStateChanged( self.__networkConfigurationManager.isOnline()) self.__networkConfigurationManager.onlineStateChanged.connect( self.__onlineStateChanged) self.__doneMethod = None self.__inDownload = False self.__pluginsToDownload = [] self.__pluginsDownloaded = [] self.__isDownloadInstall = False self.__allDownloadedOk = False self.__hiddenPlugins = Preferences.getPluginManager("HiddenPlugins") self.__populateList() @pyqtSlot(bool) def __onlineStateChanged(self, online): """ Private slot handling online state changes. @param online flag indicating the online status @type bool """ self.__updateButton.setEnabled(online) self.on_repositoryList_itemSelectionChanged() if online: msg = self.tr("Network Status: online") else: msg = self.tr("Network Status: offline") self.statusLabel.setText(msg) @pyqtSlot(QAbstractButton) def on_buttonBox_clicked(self, button): """ Private slot to handle the click of a button of the button box. @param button reference to the button pressed (QAbstractButton) """ if button == self.__updateButton: self.__updateList() elif button == self.__downloadButton: self.__isDownloadInstall = False self.__downloadPlugins() elif button == self.__downloadInstallButton: self.__isDownloadInstall = True self.__allDownloadedOk = True self.__downloadPlugins() elif button == self.__downloadCancelButton: self.__downloadCancel() elif button == self.__installButton: self.__closeAndInstall() def __formatDescription(self, lines): """ Private method to format the description. @param lines lines of the description (list of strings) @return formatted description (string) """ # remove empty line at start and end newlines = lines[:] if len(newlines) and newlines[0] == '': del newlines[0] if len(newlines) and newlines[-1] == '': del newlines[-1] # replace empty lines by newline character index = 0 while index < len(newlines): if newlines[index] == '': newlines[index] = '\n' index += 1 # join lines by a blank return ' '.join(newlines) @pyqtSlot(QPoint) def on_repositoryList_customContextMenuRequested(self, pos): """ Private slot to show the context menu. @param pos position to show the menu (QPoint) """ self.__hideAct.setEnabled( self.repositoryList.currentItem() is not None and len(self.__selectedItems()) == 1) self.__hideSelectedAct.setEnabled( len(self.__selectedItems()) > 1) self.__showAllAct.setEnabled(bool(self.__hasHiddenPlugins())) self.__pluginContextMenu.popup(self.repositoryList.mapToGlobal(pos)) @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) def on_repositoryList_currentItemChanged(self, current, previous): """ Private slot to handle the change of the current item. @param current reference to the new current item (QTreeWidgetItem) @param previous reference to the old current item (QTreeWidgetItem) """ if self.__repositoryMissing or current is None: return self.urlEdit.setText( current.data(0, PluginRepositoryWidget.UrlRole) or "") self.descriptionEdit.setPlainText( current.data(0, PluginRepositoryWidget.DescrRole) and self.__formatDescription( current.data(0, PluginRepositoryWidget.DescrRole)) or "") self.authorEdit.setText( current.data(0, PluginRepositoryWidget.AuthorRole) or "") def __selectedItems(self): """ Private method to get all selected items without the toplevel ones. @return list of selected items (list) """ ql = self.repositoryList.selectedItems() for index in range(self.repositoryList.topLevelItemCount()): ti = self.repositoryList.topLevelItem(index) if ti in ql: ql.remove(ti) return ql @pyqtSlot() def on_repositoryList_itemSelectionChanged(self): """ Private slot to handle a change of the selection. """ self.__downloadButton.setEnabled( len(self.__selectedItems()) and self.__networkConfigurationManager.isOnline()) self.__downloadInstallButton.setEnabled( len(self.__selectedItems()) and self.__networkConfigurationManager.isOnline()) self.__installButton.setEnabled(len(self.__selectedItems())) def __updateList(self): """ Private slot to download a new list and display the contents. """ url = self.repositoryUrlEdit.text() self.__downloadFile(url, self.pluginRepositoryFile, self.__downloadRepositoryFileDone) def __downloadRepositoryFileDone(self, status, filename): """ Private method called after the repository file was downloaded. @param status flaging indicating a successful download (boolean) @param filename full path of the downloaded file (string) """ self.__populateList() def __downloadPluginDone(self, status, filename): """ Private method called, when the download of a plugin is finished. @param status flag indicating a successful download (boolean) @param filename full path of the downloaded file (string) """ if status: self.__pluginsDownloaded.append(filename) if self.__isDownloadInstall: self.__allDownloadedOk &= status del self.__pluginsToDownload[0] if len(self.__pluginsToDownload): self.__downloadPlugin() else: self.__downloadPluginsDone() def __downloadPlugin(self): """ Private method to download the next plugin. """ self.__downloadFile(self.__pluginsToDownload[0][0], self.__pluginsToDownload[0][1], self.__downloadPluginDone) def __downloadPlugins(self): """ Private slot to download the selected plugins. """ self.__pluginsDownloaded = [] self.__pluginsToDownload = [] self.__downloadButton.setEnabled(False) self.__downloadInstallButton.setEnabled(False) self.__installButton.setEnabled(False) for itm in self.repositoryList.selectedItems(): if itm not in [self.__stableItem, self.__unstableItem, self.__unknownItem]: url = itm.data(0, PluginRepositoryWidget.UrlRole) filename = os.path.join( Preferences.getPluginManager("DownloadPath"), itm.data(0, PluginRepositoryWidget.FilenameRole)) self.__pluginsToDownload.append((url, filename)) self.__downloadPlugin() def __downloadPluginsDone(self): """ Private method called, when the download of the plugins is finished. """ self.__downloadButton.setEnabled(len(self.__selectedItems())) self.__downloadInstallButton.setEnabled(len(self.__selectedItems())) self.__installButton.setEnabled(True) self.__doneMethod = None if not self.__external: ui = e5App().getObject("UserInterface") else: ui = None if ui and ui.notificationsEnabled(): ui.showNotification( UI.PixmapCache.getPixmap("plugin48.png"), self.tr("Download Plugin Files"), self.tr("""The requested plugins were downloaded.""")) if self.__isDownloadInstall: self.closeAndInstall.emit() else: if ui is None or not ui.notificationsEnabled(): E5MessageBox.information( self, self.tr("Download Plugin Files"), self.tr("""The requested plugins were downloaded.""")) self.downloadProgress.setValue(0) # repopulate the list to update the refresh icons self.__populateList() def __resortRepositoryList(self): """ Private method to resort the tree. """ self.repositoryList.sortItems( self.repositoryList.sortColumn(), self.repositoryList.header().sortIndicatorOrder()) def __populateList(self): """ Private method to populate the list of available plugins. """ self.repositoryList.clear() self.__stableItem = None self.__unstableItem = None self.__unknownItem = None self.downloadProgress.setValue(0) self.__doneMethod = None if os.path.exists(self.pluginRepositoryFile): self.__repositoryMissing = False f = QFile(self.pluginRepositoryFile) if f.open(QIODevice.ReadOnly): from E5XML.PluginRepositoryReader import PluginRepositoryReader reader = PluginRepositoryReader(f, self.addEntry) reader.readXML() self.repositoryList.resizeColumnToContents(0) self.repositoryList.resizeColumnToContents(1) self.repositoryList.resizeColumnToContents(2) self.__resortRepositoryList() url = Preferences.getUI("PluginRepositoryUrl6") if url != self.repositoryUrlEdit.text(): self.repositoryUrlEdit.setText(url) E5MessageBox.warning( self, self.tr("Plugins Repository URL Changed"), self.tr( """The URL of the Plugins Repository has""" """ changed. Select the "Update" button to get""" """ the new repository file.""")) else: E5MessageBox.critical( self, self.tr("Read plugins repository file"), self.tr("<p>The plugins repository file <b>{0}</b> " "could not be read. Select Update</p>") .format(self.pluginRepositoryFile)) else: self.__repositoryMissing = True QTreeWidgetItem( self.repositoryList, ["", self.tr( "No plugin repository file available.\nSelect Update.") ]) self.repositoryList.resizeColumnToContents(1) def __downloadFile(self, url, filename, doneMethod=None): """ Private slot to download the given file. @param url URL for the download (string) @param filename local name of the file (string) @param doneMethod method to be called when done """ if self.__networkConfigurationManager.isOnline(): self.__updateButton.setEnabled(False) self.__downloadButton.setEnabled(False) self.__downloadInstallButton.setEnabled(False) self.__downloadCancelButton.setEnabled(True) self.statusLabel.setText(url) self.__doneMethod = doneMethod self.__downloadURL = url self.__downloadFileName = filename self.__downloadIODevice = QFile(self.__downloadFileName + ".tmp") self.__downloadCancelled = False request = QNetworkRequest(QUrl(url)) request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.AlwaysNetwork) reply = self.__networkManager.get(request) reply.finished.connect(self.__downloadFileDone) reply.downloadProgress.connect(self.__downloadProgress) self.__replies.append(reply) else: E5MessageBox.warning( self, self.tr("Error downloading file"), self.tr( """<p>Could not download the requested file""" """ from {0}.</p><p>Error: {1}</p>""" ).format(url, self.tr("Computer is offline."))) def __downloadFileDone(self): """ Private method called, after the file has been downloaded from the internet. """ self.__updateButton.setEnabled(True) self.__downloadCancelButton.setEnabled(False) self.__onlineStateChanged( self.__networkConfigurationManager.isOnline()) ok = True reply = self.sender() if reply in self.__replies: self.__replies.remove(reply) if reply.error() != QNetworkReply.NoError: ok = False if not self.__downloadCancelled: E5MessageBox.warning( self, self.tr("Error downloading file"), self.tr( """<p>Could not download the requested file""" """ from {0}.</p><p>Error: {1}</p>""" ).format(self.__downloadURL, reply.errorString()) ) self.downloadProgress.setValue(0) self.__downloadURL = None self.__downloadIODevice.remove() self.__downloadIODevice = None if self.repositoryList.topLevelItemCount(): if self.repositoryList.currentItem() is None: self.repositoryList.setCurrentItem( self.repositoryList.topLevelItem(0)) else: self.__downloadButton.setEnabled( len(self.__selectedItems())) self.__downloadInstallButton.setEnabled( len(self.__selectedItems())) reply.deleteLater() return self.__downloadIODevice.open(QIODevice.WriteOnly) self.__downloadIODevice.write(reply.readAll()) self.__downloadIODevice.close() if QFile.exists(self.__downloadFileName): QFile.remove(self.__downloadFileName) self.__downloadIODevice.rename(self.__downloadFileName) self.__downloadIODevice = None self.__downloadURL = None reply.deleteLater() if self.__doneMethod is not None: self.__doneMethod(ok, self.__downloadFileName) def __downloadCancel(self): """ Private slot to cancel the current download. """ if self.__replies: reply = self.__replies[0] self.__downloadCancelled = True self.__pluginsToDownload = [] reply.abort() def __downloadProgress(self, done, total): """ Private slot to show the download progress. @param done number of bytes downloaded so far (integer) @param total total bytes to be downloaded (integer) """ if total: self.downloadProgress.setMaximum(total) self.downloadProgress.setValue(done) def addEntry(self, name, short, description, url, author, version, filename, status): """ Public method to add an entry to the list. @param name data for the name field (string) @param short data for the short field (string) @param description data for the description field (list of strings) @param url data for the url field (string) @param author data for the author field (string) @param version data for the version field (string) @param filename data for the filename field (string) @param status status of the plugin (string [stable, unstable, unknown]) """ pluginName = filename.rsplit("-", 1)[0] if pluginName in self.__hiddenPlugins: return if status == "stable": if self.__stableItem is None: self.__stableItem = \ QTreeWidgetItem(self.repositoryList, [self.tr("Stable")]) self.__stableItem.setExpanded(True) parent = self.__stableItem elif status == "unstable": if self.__unstableItem is None: self.__unstableItem = \ QTreeWidgetItem(self.repositoryList, [self.tr("Unstable")]) self.__unstableItem.setExpanded(True) parent = self.__unstableItem else: if self.__unknownItem is None: self.__unknownItem = \ QTreeWidgetItem(self.repositoryList, [self.tr("Unknown")]) self.__unknownItem.setExpanded(True) parent = self.__unknownItem itm = QTreeWidgetItem(parent, [name, version, short]) itm.setData(0, PluginRepositoryWidget.UrlRole, url) itm.setData(0, PluginRepositoryWidget.FilenameRole, filename) itm.setData(0, PluginRepositoryWidget.AuthorRole, author) itm.setData(0, PluginRepositoryWidget.DescrRole, description) updateStatus = self.__updateStatus(filename, version) if updateStatus == PluginRepositoryWidget.PluginStatusUpToDate: itm.setIcon(1, UI.PixmapCache.getIcon("empty.png")) itm.setToolTip(1, self.tr("up-to-date")) elif updateStatus == PluginRepositoryWidget.PluginStatusNew: itm.setIcon(1, UI.PixmapCache.getIcon("download.png")) itm.setToolTip(1, self.tr("new download available")) elif updateStatus == PluginRepositoryWidget.PluginStatusLocalUpdate: itm.setIcon(1, UI.PixmapCache.getIcon("updateLocal.png")) itm.setToolTip(1, self.tr("update installable")) elif updateStatus == PluginRepositoryWidget.PluginStatusRemoteUpdate: itm.setIcon(1, UI.PixmapCache.getIcon("updateRemote.png")) itm.setToolTip(1, self.tr("updated download available")) def __updateStatus(self, filename, version): """ Private method to check, if the given archive update status. @param filename data for the filename field (string) @param version data for the version field (string) @return plug-in update status (integer, one of PluginStatusNew, PluginStatusUpToDate, PluginStatusLocalUpdate, PluginStatusRemoteUpdate) """ archive = os.path.join(Preferences.getPluginManager("DownloadPath"), filename) # check, if it is an update (i.e. we already have archives # with the same pattern) archivesPattern = archive.rsplit('-', 1)[0] + "-*.zip" if len(glob.glob(archivesPattern)) == 0: return PluginRepositoryWidget.PluginStatusNew # check, if the archive exists if not os.path.exists(archive): return PluginRepositoryWidget.PluginStatusRemoteUpdate # check, if the archive is a valid zip file if not zipfile.is_zipfile(archive): return PluginRepositoryWidget.PluginStatusRemoteUpdate zip = zipfile.ZipFile(archive, "r") try: aversion = zip.read("VERSION").decode("utf-8") except KeyError: aversion = "" zip.close() if aversion == version: if not self.__external: # Check against installed/loaded plug-ins pluginManager = e5App().getObject("PluginManager") pluginName = filename.rsplit('-', 1)[0] pluginDetails = pluginManager.getPluginDetails(pluginName) if pluginDetails is None or pluginDetails["version"] < version: return PluginRepositoryWidget.PluginStatusLocalUpdate return PluginRepositoryWidget.PluginStatusUpToDate else: return PluginRepositoryWidget.PluginStatusRemoteUpdate def __sslErrors(self, reply, errors): """ Private slot to handle SSL errors. @param reply reference to the reply object (QNetworkReply) @param errors list of SSL errors (list of QSslError) """ ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0] if ignored == E5SslErrorHandler.NotIgnored: self.__downloadCancelled = True def getDownloadedPlugins(self): """ Public method to get the list of recently downloaded plugin files. @return list of plugin filenames (list of strings) """ return self.__pluginsDownloaded @pyqtSlot(bool) def on_repositoryUrlEditButton_toggled(self, checked): """ Private slot to set the read only status of the repository URL line edit. @param checked state of the push button (boolean) """ self.repositoryUrlEdit.setReadOnly(not checked) def __closeAndInstall(self): """ Private method to close the dialog and invoke the install dialog. """ if not self.__pluginsDownloaded and self.__selectedItems(): for itm in self.__selectedItems(): filename = os.path.join( Preferences.getPluginManager("DownloadPath"), itm.data(0, PluginRepositoryWidget.FilenameRole)) self.__pluginsDownloaded.append(filename) self.closeAndInstall.emit() def __hidePlugin(self): """ Private slot to hide the current plug-in. """ itm = self.__selectedItems()[0] pluginName = (itm.data(0, PluginRepositoryWidget.FilenameRole) .rsplit("-", 1)[0]) self.__updateHiddenPluginsList([pluginName]) def __hideSelectedPlugins(self): """ Private slot to hide all selected plug-ins. """ hideList = [] for itm in self.__selectedItems(): pluginName = (itm.data(0, PluginRepositoryWidget.FilenameRole) .rsplit("-", 1)[0]) hideList.append(pluginName) self.__updateHiddenPluginsList(hideList) def __showAllPlugins(self): """ Private slot to show all plug-ins. """ self.__hiddenPlugins = [] self.__updateHiddenPluginsList([]) def __hasHiddenPlugins(self): """ Private method to check, if there are any hidden plug-ins. @return flag indicating the presence of hidden plug-ins (boolean) """ return bool(self.__hiddenPlugins) def __updateHiddenPluginsList(self, hideList): """ Private method to store the list of hidden plug-ins to the settings. @param hideList list of plug-ins to add to the list of hidden ones (list of string) """ if hideList: self.__hiddenPlugins.extend( [p for p in hideList if p not in self.__hiddenPlugins]) Preferences.setPluginManager("HiddenPlugins", self.__hiddenPlugins) self.__populateList() def __cleanupDownloads(self): """ Private slot to cleanup the plug-in downloads area. """ downloadPath = Preferences.getPluginManager("DownloadPath") downloads = {} # plug-in name as key, file name as value # step 1: extract plug-ins and downloaded files for pluginFile in os.listdir(downloadPath): if not os.path.isfile(os.path.join(downloadPath, pluginFile)): continue pluginName = pluginFile.rsplit("-", 1)[0] if pluginName not in downloads: downloads[pluginName] = [] downloads[pluginName].append(pluginFile) # step 2: delete old entries for pluginName in downloads: downloads[pluginName].sort() if pluginName in self.__hiddenPlugins and \ not Preferences.getPluginManager("KeepHidden"): removeFiles = downloads[pluginName] else: removeFiles = downloads[pluginName][ :-Preferences.getPluginManager("KeepGenerations")] for removeFile in removeFiles: try: os.remove(os.path.join(downloadPath, removeFile)) except (IOError, OSError) as err: E5MessageBox.critical( self, self.tr("Cleanup of Plugin Downloads"), self.tr("""<p>The plugin download <b>{0}</b> could""" """ not be deleted.</p><p>Reason: {1}</p>""") .format(removeFile, str(err)))
def save(self): """ Public slot to save the history entries to disk. """ historyFile = QFile(self.getFileName()) if not historyFile.exists(): self.__lastSavedUrl = "" saveAll = self.__lastSavedUrl == "" first = len(self.__history) - 1 if not saveAll: # find the first one to save for index in range(len(self.__history)): if self.__history[index].url == self.__lastSavedUrl: first = index - 1 break if first == len(self.__history) - 1: saveAll = True if saveAll: # use a temporary file when saving everything f = QTemporaryFile() f.setAutoRemove(False) opened = f.open() else: f = historyFile opened = f.open(QIODevice.Append) if not opened: E5MessageBox.warning( None, self.tr("Saving History"), self.tr("""<p>Unable to open history file <b>{0}</b>.<br/>""" """Reason: {1}</p>""").format( f.fileName(), f.errorString() ), ) return for index in range(first, -1, -1): data = QByteArray() stream = QDataStream(data, QIODevice.WriteOnly) stream.setVersion(QDataStream.Qt_4_6) itm = self.__history[index] stream.writeUInt32(HISTORY_VERSION) stream.writeString(itm.url.encode("utf-8")) stream << itm.dateTime stream.writeString(itm.title.encode("utf-8")) f.write(data) f.close() if saveAll: if historyFile.exists() and not historyFile.remove(): E5MessageBox.warning( None, self.tr("Saving History"), self.tr("""<p>Error removing old history file <b>{0}</b>.""" """<br/>Reason: {1}</p>""").format( historyFile.fileName(), historyFile.errorString() ), ) if not f.copy(historyFile.fileName()): E5MessageBox.warning( None, self.tr("Saving History"), self.tr( """<p>Error moving new history file over old one """ """(<b>{0}</b>).<br/>Reason: {1}</p>""" ).format(historyFile.fileName(), f.errorString()), ) self.historySaved.emit() try: self.__lastSavedUrl = self.__history[0].url except IndexError: self.__lastSavedUrl = ""
def __loadRules(self): """ Private method to load the rules of the subscription. """ fileName = self.rulesFileName() f = QFile(fileName) if f.exists(): if not f.open(QIODevice.ReadOnly): E5MessageBox.warning( None, self.tr("Load subscription rules"), self.tr( """Unable to open adblock file '{0}' for reading.""") .format(fileName)) else: textStream = QTextStream(f) header = textStream.readLine(1024) if not header.startswith("[Adblock"): E5MessageBox.warning( None, self.tr("Load subscription rules"), self.tr("""AdBlock file '{0}' does not start""" """ with [Adblock.""") .format(fileName)) f.close() f.remove() self.__lastUpdate = QDateTime() else: from .AdBlockRule import AdBlockRule self.__updatePeriod = 0 self.__remoteModified = QDateTime() self.__rules = [] self.__rules.append(AdBlockRule(header, self)) while not textStream.atEnd(): line = textStream.readLine() self.__rules.append(AdBlockRule(line, self)) expires = self.__expiresRe.search(line) if expires: period, kind = expires.groups() if kind: # hours self.__updatePeriod = int(period) else: # days self.__updatePeriod = int(period) * 24 remoteModified = self.__remoteModifiedRe.search(line) if remoteModified: day, month, year, time, hour, minute = \ remoteModified.groups() self.__remoteModified.setDate( QDate(int(year), self.__monthNameToNumber[month], int(day)) ) if time: self.__remoteModified.setTime( QTime(int(hour), int(minute))) self.__populateCache() self.changed.emit() elif not fileName.endswith("_custom"): self.__lastUpdate = QDateTime() self.checkForUpdate()
class DownloadItem(QWidget, Ui_DownloadItem): """ Class implementing a widget controlling a download. @signal statusChanged() emitted upon a status change of a download @signal downloadFinished() emitted when a download finished @signal progress(int, int) emitted to signal the download progress """ statusChanged = pyqtSignal() downloadFinished = pyqtSignal() progress = pyqtSignal(int, int) Downloading = 0 DownloadSuccessful = 1 DownloadCancelled = 2 def __init__(self, reply=None, requestFilename=False, webPage=None, download=False, parent=None, mainWindow=None): """ Constructor @keyparam reply reference to the network reply object (QNetworkReply) @keyparam requestFilename flag indicating to ask the user for a filename (boolean) @keyparam webPage reference to the web page object the download originated from (QWebPage) @keyparam download flag indicating a download operation (boolean) @keyparam parent reference to the parent widget (QWidget) @keyparam mainWindow reference to the main window (HelpWindow) """ super(DownloadItem, self).__init__(parent) self.setupUi(self) p = self.infoLabel.palette() p.setColor(QPalette.Text, Qt.darkGray) self.infoLabel.setPalette(p) self.progressBar.setMaximum(0) self.__isFtpDownload = reply is not None and \ reply.url().scheme() == "ftp" self.tryAgainButton.setIcon(UI.PixmapCache.getIcon("restart.png")) self.tryAgainButton.setEnabled(False) self.tryAgainButton.setVisible(False) self.stopButton.setIcon(UI.PixmapCache.getIcon("stopLoading.png")) self.pauseButton.setIcon(UI.PixmapCache.getIcon("pause.png")) self.openButton.setIcon(UI.PixmapCache.getIcon("open.png")) self.openButton.setEnabled(False) self.openButton.setVisible(False) if self.__isFtpDownload: self.stopButton.setEnabled(False) self.stopButton.setVisible(False) self.pauseButton.setEnabled(False) self.pauseButton.setVisible(False) self.__state = DownloadItem.Downloading icon = self.style().standardIcon(QStyle.SP_FileIcon) self.fileIcon.setPixmap(icon.pixmap(48, 48)) self.__mainWindow = mainWindow self.__reply = reply self.__requestFilename = requestFilename self.__page = webPage self.__pageUrl = webPage and webPage.mainFrame().url() or QUrl() self.__toDownload = download self.__bytesReceived = 0 self.__bytesTotal = -1 self.__downloadTime = QTime() self.__output = QFile() self.__fileName = "" self.__originalFileName = "" self.__startedSaving = False self.__finishedDownloading = False self.__gettingFileName = False self.__canceledFileSelect = False self.__autoOpen = False self.__sha1Hash = QCryptographicHash(QCryptographicHash.Sha1) self.__md5Hash = QCryptographicHash(QCryptographicHash.Md5) if not requestFilename: self.__requestFilename = \ Preferences.getUI("RequestDownloadFilename") self.__initialize() def __initialize(self, tryAgain=False): """ Private method to (re)initialize the widget. @param tryAgain flag indicating a retry (boolean) """ if self.__reply is None: return self.__startedSaving = False self.__finishedDownloading = False self.__bytesReceived = 0 self.__bytesTotal = -1 self.__sha1Hash.reset() self.__md5Hash.reset() # start timer for the download estimation self.__downloadTime.start() # attach to the reply object self.__url = self.__reply.url() self.__reply.setParent(self) self.__reply.setReadBufferSize(16 * 1024 * 1024) self.__reply.readyRead.connect(self.__readyRead) self.__reply.error.connect(self.__networkError) self.__reply.downloadProgress.connect(self.__downloadProgress) self.__reply.metaDataChanged.connect(self.__metaDataChanged) self.__reply.finished.connect(self.__finished) # reset info self.infoLabel.clear() self.progressBar.setValue(0) self.__getFileName() if self.__reply.error() != QNetworkReply.NoError: self.__networkError() self.__finished() def __getFileName(self): """ Private method to get the file name to save to from the user. """ if self.__gettingFileName: return import Helpviewer.HelpWindow downloadDirectory = Helpviewer.HelpWindow.HelpWindow\ .downloadManager().downloadDirectory() if self.__fileName: fileName = self.__fileName originalFileName = self.__originalFileName self.__toDownload = True ask = False else: defaultFileName, originalFileName = \ self.__saveFileName(downloadDirectory) fileName = defaultFileName self.__originalFileName = originalFileName ask = True self.__autoOpen = False if not self.__toDownload: from .DownloadAskActionDialog import DownloadAskActionDialog url = self.__reply.url() dlg = DownloadAskActionDialog( QFileInfo(originalFileName).fileName(), self.__reply.header(QNetworkRequest.ContentTypeHeader), "{0}://{1}".format(url.scheme(), url.authority()), self) if dlg.exec_() == QDialog.Rejected or dlg.getAction() == "cancel": self.progressBar.setVisible(False) self.__reply.close() self.on_stopButton_clicked() self.filenameLabel.setText( self.tr("Download canceled: {0}").format( QFileInfo(defaultFileName).fileName())) self.__canceledFileSelect = True return if dlg.getAction() == "scan": self.__mainWindow.requestVirusTotalScan(url) self.progressBar.setVisible(False) self.__reply.close() self.on_stopButton_clicked() self.filenameLabel.setText( self.tr("VirusTotal scan scheduled: {0}").format( QFileInfo(defaultFileName).fileName())) self.__canceledFileSelect = True return self.__autoOpen = dlg.getAction() == "open" if PYQT_VERSION_STR >= "5.0.0": from PyQt5.QtCore import QStandardPaths tempLocation = QStandardPaths.standardLocations( QStandardPaths.TempLocation)[0] else: from PyQt5.QtGui import QDesktopServices tempLocation = QDesktopServices.storageLocation( QDesktopServices.TempLocation) fileName = tempLocation + '/' + \ QFileInfo(fileName).completeBaseName() if ask and not self.__autoOpen and self.__requestFilename: self.__gettingFileName = True fileName = E5FileDialog.getSaveFileName( None, self.tr("Save File"), defaultFileName, "") self.__gettingFileName = False if not fileName: self.progressBar.setVisible(False) self.__reply.close() self.on_stopButton_clicked() self.filenameLabel.setText( self.tr("Download canceled: {0}") .format(QFileInfo(defaultFileName).fileName())) self.__canceledFileSelect = True return fileInfo = QFileInfo(fileName) Helpviewer.HelpWindow.HelpWindow.downloadManager()\ .setDownloadDirectory(fileInfo.absoluteDir().absolutePath()) self.filenameLabel.setText(fileInfo.fileName()) self.__output.setFileName(fileName + ".part") self.__fileName = fileName # check file path for saving saveDirPath = QFileInfo(self.__fileName).dir() if not saveDirPath.exists(): if not saveDirPath.mkpath(saveDirPath.absolutePath()): self.progressBar.setVisible(False) self.on_stopButton_clicked() self.infoLabel.setText(self.tr( "Download directory ({0}) couldn't be created.") .format(saveDirPath.absolutePath())) return self.filenameLabel.setText(QFileInfo(self.__fileName).fileName()) if self.__requestFilename: self.__readyRead() def __saveFileName(self, directory): """ Private method to calculate a name for the file to download. @param directory name of the directory to store the file into (string) @return proposed filename and original filename (string, string) """ path = parseContentDisposition(self.__reply) info = QFileInfo(path) baseName = info.completeBaseName() endName = info.suffix() origName = baseName if endName: origName += '.' + endName name = directory + baseName if endName: name += '.' + endName if not self.__requestFilename: # do not overwrite, if the user is not being asked i = 1 while QFile.exists(name): # file exists already, don't overwrite name = directory + baseName + ('-{0:d}'.format(i)) if endName: name += '.' + endName i += 1 return name, origName def __open(self): """ Private slot to open the downloaded file. """ info = QFileInfo(self.__output) url = QUrl.fromLocalFile(info.absoluteFilePath()) QDesktopServices.openUrl(url) @pyqtSlot() def on_tryAgainButton_clicked(self): """ Private slot to retry the download. """ self.retry() def retry(self): """ Public slot to retry the download. """ if not self.tryAgainButton.isEnabled(): return self.tryAgainButton.setEnabled(False) self.tryAgainButton.setVisible(False) self.openButton.setEnabled(False) self.openButton.setVisible(False) if not self.__isFtpDownload: self.stopButton.setEnabled(True) self.stopButton.setVisible(True) self.pauseButton.setEnabled(True) self.pauseButton.setVisible(True) self.progressBar.setVisible(True) if self.__page: nam = self.__page.networkAccessManager() else: import Helpviewer.HelpWindow nam = Helpviewer.HelpWindow.HelpWindow.networkAccessManager() reply = nam.get(QNetworkRequest(self.__url)) if self.__output.exists(): self.__output.remove() self.__output = QFile() self.__reply = reply self.__initialize(tryAgain=True) self.__state = DownloadItem.Downloading self.statusChanged.emit() @pyqtSlot(bool) def on_pauseButton_clicked(self, checked): """ Private slot to pause the download. @param checked flag indicating the state of the button (boolean) """ if checked: self.__reply.readyRead.disconnect(self.__readyRead) self.__reply.setReadBufferSize(16 * 1024) else: self.__reply.readyRead.connect(self.__readyRead) self.__reply.setReadBufferSize(16 * 1024 * 1024) self.__readyRead() @pyqtSlot() def on_stopButton_clicked(self): """ Private slot to stop the download. """ self.cancelDownload() def cancelDownload(self): """ Public slot to stop the download. """ self.setUpdatesEnabled(False) if not self.__isFtpDownload: self.stopButton.setEnabled(False) self.stopButton.setVisible(False) self.pauseButton.setEnabled(False) self.pauseButton.setVisible(False) self.tryAgainButton.setEnabled(True) self.tryAgainButton.setVisible(True) self.openButton.setEnabled(False) self.openButton.setVisible(False) self.setUpdatesEnabled(True) self.__state = DownloadItem.DownloadCancelled self.__reply.abort() self.downloadFinished.emit() @pyqtSlot() def on_openButton_clicked(self): """ Private slot to open the downloaded file. """ self.openFile() def openFile(self): """ Public slot to open the downloaded file. """ info = QFileInfo(self.__fileName) url = QUrl.fromLocalFile(info.absoluteFilePath()) QDesktopServices.openUrl(url) def openFolder(self): """ Public slot to open the folder containing the downloaded file. """ info = QFileInfo(self.__fileName) url = QUrl.fromLocalFile(info.absolutePath()) QDesktopServices.openUrl(url) def __readyRead(self): """ Private slot to read the available data. """ if self.__requestFilename and not self.__output.fileName(): return if not self.__output.isOpen(): # in case someone else has already put a file there if not self.__requestFilename: self.__getFileName() if not self.__output.open(QIODevice.WriteOnly): self.infoLabel.setText( self.tr("Error opening save file: {0}") .format(self.__output.errorString())) self.on_stopButton_clicked() self.statusChanged.emit() return self.statusChanged.emit() buffer = self.__reply.readAll() self.__sha1Hash.addData(buffer) self.__md5Hash.addData(buffer) bytesWritten = self.__output.write(buffer) if bytesWritten == -1: self.infoLabel.setText( self.tr("Error saving: {0}") .format(self.__output.errorString())) self.on_stopButton_clicked() else: self.__startedSaving = True if self.__finishedDownloading: self.__finished() def __networkError(self): """ Private slot to handle a network error. """ self.infoLabel.setText( self.tr("Network Error: {0}") .format(self.__reply.errorString())) self.tryAgainButton.setEnabled(True) self.tryAgainButton.setVisible(True) self.downloadFinished.emit() def __metaDataChanged(self): """ Private slot to handle a change of the meta data. """ locationHeader = self.__reply.header(QNetworkRequest.LocationHeader) if locationHeader and locationHeader.isValid(): self.__url = QUrl(locationHeader) import Helpviewer.HelpWindow self.__reply = Helpviewer.HelpWindow.HelpWindow\ .networkAccessManager().get(QNetworkRequest(self.__url)) self.__initialize() def __downloadProgress(self, bytesReceived, bytesTotal): """ Private method to show the download progress. @param bytesReceived number of bytes received (integer) @param bytesTotal number of total bytes (integer) """ self.__bytesReceived = bytesReceived self.__bytesTotal = bytesTotal currentValue = 0 totalValue = 0 if bytesTotal > 0: currentValue = bytesReceived * 100 / bytesTotal totalValue = 100 self.progressBar.setValue(currentValue) self.progressBar.setMaximum(totalValue) self.progress.emit(currentValue, totalValue) self.__updateInfoLabel() def bytesTotal(self): """ Public method to get the total number of bytes of the download. @return total number of bytes (integer) """ if self.__bytesTotal == -1: self.__bytesTotal = self.__reply.header( QNetworkRequest.ContentLengthHeader) if self.__bytesTotal is None: self.__bytesTotal = -1 return self.__bytesTotal def bytesReceived(self): """ Public method to get the number of bytes received. @return number of bytes received (integer) """ return self.__bytesReceived def remainingTime(self): """ Public method to get an estimation for the remaining time. @return estimation for the remaining time (float) """ if not self.downloading(): return -1.0 if self.bytesTotal() == -1: return -1.0 cSpeed = self.currentSpeed() if cSpeed != 0: timeRemaining = (self.bytesTotal() - self.bytesReceived()) / cSpeed else: timeRemaining = 1 # ETA should never be 0 if timeRemaining == 0: timeRemaining = 1 return timeRemaining def currentSpeed(self): """ Public method to get an estimation for the download speed. @return estimation for the download speed (float) """ if not self.downloading(): return -1.0 return self.__bytesReceived * 1000.0 / self.__downloadTime.elapsed() def __updateInfoLabel(self): """ Private method to update the info label. """ if self.__reply.error() != QNetworkReply.NoError: return bytesTotal = self.bytesTotal() running = not self.downloadedSuccessfully() speed = self.currentSpeed() timeRemaining = self.remainingTime() info = "" if running: remaining = "" if bytesTotal > 0: remaining = timeString(timeRemaining) info = self.tr("{0} of {1} ({2}/sec)\n{3}")\ .format( dataString(self.__bytesReceived), bytesTotal == -1 and self.tr("?") or dataString(bytesTotal), dataString(int(speed)), remaining) else: if self.__bytesReceived == bytesTotal or bytesTotal == -1: info = self.tr("{0} downloaded\nSHA1: {1}\nMD5: {2}")\ .format(dataString(self.__output.size()), str(self.__sha1Hash.result().toHex(), encoding="ascii"), str(self.__md5Hash.result().toHex(), encoding="ascii") ) else: info = self.tr("{0} of {1} - Stopped")\ .format(dataString(self.__bytesReceived), dataString(bytesTotal)) self.infoLabel.setText(info) def downloading(self): """ Public method to determine, if a download is in progress. @return flag indicating a download is in progress (boolean) """ return self.__state == DownloadItem.Downloading def downloadedSuccessfully(self): """ Public method to check for a successful download. @return flag indicating a successful download (boolean) """ return self.__state == DownloadItem.DownloadSuccessful def downloadCanceled(self): """ Public method to check, if the download was cancelled. @return flag indicating a canceled download (boolean) """ return self.__state == DownloadItem.DownloadCancelled def __finished(self): """ Private slot to handle the download finished. """ self.__finishedDownloading = True if not self.__startedSaving: return noError = self.__reply.error() == QNetworkReply.NoError self.progressBar.setVisible(False) if not self.__isFtpDownload: self.stopButton.setEnabled(False) self.stopButton.setVisible(False) self.pauseButton.setEnabled(False) self.pauseButton.setVisible(False) self.openButton.setEnabled(noError) self.openButton.setVisible(noError) self.__output.close() if QFile.exists(self.__fileName): QFile.remove(self.__fileName) self.__output.rename(self.__fileName) self.__updateInfoLabel() self.__state = DownloadItem.DownloadSuccessful self.statusChanged.emit() self.downloadFinished.emit() if self.__autoOpen: self.__open() def canceledFileSelect(self): """ Public method to check, if the user canceled the file selection. @return flag indicating cancellation (boolean) """ return self.__canceledFileSelect def setIcon(self, icon): """ Public method to set the download icon. @param icon reference to the icon to be set (QIcon) """ self.fileIcon.setPixmap(icon.pixmap(48, 48)) def fileName(self): """ Public method to get the name of the output file. @return name of the output file (string) """ return self.__fileName def absoluteFilePath(self): """ Public method to get the absolute path of the output file. @return absolute path of the output file (string) """ return QFileInfo(self.__fileName).absoluteFilePath() def getData(self): """ Public method to get the relevant download data. @return tuple of URL, save location, flag and the URL of the related web page (QUrl, string, boolean,QUrl) """ return (self.__url, QFileInfo(self.__fileName).filePath(), self.downloadedSuccessfully(), self.__pageUrl) def setData(self, data): """ Public method to set the relevant download data. @param data tuple of URL, save location, flag and the URL of the related web page (QUrl, string, boolean, QUrl) """ self.__url = data[0] self.__fileName = data[1] self.__pageUrl = data[3] self.__isFtpDownload = self.__url.scheme() == "ftp" self.filenameLabel.setText(QFileInfo(self.__fileName).fileName()) self.infoLabel.setText(self.__fileName) self.stopButton.setEnabled(False) self.stopButton.setVisible(False) self.pauseButton.setEnabled(False) self.pauseButton.setVisible(False) self.openButton.setEnabled(data[2]) self.openButton.setVisible(data[2]) self.tryAgainButton.setEnabled(not data[2]) self.tryAgainButton.setVisible(not data[2]) if data[2]: self.__state = DownloadItem.DownloadSuccessful else: self.__state = DownloadItem.DownloadCancelled self.progressBar.setVisible(False) def getInfoData(self): """ Public method to get the text of the info label. @return text of the info label (string) """ return self.infoLabel.text() def getPageUrl(self): """ Public method to get the URL of the download page. @return URL of the download page (QUrl) """ return self.__pageUrl