def copy_embedded_file(src_name, dst_name, macros={}): """ Copy an embedded source file to a destination file. src_name is the name of the source file. dst_name is the name of the destination file. macros is an optional dictionary of key/value string macros and instances of each key are replaced by the corresponding value. A UserException is raised if there was an error. """ contents = read_embedded_file(src_name) for key, value in macros.items(): contents.replace(bytes(key, encoding='ascii'), bytes(value, encoding='ascii')) dst_file = QFile(dst_name) if not dst_file.open(QIODevice.WriteOnly|QIODevice.Text): raise UserException( "Unable to create file {0}.".format(dst_file.fileName()), dst_file.errorString()) if dst_file.write(contents) < 0: raise UserException( "Unable to write to file {0}.".format(dst_file.fileName()), dst_file.errorString()) dst_file.close()
def copy_embedded_file(src_name, dst_name, macros={}): """ Copy an embedded source file to a destination file. src_name is the name of the source file. dst_name is the name of the destination file. macros is an optional dictionary of key/value string macros and instances of each key are replaced by the corresponding value. A UserException is raised if there was an error. """ contents = read_embedded_file(src_name) for key, value in macros.items(): contents.replace(bytes(key, encoding='ascii'), bytes(value, encoding='ascii')) dst_file = QFile(dst_name) if not dst_file.open(QIODevice.WriteOnly | QIODevice.Text): raise UserException( "Unable to create file {0}.".format(dst_file.fileName()), dst_file.errorString()) if dst_file.write(contents) < 0: raise UserException( "Unable to write to file {0}.".format(dst_file.fileName()), dst_file.errorString()) dst_file.close()
def resolveExeFile(self, name): dir = self.resolveDir(name) fileName = self.info[name]["filename"].split("/")[-1] pyFile = QFile(dir.path() + "/" + fileName + ".py") if pyFile.exists(): return pyFile.fileName() pywFile = QFile(dir.path() + "/" + fileName + ".pyw") if pywFile.exists(): return pywFile.fileName() Colors.debug("- WARNING: Could not resolve executable:", dir.path(), fileName) return "__executable not found__"
def construct_multipart(self, data, files): multi_part = QtNetwork.QHttpMultiPart( QtNetwork.QHttpMultiPart.FormDataType) for key, value in data.items(): post_part = QtNetwork.QHttpPart() post_part.setHeader( QtNetwork.QNetworkRequest.ContentDispositionHeader, "form-data; name=\"{}\"".format(key)) post_part.setBody(str(value).encode()) multi_part.append(post_part) for field, filepath in files.items(): if filepath: file = QFile(filepath) if not file.open(QIODevice.ReadOnly): break post_part = QtNetwork.QHttpPart() post_part.setHeader( QtNetwork.QNetworkRequest.ContentDispositionHeader, "form-data; name=\"{}\"; filename=\"{}\"".format( field, file.fileName())) post_part.setBodyDevice(file) file.setParent(multi_part) multi_part.append(post_part) else: break return multi_part
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 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 resolveExeFile(self, name): dir = self.resolveDir(name) fileName = self.info[name]['filename'].split('/')[-1] pyFile = QFile(dir.path() + '/' + fileName + '.py') if pyFile.exists(): return pyFile.fileName() pywFile = QFile(dir.path() + '/' + fileName + '.pyw') if pywFile.exists(): return pywFile.fileName() Colors.debug("- WARNING: Could not resolve executable:", dir.path(), fileName) return '__executable not found__'
def sendBackFile(self, socket, filePath): # file = QFile(filePath) print(file.size()) count = 0 with open(filePath, 'rb') as f: while 1: sleep(0.1) filedata = f.read(20480) if not filedata: break reply = QByteArray() stream = QDataStream(reply, QIODevice.WriteOnly) stream.setVersion(QDataStream.Qt_5_7) stream.writeUInt16(0) stream.writeQString('SENDFILE') stream.writeQString(file.fileName()) stream.writeInt(file.size()) stream.writeBytes(filedata) stream.device().seek(0) stream.writeUInt16(reply.size() - SIZEOF_UINT16) socket.write(reply) socket.waitForBytesWritten() count = count + filedata.__len__() print(count)
def openFile(self, svg_file: QFile): if not svg_file.exists(): return if self.backgroundItem: drawBackground = self.backgroundItem.isVisible() else: drawBackground = False s = self.scene() s.clear() self.resetTransform() self.svgItem = QGraphicsSvgItem(svg_file.fileName()) self.svgItem.setFlags(QGraphicsItem.ItemClipsToShape) self.svgItem.setCacheMode(QGraphicsItem.NoCache) self.svgItem.setZValue(0) tmp = self.svgItem.renderer().defaultSize() self.default_width = tmp.width() self.default_height = tmp.height() self.backgroundItem = QGraphicsRectItem(self.svgItem.boundingRect()) self.backgroundItem.setBrush(Qt.white) self.backgroundItem.setPen(QPen(Qt.NoPen)) self.backgroundItem.setVisible(drawBackground) self.backgroundItem.setZValue(-1) s.addItem(self.backgroundItem) s.addItem(self.svgItem)
def sendFileBytes(self, stream, filePath, fileBytes): # stream 由装饰器传值 状态 文件名 文件字节 file = QFile(filePath) print(filePath) stream.writeQString('sendFile') # 发送文件 状态 stream.writeQString(file.fileName()) # 发送文件的名字 print(file.size()) stream.writeQString(str(file.size())) # 发送文件的大小 stream.writeBytes(fileBytes)
def dropEvent(self, event): event.ignore() return if event.source(): QTreeView.dropEvent(self, event) else: ix = self.indexAt(event.pos()) if not self.model().isDir(ix): ix = ix.parent() pathDir = self.model().filePath(ix) if not pathDir: pathDir = self.model().filePath(self.rootIndex()) m = event.mimeData() if m.hasUrls(): urlLocals = [url for url in m.urls() if url.isLocalFile()] accepted = False for urlLocal in urlLocals: path = urlLocal.toLocalFile() info = QFileInfo(path) n_path = QDir(pathDir).filePath(info.fileName()) o_path = info.absoluteFilePath() if n_path == o_path: continue if info.isDir(): if QDir(n_path).exists(): reply = QMessageBox.question( self, '提示', '所选的分组中存在同名文件夹,是否全部覆盖?', QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: shutil.rmtree(n_path) shutil.copytree(o_path, n_path) else: print(o_path) for file in os.walk(o_path): print(file) shutil.copytree(o_path, n_path) self.strategy_filters.append( os.path.split(n_path)[1]) self._model.setNameFilters(self.strategy_filters) else: qfile = QFile(o_path) fname = qfile.fileName() if not fname.endswith('.py'): QMessageBox.warning(self, "提示", "暂不支持该类型文件", QMessageBox.Yes) if QFile(n_path).exists(): reply = QMessageBox.question( self, '提示', '所选的分组中存在同名文件,是否覆盖?', QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: shutil.copy(o_path, n_path) # qfile.rename(n_path) accepted = True if accepted: event.acceptProposedAction()
def resolveQmlFile(self, name): dir = self.resolveDir(name) fileName = self.info[name]['filename'].split('/')[-1] qmlFile = QFile(dir.path() + '/' + fileName + '.qml') if qmlFile.exists(): return qmlFile.fileName() Colors.debug("- WARNING: Could not resolve QML file:", dir.path(), fileName) return '__QML not found__'
def sauvertexte(self): filename, _ = QFileDialog.getSaveFileName(self) if filename: file = QFile(filename) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.critical(self, appname + version + "Save", "Writing Error %s:\n%s." % (filename, file.errorString())) return outstr = QTextStream(file) outstr << self.ui.plainTextEdit.toPlainText() QMessageBox.information(self, appname + version + "Save file", "The file is saved. \n%s" % (file.fileName()))
def resolveQmlFile(self, name): dir = self.resolveDir(name) fileName = self.info[name]["filename"].split("/")[-1] qmlFile = QFile(dir.path() + "/" + fileName + ".qml") if qmlFile.exists(): return qmlFile.fileName() Colors.debug("- WARNING: Could not resolve QML file:", dir.path(), fileName) return "__QML not found__"
def sauvertexte(self): filename, _ = QFileDialog.getSaveFileName(self) if filename: file = QFile(filename) if not file.open(QFile.WriteOnly | QFile.Text): QMessageBox.critical( self, appname + version + "Save", "Writing Error %s:\n%s." % (filename, file.errorString())) return outstr = QTextStream(file) outstr << self.ui.plainTextEdit.toPlainText() QMessageBox.information( self, appname + version + "Save file", "The file is saved. \n%s" % (file.fileName()))
def create_beep(beep_count, beep_notif): one_beep_tmp = '.\\media\\beep-01.mp3' if pathlib.Path(beep_notif).exists(): pathlib.Path(beep_notif).unlink() if not pathlib.Path(one_beep_tmp).exists(): beep = QFile("://audio/beep-01a.mp3") QFile.copy(beep.fileName(), one_beep_tmp) destination = open(beep_notif, 'wb') for i in range(1, beep_count + 1): beep_tmp = open(one_beep_tmp, 'rb') shutil.copyfileobj(beep_tmp, destination) beep_tmp.close() destination.close() pathlib.Path(one_beep_tmp).chmod(33206) pathlib.Path(one_beep_tmp).unlink()
def read_embedded_file(src_name): """ Return the contents of an embedded source file as a QByteArray. src_name is the name of the source file. A UserException is raised if there was an error. """ src_file = QFile(src_name) if not src_file.open(QIODevice.ReadOnly | QIODevice.Text): raise UserException("Unable to open file {0}.".format(src_file.fileName()), src_file.errorString()) contents = src_file.readAll() src_file.close() return contents
def read_embedded_file(src_name): """ Return the contents of an embedded text file as a QByteArray. src_name is the name of the file. A UserException is raised if there was an error. """ src_file = QFile(src_name) if not src_file.open(QIODevice.ReadOnly|QIODevice.Text): raise UserException( "Unable to open file {0}.".format(src_file.fileName()), src_file.errorString()) contents = src_file.readAll() src_file.close() return contents
def open_file(self, filename): svg_file = QFile(filename) if not svg_file.exists(): return self.file_name = svg_file self.resetTransform() self.scale(2.0, 2.0) svg_item = QGraphicsSvgItem(svg_file.fileName()) svg_item.setFlags(QGraphicsItem.ItemClipsToShape) svg_item.setCacheMode(QGraphicsItem.NoCache) svg_item.setZValue(0) s = self.scene() s.clear() s.addItem(svg_item)
def open_file(self, filename): png_file = QFile(filename) if not png_file.exists(): return self.file_name = png_file self.resetTransform() self.scale(2.0, 2.0) pixmap = QPixmap(png_file.fileName()) png_item = QGraphicsPixmapItem(pixmap) png_item.setFlags(QGraphicsItem.ItemClipsToShape) png_item.setCacheMode(QGraphicsItem.NoCache) png_item.setZValue(0) s = self.scene() s.clear() s.addItem(png_item)
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 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 Document(QObject): file = None # type: QFile database = None # type: QSqlDatabase tmp_directory = None # type: str error_occurred = pyqtSignal(DocumentError) document_created = pyqtSignal() document_disposed = pyqtSignal() def __init__(self): QObject.__init__(self) self.init_tmp_directory() @property def path(self) -> str: if self.file is None: return self.name else: return self.file.fileName() @property def name(self) -> str: _translate = QCoreApplication.translate if self.file is not None: return QFileInfo(self.file.fileName()).fileName() else: # noinspection PyArgumentList, PyTypeChecker return _translate("DocumentService", "Untitled") pass pass @property def question_types(self) -> List[str]: question_type_list = [] # type: List[str] query_command = "SELECT * FROM 'question_type'" query = QSqlQuery(self.database) if not query.exec(query_command): raise ConnectionError(query.lastError().text()) question_type_field_id = query.record().indexOf('name') while query.next(): question_type_list.append( query.value(question_type_field_id) ) return question_type_list @property def properties(self) -> Dict[str, str]: return {} @property def is_modified(self) -> bool: return False def new(self): self.init_tmp_directory() # noinspection PyTypeChecker,PyCallByClass self.database = QSqlDatabase.addDatabase('QSQLITE', ':memory:') self.init_database() self.document_created.emit() def open(self, path: str): _translate = QCoreApplication.translate self.file = QFile(path) if self.file.exists(): file_path = self.file.fileName() # type: str open_gnl_file_result = self.open_gnl_file(file_path, self.tmp_directory) logger.debug(open_gnl_file_result) logger.debug(isinstance(open_gnl_file_result, ZippedDocument)) if isinstance(open_gnl_file_result, ZippedDocument): zip_file = open_gnl_file_result # type: ZipFile # noinspection PyTypeChecker,PyCallByClass self.database = QSqlDatabase.cloneDatabase( zip_file.database, ':memory:' ) self.init_database() zip_file.close() self.document_created.emit() else: self.error_occurred.emit(open_gnl_file_result) else: self.file = None selected_file_does_not_exist = _translate( "DocumentService", "The selected file ({}) does not exist." ) self.error_occurred.emit( DocumentError( selected_file_does_not_exist.format( path ) ) ) def init_database(self): success = self.database.open() if not success: raise ConnectionError(self.database.lastError().text()) query = QSqlQuery(self.database) query_command = "CREATE TABLE IF NOT EXISTS 'question_type' ({}{}{})".format( 'id integer primary key,', 'name text,', 'position integer' ) if not query.exec(query_command): raise ConnectionError(query.lastError().text()) def init_tmp_directory(self): self.tmp_directory = mkdtemp() def dispose(self): self.file = None if self.database: self.database.close() self.database = None shutil.rmtree(self.tmp_directory) self.document_disposed.emit() @staticmethod def open_gnl_file(file_path: str, tmp_directory: str) -> Union['ZippedDocument', DocumentError]: _translate = QCoreApplication.translate output = None # type: Union[ZippedDocument, DocumentError] try: zip_file = ZippedDocument.open(file_path, tmp_directory) output = zip_file except BadZipFile as e: # noinspection PyArgumentList, PyTypeChecker file_not_valid = _translate( "DocumentService", "The file ({}) is not a valid .gnl file." ) output = DocumentError( file_not_valid.format( file_path ), e ) except LargeZipFile as e: # noinspection PyArgumentList, PyTypeChecker file_too_big = _translate( "DocumentService", "The file ({}) is too big." ) output = DocumentError( file_too_big.format( file_path ), e ) except SqlError as e: # noinspection PyArgumentList, PyTypeChecker database_corrupted = _translate( "DocumentService", "The internal database of the file ({}) is corrupted." ) output = DocumentError( database_corrupted.format( file_path ), e ) except Exception as e: # noinspection PyArgumentList, PyTypeChecker unhandled_error = _translate( "DocumentService", "An unhandled error." ) output = DocumentError( unhandled_error, e ) finally: assert isinstance(output, ZippedDocument) or isinstance(output, DocumentError) return output
def accept(self): className = self.field('className') baseClass = self.field('baseClass') macroName = self.field('macroName') baseInclude = self.field('baseInclude') outputDir = self.field('outputDir') header = self.field('header') implementation = self.field('implementation') block = '' if self.field('comment'): block += '/*\n' block += ' ' + header + '\n' block += '*/\n' block += '\n' if self.field('protect'): block += '#ifndef ' + macroName + '\n' block += '#define ' + macroName + '\n' block += '\n' if self.field('includeBase'): block += '#include ' + baseInclude + '\n' block += '\n' block += 'class ' + className if baseClass: block += ' : public ' + baseClass block += '\n' block += '{\n' if self.field('qobjectMacro'): block += ' Q_OBJECT\n' block += '\n' block += 'public:\n' if self.field('qobjectCtor'): block += ' ' + className + '(QObject *parent = 0);\n' elif self.field('qwidgetCtor'): block += ' ' + className + '(QWidget *parent = 0);\n' elif self.field('defaultCtor'): block += ' ' + className + '();\n' if self.field('copyCtor'): block += ' ' + className + '(const ' + className + ' &other);\n' block += '\n' block += ' ' + className + ' &operator=' + '(const ' + className + ' &other);\n' block += '};\n' if self.field('protect'): block += '\n' block += '#endif\n' headerFile = QFile(outputDir + '/' + header) if not headerFile.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning(None, "Class Wizard", "Cannot write file %s:\n%s" % (headerFile.fileName(), headerFile.errorString())) return headerFile.write(block) block = '' if self.field('comment'): block += '/*\n' block += ' ' + implementation + '\n' block += '*/\n' block += '\n' block += '#include "' + header + '"\n' block += '\n' if self.field('qobjectCtor'): block += className + '::' + className + '(QObject *parent)\n' block += ' : ' + baseClass + '(parent)\n' block += '{\n' block += '}\n' elif self.field('qwidgetCtor'): block += className + '::' + className + '(QWidget *parent)\n' block += ' : ' + baseClass + '(parent)\n' block += '{\n' block += '}\n' elif self.field('defaultCtor'): block += className + '::' + className + '()\n' block += '{\n' block += ' // missing code\n' block += '}\n' if self.field('copyCtor'): block += '\n' block += className + '::' + className + '(const ' + className + ' &other)\n' block += '{\n' block += ' *this = other;\n' block += '}\n' block += '\n' block += className + ' &' + className + '::operator=(const ' + className + ' &other)\n' block += '{\n' if baseClass: block += ' ' + baseClass + '::operator=(other);\n' block += ' // missing code\n' block += ' return *this;\n' block += '}\n' implementationFile = QFile(outputDir + '/' + implementation) if not implementationFile.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning(None, "Class Wizard", "Cannot write file %s:\n%s" % (implementationFile.fileName(), implementationFile.errorString())) return implementationFile.write(block) super(ClassWizard, self).accept()
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 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 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
class PluginRequestDialog(QDialog,Ui_PluginRequestDialog): """ the plugin install dialog """ def __init__(self,parent=None): QDialog.__init__(self,parent) self.setupUi(self) #center this window screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2) QObject.connect(self.pluginList, SIGNAL("customContextMenuRequested (const QPoint&)"),self.__evt_contextmenu) QObject.connect(self.update,SIGNAL("clicked ()"),self.__evt_update) self.__http = None self.__downloadFile = None self.__baseUrl = "http://localhost/" self.plugin_txt_url.setText("%splugins.txt"%self.__baseUrl) self.__evt_update() def __evt_update(self): self.progressBar.setValue(0) self.download(QUrl(self.plugin_txt_url.text())) def download(self,url): """ download something """ if None == self.__http: self.__http = QHttp() QObject.connect(self.__http, SIGNAL("done(bool)"), self.__downloadFileDone) QObject.connect(self.__http, SIGNAL("dataReadProgress(int, int)"), self.__dataReadProgress) if QUrl(url).scheme() == 'https': connectionMode = QHttp.ConnectionModeHttps else: connectionMode = QHttp.ConnectionModeHttp self.__http.setHost(url.host(),connectionMode,url.port(80)) self.__downloadFile = QFile(tempfile.NamedTemporaryFile().name) self.__http.get(url.path(),self.__downloadFile) def __downloadFileDone(self, error): """ Private method called, after the file has been downloaded from the internet. @param error flag indicating an error condition (boolean) """ if self.__downloadFile.exists(): filename = self.__downloadFile.fileName() #Notice must flush it first self.__downloadFile.flush() if not zipfile.is_zipfile(filename): plugins_info = open(filename).readlines() self.pluginList.clear() for plugin_info in plugins_info: try: plugin_name = plugin_info.split('|')[0] plugin_version = plugin_info.split('|')[1] plugin_instruction = plugin_info.split('|')[2] plugin_author = plugin_info.split('|')[3] itree = QTreeWidgetItem() itree.setText(0,plugin_name) itree.setText(1,plugin_author) itree.setText(2,plugin_version) itree.setText(3,plugin_instruction) self.pluginList.addTopLevelItem(itree) except Exception as e: raise e else: pluginDir = getPrccisePath("pluginsDir", "", "extdir") if sys.platform.startswith("win") else getPrccisePath("pluginsDir", "", "userdir") tmpZip = zipfile.ZipFile(filename) for file in tmpZip.namelist(): tmpZip.extract(file,pluginDir) tmpZip.close() self.result_label.setText("Success install the plugin ") def __dataReadProgress(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) """ self.progressBar.setMaximum(total) self.progressBar.setValue(done) def __has_this_plugin(self,plugin_name): """ Check if this plugin has installed """ for item in PluginAdapter().new().readInfos(): if item[0]==plugin_name: return item return None def __evt_contextmenu(self,point): """ show the right menu """ item = self.pluginList.currentItem() if item: menu = QMenu(self) action = QAction(QApplication.translate("default","Install plugins..."),self,triggered=lambda:self.__evt_install_plugin(item)) menu.addAction(action) action = QAction(QApplication.translate("default","Uninstall plugins..."),self) menu.addAction(action) menu.exec_(self.mapToGlobal(self.pluginList.mapTo(self,point))) def __evt_install_plugin(self,item): filename = "plugin-%s-%s.zip"%(item.text(0),item.text(2)) if not None == self.__has_this_plugin(item.text(0)): self.download(QUrl("%s%s"%(self.__baseUrl,filename))) else: self.result_label.setText("This plugin '%s' had installed "%item.text(0))
class LayoutBox(QVBoxLayout): def __init__(self): super().__init__() self.profileGroup = QGroupBox("Profile") self.profileLabel = QLabel("none") self.profileSelect = QPushButton("Open...") self.profileSelect.clicked.connect(self.openProfileClick) self.profileSave = QPushButton("Save") self.profileSave.clicked.connect(self.saveProfileClick) self.profileSave.setEnabled(False) self.profileBox = QHBoxLayout() self.profileBox.addWidget(self.profileLabel) self.profileBox.addStretch() self.profileBox.addWidget(self.profileSelect) self.profileBox.addWidget(self.profileSave) self.profileGroup.setLayout(self.profileBox) self.filesBox = FilesBox() self.filesBox.buttonBox.setEnable(False) # self.filesBox.availableTweaks.setEnabled(False) # self.filesBox.selectedTweaks.setEnabled(False) # self.filesBox.availableTweaks.itemClicked.connect(self.availClick) self.filesBox.selectedTweaks.itemClicked.connect(self.selectClick) self.descriptionGroup = QGroupBox("Tweak description") self.descriptionGroup.setMinimumHeight(50) self.description = QLabel("") self.description.setTextInteractionFlags(Qt.TextInteractionFlags(5)) self.descriptionBox = QHBoxLayout() self.descriptionBox.addWidget(self.description) self.descriptionGroup.setLayout(self.descriptionBox) self.addWidget(self.profileGroup) self.addItem(self.filesBox) self.addWidget(self.descriptionGroup) self.profileDir = QDir() self.profilePathDialog = QFileDialog() self.profilePath = "" self.appDir = QDir().current() def openProfileClick(self): #Button Open... click self.profilePath = self.profilePathDialog.getExistingDirectory( self.profileSelect, "Select Firefox profile") # self.profilePath = "~/Library/Application Support/Firefox/Profiles/rpk2uobe.default" logging.debug("Selected directory: \"%s\"", self.profilePath) if self.profilePath != "": self.selectedProfile = QDir(self.profilePath) self.firefoxDir = QDir(self.profilePath) logging.debug("Selected profile qdir: %s", self.selectedProfile.path()) self.firefoxDir.cdUp() self.profilesFile = QFile(self.firefoxDir.path() + "/profiles.ini") logging.debug("Profiles file: %s", self.profilesFile.fileName()) logging.debug("Profiles file exists: %s", self.profilesFile.exists()) logging.debug("Firefox folder: %s", self.firefoxDir.dirName()) # Basic check if parent directory is named 'firefox' and contains a file named 'profiles.ini' #if self.firefoxDir.dirName() == "firefox" and self.profilesFile.exists(): if True: self.profilePath = self.profilePath self.profileLabel.setText(self.profilePath) self.filesBox.buttonBox.setEnable(True) self.filesBox.availableTweaks.setEnabled(True) self.filesBox.selectedTweaks.setEnabled(True) self.profileSave.setEnabled(True) self.profileDir.setPath(self.profilePath) logging.debug("Profile dirs: %s", self.profileDir.entryList()) self.userChrome = QFile( self.profilePath + "/chrome/userChrome.css") self.userFFSettings = QFile( self.profilePath + "/chrome/userFirefox.json") logging.debug("userChrome exists: %s", self.userChrome.exists()) if self.userChrome.exists( ) and not self.userFFSettings.exists(): self.backupChrome = QMessageBox() self.backupChrome.setIcon(QMessageBox.Question) self.backupChrome.setText( "userChrome.css file already exists in this profile. This may be overwritten. Do you want to make a backup?" ) self.backupChrome.setStandardButtons( QMessageBox.StandardButtons(81920)) #yes, no self.backupChrome.exec() logging.debug("Dialog result: %s", self.backupChrome.result()) if self.backupChrome.result() == 16384: #yes logging.debug("Backing up userChrome") self.backupDone = QMessageBox() self.backupFile = QFile( self.profilePath + "/chrome/userChrome.css~") logging.debug("Backup file: %s", self.backupFile.fileName()) logging.debug("Backup exists: %s", self.backupFile.exists()) if self.backupFile.exists(): logging.debug("Backup already exists") self.backupDone.setIcon(QMessageBox.Warning) self.backupDone.setText( "Backup already exists. The file was NOT overwritten and new backup not made." ) else: if self.userChrome.copy(self.profilePath + "/chrome/userChrome.css~"): self.backupDone.setIcon( QMessageBox.Information) self.backupDone.setText( "Backed up to 'userChrome.css~'") else: self.backupDone.setIcon(QMessageBox.Critical) self.backupDone.setText("Backing up failed.") self.backupDone.exec() elif self.backupChrome.result() == 65536: #no logging.debug("Not backing up userChome") # Load existing settings try: with open(self.profilePath + "/chrome/userFirefox.json" ) as uFP: savedTweaks = json.load(uFP) logging.debug("Loaded json settings: %s", savedTweaks) for loadedTweak in savedTweaks: logging.debug( "Loaded tweak. check: %i, category: %s, name: %s", loadedTweak["Enabled"], loadedTweak["Category"], loadedTweak["Name"]) tweakCat = loadedTweak["Category"] tweakName = loadedTweak["Name"] self.filesBox.tweaksAdded[ tweakCat + tweakName] = QTreeWidgetItem( self.filesBox.selectedTweaks) self.filesBox.tweaksAdded[tweakCat + tweakName].setCheckState( 0, loadedTweak["Enabled"]) self.filesBox.tweaksAdded[tweakCat + tweakName].setText( 1, tweakCat) self.filesBox.tweaksAdded[tweakCat + tweakName].setText( 2, tweakName) except FileNotFoundError: pass self.filesBox.resizeColumns() else: self.noProfile = QMessageBox() self.noProfile.setIcon(QMessageBox.Warning) self.noProfile.setText( "The selected directory does not appear to be a valid Firefox profile. Profiles are usually located at '~/.mozilla/firefox/xxxx' and is most likely a hidden directory." ) self.noProfile.exec() def availClick(self): if self.filesBox.availableTweaks.currentItem().parent() is not None: tweakName = self.filesBox.availableTweaks.currentItem().text(0) tweakCat = self.filesBox.availableTweaks.currentItem().parent( ).text(0) self.showDesc(tweakCat, tweakName) def selectClick(self): try: tweakName = self.filesBox.selectedTweaks.currentItem().text(2) tweakCat = self.filesBox.selectedTweaks.currentItem().text(1) self.showDesc(tweakCat, tweakName) except: pass def showDesc(self, category, name): logging.debug("Showing description for %s/%s: ", category, name) currentDir = QDir().current().path() tweakPath = currentDir + "/" + category + "/" + name logging.debug("Loading %s", tweakPath) tweakDesc = "" descLines = 0 with open(tweakPath) as tweakContent: for line in tweakContent: if (re.search("^(\/\* ?)|( \* ?)|( \*\/)", line) is not None): if len(line) > 3: trimmedLine = line[3:] tweakDesc += trimmedLine descLines += 1 else: break logging.debug("Description: %s", tweakDesc) self.description.setText(tweakDesc) logging.debug("Desc lines: %i", descLines) def saveProfileClick(self): logging.debug("Saving profile") self.saveQuestion = QMessageBox() self.saveQuestion.setIcon(QMessageBox.Question) self.saveQuestion.setStandardButtons( QMessageBox.StandardButtons(81920)) #yes, no self.saveQuestion.setText( "Do you want to apply selected tweaks and overwrite userChrome?") self.saveQuestion.exec() self.saveCSS = "" if self.saveQuestion.result() == 16384: #yes logging.debug("Saving userChrome") selTweaksNumber = self.filesBox.selectedTweaks.topLevelItemCount() savingTweaks = [] for i in range(selTweaksNumber): currentSavingTweak = self.filesBox.selectedTweaks.topLevelItem( i) currentSavingData = {} currentSavingData["Enabled"] = currentSavingTweak.checkState(0) currentSavingData["Category"] = currentSavingTweak.text(1) currentSavingData["Name"] = currentSavingTweak.text(2) logging.debug("Tweak cat %s, name %s, selected %s", currentSavingData["Category"], currentSavingData["Name"], currentSavingData["Enabled"]) savingTweaks.append(currentSavingData) if currentSavingData["Enabled"] == 2: with open(self.appDir.path() + "/" + currentSavingData["Category"] + "/" + currentSavingData["Name"]) as twkFile: self.saveCSS += twkFile.read() + "\n" logging.debug("Selected tweaks: %s", savingTweaks) with open(self.profilePath + "/chrome/userFirefox.json", "w") as fp: json.dump(savingTweaks, fp) logging.debug("userChrome.css: %s", self.saveCSS) with open(self.profilePath + "/chrome/userChrome.css", "w") as fp: fp.write(self.saveCSS) elif self.saveQuestion.result() == 65536: #no logging.debug("Not saving userChrome.")
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
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 = ""
class Document(QObject): file = None # type: QFile database = None # type: QSqlDatabase tmp_directory = None # type: str error_occurred = pyqtSignal(DocumentError) document_created = pyqtSignal() document_disposed = pyqtSignal() def __init__(self): QObject.__init__(self) self.init_tmp_directory() @property def path(self) -> str: if self.file is None: return self.name else: return self.file.fileName() @property def name(self) -> str: _translate = QCoreApplication.translate if self.file is not None: return QFileInfo(self.file.fileName()).fileName() else: # noinspection PyArgumentList, PyTypeChecker return _translate("DocumentService", "Untitled") pass pass @property def question_types(self) -> List[str]: question_type_list = [] # type: List[str] query_command = "SELECT * FROM 'question_type'" query = QSqlQuery(self.database) if not query.exec(query_command): raise ConnectionError(query.lastError().text()) question_type_field_id = query.record().indexOf('name') while query.next(): question_type_list.append(query.value(question_type_field_id)) return question_type_list @property def properties(self) -> Dict[str, str]: return {} @property def is_modified(self) -> bool: return False def new(self): self.init_tmp_directory() # noinspection PyTypeChecker,PyCallByClass self.database = QSqlDatabase.addDatabase('QSQLITE', ':memory:') self.init_database() self.document_created.emit() def open(self, path: str): _translate = QCoreApplication.translate self.file = QFile(path) if self.file.exists(): file_path = self.file.fileName() # type: str open_gnl_file_result = self.open_gnl_file(file_path, self.tmp_directory) logger.debug(open_gnl_file_result) logger.debug(isinstance(open_gnl_file_result, ZippedDocument)) if isinstance(open_gnl_file_result, ZippedDocument): zip_file = open_gnl_file_result # type: ZipFile # noinspection PyTypeChecker,PyCallByClass self.database = QSqlDatabase.cloneDatabase( zip_file.database, ':memory:') self.init_database() zip_file.close() self.document_created.emit() else: self.error_occurred.emit(open_gnl_file_result) else: self.file = None selected_file_does_not_exist = _translate( "DocumentService", "The selected file ({}) does not exist.") self.error_occurred.emit( DocumentError(selected_file_does_not_exist.format(path))) def init_database(self): success = self.database.open() if not success: raise ConnectionError(self.database.lastError().text()) query = QSqlQuery(self.database) query_command = "CREATE TABLE IF NOT EXISTS 'question_type' ({}{}{})".format( 'id integer primary key,', 'name text,', 'position integer') if not query.exec(query_command): raise ConnectionError(query.lastError().text()) def init_tmp_directory(self): self.tmp_directory = mkdtemp() def dispose(self): self.file = None if self.database: self.database.close() self.database = None shutil.rmtree(self.tmp_directory) self.document_disposed.emit() @staticmethod def open_gnl_file( file_path: str, tmp_directory: str) -> Union['ZippedDocument', DocumentError]: _translate = QCoreApplication.translate output = None # type: Union[ZippedDocument, DocumentError] try: zip_file = ZippedDocument.open(file_path, tmp_directory) output = zip_file except BadZipFile as e: # noinspection PyArgumentList, PyTypeChecker file_not_valid = _translate( "DocumentService", "The file ({}) is not a valid .gnl file.") output = DocumentError(file_not_valid.format(file_path), e) except LargeZipFile as e: # noinspection PyArgumentList, PyTypeChecker file_too_big = _translate("DocumentService", "The file ({}) is too big.") output = DocumentError(file_too_big.format(file_path), e) except SqlError as e: # noinspection PyArgumentList, PyTypeChecker database_corrupted = _translate( "DocumentService", "The internal database of the file ({}) is corrupted.") output = DocumentError(database_corrupted.format(file_path), e) except Exception as e: # noinspection PyArgumentList, PyTypeChecker unhandled_error = _translate("DocumentService", "An unhandled error.") output = DocumentError(unhandled_error, e) finally: assert isinstance(output, ZippedDocument) or isinstance( output, DocumentError) return output
class PluginRequestDialog(QDialog, Ui_PluginRequestDialog): """ the plugin install dialog """ def __init__(self, parent=None): QDialog.__init__(self, parent) self.setupUi(self) #center this window screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) QObject.connect(self.pluginList, SIGNAL("customContextMenuRequested (const QPoint&)"), self.__evt_contextmenu) QObject.connect(self.update, SIGNAL("clicked ()"), self.__evt_update) self.__http = None self.__downloadFile = None self.__baseUrl = "http://localhost/" self.plugin_txt_url.setText("%splugins.txt" % self.__baseUrl) self.__evt_update() def __evt_update(self): self.progressBar.setValue(0) self.download(QUrl(self.plugin_txt_url.text())) def download(self, url): """ download something """ if None == self.__http: self.__http = QHttp() QObject.connect(self.__http, SIGNAL("done(bool)"), self.__downloadFileDone) QObject.connect(self.__http, SIGNAL("dataReadProgress(int, int)"), self.__dataReadProgress) if QUrl(url).scheme() == 'https': connectionMode = QHttp.ConnectionModeHttps else: connectionMode = QHttp.ConnectionModeHttp self.__http.setHost(url.host(), connectionMode, url.port(80)) self.__downloadFile = QFile(tempfile.NamedTemporaryFile().name) self.__http.get(url.path(), self.__downloadFile) def __downloadFileDone(self, error): """ Private method called, after the file has been downloaded from the internet. @param error flag indicating an error condition (boolean) """ if self.__downloadFile.exists(): filename = self.__downloadFile.fileName() #Notice must flush it first self.__downloadFile.flush() if not zipfile.is_zipfile(filename): plugins_info = open(filename).readlines() self.pluginList.clear() for plugin_info in plugins_info: try: plugin_name = plugin_info.split('|')[0] plugin_version = plugin_info.split('|')[1] plugin_instruction = plugin_info.split('|')[2] plugin_author = plugin_info.split('|')[3] itree = QTreeWidgetItem() itree.setText(0, plugin_name) itree.setText(1, plugin_author) itree.setText(2, plugin_version) itree.setText(3, plugin_instruction) self.pluginList.addTopLevelItem(itree) except Exception as e: raise e else: pluginDir = getPrccisePath( "pluginsDir", "", "extdir") if sys.platform.startswith( "win") else getPrccisePath("pluginsDir", "", "userdir") tmpZip = zipfile.ZipFile(filename) for file in tmpZip.namelist(): tmpZip.extract(file, pluginDir) tmpZip.close() self.result_label.setText("Success install the plugin ") def __dataReadProgress(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) """ self.progressBar.setMaximum(total) self.progressBar.setValue(done) def __has_this_plugin(self, plugin_name): """ Check if this plugin has installed """ for item in PluginAdapter().new().readInfos(): if item[0] == plugin_name: return item return None def __evt_contextmenu(self, point): """ show the right menu """ item = self.pluginList.currentItem() if item: menu = QMenu(self) action = QAction(QApplication.translate("default", "Install plugins..."), self, triggered=lambda: self.__evt_install_plugin(item)) menu.addAction(action) action = QAction( QApplication.translate("default", "Uninstall plugins..."), self) menu.addAction(action) menu.exec_(self.mapToGlobal(self.pluginList.mapTo(self, point))) def __evt_install_plugin(self, item): filename = "plugin-%s-%s.zip" % (item.text(0), item.text(2)) if not None == self.__has_this_plugin(item.text(0)): self.download(QUrl("%s%s" % (self.__baseUrl, filename))) else: self.result_label.setText("This plugin '%s' had installed " % item.text(0))
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 accept(self): className = self.field("className") baseClass = self.field("baseClass") macroName = self.field("macroName") baseInclude = self.field("baseInclude") outputDir = self.field("outputDir") header = self.field("header") implementation = self.field("implementation") block = "" if self.field("comment"): block += "/*\n" block += " " + header + "\n" block += "*/\n" block += "\n" if self.field("protect"): block += "#ifndef " + macroName + "\n" block += "#define " + macroName + "\n" block += "\n" if self.field("includeBase"): block += "#include " + baseInclude + "\n" block += "\n" block += "class " + className if baseClass: block += " : public " + baseClass block += "\n" block += "{\n" if self.field("qobjectMacro"): block += " Q_OBJECT\n" block += "\n" block += "public:\n" if self.field("qobjectCtor"): block += " " + className + "(QObject *parent = 0);\n" elif self.field("qwidgetCtor"): block += " " + className + "(QWidget *parent = 0);\n" elif self.field("defaultCtor"): block += " " + className + "();\n" if self.field("copyCtor"): block += " " + className + "(const " + className + " &other);\n" block += "\n" block += ( " " + className + " &operator=" + "(const " + className + " &other);\n" ) block += "};\n" if self.field("protect"): block += "\n" block += "#endif\n" headerFile = QFile(outputDir + "/" + header) if not headerFile.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning( None, "Class Wizard", "Cannot write file %s:\n%s" % (headerFile.fileName(), headerFile.errorString()), ) return headerFile.write(block) block = "" if self.field("comment"): block += "/*\n" block += " " + implementation + "\n" block += "*/\n" block += "\n" block += '#include "' + header + '"\n' block += "\n" if self.field("qobjectCtor"): block += className + "::" + className + "(QObject *parent)\n" block += " : " + baseClass + "(parent)\n" block += "{\n" block += "}\n" elif self.field("qwidgetCtor"): block += className + "::" + className + "(QWidget *parent)\n" block += " : " + baseClass + "(parent)\n" block += "{\n" block += "}\n" elif self.field("defaultCtor"): block += className + "::" + className + "()\n" block += "{\n" block += " // missing code\n" block += "}\n" if self.field("copyCtor"): block += "\n" block += ( className + "::" + className + "(const " + className + " &other)\n" ) block += "{\n" block += " *this = other;\n" block += "}\n" block += "\n" block += ( className + " &" + className + "::operator=(const " + className + " &other)\n" ) block += "{\n" if baseClass: block += " " + baseClass + "::operator=(other);\n" block += " // missing code\n" block += " return *this;\n" block += "}\n" implementationFile = QFile(outputDir + "/" + implementation) if not implementationFile.open(QFile.WriteOnly | QFile.Text): QMessageBox.warning( None, "Class Wizard", "Cannot write file %s:\n%s" % (implementationFile.fileName(), implementationFile.errorString()), ) return implementationFile.write(block) super(ClassWizard, self).accept()