class GtoSplasher: def __init__(self, info): try: self.info = info self.splasher = None self.info.iface.mainWindow().showMinimized() qgisAppDataPath = QStandardPaths.standardLocations( QStandardPaths.AppDataLocation)[0] file = os.path.join(qgisAppDataPath, "splash.png") if not os.path.isfile(file): file = os.path.join(os.path.dirname(__file__), "splash.png") if os.path.isfile(file): pixmap = QPixmap(file) self.splasher = QSplashScreen(pixmap, Qt.WindowStaysOnTopHint) self.splasher.setPixmap(pixmap) self.splasher.show() except Exception as e: self.info.err(e) def log(self, msg): try: if self.splasher is not None: self.splasher.show() self.splasher.showMessage(msg, Qt.AlignCenter | Qt.AlignBottom) QApplication.instance().processEvents() self.info.log('Splasher:', msg) except Exception as e: self.info.err(e) def close(self): if self.splasher is not None: self.splasher.close()
def welcomeExactDialog(app, settingsObject, mainwindow): # Create and display the about screen splash_pix = QPixmap(ARTWORK_DIR_NAME+'ExactWelcomeScreen.png') splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) btn = QPushButton('Enable EXACT', splash) btn.move(140, 320) btn.clicked.connect(partial(enableAndClose, splash, settingsObject,mainwindow)) btn = QPushButton('Disable EXACT',splash) btn.move(350, 320) btn.clicked.connect(partial(disableAndClose, splash, settingsObject,mainwindow)) # layout.addWidget(btn, 1,1) # splash.showMessage('Version %s\n'%version, alignment = Qt.AlignHCenter + Qt.AlignBottom, color=Qt.black) splash.setMask(splash_pix.mask()) splash.show() splash.mousePressEvent = partial(closeDlg, splash) start = time() while splash.isActiveWindow() & (time() - start < 10): sleep(0.001) app.processEvents() if (splash.isActiveWindow()): splash.close()
class waitsplash(): def __init__(self): path_here = os.path.realpath(__file__) imfile = os.path.join(os.path.split(path_here)[0], 'loading.png') splash_pix = QPixmap(imfile) self.splash = QSplashScreen(splash_pix) #, Qt.WindowStaysOnTopHint) self.splash.setMask(splash_pix.mask()) self.splash.show() QApplication.processEvents() def close(self): self.splash.close()
def show_splash_screen(): """ displays splash screen before loading main window""" splash_pix = QPixmap("res/logo.png") splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) splash.setMask(splash_pix.mask()) progress_bar = QProgressBar(splash) progress_bar.setMaximum(20) progress_bar.setGeometry(130, splash_pix.height() - 50, splash_pix.width() - 240, 20) progress_bar.setStyleSheet(""" QProgressBar { border: 1px solid #252323; border-radius: 6px; text-align: center; position: center; background-color: #252323; font-size: 1px; } QProgressBar::chunk { background-color: #04B97F; border-radius: 9px; margin-right: 23px; width: 20px; }""") splash.show() timer = QElapsedTimer() timer.start() time.sleep(1) for c in range(20): progress_bar.setValue(c) t = time.time() while time.time() < t + 0.3: app.processEvents() time.sleep(1) splash.close()
def main(): app = QApplication(sys.argv) app.setStyle("Fusion") app.setStyleSheet("QPushButton { margin: 200ex; }") dark_palette = QPalette() dark_palette.setColor(QPalette.Window, QColor(53, 53, 53)) dark_palette.setColor(QPalette.WindowText, Qt.white) dark_palette.setColor(QPalette.Base, QColor(25, 25, 25)) dark_palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53)) dark_palette.setColor(QPalette.ToolTipBase, Qt.white) dark_palette.setColor(QPalette.ToolTipText, Qt.white) dark_palette.setColor(QPalette.Text, Qt.white) dark_palette.setColor(QPalette.Button, QColor(53, 53, 53)) dark_palette.setColor(QPalette.ButtonText, Qt.white) dark_palette.setColor(QPalette.BrightText, Qt.red) dark_palette.setColor(QPalette.Link, QColor(42, 130, 218)) dark_palette.setColor(QPalette.Highlight, QColor(42, 130, 218)) dark_palette.setColor(QPalette.HighlightedText, Qt.black) app.setPalette(dark_palette) splash_pix = QPixmap('splash.png') splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) splash.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) splash.setEnabled(False) progressBar = QProgressBar(splash) progressBar.setMaximum(10) progressBar.setGeometry(0, splash_pix.height() - 50, splash_pix.width(), 20) splash.show() splash.showMessage("<h1><font color='green'>Welcome!</font></h1>", Qt.AlignTop | Qt.AlignCenter, Qt.black) for i in range(1, 11): progressBar.setValue(i) t = time.time() while time.time() < t + 0.1: app.processEvents() time.sleep(2) splash.close() controller = Controller() controller.show_first() sys.exit(app.exec_())
def aboutDialog(app, version): # Create and display the about screen splash_pix = QPixmap(ARTWORK_DIR_NAME + 'AboutScreen.png') splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint) splash.showMessage('Version %s\n' % version, alignment=Qt.AlignHCenter + Qt.AlignBottom, color=Qt.black) splash.setMask(splash_pix.mask()) splash.show() splash.mousePressEvent = partial(closeDlg, splash) start = time() while splash.isActiveWindow() & (time() - start < 10): sleep(0.001) app.processEvents() if (splash.isActiveWindow()): splash.close()
class MainUI(QtWidgets.QMainWindow): def __init__(self): super().__init__() self.setWindowTitle("OFWTMC MANAGEMENT SYSTEM") self.setGeometry(350, 45, 771, 681) self.login_ui = LoginUI() self.my_ui = MyUi() self.login_ui.login_btn.clicked.connect(self.showMainWindow) def showSplashScreen(self): self.pix = QPixmap("img/ofwtmc_splash_screen.PNG") self.splash = QSplashScreen(self.pix, Qt.WindowStaysOnTopHint) self.splash.show() def showMainWindow(self): self.setCentralWidget(self.my_ui) self.show() def showLoginUI(self): self.splash.close() self.setCentralWidget(self.login_ui) self.show()
def start(self): if self.run_flag == True : return self.updateCamFlagInfo() #self.database.updataOpenflag('cam_01',1) #self.database.updataOpenflag('cam_02',1) #self.database.updataOpenflag('cam_03',1) if(self.cam_01 or self.cam_02 or self.cam_03): ash = QSplashScreen(QtGui.QPixmap("UI/NUI.png")) ash.setFont(QtGui.QFont('Microsoft YaHei UI',20)) ash.show() ash.showMessage("摄像头链接中,请稍候",QtCore.Qt.AlignLeft | QtCore.Qt.AlignBottom, QtCore.Qt.green) self.updateCamInfo() self.run_flag = True if (self.cam_01 == True and self.vs1.isOpened() == False) or (self.cam_02 == True and self.vs2.isOpened() == False) or (self.cam_03 == True and self.vs3.isOpened() == False): self.run_flag = False ash.close() res = QMessageBox.question(self,'警告','摄像头链接失败,请核对摄像头参数') else: ash.close() else: res = QMessageBox.question(self,'警告','请先设置摄像头参数')
import os
def main(): try: locale.setlocale(locale.LC_ALL, '') except locale.Error: pass # ignore this as it might fail on macOS, we'll fallback to UTF-8 in that case if config.get_use_fusion_gui_style(): sys.argv += ['-style', 'fusion'] if '--error-report' in sys.argv: sys.exit(error_report_main()) # Catch all uncaught exceptions and show an error message for them. # PyQt5 does not silence exceptions in slots (as did PyQt4), so there # can be slots which try to (for example) send requests but don't wrap # them in an async call with error handling. argv = deepcopy(sys.argv) # Deep copy because QApplication (i.e. BrickViewer) constructor parses away Qt args and we want to know the style. if '--no-error-reporter' not in sys.argv: ExceptionReporter(argv) # Exceptions that happen before the event loop runs (f.e. syntax errors) kill the brickv so fast, that the error reporter thread # (which is daemonized) can not report the error before it is killed. Report them manually. try: # importing the MainWindow after creating the QApplication instance triggers this warning # # Qt WebEngine seems to be initialized from a plugin. Please set Qt::AA_ShareOpenGLContexts # using QCoreApplication::setAttribute before constructing QGuiApplication. # # do what the warnings says to avoid it QApplication.setAttribute(Qt.AA_ShareOpenGLContexts) brick_viewer = BrickViewer(sys.argv) if sys.platform == 'darwin': # workaround macOS QTBUG-61562 from brickv.mac_pasteboard_mime_fixed import MacPasteboardMimeFixed mac_pasteboard_mime_fixed = MacPasteboardMimeFixed() splash = QSplashScreen(load_pixmap('splash.png'), Qt.WindowStaysOnTopHint) splash.show() message = 'Starting Brick Viewer ' + config.BRICKV_VERSION if config.INTERNAL != None: message += '~{}'.format(config.INTERNAL) splash.showMessage(message, Qt.AlignHCenter | Qt.AlignBottom, Qt.white) brick_viewer.processEvents() from brickv.mainwindow import MainWindow main_window = MainWindow() main_window.show() splash.finish(main_window) except: if '--no-error-reporter' in sys.argv: raise etype, value, tb = sys.exc_info() error = "".join(traceback.format_exception(etype, value, tb)) error = "The following error is fatal. Exiting now.\n\n" + error traceback.print_exception(etype, value, tb) try: splash.close() except: pass # Either sys.executable is /path/to/python, then run calls /path/to/python /path/to/main.py --error-report, # or sys.executable is brickv[.exe], then the --error-report flag ensures, that the path to main.py is ignored. subprocess.run([sys.executable, os.path.realpath(__file__), "--error-report"] + argv, input=error, universal_newlines=True) sys.exit(1) sys.exit(brick_viewer.exec_())
class MainWindow(QMainWindow,Ui_MainWindow): def __init__(self): super(MainWindow, self).__init__() self.start_logo() self.setupUi(self) self.sysencoding =sys.stdout.encoding #self.centralWidget = PyPreviewer(self) #self.setCentralWidget(self.centralWidget) self.setupEditor() self.setWindowIcon(QIcon('PyPreviewer.ico')) #메뉴 이벤트 생성 self.createEvent() self.dirty = False self.plainTextEdit_2.textChanged.connect(self.setDirty) self.fileName = None self.plainTextEdit_2.setTabStopWidth(35) self.plainTextEdit_2.setPlainText("# -*- coding: utf-8 -*-\n# 반갑습니다~\n# #은 파이썬에서 주석입니다.\nprint(\"이 부분은 출력창입니다.\")\nprint(\"구구단 예제\")\nfor i in range(2,10):\n\tprint(i,\"단\")\n\tfor j in range(2,10):\n\t\tprint(i,\"X\", j, \"=\", i*j)\n# 파이썬 실행은 아래 실행버튼을 눌러주세요.\n# 파이썬 학습 관련 및 예제는 왼쪽 화면을 이용하시기 바랍니다.") #web view #self.exampleView.load(QUrl("http://www.google.com")) self.startfilepath=os.getcwd() +"/PyStudy_web/Main.html" self.exampleView.load(QUrl.fromLocalFile(self.startfilepath)) self.locationEdit = QLineEdit(self) self.locationEdit.setSizePolicy(QSizePolicy.Expanding, self.locationEdit.sizePolicy().verticalPolicy()) self.locationEdit.returnPressed.connect(self.changeLocation) toolBar = QToolBar() self.addToolBar(toolBar) self.insertToolBarBreak(toolBar) toolBar.addAction(self.exampleView.pageAction(QWebPage.Back)) toolBar.addAction(self.exampleView.pageAction(QWebPage.Forward)) toolBar.addAction(self.action_myHome) toolBar.addAction(self.exampleView.pageAction(QWebPage.Reload)) #toolBar.addAction(self.exampleView.pageAction(QWebPage.Stop)) toolBar.addWidget(self.locationEdit) #사용자 입력 파이썬 파일 실행 print ('Connecting process') self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setInputChannelMode(QProcess.ManagedInputChannel) self.process.readyReadStandardOutput.connect(self.stdoutReady) self.process.readyReadStandardError.connect(self.stderrReady) self.process.started.connect(lambda: print('ExampleProgramStarted!')) self.process.finished.connect(lambda:print('ExampleProgramFinished!')) print('Starting process') #self.process.start('python', ['ExampleTest.py']) def start_logo(self): img_logo = QPixmap('pystudylogo.png') self.splash = QSplashScreen(img_logo, Qt.WindowStaysOnTopHint) self.splash.setMask(img_logo.mask()) self.splash.show() time.sleep(1.8) self.splash.close() def show_logo(self): img_logo = QPixmap('pystudylogo.png') self.splash = QSplashScreen(img_logo, Qt.WindowStaysOnTopHint) self.splash.setMask(img_logo.mask()) self.splash.show() self.splash.repaint() def createEvent(self): self.ProgramRunButton.clicked.connect(self.clickAction_ProgramRunButton) self.ProgramStopButton.clicked.connect(self.clickAction_ProgramStopButton) self.actionRun.triggered.connect(self.clickAction_ProgramRunButton) self.actionStop.triggered.connect(self.clickAction_ProgramStopButton) self.ClearButton.clicked.connect(self.clickAction_ProgramEraseButton) self.actionClear.triggered.connect(self.clickAction_ProgramEraseButton) self.actionNew_File.triggered.connect(self.clickAction_fileNew) self.actionFile_Open.triggered.connect(self.clickAction_fileOpen) self.actionFile_Save.triggered.connect(self.clickAction_fileSave) self.actionFile_Save_as.triggered.connect(self.clickAction_fileSaveAs) self.action_example.triggered.connect(self.clickAction_exampleOpen) self.actionPythonHelp.triggered.connect(self.clickAction_PythonHelp) self.actionHelp.triggered.connect(self.clickAction_ProgramHelp) self.MessagepushButton.clicked.connect(self.clickAction_MessagePushButton) self.actionStyleSheet_default.triggered.connect(self.clickAction_styleDefault) self.actionStyleSheet_Black.triggered.connect(self.clickAction_styleBlack) self.actionStyleSheet_Load.triggered.connect(self.clickAction_styleLoad) self.actionAbout_PyStudy.triggered.connect(self.show_logo) self.action_myHome.triggered.connect(self.go_myHome) self.action_exit.triggered.connect(self.close) def setDirty(self): #'On change of text in textEdit window, set the flag "dirty" to True'' if self.dirty: return True self.dirty = True self.updateStatus('소스 수정중...') def clearDirty(self): #'''Clear the dirty flag and update status''' self.dirty = False def updateStatus(self, message): if self.fileName is not None: flbase = os.path.basename(self.fileName) self.setWindowTitle("PyStudy Simple Editor - " + flbase + "[*]" ) self.statusBar().showMessage(message, 3000) self.setWindowModified(self.dirty) def clickAction_exampleOpen(self): fname, filter = QFileDialog.getOpenFileName(self, "예제파일 열기창", '.', "HTML File(*.html *.htm)") if not (fname == ""): #self.exampleView.load(QUrl(fname)) self.exampleView.setUrl(QUrl.fromLocalFile(fname)) #self.plainTextEdit_2.setPlainText(codecs.open(fname, "r", "utf-8" ).read()) #self.fileName = fname else: return self.updateStatus('example File opened.') def clickAction_exampleDirectOpen(self,fname): if not (fname == ""): fname = os.getcwd()+r"\\"+fname print(fname) self.exampleView.setUrl(QUrl.fromLocalFile(fname)) else: return self.updateStatus('example File opened.') def clickAction_fileNew(self): #'''Clear the editor window for a new file with name specified in fileSaveAs method.''' self.plainTextEdit_2.clear() self.statusBar().showMessage('새 소스파일 생성', 8000) self.dirty = False self.fileName = None def clickAction_fileOpen(self): fname, filter = QFileDialog.getOpenFileName(self, "소스파일 열기창", '.', "Python File(*.py)") if not (fname == ""): self.plainTextEdit_2.setPlainText(codecs.open(fname, "r", "utf-8" ).read()) self.fileName = fname else: return self.clearDirty() self.updateStatus('File opened.') def clickAction_fileSave(self): if self.fileName is None: return self.clickAction_fileSaveAs() else: fname = self.fileName fl = codecs.open(fname, "w", "utf-8" ) tempText = self.plainTextEdit_2.toPlainText() if tempText: fl.write(tempText) fl.close() self.clearDirty() self.updateStatus('Saved file') return True else: self.statusBar().showMessage('파일 저장 실패 ...', 5000) return False def clickAction_fileSaveAs(self): path = self.fileName if self.fileName is not None else "." fname,filter = QFileDialog.getSaveFileName(self, "다른이름으로 저장", path, "Python File(*.py)") if fname: if "." not in fname: fname += ".py" self.fileName = fname self.clickAction_fileSave() self.statusBar().showMessage('SaveAs file' + fname, 8000) self.clearDirty() def clickAction_ProgramRunButton(self): self.clickAction_fileSave() self.process.start('python', [self.fileName],QIODevice.ReadWrite) def clickAction_ProgramStopButton(self): self.process.kill() self.append_plainTextEdit_3("\n\n프로세스 정지 with exit code "+str(self.process.exitCode())+"\n\n") def clickAction_ProgramEraseButton(self): self.plainTextEdit_3.clear() def append_plainTextEdit_3(self, text): cursor = self.plainTextEdit_3.textCursor() cursor.movePosition(cursor.End) cursor.insertText(text) #self.output.ensureCursorVisible() def stdoutReady(self): if self.sysencoding == "cp949": text = str(self.process.readAllStandardOutput(), "cp949")#독립실행시 elif self.sysencoding == "UTF-8": text = str(self.process.readAllStandardOutput(), "utf-8")#pycharm else: text = str(self.process.readAllStandardOutput(), "cp949")#독립실행시 self.append_plainTextEdit_3(text) def stderrReady(self): if self.sysencoding == "cp949": text = str(self.process.readAllStandardError(), "cp949")#독립실행시 elif self.sysencoding == "UTF-8": text = str(self.process.readAllStandardError(), "utf-8")#pycharm else: text = str(self.process.readAllStandardError(), "cp949")#독립실행시 self.append_plainTextEdit_3(text) def clickAction_PythonHelp(self): temppath=os.path.abspath('..')+r"\파이썬도움말\animation.py" tempoption = os.path.abspath('..')+r"\파이썬도움말" pythonhelp_process=QProcess() pythonhelp_process.start('python', [temppath,tempoption]) pythonhelp_process.started() # TypeError: native Qt signal is not callable def clickAction_MessagePushButton(self): temp = self.messagelineEdit.text() self.append_plainTextEdit_3(temp) self.append_plainTextEdit_3("\n") bArray = QByteArray() if self.sysencoding == "cp949": bArray.append(temp.encode(encoding='cp949',errors='ignore'))#독립실행시 elif self.sysencoding == "UTF-8": bArray.append(temp.encode(encoding='utf-8',errors='ignore'))#pycharm else: bArray.append(temp.encode(encoding='cp949',errors='ignore'))#독립실행시 bArray.append("\n") if( self.process.write(bArray) == -1): print("chlidprocess write error") self.messagelineEdit.clear() def clickAction_styleLoad(self): fname, filter = QFileDialog.getOpenFileName(self, "QT스타일시트파일 불러오기", '.', "Qt-StyleSheet(*.qss)") if fname: file = QFile(fname) file.open(QFile.ReadOnly) styleSheet = file.readAll() styleSheet = str(styleSheet, encoding='utf8') # Python v3. self.setStyleSheet(styleSheet) print ("test") def clickAction_styleDefault(self): self.set_StyleSheet("default") def clickAction_styleBlack(self): self.set_StyleSheet("black") def clickAction_ProgramHelp(self): self.startfilepath=os.getcwd() +"/PyStudy_web/Pystudy.html" self.exampleView.load(QUrl.fromLocalFile(self.startfilepath)) def set_StyleSheet(self, sheetName): if sheetName: file = QFile('stylesheet/%s.qss' % sheetName.lower()) file.open(QFile.ReadOnly) styleSheet = file.readAll() styleSheet = str(styleSheet, encoding='utf8') # Python v3. self.setStyleSheet(styleSheet) def setupEditor(self): font = QFont() font.setFamily('Courier') font.setFixedPitch(True) font.setPointSize(10) self.editor = self.plainTextEdit_2 self.editor.setFont(font) self.highlighter = Highlighter(self.editor.document()) def changeLocation(self): url = QUrl.fromUserInput(self.locationEdit.text()) self.exampleView.load(url) self.exampleView.setFocus() def go_myHome(self): self.exampleView.load(QUrl.fromLocalFile(self.startfilepath)) self.exampleView.setFocus()
class QtApplication(QApplication, Application, SignalEmitter): def __init__(self, **kwargs): plugin_path = "" if sys.platform == "win32": plugin_path = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "PyQt5", "plugins") Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path)) QCoreApplication.addLibraryPath(plugin_path) elif sys.platform == "darwin": plugin_path = os.path.join(Application.getInstallPrefix(), "Resources", "plugins") if plugin_path: Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path)) QCoreApplication.addLibraryPath(plugin_path) os.environ["QSG_RENDER_LOOP"] = "basic" super().__init__(sys.argv, **kwargs) self._main_qml = "main.qml" self._engine = None self._renderer = None try: self._splash = QSplashScreen(QPixmap(Resources.getPath(Resources.ImagesLocation, self.getApplicationName() + ".png"))) except FileNotFoundError: self._splash = None else: self._splash.show() self.processEvents() signal.signal(signal.SIGINT, signal.SIG_DFL) # This is done here as a lot of plugins require a correct gl context. If you want to change the framework, # these checks need to be done in your <framework>Application.py class __init__(). i18n_catalog = i18nCatalog("uranium") self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading plugins...")) self._loadPlugins() self._plugin_registry.checkRequiredPlugins(self.getRequiredPlugins()) self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading machines...")) self.loadMachines() self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading preferences...")) try: file = Resources.getPath(Resources.PreferencesLocation, self.getApplicationName() + ".cfg") Preferences.getInstance().readFromFile(file) except FileNotFoundError: pass self._translators = {} self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading translations...")) self.loadQtTranslation("uranium_qt") self.loadQtTranslation(self.getApplicationName() + "_qt") def run(self): pass def hideMessage(self, message): with self._message_lock: if message in self._visible_messages: self._visible_messages.remove(message) self.visibleMessageRemoved.emit(message) def showMessage(self, message): with self._message_lock: if message not in self._visible_messages: self._visible_messages.append(message) message.setTimer(QTimer()) self.visibleMessageAdded.emit(message) pass def setMainQml(self, path): self._main_qml = path def initializeEngine(self): # TODO: Document native/qml import trickery Bindings.register() self._engine = QQmlApplicationEngine() self.engineCreatedSignal.emit() self._engine.addImportPath(os.path.join(os.path.dirname(sys.executable), "qml")) self._engine.addImportPath(os.path.join(Application.getInstallPrefix(), "Resources", "qml")) if not hasattr(sys, "frozen"): self._engine.addImportPath(os.path.join(os.path.dirname(__file__), "qml")) self.registerObjects(self._engine) self._engine.load(self._main_qml) engineCreatedSignal = Signal() def registerObjects(self, engine): pass def getRenderer(self): if not self._renderer: self._renderer = QtGL2Renderer() return self._renderer # Overridden from QApplication::setApplicationName to call our internal setApplicationName def setApplicationName(self, name): Application.setApplicationName(self, name) # Handle a function that should be called later. def functionEvent(self, event): e = _QtFunctionEvent(event) QCoreApplication.postEvent(self, e) # Handle Qt events def event(self, event): if event.type() == _QtFunctionEvent.QtFunctionEvent: event._function_event.call() return True return super().event(event) def windowClosed(self): self.getBackend().close() self.quit() self.saveMachines() Preferences.getInstance().writeToFile(Resources.getStoragePath(Resources.PreferencesLocation, self.getApplicationName() + ".cfg")) ## Load a Qt translation catalog. # # This method will locate, load and install a Qt message catalog that can be used # by Qt's translation system, like qsTr() in QML files. # # \param file The file name to load, without extension. It will be searched for in # the i18nLocation Resources directory. If it can not be found a warning # will be logged but no error will be thrown. # \param language The language to load translations for. This can be any valid language code # or 'default' in which case the language is looked up based on system locale. # If the specified language can not be found, this method will fall back to # loading the english translations file. # # \note When `language` is `default`, the language to load can be changed with the # environment variable "LANGUAGE". def loadQtTranslation(self, file, language = "default"): #TODO Add support for specifying a language from preferences path = None if language == "default": # If we have a language set in the environment, try and use that. lang = os.getenv("LANGUAGE") if lang: try: path = Resources.getPath(Resources.i18nLocation, lang, "LC_MESSAGES", file + ".qm") except FileNotFoundError: path = None # If looking up the language from the enviroment fails, try and use Qt's system locale instead. if not path: locale = QLocale.system() # First, try and find a directory for any of the provided languages for lang in locale.uiLanguages(): try: path = Resources.getPath(Resources.i18nLocation, lang, "LC_MESSAGES", file + ".qm") language = lang except FileNotFoundError: pass else: break # If that fails, see if we can extract a language "class" from the # preferred language. This will turn "en-GB" into "en" for example. if not path: lang = locale.uiLanguages()[0] lang = lang[0:lang.find("-")] try: path = Resources.getPath(Resources.i18nLocation, lang, "LC_MESSAGES", file + ".qm") language = lang except FileNotFoundError: pass else: path = Resources.getPath(Resources.i18nLocation, language, "LC_MESSAGES", file + ".qm") # If all else fails, fall back to english. if not path: Logger.log("w", "Could not find any translations matching {0} for file {1}, falling back to english".format(language, file)) try: path = Resources.getPath(Resources.i18nLocation, "en", "LC_MESSAGES", file + ".qm") except FileNotFoundError: Logger.log("w", "Could not find English translations for file {0}. Switching to developer english.".format(file)) return translator = QTranslator() if not translator.load(path): Logger.log("e", "Unable to load translations %s", file) return # Store a reference to the translator. # This prevents the translator from being destroyed before Qt has a chance to use it. self._translators[file] = translator # Finally, install the translator so Qt can use it. self.installTranslator(translator) ## Display text on the splash screen. def showSplashMessage(self, message): if self._splash: self._splash.showMessage(message , Qt.AlignHCenter | Qt.AlignVCenter) self.processEvents() ## Close the splash screen after the application has started. def closeSplash(self): if self._splash: self._splash.close() self._splash = None
class Splash(QObject, LogMixin, EventMixin): """Splash screen class""" def __init__(self, parent, msg=""): """ Constructor of Splash screen :param parent: ui parent :param msg: initial message text """ super().__init__() self._parent = parent self.isHidden = True self._progress = 0 self._progressBar = None self.msg = msg pixmap = QtGui.QPixmap(380, 100) pixmap.fill(QtGui.QColor("darkgreen")) self._splash = QSplashScreen(pixmap) self._splash.setParent(self._parent) self.add_progressbar() def add_progressbar(self): """Add separate progress bar to splash screen""" self._progressBar = QProgressBar(self._splash) self._progressBar.setGeometry(self._splash.width() / 10, 8 * self._splash.height() / 10, 8 * self._splash.width() / 10, self._splash.height() / 10) self._progressBar.hide() def setProgress(self, val): """ Set progress bar to ``val`` If splash has no progressbar, it will be added dynamically. Remove progressbar with ``val`` as None. :param val: absolut percent value :return: """ if val is not None: self._progressBar.show() self._progressBar.setTextVisible(True) self.progress = val try: self._progressBar.setValue(self.progress) except: pass else: self._progressBar.setTextVisible(False) self._progressBar.hide() self._progressBar.reset() if self.isHidden is True: self.isHidden = False self.show_() def incProgress(self, val): """ Increase progressbar value by ``val`` If splash has no progressbar, it will be added dynamically. Remove progressbar with ``val`` as None. :param val: value to increase by :return: """ if val is not None: self._progressBar.show() self._progressBar.setTextVisible(True) self.progress = self.progress + val try: self._progressBar.setValue(self.progress) qApp.processEvents() except: pass else: self._progressBar.setTextVisible(False) self._progressBar.hide() self._progressBar.reset() if self.isHidden is True: self.isHidden = False self.show_() def setParent(self, parent): """Set splash's parent""" self._parent = parent self._splash.setParent(parent) @pyqtSlot() @pyqtSlot(bool) def close(self, dummy=True): self.logger.debug("Hide splash") self.isHidden = True self._progressBar.hide() self._progressBar.reset() self._splash.close() @pyqtSlot() @pyqtSlot(str) def show_(self, msg=""): if msg != "": self._splash.showMessage(msg, QtCore.Qt.AlignCenter, QtCore.Qt.white) else: self.logger.debug("Show splash, parent: " + str(self._parent)) self._splash.showMessage(self.msg, QtCore.Qt.AlignCenter, QtCore.Qt.white) try: #if platform.system() == "Linux": parentUi = self._parent.centralwidget.geometry( ) # need to use centralwidget for linux preferably, don't know why except: #else: parentUi = self._parent.childrenRect() mysize = self._splash.geometry() hpos = parentUi.x() + ((parentUi.width() - mysize.width()) / 2) vpos = parentUi.y() + ((parentUi.height() - mysize.height()) / 2) self._splash.move(hpos, vpos) self._splash.show() qApp.processEvents() @property def progress(self): return self._progress @progress.setter def progress(self, value): # create new exception handling vor properties # if (value != "True") and (value != "False"): # raise ValueError("describe exception") if value > 100: value = 0 if value < 0: value = 0 self._progress = value
class Splash(QObject, LogMixin, EventMixin): """Splash screen class""" def __init__(self, parent, msg = ""): """ Constructor of Splash screen :param parent: ui parent :param msg: initial message text """ super().__init__() self._parent = parent self.isHidden = True self._progress = 0 self._progressBar = None self.msg = msg pixmap = QtGui.QPixmap(380, 100) pixmap.fill(QtGui.QColor("darkgreen")) self._splash = QSplashScreen(pixmap) self._splash.setParent(self._parent) self.add_progressbar() def add_progressbar(self): """Add separate progress bar to splash screen""" self._progressBar = QProgressBar(self._splash) self._progressBar.setGeometry(self._splash.width() / 10, 8 * self._splash.height() / 10, 8 * self._splash.width() / 10, self._splash.height() / 10) self._progressBar.hide() def setProgress(self, val): """ Set progress bar to ``val`` If splash has no progressbar, it will be added dynamically. Remove progressbar with ``val`` as None. :param val: absolut percent value :return: """ if val is not None: self._progressBar.show() self._progressBar.setTextVisible(True) self.progress = val try: self._progressBar.setValue(self.progress) except: pass else: self._progressBar.setTextVisible(False) self._progressBar.hide() self._progressBar.reset() if self.isHidden is True: self.isHidden = False self.show_() def incProgress(self, val): """ Increase progressbar value by ``val`` If splash has no progressbar, it will be added dynamically. Remove progressbar with ``val`` as None. :param val: value to increase by :return: """ if val is not None: self._progressBar.show() self._progressBar.setTextVisible(True) self.progress = self.progress + val try: self._progressBar.setValue(self.progress) qApp.processEvents() except: pass else: self._progressBar.setTextVisible(False) self._progressBar.hide() self._progressBar.reset() if self.isHidden is True: self.isHidden = False self.show_() def setParent(self, parent): """Set splash's parent""" self._parent = parent self._splash.setParent(parent) @pyqtSlot() @pyqtSlot(bool) def close(self, dummy = True): self.logger.debug("Hide splash") self.isHidden = True self._progressBar.hide() self._progressBar.reset() self._splash.close() @pyqtSlot() @pyqtSlot(str) def show_(self, msg = ""): if msg != "": self._splash.showMessage(msg, QtCore.Qt.AlignCenter, QtCore.Qt.white) else: self.logger.debug("Show splash, parent: " + str(self._parent)) self._splash.showMessage(self.msg, QtCore.Qt.AlignCenter, QtCore.Qt.white) try: #if platform.system() == "Linux": parentUi = self._parent.centralwidget.geometry() # need to use centralwidget for linux preferably, don't know why except: #else: parentUi = self._parent.childrenRect() mysize = self._splash.geometry() hpos = parentUi.x() + ((parentUi.width() - mysize.width()) / 2) vpos = parentUi.y() + ((parentUi.height() - mysize.height()) / 2) self._splash.move(hpos, vpos) self._splash.show() qApp.processEvents() @property def progress(self): return self._progress @progress.setter def progress(self, value): # create new exception handling vor properties # if (value != "True") and (value != "False"): # raise ValueError("describe exception") if value > 100: value = 0 if value < 0: value = 0 self._progress = value
| Qt.Tool) splash.showMessage("Loading... 0%", Qt.AlignHCenter | Qt.AlignBottom, Qt.white) splash.show() qApp.processEvents() Util.loadTheme() #main Window.Margins = 5 if Util.getConfigValue('resizable') else 0 Window.StayOnTop = Util.getConfigValue('windowStayOnTop') mainWnd = MainWindow() mainWnd.setWidget(WebWindow(mainWnd)) mainWnd.loadData(splash) #ui mainWnd.setWindowTitle( Util.getWindowTitle(Util.lang('loading', 'Loading...'))) mainWnd.setWindowIcon(Icon.getLogoIcon()) if not Util.getConfigValue('showTitleBar'): mainWnd.titleBar.hide() mainWnd.resizeCenter(Util.getConfigValue('width'), Util.getConfigValue('height')) mainWnd.show_(Util.getConfigValue('fullscreen')) #MessageBox.alert(sys.argv[0]) splash and splash.close() sys.exit(app.exec_())
class Main(QObject): def __init__(self, parent = None): """Create a wizard or the mainwindow""" self._parent = parent super().__init__(self._parent) print("runner/Main parent: ", self._parent, " -> self: ", self) if oPB.PRINTHIER else None self.logger = None self.args = self.get_args() self._log_level = None self._log_file = None self.translator = None # make it really quiet, part 1 if self.args.quiet: self.args.nogui = True # instantiate configuration class confighandler.ConfigHandler(oPB.CONFIG_INI) # redirect system exception hook if not self.args.noexcepthook: sys.excepthook = self.excepthook # pre-instantiating the application, avoid some nasty OpenGL messages QApplication.setAttribute(QtCore.Qt.AA_UseOpenGLES) # create new application and install stylesheet self.app = QApplication(sys.argv) self.install_stylesheet() # Create and display the splash screen, if in ui mode if not self.args.nogui: splash_pix = QPixmap(':/images/splash.png') self.splash = QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint) self.splash.setMask(splash_pix.mask()) # splash.showMessage("opsi Package Builder " + oPB.PROGRAM_VERSION + " " + translate("Main", "is loading..."), QtCore.Qt.AlignCenter, QtCore.Qt.white) self.splash.show() self.app.processEvents() # Application name self.app.setOrganizationName("opsi Package Builder") self.app.setApplicationName("opsi Package Builder " + oPB.PROGRAM_VERSION) # save ourselves in main instance property to be easily accessd via qApp # i.e. # from PyQt5.QtWidgets import qApp # main = qApp.property("main") self.app.setProperty("main", self) if confighandler.ConfigHandler.cfg.log_always == "True": if self.args.log_file is not None: self._log_file = self.args.log_file else: self._log_file = confighandler.ConfigHandler.cfg.log_file if self.args.log_level.upper() != "NOTSET": self._log_level = self.args.log_level.upper() else: self._log_level = confighandler.ConfigHandler.cfg.log_level else: self._log_file = self.args.log_file if self.args.log_level.upper() == "NOTSET": self._log_level = "CRITICAL" else: self._log_level = self.args.log_level.upper() if self._log_file is not None: if not pathlib.Path(self._log_file).is_absolute(): if platform.system() == "Windows": self._log_file = str(pathlib.PurePath(oPB.WIN_TMP_PATH, self._log_file)) if platform.system() in ["Darwin", "Linux"]: self._log_file = str(pathlib.PurePath(oPB.UNIX_TMP_PATH, self._log_file)) # overwrite development directory from config with command line arg if self.args.dev_dir is not None: confighandler.ConfigHandler.cfg.dev_dir = self.args.dev_dir # Initialize the logger and reroute QtCore messages to it self.logWindow = oPB.gui.logging.LogDialog(None, self, self._log_level) self.instantiate_logger(False) QtCore.qInstallMessageHandler(self.qt_message_handler) # log program version and user self.logger.info(80 * "-") self.logger.info("opsi PackageBuilder (MIT licensed) " + oPB.PROGRAM_VERSION) self.logger.info("Current user: "******"Command line arguments given:") for key, val in vars(self.args).items(): self.logger.info(" " + key + ": " + str(val)) if self._log_level not in ["DEBUG", "INFO", "SSHINFO", "WARNING", "ERROR", "CRITICAL", "SSH"]: self.logger.error(" Undefined log level: " + self._log_level) self.logger.error(" Log level has been set to ERROR") for elem in self.app.libraryPaths(): self.logger.debug("QT5 library path: " + elem) # write config to log, if necessary confighandler.ConfigHandler.cfg.log_config() self.check_online_status() # ----------------------------------------------------------------------------------------- # main ui dispatching # startup gui variant if not self.args.nogui: # hide console window, but only under Windows and only if app is frozen if sys.platform.lower().startswith('win'): if getattr(sys, 'frozen', False): hideConsole() # installing translators self.translator = Translator(self.app, "opsipackagebuilder") self.translator.install_translations(confighandler.ConfigHandler.cfg.language) # retranslate logWindow, as it is loaded before the translations self.logWindow.retranslateUi(self.logWindow) # create app icon app_icon = QtGui.QIcon() app_icon.addFile(':images/prog_icons/opb/package_16x16.png', QtCore.QSize(16, 16)) app_icon.addFile(':images/prog_icons/opb/package_24x24.png', QtCore.QSize(24, 24)) app_icon.addFile(':images/prog_icons/opb/package_32x32.png', QtCore.QSize(32, 32)) app_icon.addFile(':images/prog_icons/opb/package_48x48.png', QtCore.QSize(48, 48)) app_icon.addFile(':images/prog_icons/opb/package_64x64.png', QtCore.QSize(64, 64)) app_icon.addFile(':images/prog_icons/opb/package_92x92.png', QtCore.QSize(92, 92)) app_icon.addFile(':images/prog_icons/opb/package_128x128.png', QtCore.QSize(128, 128)) app_icon.addFile(':images/prog_icons/opb/package_256x256.png', QtCore.QSize(256, 256)) self.app.setProperty("prog_icon",app_icon) # startup program window self.mainWindow = main.MainWindowController(self.args) self.mainWindow.ui.showLogRequested.connect(self.logWindow.show) self.mainWindow.closeAppRequested.connect(self.logWindow.close) self.splash.finish(self.mainWindow.ui) # check for updates if configured if confighandler.ConfigHandler.cfg.updatecheck == "True": self.mainWindow.update_check() # run main app loop self.app.exec_() # only process commandline else: self.logger.info("No-GUI parameter set") # startup program window self.console = console.ConsoleController(self.args) # ----------------------------------------------------------------------------------------- # unmount drive (if exist) after end of program if (oPB.NETDRV is not None) and oPB.NETDRV != "offline": ret = MapDrive.unMapDrive(oPB.NETDRV) if ret[0] != 0: self.logger.error("Error unmounting path: " + str(ret)) else: self.logger.info("Network drive successfully unmounted") # exit and set return code self.logger.info("Exit code: " + str(oPB.EXITCODE)) # show console window if not self.args.nogui: if sys.platform.lower().startswith('win'): if getattr(sys, 'frozen', False): showConsole() sys.exit(oPB.EXITCODE) def qt_message_handler(self, mode, context, message): if mode == QtCore.QtInfoMsg: mode = 'INFO' fun = self.logger.info elif mode == QtCore.QtWarningMsg: mode = 'WARNING' fun = self.logger.warning elif mode == QtCore.QtCriticalMsg: mode = 'CRITICAL' fun = self.logger.critical elif mode == QtCore.QtFatalMsg: mode = 'FATAL' fun = self.logger.error else: mode = 'DEBUG' fun = self.logger.debug fun('Qt framework message handler: line: %d, func: %s(), file: %s' % ( context.line, context.function, context.file)) fun('Qt framework message handler: %s: %s' % (mode, message)) def install_stylesheet(self): if platform.system() == "Darwin": css = os.environ['OPB_BASE'] + "/ui/stylesheet-mac.qss" else: css = os.environ['OPB_BASE'] + "/ui/stylesheet.qss" try: with open(css, "r", encoding="utf-8", newline="\n") as file: style = file.readlines() file.close() except: self.logger.debug("Stylesheet could not be opened.") else: self.app.setStyleSheet(("\n").join(style)) def check_online_status(self): self.logger.debug("Check online status") # check if server is generally available # use SSH port for connection test ret = Helper.test_port(confighandler.ConfigHandler.cfg.opsi_server, confighandler.ConfigHandler.cfg.sshport, 0.5) if ret is True: # check network access and mount network drive if on linux if sys.platform == 'win32': self.logger.info("System platform: "+ sys.platform) if self.args.nonetdrive is False: if confighandler.ConfigHandler.cfg.usenetdrive == "False": drives = Helper.get_available_drive_letters() if not drives: self.logger.error("No free drive letter found") else: self.logger.info("Free drive letter found: " + repr(drives)) self.logger.info("Using drive letter: " + drives[::-1][0]) path = "\\\\" + confighandler.ConfigHandler.cfg.opsi_server + "\\" + "opsi_workbench" self.logger.info("Trying to mount path: " + path) ret = MapDrive.mapDrive(drives[::-1][0] + ":", path, confighandler.ConfigHandler.cfg.opsi_user, confighandler.ConfigHandler.cfg.opsi_pass) if ret[0] != 0: self.logger.error("Error mounting path: " + str(ret)) else: self.logger.info("Network drive successfully mounted") oPB.NETDRV = drives[::-1][0] + ":" else: self.logger.info("Using existing network drive") else: self.logger.info("Mounting of network drive via command line disabled") else: self.logger.info("System platform: "+ sys.platform) self.logger.warning("This is not a windows based system. No network drive will be associated") self.logger.warning("Please take care, that the specified development base path is correct.") else: self.logger.warning("opsi server not available. Offline mode activated.") self.logger.warning("Return value from connection test: " + str(ret)) oPB.NETMODE = "offline" def get_args(self): # get cmdline args cmd_params = CommandLine() return cmd_params.getArgs() def set_log_level(self, level, handler): # set log level if level == "DEBUG": handler.setLevel(logging.DEBUG) elif level == "INFO": handler.setLevel(logging.INFO) elif level == "WARNING": handler.setLevel(logging.WARNING) elif level == "ERROR": handler.setLevel(logging.ERROR) elif level == "CRITICAL": handler.setLevel(logging.WARNING) elif level == "SSH": handler.setLevel(oPB.core.logging.SSH) elif level == "SSHINFO": handler.setLevel(oPB.core.logging.SSHINFO) else: handler.setLevel(logging.ERROR) def instantiate_logger(self, long): # for additional log facilities, see # http://stackoverflow.com/questions/2183233/how-to-add-a-custom-loglevel-to-pythons-logging-facility # Create logger logger = logging.getLogger('oPB') # to add a further logging facility, we have to subclass current logger class # and set this new one to be the default logger class setLoggerClass(oPB.core.logging.SSHLogger) # log level for logger(!) - we filter on handler-based log level later self.set_log_level("DEBUG", logger) # make it really quiet, part 2 if self.args.quiet: self.noop = logging.NullHandler() logger.addHandler(self.noop) else: if long: format = logging.Formatter(oPB.LOG_LONG, oPB.LOG_DATETIME) else: format = logging.Formatter(oPB.LOG_SHORT, oPB.LOG_DATETIME) # redirect stdout / stdin if gui if not self.args.nogui: # Output forwarding sys.stdout = oPB.core.logging.LogOutput(self.logWindow.editOutput, sys.__stdout__, self.logWindow.editOutput.textColor()) sys.stderr = oPB.core.logging.LogOutput(self.logWindow.editOutput, sys.__stderr__, QtGui.QColor(QtCore.Qt.red)) # Create standart output handler self.stdout = logging.StreamHandler(sys.__stderr__) self.set_log_level(self._log_level, self.stdout) self.stdout.setFormatter(format) # Add handlers to logger logger.addHandler(self.stdout) # Create different log window handler if not self.args.nogui: # output standard msg into dialog tab "Logging" self.dialogHandler = oPB.core.logging.LogStreamHandler(self.logWindow.editLog, self) self.dialogHandler.colors = oPB.OPB_LOG_COLORS self.dialogHandler.colorize = True self.set_log_level(self._log_level, self.dialogHandler) self.dialogHandler.setFormatter(format) logger.addHandler(self.dialogHandler) # Create special SSH output log facility, put this into tab "SSH Output" self.sshHandler = oPB.core.logging.LogStreamHandler(self.logWindow.editSSH, self) self.set_log_level("SSHINFO", self.sshHandler) sshformat = logging.Formatter(oPB.LOG_SSH, oPB.LOG_DATETIME) self.sshHandler.setFormatter(sshformat) logger.addHandler(self.sshHandler) # Create log file handler, possible try: if self._log_file is not None: self.fileHandler = logging.FileHandler(self._log_file) self.set_log_level(self._log_level, self.fileHandler) self.fileHandler.setFormatter(format) logger.addHandler(self.fileHandler) except IOError as error: logger.error("Log file could not be opened: " + self._log_file) logger.error(error) self.logger = logger def excepthook(self, excType, excValue, tracebackobj): """ Global function to catch unhandled exceptions. Writes traceback to temporary file. Adopted to Python 3 from here: http://www.riverbankcomputing.com/pipermail/pyqt/2009-May/022961.html :param excType: exception type :param excValue: exception value :param tracebackobj: traceback object """ try: self.splash.close() except: pass self.logger.debug("Entering excepthook") separator = '-' * 80 logFile = tempfile.NamedTemporaryFile(mode = "w+", suffix = ".log", prefix = "opb-error-", delete = False) # """If you have any additional, confidential information you can\n""" \ # """use this mail address: <%s>\n\n""" \ notice = \ """An unhandled exception occurred. Please report the problem\n"""\ """via the official opsi PackageBuilder forum:\n\n"""\ """https://forum.opsi.org/viewforum.php?f=22\n\n"""\ """Thank you!\n\n"""\ """A log has been written to "%s".\n\nError information:\n""" % \ (logFile.name) versionInfo="0.0.1" timeString = datetime.datetime.now().strftime("%Y-%m-%d, %H:%M:%S") tbinfofile = StringIO() traceback.print_tb(tracebackobj, None, tbinfofile) tbinfofile.seek(0) tbinfo = tbinfofile.read() errmsg = '%s: \n%s' % (str(excType), str(excValue)) sections = [separator, timeString, separator, errmsg, separator, tbinfo] msg = '\n'.join(sections) try: logFile.file.write(msg) logFile.file.write(versionInfo) logFile.close() except IOError: pass if not self.args.nogui: errorbox = QtWidgets.QMessageBox() errorbox.setText(str(notice) + str(msg) + str(versionInfo)) errorbox.exec_() else: print(str(notice) + str(msg) + str(versionInfo))
class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() self._specfile = None self._config = {} self._config.update(self.appDefaults) self.checkBoxes = {} self.specObjects = {} self.envPaths = {} self.ui = Ui_MainWindow() self.ui.setupUi(self) self.setWindowTitle('BuilderTron v{0}'.format(__version__)) self.setWindowIcon(QIcon(appPath + 'buildertron.ico')) self.createToolbar() self.collectUiObjects() self.loadDefaultSpec() self.appLoadConfig() self.updateUI() if self.config.get('show_splashscreen', True): self.initSplash() self.show() self.refreshPreview() self.loadRecentFile() @property def appDefaults(self): return { 'ask_save_on_close': True, 'show_splashscreen': True, 'keep_recent_files': True, 'recent_files': [], 'override_build': False, 'override_build_cmd': 'buildozer {target} {buildmode}', 'override_clean': False, 'override_clean_cmd': 'buildozer {target} clean', 'override_deploy': False, 'override_deploy_cmd': 'buildozer {target} deploy', 'override_distclean': False, 'override_distclean_cmd': 'buildozer distclean', 'override_run': False, 'override_run_cmd': 'buildozer {target} run', 'override_serve': False, 'override_serve_cmd': 'buildozer {target} serve', 'override_terminal': False, 'override_terminal_cmd': 'xterm -hold -e', 'custom_target': '', 'use_app_blacklist': False, 'app_blacklist': '', 'use_buildozer_blacklist': False, 'buildozer_blacklist': '', 'use_app_substitute': False, 'app_substitute': '', 'use_buildozer_substitute': False, 'buildozer_substitute': '', 'use_custom_spec': False, 'custom_spec': get_default_template(), } def appLoadConfig(self): logging.info('MainWindow->appLoadConfig') try: with open(self.settingsPath, 'r') as file: data = json.load(file) file.close() self.config.update(data) except Exception: self.appSaveConfig() self.appRestoreStore() def appRestoreStore(self): logging.info('MainWindow->appRestoreStore') self.updateRecentFilesMenu() def appSaveConfig(self): logging.info('MainWindow->appSaveConfig') try: with open(self.settingsPath, 'w') as file: json.dump(self.config, file, sort_keys=True, indent=2) except PermissionError: logging.info( 'PermissionError: you do not permission to save config') logging.info(self.config) @property def buildmode(self): buildmode = self.comboBuild.currentText() return buildmode @property def buildozerSpecDefault(self): return join(appPath, 'spec', 'buildozer-default.spec') @property def cmdBuild(self): default = self.appDefaults['override_build_cmd'] if self.config.get('override_build', False): return self.config.get('override_build_cmd', default) return default @property def cmdClean(self): default = self.appDefaults['override_clean_cmd'] if self.config.get('override_distclean', False): return self.config.get('override_clean_cmd', default) return default @property def cmdDeploy(self): default = self.appDefaults['override_deploy_cmd'] if self.config.get('override_deploy', False): return self.config.get('override_deploy_cmd', default) return default @property def cmdDistclean(self): default = self.appDefaults['override_distclean_cmd'] if self.config.get('override_distclean', False): return self.config.get('override_distclean_cmd', default) return default @property def cmdRun(self): default = self.appDefaults['override_run_cmd'] if self.config.get('override_run', False): return self.config.get('override_run_cmd', default) return default @property def cmdServe(self): default = self.appDefaults['override_serve_cmd'] if self.config.get('override_serve', False): return self.config.get('override_serve_cmd', default) return default @property def config(self): return self._config @property def settingsPath(self): if platform == 'linux': home = expanduser('~') base = '{0}/.local/share/buildertron/'.format(home) os.system('mkdir -p {0}'.format(base)) path = join(base, 'settings.json') else: path = 'settings.json' return path @property def specfileDir(self): return dirname(self._specfile) @property def logcat(self): return self.comboLogcat.currentText() @property def targetname(self): return self.comboTarget.currentText() def checkCommandOutput(self, cmd): out = '' try: out = check_output(cmd).decode('utf8') except Exception: pass return out def clearRecentFiles(self): self.config['recent_files'] = [] self.updateRecentFilesMenu() self.appSaveConfig() def closeEvent(self, event): try: self.splash.close() except Exception: pass if not self.config.get('ask_save_on_close', True): event.accept() return confirm = QMessageBox(self) confirm.setWindowTitle('Save changes?') confirm.setText('Save changes before closing') confirm.setStandardButtons(QMessageBox.No | QMessageBox.Cancel | QMessageBox.Save) ret = confirm.exec() if ret == QMessageBox.Save: save = self.onSave() if save is False: event.ignore() return elif ret == QMessageBox.Cancel: event.ignore() return self.appSaveConfig() event.accept() def closeFile(self): logging.info('MainWindow->closeFile') def collectUiObjects(self): logging.debug(self.ui.__dict__.keys()) for n, obj in self.ui.__dict__.items(): if n.startswith('checkbox_'): self.checkBoxes[n[9:]] = obj elif n.startswith('lineedit_'): self.specObjects[n[9:]] = obj elif n.startswith('lineedit2_'): self.specObjects[n[10:]] = obj elif n.startswith('checkbox2_'): self.specObjects[n[10:]] = obj elif n.startswith('combobox_'): self.specObjects[n[9:]] = obj elif n.startswith('spinbox_'): self.specObjects[n[8:]] = obj elif n.startswith('colorpick_'): obj.clicked.connect(self.openPresplashPicker) elif n.startswith('permissions_'): obj.clicked.connect(self.openAndroidPermissions) elif n.startswith('toolbutton_'): obj.clicked.connect(partial(self.onToolButton, name=n[11:])) def createToolbar(self): self.toolbar = self.addToolBar('Toolbar') self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.toolbar.setIconSize(QSize(32, 32)) self.toolbar.setMovable(False) act = QAction(QIcon(self.iconPath('new.png')), 'New', self) self.toolbar.addAction(act) act.triggered.connect(self.onNew) act = QAction(QIcon(self.iconPath('open.png')), 'Open', self) self.toolbar.addAction(act) act.triggered.connect(self.onLoad) act = QAction(QIcon(self.iconPath('save.png')), 'Save', self) self.toolbar.addAction(act) act.triggered.connect(self.onSave) act = QAction(QIcon(self.iconPath('saveas.png')), 'Save As...', self) self.toolbar.addAction(act) act.triggered.connect(self.onSaveAs) self.toolbar.addSeparator() act = QAction(QIcon(self.iconPath('distclean.png')), 'Dist Clean', self) self.toolbar.addAction(act) act.triggered.connect(partial(self.onCmd, act)) act.setToolTip('buildozer distclean') act = QAction(QIcon(self.iconPath('clean.png')), 'Clean', self) self.toolbar.addAction(act) act.triggered.connect(partial(self.onCmd, act)) act.hovered.connect(partial(self.onToolbarHover, act)) label = QLabel(self) label.setText(' Build: ') self.toolbar.addWidget(label) self.comboBuild = QComboBox(self) self.toolbar.addWidget(self.comboBuild) self.comboBuild.addItems(['debug', 'release']) act = QAction(QIcon(self.iconPath('build.png')), 'Build', self) self.toolbar.addAction(act) act.triggered.connect(partial(self.onCmd, act)) act.hovered.connect(partial(self.onToolbarHover, act)) self.toolbar.addSeparator() act = QAction(QIcon(self.iconPath('deploy.png')), 'Deploy', self) self.toolbar.addAction(act) act.triggered.connect(partial(self.onCmd, act)) act.hovered.connect(partial(self.onToolbarHover, act)) act = QAction(QIcon(self.iconPath('run.png')), 'Run', self) self.toolbar.addAction(act) act.triggered.connect(partial(self.onCmd, act)) act.hovered.connect(partial(self.onToolbarHover, act)) act = QAction(QIcon(self.iconPath('serve.png')), 'Serve', self) self.toolbar.addAction(act) act.triggered.connect(partial(self.onCmd, act)) act.hovered.connect(partial(self.onToolbarHover, act)) label = QLabel(self) label.setText(' Target: ') self.toolbar.addWidget(label) self.comboTarget = QComboBox(self) self.toolbar.addWidget(self.comboTarget) label = QLabel(self) label.setText(' Logcat: ') self.toolbar.addWidget(label) self.comboLogcat = QComboBox(self) self.toolbar.addWidget(self.comboLogcat) self.comboLogcat.addItems(['off', 'on']) label = QLabel(self) label.setText(' Log Level: ') self.toolbar.addWidget(label) self.comboLogLevel = QComboBox(self) self.toolbar.addWidget(self.comboLogLevel) self.comboLogLevel.addItems(['2', '1', '0']) self.specObjects['log_level'] = self.comboLogLevel def getObjectValue(self, object): # checkBox? value = None try: value = object.checkState() if value == 0: value = False else: value = True return value except Exception: pass # lineEdit? try: value = object.text() return value except Exception: pass # comboBox? try: value = object.currentText() return value except Exception: pass # spinBox? try: value = object.value() return value except Exception: pass return value def getSpec(self): """Returns specification""" spec = {} for k, v in self.specObjects.items(): if not v.isEnabled(): spec[k] = None continue spec[k] = self.getObjectValue(v) return spec def getSpecOutput(self): # TODO - needs refactoring target = self.getObjectValue(self.comboTarget) logcat = self.getObjectValue(self.comboLogcat) build = self.getObjectValue(self.comboBuild) app_blacklist = None use_app_blacklist = self.config.get('use_app_blacklist') if use_app_blacklist: app_blacklist = self.config.get('app_blacklist') app_blacklist = app_blacklist.replace('\n', '') app_blacklist = app_blacklist.split(',') buildozer_blacklist = None use_buildozer_blacklist = self.config.get('use_buildozer_blacklist') if use_buildozer_blacklist: buildozer_blacklist = self.config.get('buildozer_blacklist') buildozer_blacklist = buildozer_blacklist.replace('\n', '') buildozer_blacklist = buildozer_blacklist.split(',') app_substitute = {} appsub = {} use_app_substitute = self.config.get('use_app_substitute') if use_app_substitute: appsub = self.config.get('app_substitute') appsub = appsub.replace('\n', '') appsub = appsub.split(',') appsub = [k for k in appsub if '=' in k] for k in appsub: try: key, sub = k.split('=') app_substitute[key] = sub except Exception: continue buildozer_substitute = {} buildozersub = {} use_buildozer_substitute = self.config.get('use_buildozer_substitute') if use_buildozer_substitute: buildozersub = self.config.get('buildozer_substitute') buildozersub = buildozersub.replace('\n', '') buildozersub = buildozersub.split(',') buildozersub = [k for k in buildozersub if '=' in k] for k in buildozersub: try: key, sub = k.split('=') buildozer_substitute[key] = sub except Exception: continue spec = self.getSpec() trans = translate_objects.translate app_text = '' buildozer_text = '' if self.config.get('use_custom_spec', False): custom_spec = self.config.get('custom_spec') else: custom_spec = self.appDefaults['custom_spec'] custom_spec += '[{0}]\n'.format('buildertron') custom_spec += '{0} = {1}\n'.format('targetname', target) custom_spec += '{0} = {1}\n'.format('logcat', logcat) custom_spec += '{0} = {1}\n'.format('build', build) if app_substitute: custom_spec += 'app_substitute = {0}\n'.format( list(app_substitute.items())) if buildozer_substitute: custom_spec += 'buildozer_substitute = {0}\n'.format( list(buildozer_substitute.items())) for k, v in trans['app'].items(): if v not in spec: continue value = spec[v] if value is None: continue if app_blacklist and k in app_blacklist: continue j = None if app_substitute: j = app_substitute.get(k, None) if j: k = j app_text += ('{0} = {1}\n'.format(k, str(value))) for k, v in trans['buildozer'].items(): if v not in spec: continue value = spec[v] if value is None: continue if buildozer_blacklist and k in buildozer_blacklist: continue if buildozer_substitute: j = buildozer_substitute.get(k, None) j = None if j: k = j buildozer_text += ('{0} = {1}\n'.format(k, str(value))) result = custom_spec.format(app=app_text, buildozer=buildozer_text) return result def loadDefaultSpec(self): logging.info('MainWindow->loadDefaultSpec') self.loadSpec('spec/buildozer-default.spec') for chk in self.checkBoxes.values(): chk.setCheckState(0) def loadRecentFile(self): recent_files = self.config.get('recent_files', []) try: file = recent_files[0] if exists(file): self.loadSpec(file) self._specfile = file self.updateTitle() except Exception as e: logging.info('Failed to open recent file. {0}'.format(e)) self.refreshPreview() def loadSpec(self, specfile): """Loads buildozer spec """ logging.info('MainWindow->loadSpec') logging.info(specfile) specfile = realpath(specfile) if not exists(specfile): return config = SafeConfigParser() trans = translate_objects.translate config.read([specfile]) config_dict = {} for s in config.sections(): config_dict[s] = {} for k, v in config.items(s): try: config_dict[s][k] = v except Exception as e: continue app_substitute = {} buildozer_substitute = {} buildertron_conf = {} try: buildertron_conf = config_dict['buildertron'] except Exception as e: logging.info(e) if buildertron_conf: target = buildertron_conf.get('targetname', None) if target: index = self.comboTarget.findText(target) self.comboTarget.setCurrentIndex(index) logcat = buildertron_conf.get('logcat', None) if logcat: index = self.comboLogcat.findText(logcat) self.comboLogcat.setCurrentIndex(index) build = buildertron_conf.get('build', None) if build: index = self.comboBuild.findText(str(build)) self.comboBuild.setCurrentIndex(index) # unsubstitute values app_substitute = buildertron_conf.get('app_substitute', {}) try: app_substitute = { v: k for k, v in make_tuple(str((app_substitute))) } except Exception as e: app_substitute = {} logging.info(e) try: buildozer_substitute = { v: k for k, v in make_tuple(str(buildozer_substitute)) } except Exception as e: buildozer_substitute = {} logging.info(e) for section in config_dict: if section == 'buildertron': continue for key, value in config_dict[section].items(): if section == 'app': key = app_substitute.get(key, key) elif section == 'buildozer': key = buildozer_substitute.get(key, key) t = trans[section].get(key) obj = self.specObjects.get(t) if not obj: continue try: self.setObjectValue(obj, value) except Exception as e: logging.info(e) # also try to check box if it exists try: self.checkBoxes[t].setCheckState(2) except Exception as e: logging.info(e) return specfile def iconPath(self, icon): return join(appPath, 'icons', icon) def initSplash(self): self.splash = QSplashScreen(QPixmap(appPath + "splash.png"), Qt.WindowStaysOnTopHint) self.splash.show() QTimer.singleShot(SPLASH_TIMEOUT, lambda: self.splash.close()) def onButton(self): print(1) def onCmd(self, act): label = act.text() if not self._specfile and label != 'Dist Clean': return if label == 'Dist Clean': label = 'Distclean' elif not self._specfile: return try: cmd = getattr(self, 'cmd' + label) except Exception as e: return logcat = self.logcat buildmode = self.buildmode targetname = self.targetname if logcat == 'on' and label not in ['Distclean', 'Clean']: logcat = ' logcat' else: logcat = '' cmd = '{c}{logcat}'.format(c=cmd.format(target=targetname, buildmode=buildmode), logcat=logcat) if label == 'Distclean': self.runCmd(cmd=cmd) return self.runCmd(cwd=self.specfileDir, cmd=cmd) def onLoad(self, **kwargs): logging.info('MainWindow->onLoad') ask_save = kwargs.get('ask_save', True) if ask_save: confirm = QMessageBox(self) confirm.setWindowTitle("Save changes?") confirm.setText("Save changes before loading another file?") confirm.setStandardButtons(QMessageBox.No | QMessageBox.Cancel | QMessageBox.Save) ret = confirm.exec() if ret == QMessageBox.Save: self.onSave() elif ret == QMessageBox.Cancel: return dlg = QFileDialog(self) options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog options |= QFileDialog.ExistingFiles while True: specfile, _ = dlg.getOpenFileName(self, 'Load buildozer.spec', 'buildozer.spec', options=options) if not specfile: return if not basename(specfile) == 'buildozer.spec': continue break if not basename(specfile) == 'buildozer.spec': return self.loadSpec(specfile) self._specfile = specfile self.updateTitle() self.updateRecentFiles() def onMenubar(self, action): logging.info('MainWindow->Menubar->{}'.format(action.text())) text = action.text() if text == 'About...': self.openAbout() elif text == 'Build': self.onCmd(text) elif text == 'Clean': self.onCmd(text) elif text == 'Clear Recent Files': self.clearRecentFiles() elif text == 'Dist Clean': self.onCmd(text) elif text == 'Deploy': self.onCmd(text) elif text == 'Serve': self.onCmd(text) elif text == 'Exit': self.close() elif text == 'Load': self.onLoad() elif text == 'New': self.onNew() elif text == 'Settings': self.openSettings() elif text == 'Save': self.onSave() elif text == 'Save As...': self.onSaveAs() elif text == 'Submit Issue': self.openSubmitIssue() def onNew(self): logging.info('MainWindow->onNew') confirm = QMessageBox(self) confirm.setWindowTitle("Save changes?") confirm.setText("Save changes before creating new file?") confirm.setStandardButtons(QMessageBox.No | QMessageBox.Cancel | QMessageBox.Save) ret = confirm.exec() if ret == QMessageBox.Save: self.onSave() elif ret == QMessageBox.Cancel: return self.loadDefaultSpec() self._specfile = None self.updateTitle() def onRecentFile(self, file): logging.info('MainWindow->onRecentFile') confirm = QMessageBox(self) confirm.setWindowTitle('Load Recent File?') confirm.setText('Current changes will be lost. Continue?') confirm.setStandardButtons(QMessageBox.Cancel | QMessageBox.Yes) ret = confirm.exec() if ret != QMessageBox.Yes: return self.loadDefaultSpec() self._specfile = None file = self.loadSpec(file) if file: self._specfile = file self.updateTitle() def onSave(self, **kwargs): logging.info('MainWindow->onSave') msg = kwargs.get('msg', 'Save buildozer.spec') if not self._specfile: dlg = QFileDialog(self) options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog while True: specfile, _ = dlg.getSaveFileName(self, msg, 'buildozer.spec', options=options) if not specfile: return False if not basename(specfile) == 'buildozer.spec': continue break self._specfile = specfile specfile = self._specfile result = self.getSpecOutput() with open(specfile, 'w') as file: file.write(result) self.updateRecentFiles() self.appSaveConfig() self.updateTitle() def onSaveAs(self): dlg = QFileDialog(self) options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog while True: specfile, _ = dlg.getSaveFileName(self, 'Save to buildozer.spec', 'buildozer.spec', options=options) if not specfile: return if not basename(specfile) == 'buildozer.spec': continue break self._specfile = specfile self.onSave() def onToolbarHover(self, act): label = act.text() try: cmd = getattr(self, 'cmd' + label) except Exception as e: return logcat = self.logcat buildmode = self.buildmode targetname = self.targetname if logcat == 'on' and label not in ['Dist Clean', 'Clean']: logcat = ' logcat' else: logcat = '' cmd = '{c}{logcat}'.format(c=cmd.format(target=targetname, buildmode=buildmode), logcat=logcat) act.setToolTip('cmd: {0}'.format(cmd)) def onToolButton(self, name): logging.info('MainWindow->onToolButton->{0}'.format(name)) object = self.specObjects[name] dlg = QFileDialog(self) options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog options |= QFileDialog.DirectoryOnly folder = dlg.getExistingDirectory(self, 'Choose directory', '.', options=options) if not folder: return object.setText(folder) def openAbout(self): aboutdialog.AboutDialog(self) def openAndroidPermissions(self): perm = self.specObjects['android_permissions'] ret = androidpermissionsdialog.AndroidPermissionsDialog(self) ret.setValue(perm.text()) ret.accepted.connect(lambda: perm.setText(ret.value)) ret.open() def openPresplashPicker(self): object = self.specObjects['android_presplash_color'] dlg = QColorDialog(self) c = QColor(object.currentText()) dlg.setCurrentColor(c) color = dlg.getColor() if not color.isValid(): return object.setEditText(color.name()) def openSettings(self): dlg = settingsdialog.SettingsDialog(self) dlg.setDefaultConfig(self.appDefaults) dlg.setConfig(self.config) dlg.accepted.connect(lambda: self.updateConfig(dlg.value())) dlg.exec() def openSubmitIssue(self): submitissuedialog.SubmitIssueDialog(self) def refreshPreview(self): logging.info('Refreshing preview text') preview = self.ui.previewText preview.clear() result = self.getSpecOutput() preview.insertPlainText(result) def refreshSystemDetails(self): logging.info('refreshSystemDetails') textEdit = self.ui.textEditSystem textEdit.clear() textEdit.insertPlainText('cmd: buildozer version\n') out = self.checkCommandOutput('buildozer version') out = out.replace('# Check configuration tokens', '') if out: textEdit.insertPlainText('{0}\n'.format(out)) else: textEdit.insertPlainText( 'No output. Is buildozer installed?\n'.format(out)) textEdit.insertPlainText('Pip checking dependency versions.\n') textEdit.insertPlainText( 'Note: This check may be using incorrect pip to check dependencies.' ) textEdit.insertPlainText( 'Future releases should improve this method.\n\n') out = self.checkCommandOutput('pip --version') textEdit.insertPlainText('{0}'.format(out)) for d in ['cython', 'jinja2', 'pexpect', 'virtualenv']: cmd = 'pip show {0}'.format(d) textEdit.insertPlainText('cmd: {0}\n'.format(cmd)) out = self.checkCommandOutput('{0}'.format(cmd)) textEdit.insertPlainText('{0}\n'.format(out)) if not out: textEdit.insertPlainText( 'No output. Is {} installed?\n\n'.format(d)) def runCmd(self, cwd='.', cmd=''): logging.info('runCmd') print('runCmd') override_terminal = self.config.get( 'override_terminal', self.appDefaults['override_terminal']) override_terminal_cmd = self.config.get( 'override_terminal_cmd', self.appDefaults['override_terminal_cmd']) if override_terminal: override_terminal_cmd = self.config.get( 'override_terminal', self.appDefaults['override_terminal']) if platform == 'win32': return elif platform == 'linux': c = '{term} "'.format(term=override_terminal_cmd) c += 'cd {cwd} '.format(cwd=cwd) c += '&& {cmd}"'.format(cmd=cmd) logging.info(c) call(c, stdin=PIPE, shell=True) def setObjectValue(self, object, value): # checkBox? try: v = value if v == 'True': v = 2 else: v = 0 object.setCheckState(v) return except Exception: pass # lineEdit? try: object.setText(value) return except Exception: pass # comboBox? try: index = object.findText(str(value)) object.setCurrentIndex(index) return except Exception: pass # spinBox? try: object.setValue(int(value)) return except Exception: pass def updateConfig(self, config): self.config.update(config) if self.config['keep_recent_files'] is False: self.config['recent_files'] = [] self.updateRecentFilesMenu() self.appSaveConfig() self.updateTargetNamesMenu() def updateRecentFiles(self): logging.info('MainWindow->updateRecentFiles') keep_recent_files = self.config.get('keep_recent_files', True) if keep_recent_files is False: self.config['recent_files'] = [] else: recent_files = self.config.get('recent_files', []) if self._specfile in recent_files: idx = recent_files.index(self._specfile) del recent_files[idx] new = set() for f in recent_files: new.add(f) new = list(new) new.insert(0, self._specfile) self.config['recent_files'] = new[:10] self.updateRecentFilesMenu() self.appSaveConfig() def updateRecentFilesMenu(self): recent_files = self.config.get('recent_files', []) self.ui.menuRecentFiles.clear() for file in recent_files: act = QAction(self) act.setText(file) self.ui.menuRecentFiles.addAction(act) act.triggered.connect(partial(self.onRecentFile, file)) self.ui.menuRecentFiles.addSeparator() act = QAction(self) act.setText('Clear Recent Files') self.ui.menuRecentFiles.addAction(act) if not recent_files: act.setEnabled(False) def updateTargetNamesMenu(self): custom_targets = self.config.get('custom_target', []) custom_targets = custom_targets.replace('\n', '') self.comboTarget.clear() self.comboTarget.addItems( ['android', 'android_new', 'android_old', 'ios', 'osx']) self.comboTarget.addItems(custom_targets.split(',')) def updateTitle(self): logging.info('MainWindow->updateTitle') title = 'BuilderTron v{0}'.format(__version__) if self._specfile: title += ' - {0}'.format(self._specfile) self.setWindowTitle(title) def updateUI(self): self.specObjects['android_presplash_color'].addItems( sorted(ANDROID_PRESPLASH_COLORS)) self.updateTargetNamesMenu()
class PhotoFrame(QtWidgets.QMainWindow): def __init__(self, config): super(PhotoFrame, self).__init__() self.config = config # load logo already for splashscreen self.logo_large = QImage("logo.png") # instance variables to be read from config file self.slideshow_delay = None self.root_folder = None self.font_size = None self.compass = None self.flip_rotation = None self.rotation = None self.shuffle = None self.google_maps = None self.players = None self.current_player_index = 0 self.watermark = None self.frame_size = QSize() self.splash_window = None self.popup = None self.stack = None def start(self): # start timer timer = QtCore.QTimer(self) timer.timeout.connect(self._timer_callback) timer.start(self.slideshow_delay) # go... self.showFullScreen() self._timer_callback() def setup(self): # read values from the config file self._setup_general_config() # setup an accelerometer if frame rotation enabled if self.compass == "mpu6050": from utils.mpu6050 import Mpu6050Compass self.compass = Mpu6050Compass(self.flip_rotation) elif self.compass == "fake": from utils.orientation import Compass self.compass = Compass(self.flip_rotation) self.compass.set_angle(self.rotation) else: self.compass = None # create a watermark based on the logo #self.watermark = self.logo_large.scaledToWidth(50, QtCore.Qt.SmoothTransformation) # screen dimensions self.frame_size = QGuiApplication.primaryScreen().geometry().size() logger.info("Frame size = %s", self.frame_size) # create frame content self._setup_players() self._build_ui() def _setup_general_config(self): """ Read config values from config.yml file """ frame_config = self.config.get_config_value("frame", self.config.root) if not frame_config: raise KeyError( "Could not find section 'frame' in config file. Exiting") self.slideshow_delay = int( self.config.get_config_value("slideshow_delay", frame_config)) logger.info("Slideshow delay = %d", self.slideshow_delay) self.root_folder = self.config.get_config_value( "root_folder", frame_config) logger.info("Media folder = %s", self.root_folder) self.font_size = int(self.config.get_config_value( "font", frame_config)) logger.info("Font size = %d", self.font_size) self.compass = self.config.get_config_value("compass", frame_config) logger.info("Compass = %s", self.compass) self.rotation = self.config.get_config_value("rotation", frame_config) logger.info("Rotation = %d", self.rotation) self.flip_rotation = self.config.get_config_value( "flip_rotation", frame_config) logger.info("Flip Rotation = %s", self.flip_rotation) self.shuffle = self.config.get_config_value("shuffle", frame_config) logger.info("Shuffle = %s", self.shuffle) self.google_maps = self.config.get_config_value( "google_maps", frame_config) logger.info("Google Maps API = %s", self.google_maps) def _setup_players(self): """ Factory method to create the set of media players :return: a list of AbstractMediaPlayer instances """ players_config = self.config.get_config_value("players", self.config.root) if not players_config: raise KeyError( "Could not find section 'players' in config file. Exiting") self.players = [] # iterate through each entry, creating a corresponding media player for name in players_config: player = None if players_config[name]["type"] == "photo_player": from gui.media_players import PhotoPlayer player = PhotoPlayer( name, self.root_folder + "/" + self.config.get_config_value( "folder", players_config[name]), self, self.config.get_config_value("shuffle", players_config[name])) elif players_config[name]["type"] == "dashboard": from gui.dashboard import FrameDashboard player = FrameDashboard(name, self) elif players_config[name]["type"] == "video_player": from gui.media_players import VideoPlayer # TODO - replace instance call with static method call player = VideoPlayer( name, self.root_folder + "/" + self.config.get_config_value( "folder", players_config[name]), self, self.config.get_config_value("shuffle", players_config[name])) logger.info("Creating player %s", player.get_name()) self.players.append(player) self.current_player_index = 0 def next_player(self) -> PhotoFrameContent: """ Switch to the next media player. If at the end of the player list, jump to the start """ logger.debug("current_player_index = %d", self.current_player_index) logger.debug("length player_list = %d", len(self.players)) if self.current_player_index >= len(self.players) - 1: logger.debug("Starting at beginning of media") new_index = 0 else: new_index = self.current_player_index + 1 self._set_player_by_index(new_index) return self.get_current_player() def prev_player(self) -> PhotoFrameContent: """ Switch to the previous media player. If at the end of the player list, jump to the start """ logger.debug("current_player_index = %d", self.current_player_index) logger.debug("length player_list = %d", len(self.players)) if self.current_player_index <= 0: logger.debug("Starting at end of players") new_index = len(self.players) - 1 else: new_index = self.current_player_index - 1 self._set_player_by_index(new_index) return self.get_current_player() def get_current_player(self) -> PhotoFrameContent: """ Get a reference to the current media player :return: the current media player """ return self.players[self.current_player_index] def _timer_callback(self): self.get_current_player().next() def _build_ui(self): # setup UI - use a QStackedWidget to avoid widgets being destroyed self.stack = QtWidgets.QStackedWidget(self) for p in self.players: player_widget = p.get_main_widget() # prevent oversize widgets # logger.info("main_widget size before = %s", player_widget.size()) # policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) # player_widget.setSizePolicy(policy) # player_widget.resize(self.frame_size) # logger.info("main_widget size after = %s", player_widget.size()) # If the media player returns a widget, add it. Else create a dummy 'not implemented' widget if player_widget: player_widget.setParent(self) self.stack.addWidget(player_widget) else: not_implemented = QtWidgets.QLabel( "Media Player %s: Not yet implemented" % p.get_name(), self) not_implemented.setAlignment(QtCore.Qt.AlignCenter) self.stack.addWidget(not_implemented) self.setCentralWidget(self.stack) def _set_player_by_index(self, index: int): new_player = self.players[index] logger.debug("Changing to player index %d (%s)", index, new_player.get_name()) self.current_player_index = index # bring new player to the top and update self.stack.setCurrentIndex(index) new_player.next() def mousePressEvent(self, mouse): """ Handle mouse clicks :param mouse: the mouse event """ # close the popup (if open) if self.popup and self.popup.isVisible(): self.popup.hide() return # make sure we return here, otherwise the dialog re-opens further down! # get the width/height of the screen, and the mouse click lco-ords width, height = self.size().width(), self.size().height() x, y = mouse.pos().x(), mouse.pos().y() # flip click areas if frame is rotated if self.compass and self.compass.is_portrait_frame(): x, y = y, x # click on left/right borders = prev/next image if x >= width * 0.8: self.get_current_player().next() elif x <= width * 0.2: self.get_current_player().prev() # click on the top/bottom borders = prev/next media player elif y >= height * 0.8: self.next_player().next() elif y <= height * 0.2: self.prev_player().next() # click in the centre = raise popup showing photo information else: self._popup() def keyPressEvent(self, key): """ Handle key-presses :param key: the pressed key """ key_press = key.key() if key_press == QtCore.Qt.Key_Escape: # escape = exit self.close() sys.exit(0) if key_press == QtCore.Qt.Key_Left: # left = prev image self.get_current_player().prev() if key_press == QtCore.Qt.Key_Right: # right = next image self.get_current_player().next() if key_press == QtCore.Qt.Key_Up: # up = next media player self.prev_player() if key_press in [Qt.Key_Enter, Qt.Key_Return]: # space = reload image list self._popup() if key_press == QtCore.Qt.Key_Down: # down = next player self.next_player() def refresh_current_playlist(self): logger.info("Refreshing media list for %s", self.get_current_player().get_name()) self.get_current_player().refresh_media_list() def _popup(self): # only show popup for photo player from gui.media_players import PhotoPlayer if not isinstance(self.get_current_player(), PhotoPlayer): return logger.debug("Open popup") if not self.popup: self.popup = Popup(self, self.font_size) filename, exif = self.get_current_player().get_current_media_exif( ) # filename and EXIF may be none self.popup.update_popup(filename, exif) def splash_screen(self, delay: int): angle_to_rotate_photo = 0 # detect if frame is rotated # if self.compass: # logger.debug("Frame rotated by %d", self.compass.get_rotation_simple()) # angle_to_rotate_photo = -self.compass.get_rotation_simple() logger.debug("Rotating photo by %f", angle_to_rotate_photo) splash_logo = QtGui.QPixmap.fromImage( self.logo_large.transformed( QtGui.QTransform().rotate(angle_to_rotate_photo))).scaled( 500, 500, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation) self.splash_window = QSplashScreen(self, splash_logo, Qt.WindowStaysOnTopHint) self.splash_window.show() # set timer to close the splashscreen def wrap_close(): self.splash_window.close() QtCore.QTimer.singleShot(delay, wrap_close)
splash.showMessage("Copying temp files", Qt.AlignBottom | Qt.AlignCenter, Qt.black) if percentage >= 70 and percentage < 80: splash.showMessage("Checking files", Qt.AlignBottom | Qt.AlignCenter, Qt.black) if percentage >= 80 and percentage < 90: splash.showMessage("Loading PyQt", Qt.AlignBottom | Qt.AlignCenter, Qt.black) if percentage >= 90 and percentage < 98: splash.showMessage("Loading App", Qt.AlignBottom | Qt.AlignCenter, Qt.black) if percentage >= 98: splash.showMessage("Almost there!", Qt.AlignBottom | Qt.AlignCenter, Qt.black) app.processEvents() zf.extract(file, extractDir) zf.close() print('finished unzipping') splash.hide() splash.close() appDir = os.path.join(bundle_dir, 'ui', 'ui') # zip always putting a double dir ... don't know why print('Main app will be run in appDir = ', appDir) os.chdir(appDir) # os.system(['python3', 'ui.py']) # this work fine if OS == 'Linux': os.system(os.path.join(appDir, 'ResIPy')) else: p = Popen(os.path.join(appDir, 'ResIPy.exe'), shell=False, stdout=None, stdin=None) # this works now as well ! p.communicate() # block and wait for the main program to finish # this last one doesn't work on linux WHEN COMPILED and I don't know why print('splashScreen is exiting') sys.exit(0) # send the SIGTERM signal -> works # sys.exit(app.exec_()) # doesn't work
def main(): try: locale.setlocale(locale.LC_ALL, '') except locale.Error: pass # ignore this as it might fail on macOS, we'll fallback to UTF-8 in that case if config.get_use_fusion_gui_style(): sys.argv += ['-style', 'fusion'] if '--error-report' in sys.argv: sys.exit(error_report_main()) # Catch all uncaught exceptions and show an error message for them. # PyQt5 does not silence exceptions in slots (as did PyQt4), so there # can be slots which try to (for example) send requests but don't wrap # them in an async call with error handling. argv = deepcopy(sys.argv) # Deep copy because QApplication (i.e. BrickViewer) constructor parses away Qt args and we want to know the style. if '--no-error-reporter' not in sys.argv: ExceptionReporter(argv) # Exceptions that happen before the event loop runs (f.e. syntax errors) kill the brickv so fast, that the error reporter thread # (which is daemonized) can not report the error before it is killed. Report them manually. try: # importing the MainWindow after creating the QApplication instance triggers this warning # # Qt WebEngine seems to be initialized from a plugin. Please set Qt::AA_ShareOpenGLContexts # using QCoreApplication::setAttribute before constructing QGuiApplication. # # do what the warnings says to avoid it QApplication.setAttribute(Qt.AA_ShareOpenGLContexts) brick_viewer = BrickViewer(sys.argv) if sys.platform == 'darwin': # workaround macOS QTBUG-61562 from brickv.mac_pasteboard_mime_fixed import MacPasteboardMimeFixed mac_pasteboard_mime_fixed = MacPasteboardMimeFixed() splash = QSplashScreen(load_pixmap('splash.png'), Qt.WindowStaysOnTopHint) splash.show() message = 'Starting Brick Viewer ' + config.BRICKV_FULL_VERSION splash.showMessage(message, Qt.AlignHCenter | Qt.AlignBottom, Qt.white) brick_viewer.processEvents() from brickv.mainwindow import MainWindow main_window = MainWindow() main_window.show() splash.finish(main_window) except: if '--no-error-reporter' in sys.argv: raise etype, value, tb = sys.exc_info() error = "".join(traceback.format_exception(etype, value, tb)) error = "The following error is fatal. Exiting now.\n\n" + error traceback.print_exception(etype, value, tb) try: splash.close() except: pass # Either sys.executable is /path/to/python, then run calls /path/to/python /path/to/main.py --error-report, # or sys.executable is brickv[.exe], then the --error-report flag ensures, that the path to main.py is ignored. subprocess.run([sys.executable, os.path.realpath(__file__), "--error-report"] + argv, input=error, universal_newlines=True) sys.exit(1) sys.exit(brick_viewer.exec_())
class Viewer(Ui_MainWindow): def __init__(self): super(Ui_MainWindow, self).__init__() splash_pix = QPixmap(':/imgs/imgs/splash.png') self.splash = QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint) self.splash.show() self.controller = Controller(self) self.progress = 0 self.timer = QBasicTimer() def setupUi(self, MainWindow): self.MainWindow = MainWindow Ui_MainWindow.setupUi(self,MainWindow) # set logger window self.logger = WinLogger(self.text_console) self.logger.register_logger() self._connect_signals(MainWindow) self.setFixedSize(self.size()) self.load_config() self.splash.close() def _connect_signals(self, MainWindow): # menu action self.action_exit.triggered.connect(self.app_quit) self.action_open.triggered.connect(self.load_file) self.action_about.triggered.connect(self.about) self.dview_variables.cellClicked.connect(self.controller.update_cur_fact) # button action #self.pb_start.clicked.connect(self.b_start) #self.pb_stop.clicked.connect(self.b_stop) #self.pb_pause.clicked.connect(self.b_pause) # Menu actions def app_quit(self): self.MainWindow.close() def about(self): dialog = QDialog() dialog.ui = Ui_AboutDialog() dialog.ui.setupUi(dialog) dialog.setModal(True) dialog.show() dialog.exec_() def load_config(self): #self.controller.load_setting() #self.refresh() #init view ## init fact operators fo = FactOperator() operators = fo.get_operators() self.comb_variable_to_fact_func.addItems(operators) return def load_file(self): fname = QFileDialog.getOpenFileName(self, 'Open file', '', "volume data (*.inp);; mesh model (*.stl);") for s in fname: logging.debug(s) if fname[0]: ext_file = path.splitext(fname[0])[1] if ext_file in fname[1]: logging.info("Load " + fname[0]) if ext_file == '.stl': self.controller.load_mesh(fname[0]) if ext_file == '.inp': self.controller.load_inp(fname[0]) else: return
class proxyMaker(QWidget): DEFAULT_LOC = 'ord1' def __init__(self): super().__init__() self.initUI() self.initSplashScreen() def initUI(self): serverNames = ['GigaNet', 'UpCloud', 'Vultr', 'NetNut'] actionNames = ['Create', 'Info', 'Destroy', 'Save and Quit'] # Input Horizontal hbox = QVBoxLayout(self) splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) # Top Horizontal top = QFrame(splitter) top.setFrameShape(QFrame.StyledPanel) # Bottom Horizontal bottom = QFrame(splitter) bottom.setFrameShape(QFrame.StyledPanel) # Inputs # Server, NumberProxies, Location, Action inputBox = QHBoxLayout(top) serverSplitter = QSplitter(top) serverSplitter.setOrientation(Qt.Horizontal) numberSplitter = QSplitter(top) numberSplitter.setOrientation(Qt.Horizontal) locationSplitter = QSplitter(top) locationSplitter.setOrientation(Qt.Horizontal) actionSplitter = QSplitter(top) actionSplitter.setOrientation(Qt.Horizontal) # Server, NumberProxies, Location, Action Verticals serverBox = QFrame(serverSplitter) serverBox.setFrameShape(QFrame.StyledPanel) numberBox = QFrame(numberSplitter) numberBox.setFrameShape(QFrame.StyledPanel) locationBox = QFrame(locationSplitter) locationBox.setFrameShape(QFrame.StyledPanel) actionBox = QFrame(actionSplitter) actionBox.setFrameShape(QFrame.StyledPanel) ### Server self.serverLayout = QVBoxLayout(serverBox) self.serverButtons = [QPushButton(x) for x in serverNames] [x.setCheckable(True) for x in self.serverButtons] self.serverButtonsGroup = QButtonGroup() [self.serverButtonsGroup.addButton(x) for x in self.serverButtons] self.serverButtonsGroup.setExclusive(True) self.serverButtons[0].clicked.connect(self.giganet) self.serverButtons[1].clicked.connect(self.upcloud) self.serverButtons[2].clicked.connect(self.vultr) self.serverButtons[3].clicked.connect(self.netnut) # Number and Location Box generalInfoLayout = QVBoxLayout(numberBox) self.numberDisplay = QPlainTextEdit() self.numberDisplay.setPlaceholderText("Number of proxies.") self.locationDisplay = QPlainTextEdit() self.locationDisplay.setPlaceholderText("Location of proxies.") # Server specific requirements specificInfoLayout = QVBoxLayout(locationBox) self.gigaInfo = ['APIKEY', 'APIHASH'] self.gigaInfo[0] = QPlainTextEdit() self.gigaInfo[0].setPlaceholderText("GigaNet API KEY.") self.gigaInfo[0].setVisible(False) self.gigaInfo[1] = QPlainTextEdit() self.gigaInfo[1].setPlaceholderText("GigaNet API HASH.") self.gigaInfo[1].setVisible(False) self.ucInfo = ['ucUSR', 'ucPSWD'] self.ucInfo[0] = QPlainTextEdit() self.ucInfo[0].setPlaceholderText("UpCloud Username.") self.ucInfo[0].setVisible(False) self.ucInfo[1] = QPlainTextEdit() self.ucInfo[1].setPlaceholderText("UpCloud Password.") self.ucInfo[1].setVisible(False) self.vInfo = ['vtoken'] self.vInfo[0] = QPlainTextEdit() self.vInfo[0].setPlaceholderText("Vultr.") self.vInfo[0].setVisible(False) self.nnInfo = ['nnUSR', 'nnPSWD'] self.nnInfo[0] = QPlainTextEdit() self.nnInfo[0].setPlaceholderText("NetNut Username.") self.nnInfo[0].setVisible(False) self.nnInfo[1] = QPlainTextEdit() self.nnInfo[1].setPlaceholderText("NetNut Password.") self.nnInfo[1].setVisible(False) # Action Box self.actionLayout = QVBoxLayout(actionBox) self.actionButtons = [QPushButton(x) for x in actionNames] [x.setCheckable(True) for x in self.actionButtons] self.actionButtonsGroup = QButtonGroup() [self.actionButtonsGroup.addButton(x) for x in self.actionButtons] self.actionButtonsGroup.setExclusive(True) self.actionButtons[0].clicked.connect(self.create) self.actionButtons[1].clicked.connect(self.info) self.actionButtons[2].clicked.connect(self.destroy) self.actionButtons[3].clicked.connect(self.quit) # Output # Log, Verticals outputBox = QHBoxLayout(bottom) logSplitter = QSplitter(bottom) logSplitter.setOrientation(Qt.Horizontal) proxySplitter = QSplitter(bottom) proxySplitter.setOrientation(Qt.Horizontal) # Log, Proxy Verticals logBox = QFrame(logSplitter) logBox.setFrameShape(QFrame.StyledPanel) proxyBox = QFrame(proxySplitter) proxyBox.setFrameShape(QFrame.StyledPanel) # Log logLayout = QVBoxLayout(logBox) self.logDisplay = QPlainTextEdit() self.logDisplay.setReadOnly(True) self.logDisplay.setPlainText("Log will display here.") # Proxy proxyLayout = QVBoxLayout(proxyBox) self.proxyDisplay = QPlainTextEdit() self.proxyDisplay.setPlainText("Proxies:") self.proxyDisplay.setReadOnly(True) # Add widgets into layout [self.serverLayout.addWidget(x) for x in self.serverButtons] [self.actionLayout.addWidget(x) for x in self.actionButtons] generalInfoLayout.addWidget(self.numberDisplay) generalInfoLayout.addWidget(self.locationDisplay) [ specificInfoLayout.addWidget(self.gigaInfo[i]) for i in range(len(self.gigaInfo)) ] [ specificInfoLayout.addWidget(self.ucInfo[i]) for i in range(len(self.ucInfo)) ] [ specificInfoLayout.addWidget(self.vInfo[i]) for i in range(len(self.vInfo)) ] [ specificInfoLayout.addWidget(self.nnInfo[i]) for i in range(len(self.nnInfo)) ] logLayout.addWidget(self.logDisplay) proxyLayout.addWidget(self.proxyDisplay) inputBox.addWidget(serverSplitter) inputBox.addWidget(numberSplitter) inputBox.addWidget(locationSplitter) inputBox.addWidget(actionSplitter) outputBox.addWidget(logSplitter) outputBox.addWidget(proxySplitter) hbox.addWidget(splitter) # Restore Information from data/info.txt if exists if os.path.isfile("data/info.txt"): print("Info.txt found.") with open("data/info.txt") as fh: data = json.load(fh) for dataHandler in data['giganet']: self.gigaInfo[0].setPlainText(dataHandler['apikey']) self.gigaInfo[1].setPlainText(dataHandler['apihash']) for dataHandler in data['upcloud']: self.ucInfo[0].setPlainText(dataHandler['ucuser']) self.ucInfo[1].setPlainText(dataHandler['ucpass']) for dataHandler in data['vultr']: self.vInfo[0].setPlainText(dataHandler['vtoken']) for dataHandler in data['netnut']: self.nnInfo[0].setPlainText(dataHandler['nnuser']) self.nnInfo[1].setPlainText(dataHandler['nnpass']) def initSplashScreen(self): splash_pix = QPixmap('data/image/loading.jpg') self.splash = QSplashScreen(splash_pix) self.splash.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint) self.splash.setEnabled(False) def giganet(self): print("Giganet") [self.gigaInfo[i].setVisible(True) for i in range(len(self.gigaInfo))] [self.ucInfo[i].setVisible(False) for i in range(len(self.ucInfo))] [self.vInfo[i].setVisible(False) for i in range(len(self.vInfo))] [self.nnInfo[i].setVisible(False) for i in range(len(self.nnInfo))] self.locationDisplay.setDisabled(False) def upcloud(self): print("UpCloud") [self.gigaInfo[i].setVisible(False) for i in range(len(self.gigaInfo))] [self.ucInfo[i].setVisible(True) for i in range(len(self.ucInfo))] [self.vInfo[i].setVisible(False) for i in range(len(self.vInfo))] [self.nnInfo[i].setVisible(False) for i in range(len(self.nnInfo))] self.locationDisplay.setDisabled(False) def vultr(self): print("Vultr") [self.gigaInfo[i].setVisible(False) for i in range(len(self.gigaInfo))] [self.ucInfo[i].setVisible(False) for i in range(len(self.ucInfo))] [self.vInfo[i].setVisible(True) for i in range(len(self.vInfo))] [self.nnInfo[i].setVisible(False) for i in range(len(self.nnInfo))] self.locationDisplay.setDisabled(False) def netnut(self): print("NetNut") [self.gigaInfo[i].setVisible(False) for i in range(len(self.gigaInfo))] [self.ucInfo[i].setVisible(False) for i in range(len(self.ucInfo))] [self.vInfo[i].setVisible(False) for i in range(len(self.vInfo))] [self.nnInfo[i].setVisible(True) for i in range(len(self.nnInfo))] self.locationDisplay.setDisabled(True) def enableAll(self): # Enable all buttons and text boxes [x.setDisabled(False) for x in self.serverButtons] [x.setDisabled(False) for x in self.actionButtons] self.numberDisplay.setDisabled(False) self.locationDisplay.setDisabled(False) [ self.gigaInfo[i].setDisabled(False) for i in range(len(self.gigaInfo)) ] [self.ucInfo[i].setDisabled(False) for i in range(len(self.ucInfo))] [self.vInfo[i].setDisabled(False) for i in range(len(self.vInfo))] [self.nnInfo[i].setDisabled(False) for i in range(len(self.nnInfo))] self.logDisplay.setDisabled(False) self.proxyDisplay.setDisabled(False) def disableAll(self): # Disable all buttons and text boxes [x.setDisabled(True) for x in self.serverButtons] [x.setDisabled(True) for x in self.actionButtons] self.numberDisplay.setDisabled(True) self.locationDisplay.setDisabled(True) [self.gigaInfo[i].setDisabled(True) for i in range(len(self.gigaInfo))] [self.ucInfo[i].setDisabled(True) for i in range(len(self.ucInfo))] [self.vInfo[i].setDisabled(True) for i in range(len(self.vInfo))] [self.nnInfo[i].setDisabled(True) for i in range(len(self.nnInfo))] self.logDisplay.setDisabled(True) self.proxyDisplay.setDisabled(True) def threadHelper(self, func, args, res): res.append(func(*args)) def threadHelperNoArgs(self, func): func() def create(self): print("Create") if self.serverButtons[0].isChecked() \ and len(self.numberDisplay.toPlainText()) != 0 \ and len(self.locationDisplay.toPlainText()) != 0: print("Giga create") numProxies = self.numberDisplay.toPlainText() serverLocation = self.locationDisplay.toPlainText() gigaKey = self.gigaInfo[0].toPlainText() gigaHash = self.gigaInfo[1].toPlainText() self.logDisplay.setPlainText("Giganet chosen. Creating ...") self.logDisplay.appendPlainText( "Number of Proxies: {}".format(numProxies)) self.logDisplay.appendPlainText( "Server Location: {}".format(serverLocation)) # Mutliple Gigenet accounts (key, hash) split by ',' if ',' in gigaKey or ',' in gigaHash: gigaKey = gigaKey.split(",") gigaHash = gigaHash.split(",") else: gigaKey = [gigaKey] gigaHash = [gigaHash] keyHash = {} for i in range(0, len(gigaKey)): keyHash["gigaKey{0}".format(i)] = ( gigaKey[i], gigaHash[i], ) self.taskGigaCreate(i, keyHash, numProxies, serverLocation) elif self.serverButtons[1].isChecked() \ and len(self.numberDisplay.toPlainText()) != 0: print("Upcloud create") numProxies = self.numberDisplay.toPlainText() ucUsr = self.ucInfo[0].toPlainText() ucPswd = self.ucInfo[1].toPlainText() self.logDisplay.setPlainText("UpCloud chosen. Creating ...") self.logDisplay.appendPlainText( "Number of Proxies: {}".format(numProxies)) self.logDisplay.appendPlainText( "Server Location preset as us-chi1 ") res = [] ucApiInit(ucUsr, ucPswd) thread = threading.Thread(target=self.threadHelper, args=(ucApiCreate, (numProxies, ), res)) thread.start() thread.join() # Show splash screen when thread is still running. stillAlive = 0 while thread.is_alive(): if not stillAlive: self.splash.show() self.disableAll() # When QSplashScreen is running, there should be an event loop running # processEvents forces app to process all events app.processEvents() stillAlive = 1 self.splash.close() self.enableAll() logFile, infoFile = ucApiReturnFileName() logThread = displayOutput(logFile, self.logDisplay) proxyThread = displayOutput(infoFile, self.proxyDisplay) elif self.serverButtons[2].isChecked() \ and len(self.numberDisplay.toPlainText()) != 0 \ and len(self.locationDisplay.toPlainText()) != 0: print("Vultr") elif self.serverButtons[3].isChecked() \ and len(self.numberDisplay.toPlainText()) != 0: print("NetNut") numProxies = self.numberDisplay.toPlainText() self.logDisplay.setPlainText("NetNut chosen. Creating ...") self.logDisplay.appendPlainText( "Number of Proxies: {}".format(numProxies)) nnUsername = self.nnInfo[0].toPlainText() nnPassword = self.nnInfo[1].toPlainText() # Run API function in a thread and return value store in res. res = [] nnApiInit() thread = threading.Thread(target=self.threadHelper, args=(nnApiCreate, ( numProxies, nnUsername, nnPassword, ), res)) thread.start() # Show splash screen when thread is still running. stillAlive = 0 while thread.is_alive(): if not stillAlive: self.splash.show() self.disableAll() # When QSplashScreen is running, there should be an event loop running # processEvents forces app to process all events app.processEvents() stillAlive = 1 self.splash.close() self.enableAll() logFile, infoFile = nnApiReturnFileName() logThread = displayThread(logFile, self.logDisplay) proxyThread = displayThread(infoFile, self.proxyDisplay) logThread.start() proxyThread.start() else: print("Check input") def info(self): print("Info") if self.serverButtons[0].isChecked(): print("Giga Info") serverLocation = self.locationDisplay.toPlainText() gigaKey = self.gigaInfo[0].toPlainText() gigaHash = self.gigaInfo[1].toPlainText() self.logDisplay.setPlainText("Giganet chosen. Getting Info ...") # Mutliple Gigenet accounts (key, hash) split by ',' if ',' in gigaKey or ',' in gigaHash: gigaKey = gigaKey.split(",") gigaHash = gigaHash.split(",") else: gigaKey = [gigaKey] gigaHash = [gigaHash] keyHash = {} for i in range(0, len(gigaKey)): keyHash["gigaKey{0}".format(i)] = ( gigaKey[i], gigaHash[i], ) self.taskGigaInfo(i, keyHash, serverLocation) else: print("Check input") def destroy(self): print("Destroy") if self.serverButtons[0].isChecked(): print("Giga destroy") self.logDisplay.setPlainText("Giganet chosen. Destroying ...") serverLocation = self.locationDisplay.toPlainText() gigaKey = self.gigaInfo[0].toPlainText() gigaHash = self.gigaInfo[1].toPlainText() # Mutliple Gigenet accounts (key, hash) split by ',' if ',' in gigaKey or ',' in gigaHash: gigaKey = gigaKey.split(",") gigaHash = gigaHash.split(",") else: gigaKey = [gigaKey] gigaHash = [gigaHash] keyHash = {} for i in range(0, len(gigaKey)): keyHash["gigaKey{0}".format(i)] = ( gigaKey[i], gigaHash[i], ) self.taskGigaDestroy(i, keyHash, serverLocation) elif self.serverButtons[1].isChecked(): print("Upcloud destroy") ucUsr = self.ucInfo[0].toPlainText() ucPswd = self.ucInfo[1].toPlainText() self.logDisplay.setPlainText("UpCloud chosen. destroy ...") res = [] ucApiInit(ucUsr, ucPswd) ucApiDestroy() logFile, infoFile = ucApiReturnFileName() logThread = displayOutput(logFile, self.logDisplay) proxyThread = displayOutput(infoFile, self.proxyDisplay) else: print("Check input") if sys.platform == 'linux': os.system("rm *.txt") def quit(self): data = {} data['giganet'] = [] data['giganet'].append({ 'apikey': self.gigaInfo[0].toPlainText(), 'apihash': self.gigaInfo[1].toPlainText() }) data['upcloud'] = [] data['upcloud'].append({ 'ucuser': self.ucInfo[0].toPlainText(), 'ucpass': self.ucInfo[1].toPlainText() }) data['vultr'] = [] data['vultr'].append({'vtoken': self.vInfo[0].toPlainText()}) data['netnut'] = [] data['netnut'].append({ 'nnuser': self.nnInfo[0].toPlainText(), 'nnpass': self.nnInfo[1].toPlainText() }) with open('data/info.txt', 'w') as fh: json.dump(data, fh) QApplication.quit() def taskGigaCreate(self, idx, keyHashDict, numProxies, serverLocation): keyHash = keyHashDict["gigaKey{0}".format(idx)] print("[DEBUG] Runnning {}: {} | {} | {} | {} | {}".format( idx, keyHashDict["gigaKey{0}".format(idx)], keyHash[0], keyHash[1], numProxies, serverLocation)) # Run API function in a thread and return value store in res. res = [] gigaApiInit(serverLocation, keyHash[0], keyHash[1]) thread = threading.Thread(target=self.threadHelper, args=(gigaApiCreate, ( numProxies, serverLocation, ), res)) thread.start() thread.join() # Show splash screen when thread is still running. stillAlive = 0 while thread.is_alive(): if not stillAlive: self.splash.show() self.disableAll() # When QSplashScreen is running, there should be an event loop running # processEvents forces app to process all events app.processEvents() stillAlive = 1 self.splash.close() self.enableAll() logFile, infoFile = gigaApiReturnFileName() logThread = displayOutput(logFile, self.logDisplay) proxyThread = displayOutput(infoFile, self.proxyDisplay) def taskGigaInfo(self, idx, keyHashDict, serverLocation): keyHash = keyHashDict["gigaKey{0}".format(idx)] print("[DEBUG]Runnning {}: {} | {} | {} | {}".format( idx, keyHashDict["gigaKey{0}".format(idx)], keyHash[0], keyHash[1], serverLocation)) gigaApiInit(serverLocation, keyHash[0], keyHash[1]) # Run API function in a thread and return value store in res. thread = threading.Thread(target=self.threadHelperNoArgs, args=(gigaApiInfo, )) thread.start() # Show splash screen when thread is still running. stillAlive = 0 while thread.is_alive(): if not stillAlive: self.splash.show() self.disableAll() # When QSplashScreen is running, there should be an event loop running # processEvents forces app to process all events app.processEvents() stillAlive = 1 self.splash.close() self.enableAll() logFile, infoFile = gigaApiReturnFileName() logThread = displayOutput(logFile, self.logDisplay) proxyThread = displayOutput(infoFile, self.proxyDisplay) def taskGigaDestroy(self, idx, keyHashDict, serverLocation=DEFAULT_LOC): keyHash = keyHashDict["gigaKey{0}".format(idx)] print("[DEBUG] Runnning {}: {} | {} | {} | {}".format( idx, keyHashDict["gigaKey{0}".format(idx)], keyHash[0], keyHash[1], serverLocation)) gigaApiInit(serverLocation, keyHash[0], keyHash[1]) # Run API function in a thread and return value store in res. thread = threading.Thread(target=self.threadHelperNoArgs, args=(gigaApiDestroy, )) thread.start() # Show splash screen when thread is still running. stillAlive = 0 while thread.is_alive(): if not stillAlive: self.splash.show() self.disableAll() # When QSplashScreen is running, there should be an event loop running # processEvents forces app to process all events app.processEvents() stillAlive = 1 self.splash.close() self.enableAll() logFile, infoFile = gigaApiReturnFileName() logThread = displayOutput(logFile, self.logDisplay)