コード例 #1
0
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()
コード例 #2
0
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()
コード例 #3
0
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()
コード例 #4
0
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()
コード例 #5
0
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_())
コード例 #6
0
ファイル: about.py プロジェクト: medical-projects/SlideRunner
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()
コード例 #7
0
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()
コード例 #8
0
 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,'警告','请先设置摄像头参数')
コード例 #9
0
import os
コード例 #10
0
ファイル: main.py プロジェクト: Tinkerforge/brickv
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_())
コード例 #11
0
ファイル: PyPreviewer.py プロジェクト: louisraccoon/PyStudy
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()
コード例 #12
0
ファイル: QtApplication.py プロジェクト: derekhe/Uranium
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
コード例 #13
0
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
コード例 #14
0
ファイル: splash.py プロジェクト: pandel/opsiPackageBuilder
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
コード例 #15
0
ファイル: main.py プロジェクト: pipibear/web-browser
                              | 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_())
コード例 #16
0
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))
コード例 #17
0
ファイル: buildertron.py プロジェクト: simon2x/Buildertron
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()
コード例 #18
0
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)
コード例 #19
0
ファイル: splashScreen.py プロジェクト: lisa-simon/resipy
            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
    
コード例 #20
0
ファイル: main.py プロジェクト: bmwiedemann/brickv
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_())
コード例 #21
0
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        
コード例 #22
0
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)