def loadFile(self, filename): file = QFile() file.setFileName("./js/" + filename) file.open(QIODevice.ReadOnly) code = file.readAll() file.close() return "".join(str(line) for line in code)
def read_project_info(self) -> None: """Reads project configuration data from default storage location""" if QFile.exists(self.root_path + "/.manuwrite/project.toml"): try: file = QFile() file.setFileName(self.root_path + "/.manuwrite/project.toml") file.open(QFile.ReadOnly) data = OrderedDict(toml.loads(file.readAll().data().decode())) except OSError: raise ProjectError("An error occured while reading project file") finally: file.close() self.project_info = data for key in self.defaults.keys(): if key not in self.project_info: self.project_info[key] = self.defaults[key] # Update project structure filenames = [] for filename in self.get_setting_value("Files to render"): filenames.append(self.get_setting_value("Absolute path") + "/" + filename) self.ThreadManager.perform_operation("parse_project", self.on_MarkdownProjectParserThread_finished, filepaths=filenames) self.set_setting_value("Absolute path", self.root_path) else: raise ProjectError("Project file doesn't exits")
def readThemeIndex(self, themeName): dirList = [] parents = [] themeIndex = QFile() # Read theme index files for i in range(len(self.iconDirs)): themeIndex.setFileName(path.join(unicode(self.iconDirs[i]), unicode(themeName), "index.theme")) if themeIndex.exists(): indexReader = QSettings(themeIndex.fileName(), QSettings.IniFormat) for key in indexReader.allKeys(): if str(key).endswith("/Size"): size = str(indexReader.value(key)) dirList.append((size, unicode(key[:-5]))) parents = indexReader.value('Icon Theme/Inherits') dump=parents parents = list() parents.append(dump) break return QIconTheme(dirList, parents)
def __init__(self, url): super().__init__() self.setAttribute(Qt.WA_DeleteOnClose, True) self.progress = 0 f = QFile() f.setFileName(":/jquery.min.js") f.open(QIODevice.ReadOnly) self.jQuery = f.readAll().data().decode() self.jQuery += "\nvar qt = { 'jQuery': jQuery.noConflict(true) };" f.close() self.view = QWebEngineView(self) self.view.load(url) self.view.loadFinished.connect(self.adjustLocation) self.view.titleChanged.connect(self.adjustTitle) self.view.loadProgress.connect(self.setProgress) self.view.loadFinished.connect(self.finishLoading) self.locationEdit = QLineEdit(self) self.locationEdit.setSizePolicy( QSizePolicy.Expanding, self.locationEdit.sizePolicy().verticalPolicy()) self.locationEdit.returnPressed.connect(self.changeLocation) toolBar = self.addToolBar(self.tr("Navigation")) toolBar.addAction(self.view.pageAction(QWebEnginePage.Back)) toolBar.addAction(self.view.pageAction(QWebEnginePage.Forward)) toolBar.addAction(self.view.pageAction(QWebEnginePage.Reload)) toolBar.addAction(self.view.pageAction(QWebEnginePage.Stop)) toolBar.addWidget(self.locationEdit) viewMenu = self.menuBar().addMenu(self.tr("&View")) viewSourceAction = QAction(self.tr("Page Source"), self) viewSourceAction.triggered.connect(self.viewSource) viewMenu.addAction(viewSourceAction) effectMenu = self.menuBar().addMenu(self.tr("&Effect")) effectMenu.addAction(self.tr("Highlight all links"), self.highlightAllLinks) self.rotateAction = QAction(self) self.rotateAction.setIcon(self.style().standardIcon( QStyle.SP_FileDialogDetailedView)) self.rotateAction.setCheckable(True) self.rotateAction.setText(self.tr("Turn images upside down")) self.rotateAction.toggled.connect(self.rotateImages) effectMenu.addAction(self.rotateAction) toolsMenu = self.menuBar().addMenu(self.tr("&Tools")) toolsMenu.addAction(self.tr("Remove GIF images"), self.removeGifImages) toolsMenu.addAction(self.tr("Remove all inline frames"), self.removeInlineFrames) toolsMenu.addAction(self.tr("Remove all object elements"), self.removeObjectElements) toolsMenu.addAction(self.tr("Remove all embedded elements"), self.removeEmbeddedElements) self.setCentralWidget(self.view)
def readThemeIndex(self, themeName): dirList = [] parents = [] themeIndex = QFile() # Read theme index files for i in range(len(self.iconDirs)): themeIndex.setFileName( path.join(unicode(self.iconDirs[i]), unicode(themeName), "index.theme")) if themeIndex.exists(): indexReader = QSettings(themeIndex.fileName(), QSettings.IniFormat) for key in indexReader.allKeys(): if str(key).endswith("/Size"): size = str(indexReader.value(key)) dirList.append((size, unicode(key[:-5]))) parents = indexReader.value('Icon Theme/Inherits') dump = parents parents = list() parents.append(dump) break return QIconTheme(dirList, parents)
def transferFile(self, src_path): dest_path = self.model.filePath(self.rootIndex()) src_file = QFile() src_file.setFileName(src_path) src_file_info = QFileInfo(src_path) dst_path = os.path.join(dest_path, src_file_info.fileName()) src_file.copy(dst_path)
def save_project_data(self) -> None: """Saves project configuration data to permanent storage""" try: file = QFile() file.setFileName(self.root_path + "/.manuwrite/project.toml") file.open(QFile.WriteOnly) file.write(toml.dumps(self.project_info).encode()) except OSError: raise ProjectError("Failed to write project configuration data") finally: file.close()
def create_file(self, path: str) -> None: """Creates a file at a given path""" try: file = QFile() file.setFileName(path) file.open(QFile.ReadWrite) except OSError: raise ProjectError finally: file.close()
def readFile(selfself): file = QFile() file.setFileName("./doc/test.txt") isok = file.open(QIODevice.ReadOnly) if isok: stream = QTextStream(file) #stream.setCodec("utf8") str = stream.readAll() print(str) file.close()
class DocumentReader: def __init__(self, filename): self.file = QFile() self.file.setFileName(filename) self.is_error = False self.errorString = "" if not self.file.open(QFile.ReadOnly): error = self.file.errorString() qDebug("cannot open file \"{1}\"".format(error)) self.is_error = True self.errorString = error def read(self, document): if not self.file.isOpen(): return text = str(self.file.readAll().data(), encoding='utf-8') document.setPlainText(text)
class QDeckAudioItemWidget(QAudioInput): audio_input = None outputFile = None def __init__(self): super().__init__() def initAudioInput(self, filepath): self.outputFile = QFile() self.outputFile.setFileName(filepath) self.outputFile.open(QIODevice.WriteOnly | QIODevice.Truncate) format = QAudioFormat() format.setSampleType(QAudioFormat.Float) format.setSampleRate(44100) format.setChannelCount(1) format.setSampleSize(32) format.setCodec("audio/pcm") format.setByteOrder(QAudioFormat.LittleEndian) print(format.codec()) #self.audio_input = QAudioInput(QAudioDeviceInfo.defaultInputDevice(), format); self.audio_input = QAudioInput(format) print(self.audio_input.error()) print(self.audio_input.state()) #QTimer.singleShot(3000, self, def start(self): self.audio_input.start(self.outputFile) def stop(self): self.audio_input.stop() self.outputFile.close() def suspend(self): self.audio_input.suspend() def resume(self): self.audio_input.resume()
class DocumentWriter: def __init__(self, filename): self.file = QFile() self.file.setFileName(filename) self.is_error = False self.errorString = "" if not self.file.open(QFile.WriteOnly): error = self.file.errorString() qDebug("cannot open file \"{1}\"".format(error)) self.is_error = True self.errorString = error def write(self, document): if not self.file.isOpen(): return writer = QTextDocumentWriter() writer.setFormat(QByteArray().append("plaintext")) writer.setDevice(self.file) writer.write(document)
def readThemeIndex(self, themeName): dirList = [] parents = [] themeIndex = QFile() # Read theme index files for i in range(len(self.iconDirs)): themeIndex.setFileName(path.join(unicode(self.iconDirs[i]), unicode(themeName), "index.theme")) if themeIndex.exists(): indexReader = QSettings(themeIndex.fileName(), QSettings.IniFormat) for key in indexReader.allKeys(): if key.endswith("/Size"): size = indexReader.value(key) dirList.append((size[0], unicode(key.left(key.size() - 5)))) parents = indexReader.value('Icon Theme/Inherits') parents = parents.toStringList() break return QIconTheme(dirList, parents)
def create_project(directory_path: str) -> None: """Creates a new project at given path""" try: directory = QDir(directory_path) directory.mkdir(".manuwrite") directory.mkdir("images") directory.mkdir("notes") directory.mkdir("data") directory.mkpath(".manuwrite/render") file = QFile() file.setFileName(directory_path + "/.manuwrite/project.toml") file.open(QFile.ReadWrite) project_settings = copy.deepcopy(defaults.project_settings) project_settings["Absolute path"] = {"type": "str", "value": directory_path} file.write(toml.dumps(project_settings).encode()) file.close() except OSError: raise ProjectError("Error creating project files")
def readThemeIndex(self, themeName): dirList = [] parents = [] themeIndex = QFile() # Read theme index files for i in range(len(self.iconDirs)): themeIndex.setFileName( path.join(unicode(self.iconDirs[i]), unicode(themeName), "index.theme")) if themeIndex.exists(): indexReader = QSettings(themeIndex.fileName(), QSettings.IniFormat) for key in indexReader.allKeys(): if key.endswith("/Size"): size = indexReader.value(key) dirList.append( (size[0], unicode(key.left(key.size() - 5)))) parents = indexReader.value('Icon Theme/Inherits') parents = parents.toStringList() break return QIconTheme(dirList, parents)
class NSwapFile(QObject): """ In case Ninja-IDE crash, this can be used to recover the lost data. When the user begins to edit an existing file on the disk, this object creates a swap file and activates a timer that will execute a function, that will update that swap file as soon as the timeout ends (by default, is 15 seconds). The swap file is deleted when the original file is saved or closed. When system or Ninja crash, the swap file exists on disk and Ninja will used to recover the lost data. """ canBeRecovered = pyqtSignal() def __init__(self, neditable): QObject.__init__(self) self._neditable = neditable self.__swap_file = QFile() self.__stream = QTextStream() # Activate timer when user typing self.__timer = QTimer() self.__timer.setSingleShot(True) self.__timer.timeout.connect(self._finish_typing) self._neditable.fileLoaded.connect(self._file_loaded) self._neditable.fileSaved.connect(self._file_saved) self.init(tracking=True) def init(self, tracking): if tracking: self._neditable.editor.textChanged.connect(self._start_typing) self._neditable.fileClosing.connect(self._file_closed) else: self._neditable.editor.textChanged.disconnect(self._start_typing) self._neditable.fileClosing.disconnect(self._file_closed) def _file_closed(self): """Editor was closed normally, now remove swap file""" self.__remove() def _file_saved(self): """If file is saved, remove swap file""" # Remove old swap file and set the name for the new swap file self.__remove() self.__update_filename() def __remove(self): """Remove swap file""" if self.__swap_file.fileName() and self.__swap_file.exists(): self.__stream.setDevice(None) self.__swap_file.close() self.__swap_file.remove() def _file_loaded(self): """This slot is executed when a file is loaded on the editor and look for swap file, if exists then can be recover""" self.__update_filename() if self.__swap_file.exists(): # In recovery process can't edit self._neditable.editor.setReadOnly(True) # Ok, can be recover self.canBeRecovered.emit() def __update_filename(self): # First clear filename self.__swap_file.setFileName("") # Get new path filename = self.filename() self.__swap_file.setFileName(filename) def _start_typing(self): # Skip if editor is not modified if not self._neditable.editor.is_modified: return # No swap file, no work if not self.__swap_file.fileName(): return # Create the file if not self.__swap_file.exists(): self.__swap_file.open(QIODevice.WriteOnly) permissions = QFileDevice.ReadOwner | QFileDevice.WriteOwner self.__swap_file.setPermissions(permissions) self.__stream.setDevice(self.__swap_file) if self.__timer.isActive(): self.__timer.stop() # Write swap file to the disk every 10 seconds by default self.__timer.start(settings.SWAP_FILE_INTERVAL * 1000) def _finish_typing(self): if not self.__swap_file.isOpen(): return logger.debug("Now write the swap file...") text = self._neditable.editor.text self.__swap_file.write(text.encode()) self.__swap_file.flush() def filename(self): """Returns the filename for swap file""" path, name = os.path.split( os.path.join(SWAP_PATH, self._neditable.nfile.file_name)) filename = os.path.join(path, "%s.ninja-swap" % name) return filename def recover(self): self._neditable.editor.setReadOnly(False) # Disconnect signals self.init(tracking=False) self.__stream.setDevice(self.__swap_file) if not self.__swap_file.open(QIODevice.ReadOnly): logger.warning("Can't open swap file") return # Ok data = [] append = data.append while not self.__stream.atEnd(): line = self.__stream.readLine() append(line) # Set data in the editor self._neditable.editor.text = "\n".join(data) self._neditable.document.setModified(True) # Close swap file self.__stream.setDevice(None) self.__swap_file.close() # Reconnect signals self.init(tracking=True) def discard(self): self._neditable.editor.setReadOnly(False) # Remove swap file self.__remove()
class QHexWindow(QMainWindow): def __init__(self): super().__init__() self.currentFile = str() self.isUntitled = False self.hexEdit = QHexEdit(self) self.file = QFile() self.fileMenu = QMenu() self.editMenu = QMenu() self.helpMenu = QMenu() self.labelSize = QLabel() self.fileToolBar = QToolBar() self.editToolBar = QToolBar() self.undoAction = QAction() self.redoAction = QAction() self.openAction = QAction() self.saveAction = QAction() self.exitAction = QAction() self.findAction = QAction() self.aboutAction = QAction() self.closeAction = QAction() self.saveAsAction = QAction() self.saveReadable = QAction() self.aboutQtAction = QAction() self.optionsAction = QAction() self.findNextAction = QAction() self.saveReadableSelection = QAction() self.optionsDialog = OptionsDialog(self) self.setAcceptDrops(True) self.init() self.setFixedSize(QSize(1200, 600)) self.show() def closeEvent(self, event: QCloseEvent) -> None: self.writeSettings() def dragEnterEvent(self, event: QDragEnterEvent) -> None: if event.mimeData().hasUrls(): event.accept() def dropEvent(self, event: QDropEvent) -> None: if event.mimeData().hasUrls(): urls = event.mimeData().urls() filepath = urls[0].toLocalFile() self.loadFile(filepath) event.accept() def about(self): QMessageBox.about(self, 'Hex', 'Hexadecimal View') def dataChanged(self): self.setWindowModified(self.hexEdit.isModified()) def open(self): options = QFileDialog().Options() options |= QFileDialog.DontUseNativeDialog filename, _ = QFileDialog.getOpenFileName(self, "Select File", options=options) if filename: self.loadFile(filename) def optionsAccepted(self): self.writeSettings() self.readSettings() def findNext(self): pass def save(self): if self.isUntitled: self.saveAs() else: self.saveFile(self.currentFile) def saveAs(self): filename = QFileDialog.getSaveFileName(self, 'Save As...', self.currentFile) if len(filename) == 0: return False return self.saveFile(filename) def saveSelectionToReadableFile(self): pass def saveToReadableFile(self): pass def setAddress(self): pass def setOverwriteMode(self): pass def setSize(self, size): self.labelSize.setText(str(size)) def showOptionsDialog(self): pass def showSearchDialog(self): pass # noinspection PyUnresolvedReferences def init(self): self.optionsDialog.accepted.connect(self.optionsAccepted) self.hexEdit.dataChanged.connect(self.dataChanged) self.hexEdit.overwriteModeChanged.connect(self.setOverwriteMode) self.setUnifiedTitleAndToolBarOnMac(True) self.setCentralWidget(self.hexEdit) self.createActions() self.createMenus() self.createStatusBar() self.createToolBars() self.readSettings() # noinspection PyUnresolvedReferences def createActions(self): self.openAction = QAction(QIcon('Icons/MenuOpen.svg'), '&Open', self) self.openAction.setStatusTip('Open a existing file') self.openAction.setShortcut(QKeySequence.Open) self.openAction.triggered.connect(self.open) self.saveAction = QAction(QIcon('Icons/MenuSaveAll'), '&Save', self) self.saveAsAction = QAction('Save &As...', self) self.saveReadable = QAction('Save &Readable', self) self.exitAction = QAction('E&xit', self) self.undoAction = QAction(QIcon('Icons/Undo.svg'), '&Undo', self) self.redoAction = QAction(QIcon('Icons/Redo.svg'), '&Redo', self) self.saveReadableSelection = QAction('Save Selection Readable', self) self.aboutAction = QAction('&About', self) self.aboutQtAction = QAction('About &Qt', self) self.findAction = QAction(QIcon('Icons/Find.svg'), '&Find/Replace', self) self.findNextAction = QAction('Find &Next', self) self.optionsAction = QAction('&Options', self) def createMenus(self): self.fileMenu = self.menuBar().addMenu('&File') self.fileMenu.addAction(self.openAction) self.fileMenu.addAction(self.saveAction) self.fileMenu.addAction(self.saveAsAction) self.fileMenu.addAction(self.saveReadable) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exitAction) self.editMenu = self.menuBar().addMenu('&Edit') self.editMenu.addAction(self.undoAction) self.editMenu.addAction(self.redoAction) self.editMenu.addAction(self.saveReadableSelection) self.editMenu.addSeparator() self.editMenu.addAction(self.findAction) self.editMenu.addAction(self.findNextAction) self.editMenu.addSeparator() self.editMenu.addAction(self.optionsAction) self.helpMenu = self.menuBar().addMenu('&Help') self.helpMenu.addAction(self.aboutAction) self.helpMenu.addAction(self.aboutQtAction) def createStatusBar(self): self.statusBar().addPermanentWidget(QLabel('Address:')) labelAddress = QLabel() labelAddress.setMinimumWidth(70) self.statusBar().addPermanentWidget(labelAddress) self.statusBar().addPermanentWidget(QLabel('Size:')) self.labelSize.setMinimumWidth(70) self.statusBar().addPermanentWidget(self.labelSize) self.hexEdit.currentSizeChanged.connect(self.setSize) self.statusBar().addPermanentWidget(QLabel('Mode:')) labelOverwriteMode = QLabel() labelOverwriteMode.setMinimumWidth(70) self.statusBar().addPermanentWidget(labelOverwriteMode) self.statusBar().showMessage('Ready', 2000) def createToolBars(self): self.fileToolBar = self.addToolBar('File') self.fileToolBar.setIconSize(QSize(16, 16)) self.fileToolBar.addAction(self.openAction) self.fileToolBar.addAction(self.saveAction) self.editToolBar = self.addToolBar('Edit') self.editToolBar.setIconSize(QSize(16, 16)) self.editToolBar.addAction(self.undoAction) self.editToolBar.addAction(self.redoAction) self.editToolBar.addAction(self.findAction) def loadFile(self, filename: str): self.file.setFileName(filename) if not self.hexEdit.setDataDevice(self.file): QMessageBox.warning( self, "Hex", f"Cannot read the file {filename}: {self.file.errorString()}.") self.setCurrentFile(filename) self.statusBar().showMessage('File Loaded', 2000) def readSettings(self): pass def saveFile(self, filename: str): pass def setCurrentFile(self, filename: str): currentFile = QFileInfo(filename).canonicalFilePath() isUntitled = len(currentFile) == 0 self.setWindowModified(False) if isUntitled: self.setWindowFilePath("QHexEdit") else: self.setWindowFilePath(currentFile + " - QHexEdit") @staticmethod def strippedName(fullFilename: str) -> str: return QFileInfo(fullFilename).fileName() def writeSettings(self): settings = QSettings() settings.setValue("pos", self.pos()) settings.setValue("size", self.size())
class Recorder(QMainWindow, Ui_MainWindow): def __init__(self): super(Recorder, self).__init__() self.setupUi(self) self.output = QFile() self.audio = QAudioInput() self.NEED_ASR = False self.Open = True self.th1 = threading.Thread(target=self.ASR) self.th1.start() self.Pause_Button.clicked.connect(self.toggle_pause) self.Record_Button.clicked.connect(self.toggle_record) def closeEvent(self, event): self.Open = False def toggle_record(self): if self.Record_Button.text() == "开始录音": self.statusbar.showMessage("开始录音") self.setup() self.audio.start(self.output) self.Record_Button.setText("停止") self.Pause_Button.setText("暂停") self.Pause_Button.setEnabled(True) else: self.audio.stop() self.output.close() self.Pause_Button.setText("暂停") self.Record_Button.setText("开始录音") self.statusbar.showMessage("正在使用百度智能云识别,请稍等") self.NEED_ASR = True def toggle_pause(self): if self.Pause_Button.text() == "暂停": self.Pause_Button.setText("继续") self.audio.suspend() else: self.Pause_Button.setText("暂停") self.audio.resume() def ASR(self): while self.Open: print(1) if self.NEED_ASR: try: text = ASR().Baidu_ASR("record.pcm") print(text) if text['err_msg'] == 'success.': self.Text_plainTextEdit.setPlainText(text['result'][0]) self.statusbar.showMessage("识别成功") else: self.statusbar.showMessage("识别失败,请再说一遍") except: self.statusbar.showMessage("网络故障,请检查网络设置以及百度智能云账号") self.NEED_ASR = False else: pass def setup(self): self.output.setFileName("record.pcm") self.output.open(QIODevice.WriteOnly | QIODevice.Truncate) settings = QAudioFormat() settings.setCodec("audio/pcm") settings.setSampleRate(16000) settings.setSampleSize(16) settings.setChannelCount(1) settings.setByteOrder(QAudioFormat.LittleEndian) settings.setSampleType(QAudioFormat.SignedInt) self.audio = QAudioInput(settings)
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
class QmyMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui=Ui_MainWindow() #创建UI对象 self.ui.setupUi(self) #构造UI界面 self.ui.progBar_Max.setMaximum(256) self.ui.progBar_Min.setMaximum(256) self.ui.progBar_Diff.setMaximum(256) self.ui.sliderVolumn.setMaximum(100) self.ui.sliderVolumn.setValue(100) self.ui.comboDevices.clear() self.__deviceList=QAudioDeviceInfo.availableDevices(QAudio.AudioInput) #音频输入设备列表 for i in range(len(self.__deviceList)): device=self.__deviceList[i] #QAudioDeviceInfo类 self.ui.comboDevices.addItem(device.deviceName()) ## self.__deviceInfo =None #当前设备信息,QAudioDeviceInfo self.audioDevice=None #音频输入设备,QAudioInput self.BUFFER_SIZE=4000 self.ioDevice=None #第1种读取方法,内建的IODevice ## self.externalReader=None #第2种读取方法,外建的IODevice self.recordFile=QFile() #第3种读取方法,使用QFile直接写入文件 if len(self.__deviceList)>0: self.ui.comboDevices.setCurrentIndex(0) #触发comboDevices的信号currentIndexChanged() ## self.__deviceInfo =deviceList[0] else: self.ui.actStart.setEnabled(False) self.ui.actDeviceTest.setEnabled(False) self.ui.groupBoxDevice.setTitle("支持的音频输入设置(无设备)") ## ==============自定义功能函数======================== def __getSampleTypeStr(self,sampleType): result="Unknown" if sampleType==QAudioFormat.SignedInt: result = "SignedInt" elif sampleType==QAudioFormat.UnSignedInt: result = "UnSignedInt" elif sampleType==QAudioFormat.Float: result = "Float" elif sampleType==QAudioFormat.Unknown: result = "Unknown" return result def __getByteOrderStr(self,endian): if (endian==QAudioFormat.LittleEndian): return "LittleEndian" else: return "BigEndian" ## ==============event处理函数========================== ## ==========由connectSlotsByName()自动连接的槽函数============ @pyqtSlot(int) ##选择音频输入设备 def on_comboDevices_currentIndexChanged(self,index): deviceInfo =self.__deviceList[index] #当前音频设备,QAudioDeviceInfo类型 self.ui.comboCodec.clear() codecs = deviceInfo.supportedCodecs() #支持的音频编码,字符串列表 for strLine in codecs: self.ui.comboCodec.addItem(strLine) self.ui.comboSampleRate.clear() #支持的采样率 sampleRates = deviceInfo.supportedSampleRates() #QList<int> for i in sampleRates: self.ui.comboSampleRate.addItem("%d"% i) self.ui.comboChannels.clear() #支持的通道数 Channels = deviceInfo.supportedChannelCounts() #QList<int> for i in Channels: self.ui.comboChannels.addItem("%d"%i ) self.ui.comboSampleTypes.clear() #支持的采样点类型 sampleTypes = deviceInfo.supportedSampleTypes() #QList<QAudioFormat::SampleType> for i in sampleTypes: sampTypeStr=self.__getSampleTypeStr(i) self.ui.comboSampleTypes.addItem(sampTypeStr,i) self.ui.comboSampleSizes.clear() #采样点大小 sampleSizes = deviceInfo.supportedSampleSizes() #QList<int> for i in sampleSizes: self.ui.comboSampleSizes.addItem("%d"%i) self.ui.comboByteOrder.clear() #字节序 endians = deviceInfo.supportedByteOrders() #QList<QAudioFormat::Endian> for i in endians: self.ui.comboByteOrder.addItem(self.__getByteOrderStr(i)) @pyqtSlot() ##使用内建IODevice def on_radioSaveMode_Inner_clicked(self): self.ui.groupBox_disp.setVisible(True) @pyqtSlot() ##使用QFile对象(test.raw) def on_radioSaveMode_QFile_clicked(self): self.ui.groupBox_disp.setVisible(False) @pyqtSlot(int) ##调节录音音量 def on_sliderVolumn_valueChanged(self,value): self.ui.LabVol.setText("录音音量(%d%%)"%value) @pyqtSlot() ##测试音频输入设备是否支持选择的设置 def on_actDeviceTest_triggered(self): settings=QAudioFormat() settings.setCodec(self.ui.comboCodec.currentText()) settings.setSampleRate(int(self.ui.comboSampleRate.currentText())) settings.setChannelCount(int(self.ui.comboChannels.currentText())) k=self.ui.comboSampleTypes.currentData() settings.setSampleType(k) #QAudioFormat.SampleType settings.setSampleSize(int(self.ui.comboSampleSizes.currentText())) if (self.ui.comboByteOrder.currentText()=="LittleEndian"): settings.setByteOrder(QAudioFormat.LittleEndian) else: settings.setByteOrder(QAudioFormat.BigEndian) index=self.ui.comboDevices.currentIndex() deviceInfo =self.__deviceList[index] #当前音频设备 if deviceInfo.isFormatSupported(settings): QMessageBox.information(self,"消息","测试成功,设备支持此设置") else: QMessageBox.critical(self,"错误","测试失败,设备不支持此设置") @pyqtSlot() ##开始音频输入 def on_actStart_triggered(self): audioFormat=QAudioFormat() #使用固定格式 audioFormat.setSampleRate(8000) audioFormat.setChannelCount(1) audioFormat.setSampleSize(8) audioFormat.setCodec("audio/pcm") audioFormat.setByteOrder(QAudioFormat.LittleEndian) audioFormat.setSampleType(QAudioFormat.UnSignedInt) index=self.ui.comboDevices.currentIndex() deviceInfo =self.__deviceList[index] #当前音频设备 if (False== deviceInfo.isFormatSupported(audioFormat)): QMessageBox.critical(self,"错误","测试失败,输入设备不支持此设置") return self.audioDevice = QAudioInput(deviceInfo,audioFormat) #音频输入设备 self.audioDevice.setBufferSize(self.BUFFER_SIZE) #设置的缓冲区大小,字节数,并不一定等于实际数据块大小 self.audioDevice.stateChanged.connect(self.do_stateChanged) #状态变化 ##1. 使用 start()->QIODevice 启动,返回的内置的IODevice, pull mode,利用readyRead()信号读出数据 if self.ui.radioSaveMode_Inner.isChecked(): self.ioDevice=self.audioDevice.start() #返回内建的IODevice self.ioDevice.readyRead.connect(self.do_IO_readyRead) ## 2. 自定义流设备QWAudioBlockReader,push mode, start(QIODevice),不行 ## if self.ui.radioSaveMode_External.isChecked(): ## self.externalReader = QmyAudioReader() ## self.externalReader.open(QIODevice.WriteOnly) ## self.externalReader.updateBlockInfo.connect(self.do_updateBlockInfo) ## self.audioDevice.start(self.externalReader) #使用外建的IODevice ##3. 写入文件,用 start(QIODevice)启动 if self.ui.radioSaveMode_QFile.isChecked(): self.recordFile.setFileName("test.raw") self.recordFile.open(QIODevice.WriteOnly) self.audioDevice.start(self.recordFile) @pyqtSlot() ##停止音频输入 def on_actStop_triggered(self): self.audioDevice.stop() self.audioDevice.deleteLater() ##1. 使用 QIODevice =start()返回的内置的IODevice, pull mode,利用readyRead()信号读出数据 #无需处理,停止后self.ioDevice自动变为无效 ##2. 外部IODevice接收音频输入数据的流设备 ## if self.ui.radioSaveMode_External.isChecked(): ## self.externalReader.close() ## self.externalReader.updateBlockSize.disconnect(self.do_updateBlockInfo) ## del self.externalReader #删除外建设备 ##3. 写入文件,start(QIODevice) 启动 if self.ui.radioSaveMode_QFile.isChecked(): self.recordFile.close() #关闭文件 ## =============自定义槽函数=============================== ##1. 使用QIODevice* start()返回的内置的IODevice, pull mode,利用readyRead()信号读出数据 def do_IO_readyRead(self): ##内建IODevice,读取缓冲区数据 self.ui.LabBufferSize.setText("bufferSize()=%d" %self.audioDevice.bufferSize()) byteCount = self.audioDevice.bytesReady() #可以读取的字节数 self.ui.LabBytesReady.setText("bytesReady()=%d"%byteCount) if byteCount>self.BUFFER_SIZE: byteCount=self.BUFFER_SIZE buffer=self.ioDevice.read(byteCount) #返回的是bytes类型,便于处理 ## buffer=self.ioDevice.readAll() #不能用readAll()读取,返回的是QByteArray,需要再转换为bytes ## print(type(buffer)) ## print(buffer) maxSize=len(buffer) ## print(maxSize) self.ui.LabBlockSize.setText("IODevice数据字节数=%d"%maxSize) maxV=0 minV=255 for k in range(maxSize): V=buffer[k] #取一个字节,整数 if V>maxV: maxV=V #求最大值 if V<minV: minV=V #求最小值 self.ui.progBar_Max.setValue(maxV) self.ui.progBar_Min.setValue(minV) self.ui.progBar_Diff.setValue(maxV-minV) def do_stateChanged(self,state): ##设备状态变化 isStoped=(state== QAudio.StoppedState) #停止状态 self.ui.groupBox_saveMode.setEnabled(isStoped) self.ui.sliderVolumn.setEnabled(isStoped) self.ui.actStart.setEnabled(isStoped) self.ui.actStop.setEnabled(not isStoped) self.ui.actDeviceTest.setEnabled(isStoped) self.ui.sliderVolumn.setEnabled(isStoped) if state== QAudio.ActiveState: self.ui.statusBar.showMessage("state: ActiveState") elif state== QAudio.SuspendedState: self.ui.statusBar.showMessage("state: SuspendedState") elif state== QAudio.StoppedState: self.ui.statusBar.showMessage("state: StoppedState") elif state== QAudio.IdleState: self.ui.statusBar.showMessage("state: IdleState") elif state== QAudio.InterruptedState: self.ui.statusBar.showMessage("state: InterruptedState")
class LogFilePositionSource(QGeoPositionInfoSource): def __init__(self, parent=None): super().__init__(parent) self.lastPosition = QGeoPositionInfo() self.logFile = QFile(self) self.timer = QTimer(self) self.timer.timeout.connect(self.readNextPosition) self.logFile.setFileName(":/simplelog.txt") if not self.logFile.open(QIODevice.ReadOnly): print("Error: cannot open source file", self.logFile.fileName()) def lastKnownPosition(self, fromSatellitePositioningMethodsOnly=False): return self.lastPosition def supportedPositioningMethods(self): return QGeoPositionInfoSource.AllPositioningMethods def minimumUpdateInterval(self): return 500 def error(self): return QGeoPositionInfoSource.NoError def startUpdates(self): interval = self.updateInterval() if interval < self.minimumUpdateInterval(): interval = self.minimumUpdateInterval() self.timer.start(interval) def stopUpdates(self): self.timer.stop() def requestUpdate(self, timeout=5000): # For simplicity, ignore timeout - assume that if data is not available # now, no data will be added to the file later if self.logFile.canReadLine(): self.readNextPosition() else: self.updateTimeout.emit() def readNextPosition(self): line = self.logFile.readLine().trimmed() if not line.isEmpty(): data = line.split(" ") latitude = 0 longitude = 0 hasLatitude = False hasLongitude = False timestamp = QDateTime.fromString(data[0].data().decode(), Qt.ISODate) latitude, hasLatitude = data[1].toDouble() longitude, hasLongitude = data[2].toDouble() if hasLatitude and hasLongitude and timestamp.isValid(): coordinate = QGeoCoordinate(latitude, longitude) info = QGeoPositionInfo(coordinate, timestamp) if info.isValid(): self.lastPosition = info self.positionUpdated.emit(info)
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.storageLocation( QStandardPaths.TempLocation) 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 = "" if self.__reply.hasRawHeader("Content-Disposition"): header = bytes(self.__reply.rawHeader("Content-Disposition"))\ .decode() if header: pos = header.find("filename=") if pos != -1: path = header[pos + 9:] if path.startswith('"') and path.endswith('"'): path = path[1:-1] if not path: path = self.__url.path() info = QFileInfo(path) baseName = info.completeBaseName() endName = info.suffix() if not baseName: baseName = "unnamed_download" 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 timeRemaining = (self.bytesTotal() - self.bytesReceived()) / self.currentSpeed() # 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