Beispiel #1
0
class HelpWindow(QtWidgets.QWidget):

    # TODO: do not hardcode this path like this.
    __doc_path = os.path.abspath(
        os.path.join(
            os.path.abspath(os.path.dirname(__file__)),
            "..", "..", "doc", "index.html"))

    def __init__(self, parent=None):
        super().__init__(parent)

        # The help display.
        self.help_display = QWebView(parent=self)
        self.help_display.load(QtCore.QUrl("file://" + self.__doc_path))

        # Close button.
        self.close_button = QtWidgets.QPushButton("Close")
        self.close_button.clicked.connect(self.close)

        # Layout for the widgets.
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.help_display)
        layout.addWidget(self.close_button)
        self.setLayout(layout)

        # Title
        self.setWindowTitle("{} help".format(version.progname))
class HelpView(SizePersistedDialog):
    '''
    Modeless dialog for presenting HTML help content
    '''

    def __init__(self, parent, icon, prefs, html=None, page=None, title=''):
        self.prefs = prefs
        #QDialog.__init__(self, parent=parent)
        super(HelpView, self).__init__(parent, 'help_dialog')
        self.setWindowTitle(title)
        self.setWindowIcon(icon)
        self.l = QVBoxLayout(self)
        self.setLayout(self.l)

        self.wv = QWebView()
        if html is not None:
            self.wv.setHtml(html)
        elif page is not None:
            self.wv.load(QUrl(page))
        self.wv.setMinimumHeight(100)
        self.wv.setMaximumHeight(16777215)
        self.wv.setMinimumWidth(400)
        self.wv.setMaximumWidth(16777215)
        self.wv.setGeometry(0, 0, 400, 100)
        self.wv.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.l.addWidget(self.wv)

        # Sizing
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)
        self.resize_dialog()
Beispiel #3
0
def PdfConverter(username):

        htmllink = "bootstrap_mod/usertemp/"+username+".html"
        app1 = QApplication(sys.argv)

        web = QWebView()

        link =QUrl.fromLocalFile(QFileInfo(htmllink).absoluteFilePath())

        web.load(QUrl(link))

        printer = QPrinter()
        printer.setPageSize(QPrinter.A4)
        printer.setOutputFormat(QPrinter.PdfFormat)
        Pdf_Generated_Name="bootstrap_mod/usertemp/"+username+".pdf"
        printer.setOutputFileName(Pdf_Generated_Name)

        web.print(printer)
        QApplication.exit()
        def convertIt():
                web.print(printer)
                print("Pdf generated")
                QApplication.exit()

        web.loadFinished.connect(convertIt)
        sys.exit(app1.exec_())
        return 0
def run_browser(url):
    app = QApplication(['info-display'])
    browser = QWebView()
    page = WebPage()
    browser.setPage(page)
    browser.load(QUrl(url))
    browser.show()

    app.exec()
Beispiel #5
0
class Browser(object):

    def __init__(self):
        self.network_manager = QNetworkAccessManager()
        self.network_manager.createRequest = self._create_request
        self.network_manager.finished.connect(self._request_finished)

        self.web_page = QWebPage()
        self.web_page.setNetworkAccessManager(self.network_manager)

        self.web_view = QWebView()
        self.web_view.setPage(self.web_page)

    def _create_request(self, operation, request, data):
        print(data.readAll())
        reply = QNetworkAccessManager.createRequest(self.network_manager,
                                                    operation,
                                                    request,
                                                    data)
        return reply

    def _request_finished(self, reply):
        if not reply.error() == QNetworkReply.NoError:
            # request probably failed
            print(reply.error())
            print(reply.errorString())

    def _make_request(self, url):
        request = QNetworkRequest()
        request.setUrl(QUrl(url))
        return request

    def _urlencode_post_data(self, post_data):
        post_params = QUrl()
        for (key, value) in post_data.items():
            post_params.addQueryItem(key, value)

        return post_params.encodedQuery()

    def perform(self, url, method='GET', post_data=dict()):
        request = self._make_request(url)

        if method == 'GET':
            self.web_view.load(request)
        else:
            encoded_data = self._urlencode_post_data(post_data)
            request.setRawHeader('Content-Type',
                                 QByteArray('application/x-www-form-urlencoded'))
            self.web_view.load(request,
                               QNetworkAccessManager.PostOperation,
                               encoded_data)
class BrowserWidget(QWidget, itab_item.ITabItem):

###############################################################################
# RecentProjectItem SIGNALS
###############################################################################
    """
    openProject(QString)
    openPreferences()
    dontOpenStartPage()
    """
    openProject = pyqtSignal(str)
    openPreferences = pyqtSignal()
    dontOpenStartPage = pyqtSignal()
###############################################################################

    def __init__(self, url, process=None, parent=None):
        super(BrowserWidget, self).__init__(parent)
        self._id = url
        self._process = process
        vbox = QVBoxLayout(self)
        #Web Frame
        self.webFrame = QWebView(self)
        self.webFrame.setAcceptDrops(False)

        self.webFrame.load(QUrl(url))

        vbox.addWidget(self.webFrame)

        if process is not None:
            time.sleep(0.5)
            self.webFrame.load(QUrl(url))

        self.webFrame.page().currentFrame().setScrollBarPolicy(
            Qt.Vertical, Qt.ScrollBarAsNeeded)
        self.webFrame.page().currentFrame().setScrollBarPolicy(
            Qt.Horizontal, Qt.ScrollBarAsNeeded)

    def start_page_operations(self, url):
        opt = file_manager.get_basename(url.toString())
        print("señal", opt, "self.emit(SIGNAL(opt))")
        #self.emit(SIGNAL(opt))

    def shutdown_pydoc(self):
        if self._process is not None:
            self._process.kill()

    def find_match(self, word, back=False, sensitive=False, whole=False):
        self.webFrame.page().findText(word)
Beispiel #7
0
class Browser(StickWidget):
    def __init__(self, url):
        super(Browser, self).__init__()
        
        self.view = QWebView(self)
        self.view.load(QUrl(url))
        self.view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.view.page().linkClicked.connect(self.link_clicked)
        self.view.page().mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
            
        self.view.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(os.path.join(get_parent_dir(__file__), "scrollbar.css")))
        
        self.layout.addWidget(self.view)
        
    def link_clicked(self, url):
        self.view.load(url)
Beispiel #8
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        vbox = QVBoxLayout(self)
        self.webView = QWebView(self)
        self.setCentralWidget(self.webView)
        self.webView.setUrl(QUrl("http://127.0.0.1:5000"))
        self.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.webView.linkClicked.connect(self.linkClicked)
        self.setWindowTitle("Inventory DB")

    def linkClicked(self, url):
        print("Page changed: " + url.toString())
        if url.toString().startswith("http://127.0.0.1"):
            self.webView.load(url)
            self.webView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        else:
            webbrowser.open(str(url.toString()))
Beispiel #9
0
class WebRender(QWidget):

    def __init__(self):
        super(WebRender, self).__init__()

        vbox = QVBoxLayout(self)
        #Web Frame
        self.webFrame = QWebView()
        QWebSettings.globalSettings().setAttribute(
            QWebSettings.DeveloperExtrasEnabled, True)
        vbox.addWidget(self.webFrame)

    def render_page(self, url):
        self.webFrame.load(QUrl('file:///' + url))

    def render_from_html(self, html, url=None):
        url = url and QUrl(url) or ""
        self.webFrame.setHtml(html, url)
class MainWindow(QMainWindow):
    def __init__(self, url):
        super(MainWindow, self).__init__()
        self.view = QWebView(self)
        self.view.load(url)
        self.view.setFixedSize(890, 550)
        # comment out the following line to allow refresh for debugging
        self.view.setContextMenuPolicy(Qt.NoContextMenu)

    @staticmethod
    def display_dir_dialog():
        dialog = QFileDialog()
        dir_path = QFileDialog.getExistingDirectory(dialog, "Select Directory")
        return dir_path

    @staticmethod
    def display_file_dialog():
        dialog = QFileDialog()
        file_path = QFileDialog.getOpenFileName(dialog, "Select File")
        return file_path
Beispiel #11
0
class TestWindow(QWidget):
    TMPDIR = "tmp"
    TMPHTMLFILE = os.path.join(TMPDIR,'tmptext.html')
    def __init__(self,parent = None):
        QWidget.__init__(self,parent)
        
        if os.path.isdir(TestWindow.TMPDIR) == False:
            os.mkdir(TestWindow.TMPDIR)
        
        self.textEditor = TextEditor(self)
        self.webViewer = QWebView(self)
        self.setupUI()
        self.textEditor.textChangeSignal.connect(self.reloadText)
    
    def reloadText(self,dataDict):
        if self.webViewer.isVisible() == False:
            self.webViewer.show()
        with codecs.open( ResourceManager.getResourceAbsPath('template.html'),'r','utf-8' ) as templateFileObj:
            templateStr = templateFileObj.read()
        with open( TestWindow.TMPHTMLFILE,'wb' ) as tempFileObj:
            tempFileObj.write( (templateStr % dataDict[TextEditor.KEY_ORIGINALTXET]).encode('utf-8') )
        self.webViewer.load(QUrl( "file:///%s" % os.path.abspath( TestWindow.TMPHTMLFILE ) ))


    def setupUI(self):
        self.webViewer.hide()
        
        layout = QHBoxLayout(self)
        self.splitter = QSplitter(self)
        self.splitter.addWidget(self.textEditor)
        self.splitter.addWidget(self.webViewer)
        layout.addWidget(self.splitter)

        self.textEditor.resize(400,600)
        self.webViewer.resize(400,600)
        self.resize(800,600)
        
        self.splitter.setStyleSheet("background-color:green;")
        self.textEditor.setStyleSheet("background-color:white;border:none;")
        self.webViewer.setStyleSheet("background-color:white;")
class WebRender(QWidget):

    """Render a web page inside the tools dock area."""

    def __init__(self):
        super(WebRender, self).__init__()
        vbox, temporary_directory = QVBoxLayout(self), mkdtemp()
        # Web Frame
        self.webFrame = QWebView()  # QWebView = QWebFrame + QWebSettings
        self.webFrame.setStyleSheet("QWebView{ background:#fff }")  # no dark bg
        settings = self.webFrame.settings()  # QWebSettings instance
        settings.setDefaultTextEncoding("utf-8")
        settings.setIconDatabasePath(temporary_directory)
        settings.setLocalStoragePath(temporary_directory)
        settings.setOfflineStoragePath(temporary_directory)
        settings.setOfflineWebApplicationCachePath(temporary_directory)
        settings.setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
        settings.setAttribute(QWebSettings.LocalStorageEnabled, True)
        settings.setAttribute(QWebSettings.OfflineStorageDatabaseEnabled, True)
        settings.setAttribute(QWebSettings.PluginsEnabled, True)
        settings.setAttribute(QWebSettings.DnsPrefetchEnabled, True)
        settings.setAttribute(QWebSettings.JavascriptCanOpenWindows, True)
        settings.setAttribute(QWebSettings.JavascriptCanCloseWindows, True)
        settings.setAttribute(QWebSettings.JavascriptCanAccessClipboard, True)
        settings.setAttribute(QWebSettings.SpatialNavigationEnabled, True)
        settings.setAttribute(
            QWebSettings.LocalContentCanAccessRemoteUrls, True)
        settings.setAttribute(
            QWebSettings.OfflineWebApplicationCacheEnabled, True)
        vbox.addWidget(self.webFrame)

    def render_page(self, url):
        """Render a web page from a local file."""
        self.webFrame.load(QUrl('file:///' + url))

    def render_from_html(self, html, url=None):
        """Render a webpage from a string."""
        url = url and QUrl(url) or ""
        self.webFrame.setHtml(html, url)
Beispiel #13
0
    def __init__(self, program, web, courseName, endTime, sock, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.ui = uic.loadUi(config.config.ROOT_PATH + 'view/webView.ui', self)

        self.banProgram = program
        self.allowWeb = web
        self.sock = sock
        self.courseName = courseName
        self.endTime = datetime.datetime.strptime(endTime, "%Y-%m-%d %H:%M:%S")
        self.checkPopup = False

        for i in self.allowWeb:
            view = QWebView()
            view.load(QUrl(config.config.ALLOW_SITE[i]))
            self.ui.tabWidget.addTab(view, config.config.ALLOW_SITE[i].lstrip('https://www.'))

        self.ui.webView.load(QUrl('http://www.kookmin.ac.kr'))

        try:
            self.timer = QTimer(self)
            self.timer.timeout.connect(self.rest_time_display)
            self.timer.start(900)

        except Exception as e:
            print(e)

        self.ui.show()

        try:
            self.threadTimer = QTimer(self)
            self.threadTimer.timeout.connect(self.check_thread_run)

            self.mp = checkSystem.checkSystem(self.courseName, self.banProgram, self.sock)
            self.mp.start()

            self.threadTimer.start(41000)

        except Exception as e:
            print(e)
Beispiel #14
0
class Browser(StickWidget):
    def __init__(self, url):
        super(Browser, self).__init__()
        
        self.view = QWebView(self)
        self.layout.addWidget(self.view)        
        self.view.settings().setAttribute(QWebSettings.PluginsEnabled, True) # enable plugins
        self.view.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True) # enable dev tools
        self.view.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(os.path.join(get_parent_dir(__file__), "scrollbar.css")))
        
        self.view.load(QUrl(url))
        self.view.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.view.page().mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
        # self.view.page().mainFrame().evaluateJavaScript(self.plugin_public_js)
        self.view.page().mainFrame().evaluateJavaScript(self.plugin_qvod_search_js)
        
        self.view.loadFinished.connect(self.url_load_finished)
        self.view.page().linkClicked.connect(self.link_clicked)        
        
    def url_load_finished(self):
        # self.view.page().mainFrame().evaluateJavaScript("setTimeout(function () {startsearch(document)}, 3000)")
        self.view.page().mainFrame().evaluateJavaScript("setTimeout(function () {search()}, 3000)")
        
    def link_clicked(self, url):
        self.view.load(url)
        
    @property
    def plugin_qvod_search_js(self):
        fd = QFile("qvod/search.js") 
 
        if fd.open(QIODevice.ReadOnly | QFile.Text): 
            result = QTextStream(fd).readAll() 
            fd.close() 
        else: 
            result = '' 
            
        return result
Beispiel #15
0
def process_html(htmlpath, args, app):
    
    
    htmlurl = urllib.parse.quote(htmlpath.resolve().absolute().as_posix())
    htmlQurl = QUrl("file://{}".format(htmlurl))
 
    pdfOutputPath = htmlpath.with_suffix(".pdf")
    
    print("htmlpath:", htmlpath)
    print("htmlurl:", htmlurl)
    print("htmlQurl:", htmlQurl)
    print("pdfOutputPath:", pdfOutputPath)
    
    web = QWebView()
    web.page().settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
    
    printer = QPrinter()
    printer.setPageSize(QPrinter.A4)
    printer.setOutputFormat(QPrinter.PdfFormat)
    printer.setOutputFileName(str(pdfOutputPath))
 
    def convertIt():
        web.print_(printer)
        print("Pdf generated")
    
    def closeIt():
        QApplication.exit()
 
    web.loadFinished.connect(convertIt)

    if args.show:
        web.show()
    else:
        web.loadFinished.connect(closeIt)
    
    web.load(htmlQurl)
Beispiel #16
0
class KuGou(QWidget):
    def __init__(self, parent = None):
        super(KuGou, self).__init__(parent)
        self.createLayout()
        self.createConnection()
       
      
    def createLayout(self):
        self.setWindowTitle("kugou player")
    
        #self.addressBar = QLineEdit()
        #self.goButton = QPushButton("&GO")
        #bl = QHBoxLayout()
        #bl.addWidget(self.addressBar)
        #bl.addWidget(self.goButton)
          
        self.webView = QWebView()
          
        layout = QVBoxLayout()
        layout.addWidget(self.webView)
        self.setLayout(layout)
      
    def createConnection(self):
        self.webView.load(QUrl("http://web.kugou.com"))
Beispiel #17
0
class Window(QMainWindow):
    def __init__(self, url, app):
        super(Window, self).__init__()
        self.progress = 0
        self.app = app

        self.UI_FILE_PATH = 'ui/room_design.ui'
        self.CALLBACK = 'python_callback'
        self.MODELS_INFO = 'assets/models_info.json'
        self.TEXTURES_INFO = 'assets/textures_info.json'
        self.WIIMOTE_FREQUENCY = 50
        self.DEFAULT_SCALE = 1.0
        self.DEFAULT_ROTATION = 0.0
        self.PLANE_XZ = 'xz'
        self.PLANE_XY = 'xy'
        self.PLANE_YZ = 'yz'

        self.WIN_X = 30
        self.WIN_Y = 60
        self.WIN_WIDTH = 1000
        self.WIN_HEIGHT = 650

        self.WIIMOTE_DEFAULT_ACCEL_SENSOR_VALUE = 512
        self.WIIMOTE_MIN_ACCEL_SENSOR_VALUE = 407
        self.WIIMOTE_MAX_ACCEL_SENSOR_VALUE = 610
        self.WIIMOTE_SENSITIVITY = 10000

        self.MESH_SELECT_TABLE_X_LEFT = 250
        self.TEXTURE_SELECT_TABLE_X_LEFT = 50
        self.SELECT_TABLES_Y = 665

        screen_dimens = self.app.desktop().screenGeometry()
        self.url = url
        self.monitor_width = screen_dimens.width()
        self.monitor_height = screen_dimens.height()

        QNetworkProxyFactory.setUseSystemConfiguration(True)

        self.win = uic.loadUi(self.UI_FILE_PATH)
        self.wv = QWebView(self.win)

        js.SetupScene.init(self.wv)
        js.SetupScene.apply_callback(self.CALLBACK, self)

        self.wv.load(self.url)

        self.list_widget = self.win.list_widget
        self.mesh_select_table = None
        self.model_table = None
        self.texture_select_table = None

        self.setup_ui()

        self.meshes = []
        self.selected_mesh = None
        self.mesh_translation = []
        self.mesh_rotation = []
        self.mesh_scale = []

        self.is_first_b_button_callback = True
        self.wm_current_a_button_state = False

        self.address_line_edit = self.win.line_edit_address
        self.connect_btn = self.win.btn_connect

        self.connect_btn.clicked.connect(self.connect_wiimote)

        self.initial_accelerometer_data = None

        self.wiimote = wii.Wiimote(self.WIIMOTE_FREQUENCY, self.monitor_width,
                                   self.monitor_height)
        self.dpad_button_states = {}
        self.setup_wiimote()

        self.last_angle_y_rotation = self.DEFAULT_ROTATION
        self.last_scale_factor = self.DEFAULT_SCALE

        self.win.show()

        self.undo_utility = undo.UndoUtility()

        self.selected_plane = self.PLANE_XZ
        self.select_plane(self.selected_plane)

    # WIIMOTE BINDINGS & METHODS

    def setup_wiimote(self):
        self.wiimote.a_button_clicked.connect(
            lambda: self.on_wm_a_button_press(self.wiimote.accelerometer_data))
        self.wiimote.a_button_released.connect(self.on_wm_a_button_release)

        self.wiimote.b_button_clicked.connect(
            lambda: self.on_wm_b_button_press(self.wiimote.accelerometer_data))

        self.wiimote.ir_data_updated.connect(
            lambda: self.on_wm_ir_data_update(self.wiimote.pointer_location))

        self.wiimote.b_button_released.connect(self.on_wm_b_button_release)

        self.wiimote.plus_button_clicked.connect(self.on_wm_plus_button_press)
        self.wiimote.minus_button_clicked.connect(self.on_wm_minus_button_press)

        self.wiimote.one_button_clicked.connect(self.request_undo)
        self.wiimote.two_button_clicked.connect(self.redo)

        self.dpad_button_states = {
            Qt.Key_Up: False, Qt.Key_Down: False,
            Qt.Key_Left: False, Qt.Key_Right: False, }
        self.wiimote.up_button_clicked.connect(
            lambda: self.on_wm_dpad_button_press(Qt.Key_Up))
        self.wiimote.up_button_released.connect(
            lambda: self.on_wm_dpad_button_release(Qt.Key_Up))
        self.wiimote.down_button_clicked.connect(
            lambda: self.on_wm_dpad_button_press(Qt.Key_Down))
        self.wiimote.down_button_released.connect(
            lambda: self.on_wm_dpad_button_release(Qt.Key_Down))
        self.wiimote.left_button_clicked.connect(
            lambda: self.on_wm_dpad_button_press(Qt.Key_Left))
        self.wiimote.left_button_released.connect(
            lambda: self.on_wm_dpad_button_release(Qt.Key_Left))
        self.wiimote.right_button_clicked.connect(
            lambda: self.on_wm_dpad_button_press(Qt.Key_Right))
        self.wiimote.right_button_released.connect(
            lambda: self.on_wm_dpad_button_release(Qt.Key_Right))
        self.wiimote.home_button_clicked.connect(self.on_wm_home_button_clicked)

    def on_wm_ir_data_update(self, data):
        x, y = data
        self.set_cursor_position(x, y, True)

    def on_wm_a_button_press(self, data):
        if self.wm_current_a_button_state:
            return
        self.wm_current_a_button_state = True
        self.simulate_mouse_press()
        if self.selected_mesh is not None:
            self.initial_accelerometer_data = data

    def on_wm_a_button_release(self):
        if self.wm_current_a_button_state is False:
            return
        self.wm_current_a_button_state = False
        self.simulate_mouse_release()

    def on_wm_b_button_press(self, data):
        if self.is_first_b_button_callback:
            js.SetupScene.save_state("wiimote_transform")
            self.initial_accelerometer_data = data
            self.is_first_b_button_callback = False

        if self.selected_mesh is not None:
            js.SetupScene.get_translation_rotation_scale(self.selected_mesh)
            self.handle_mesh_scaling_fine(data)
            self.handle_mesh_rotation_y(data)

    def on_wm_dpad_button_press(self, button):
        self.dpad_button_states[button] = True
        self.simulate_camera_event(QtGui.QKeyEvent.KeyPress, button)

    def on_wm_dpad_button_release(self, button):
        if self.dpad_button_states[button]:  # = last frame: button was pressed
            self.simulate_camera_event(QtGui.QKeyEvent.KeyRelease, button)
        self.dpad_button_states[button] = False

    def on_wm_plus_button_press(self):
        if self.selected_mesh is not None:
            js.SetupScene.save_state("duplicate_mesh")
            if self.selected_mesh is not None:
                self.request_duplicate_mesh(self.selected_mesh)

    def on_wm_minus_button_press(self):
        if self.selected_mesh is not None:
            js.SetupScene.save_state("remove_mesh")
            self.delete_mesh(self.selected_mesh)

    def on_wm_home_button_clicked(self):
        js.SetupScene.set_camera_to_default()

    def on_wm_b_button_release(self):
        if len(self.mesh_rotation) != 0:
            self.last_angle_y_rotation = self.mesh_rotation[1]

        if len(self.mesh_scale) != 0:
            self.last_scale_factor = self.mesh_scale[0]

            if self.mesh_scale[0] < 0.1:
                js.SetupScene.scale_mesh_by_id(self.selected_mesh, 0.1, 0.1,
                                               0.1)

                self.last_scale_factor = 0.1

        js.SetupScene.on_scale_end()
        self.is_first_b_button_callback = True

    def connect_wiimote(self):
        address = self.address_line_edit.text()
        self.wiimote.connect(address)

    # UI SETUP

    def setup_ui(self):
        self.wv.setGeometry(self.WIN_X, self.WIN_Y, self.WIN_WIDTH,
                            self.WIN_HEIGHT)
        self.wv.installEventFilter(self)
        self.win.installEventFilter(self)

        self.list_widget.selectionModel().selectionChanged.connect(
            self.mesh_selection_changed)

        self.setup_selection_tables()

        self.win.explain_controls_btn.clicked.connect(self.explain_controls)

        self.win.x_y_plane_btn.clicked.connect(
            lambda: self.select_plane(self.PLANE_XY))
        self.win.x_z_plane_btn.clicked.connect(
            lambda: self.select_plane(self.PLANE_XZ))
        self.win.y_z_plane_btn.clicked.connect(
            lambda: self.select_plane(self.PLANE_YZ))

        self.win.x_y_plane_cam_btn.clicked.connect(
            lambda: self.target_cam_to_plane(self.PLANE_XY))
        self.win.x_z_plane_cam_btn.clicked.connect(
            lambda: self.target_cam_to_plane(self.PLANE_XZ))
        self.win.y_z_plane_cam_btn.clicked.connect(
            lambda: self.target_cam_to_plane(self.PLANE_YZ))

        self.win.btn_new.clicked.connect(self.on_new_action)
        self.win.btn_save.clicked.connect(self.on_save_action)
        self.win.btn_load.clicked.connect(self.on_load_action)

    def set_bt_address(self, address):
        self.win.line_edit_address.setText(address)

    # SELECTION TABLES

    def setup_selection_tables(self):
        """ Sets up the mesh_select_table and texture_select_table
        """
        # magic numbers = coordinates (the app is not responsive anyway)

        # mesh_select_table (for the models)
        self.mesh_select_table = model_table.ExpandableSelectionTable(
            self, 'Mesh', self.win)
        self.mesh_select_table.set_create_from_center(False)
        self.mesh_select_table.move(
            self.MESH_SELECT_TABLE_X_LEFT,
            self.SELECT_TABLES_Y + model_table.TABLE_ITEM_SIZE)
        self.mesh_select_table.itemSelectionChanged.connect(
            lambda: self.table_selection_changed(self.mesh_select_table))
        self.read_selection_table_data(self.MODELS_INFO,
                                       self.mesh_select_table)

        # texture_select_table (ground, wall textures)
        self.texture_select_table = model_table.ExpandableSelectionTable(
            self, 'Texture', self.win)
        self.texture_select_table.set_create_from_center(False)
        self.texture_select_table.move(
            self.TEXTURE_SELECT_TABLE_X_LEFT,
            self.SELECT_TABLES_Y + model_table.TABLE_ITEM_SIZE)
        self.texture_select_table.itemSelectionChanged.connect(
            lambda: self.table_selection_changed(self.texture_select_table))
        self.read_selection_table_data(self.TEXTURES_INFO,
                                       self.texture_select_table)

    def table_selection_changed(self, table):
        """ Callback method; simply de-selects the other table.
            "Table" refers to the mesh selection bar or the
            texture selection bar (which are, technically, tables).
        """
        other_table = None
        if table == self.mesh_select_table:
            other_table = self.texture_select_table
        else:
            other_table = self.mesh_select_table

        if len(table.selectedIndexes()) > 0:
            other_table.lose_focus()

    def read_selection_table_data(self, file_path, selection_table):
        """ Reads the data from the file (e.g. assets/models_info.json)
            and sets up the seletion_table, i.e., tells it what categories
            there are & what icons and subitems they have.
        """
        with open(file_path, 'r') as data_file:
            data = json.loads(data_file.read())
            for category in data['categories']:
                selection_table.add_item(category)

    # ADDING MESHES / SELECTING TEXTURES

    def request_add_mesh(self, mesh_file_name, type_, name=None,
                         transform="null", from_load=False):
        """ Tells the JS component to add a mesh (scene object).

            name: might be overwritten if it is already in use
            transform: location, rotation and scale (default="null" = at the
                       center of the scene, scale = 1 & rotation = 0, 0, 0)
            from_load: when this method is called to load another state (True),
                       no new "undo state" will be created. Default=False
        """
        if not from_load:
            js.SetupScene.save_state("add_mesh")

        name = um.get_name_for_new_mesh(name, type_, self.meshes)

        mesh_file = open(mesh_file_name)
        data, json_data = um.read_file_as_js_string(mesh_file, True)
        mesh_file.close()

        texture_images = um.load_images_as_base64(json_data)

        js.SetupScene.add_mesh(data, name, texture_images, type_, transform,
                               mesh_file_name)

    @QtCore.pyqtSlot(str)
    def js_mesh_loaded(self, mesh_name):
        """ Gets called when the JS component successfully created an object.
        """
        self.list_widget.addItem(mesh_name)
        self.meshes.append(mesh_name)
        self.select_mesh(mesh_name)

    @QtCore.pyqtSlot(str, str)
    def js_mesh_load_error(self, mesh_name, error):
        """ Gets called when the JS component failed to create an object. """
        print(mesh_name, error)

    def request_change_texture(self, file_name, name, type_,
                               create_undo_point=True):
        if create_undo_point:
            js.SetupScene.save_state("change_texture")

        base64data = um.load_single_img_as_base64(file_name)
        js.SetupScene.set_texture(type_, name, base64data, file_name)

    # PLANE / CAMERA BUTTONS ON THE SIDE

    def target_cam_to_plane(self, plane):
            js.SetupScene.target_camera_to_plane(plane)

    def select_plane(self, which):
        self.selected_plane = which

        data = {self.PLANE_XY: [False, True, True],
                self.PLANE_XZ: [True, False, True],
                self.PLANE_YZ: [True, True, False], }

        self.win.x_y_plane_btn.setEnabled(data[which][0])
        self.win.x_z_plane_btn.setEnabled(data[which][1])
        self.win.y_z_plane_btn.setEnabled(data[which][2])

        js.SetupScene.set_selected_plane(which)

    # OBJECT MANIPULATIONS

    def request_duplicate_mesh(self, mesh_id):
        js.SetupScene.save_state("duplicate_mesh")
        name = um.get_name_for_copy(mesh_id, self.meshes)
        js.SetupScene.duplicate_mesh(mesh_id, name)

    def handle_mesh_scaling_fine(self, data):
        scale_step = (self.WIIMOTE_DEFAULT_ACCEL_SENSOR_VALUE -
                      self.WIIMOTE_MIN_ACCEL_SENSOR_VALUE) / \
                     self.WIIMOTE_SENSITIVITY

        scale = ((self.initial_accelerometer_data[1]-data[1]) * scale_step)

        if data[2] > self.WIIMOTE_DEFAULT_ACCEL_SENSOR_VALUE - 1:
            js.SetupScene.scale_mesh_by_id(self.selected_mesh,
                                           scale + self.last_scale_factor,
                                           scale + self.last_scale_factor,
                                           scale + self.last_scale_factor)

    def handle_mesh_rotation_y(self, data):
        right_angle = 90
        angle_step_smoothing = 1.3
        sensor_data_smoothing = 6

        angle_step = (self.WIIMOTE_DEFAULT_ACCEL_SENSOR_VALUE -
                      self.WIIMOTE_MIN_ACCEL_SENSOR_VALUE) / \
            right_angle * np.pi / (right_angle * 2)

        angle = (self.initial_accelerometer_data[0]-data[0]) * angle_step / \
            angle_step_smoothing

        if data[2] > self.WIIMOTE_DEFAULT_ACCEL_SENSOR_VALUE - \
                sensor_data_smoothing:
            js.SetupScene.rotate_mesh_by_id(self.selected_mesh, 0, angle +
                                            self.last_angle_y_rotation, 0)

    @QtCore.pyqtSlot(str, str, str)
    def on_translation_rotation_scale_request(self, trans, rot, scale):
        self.get_mesh_properties(trans, 'trans')
        self.get_mesh_properties(rot, 'rot')
        self.get_mesh_properties(scale, 'scale')

    def get_mesh_properties(self, data, mode):

        if mode == 'trans':
            self.mesh_translation = js.deserialize_list(data)

        if mode == 'rot':
            self.mesh_rotation = js.deserialize_list(data)

        if mode == 'scale':
            self.mesh_scale = js.deserialize_list(data)

    # dragging happens in JS, Python is notified when it starts to enable Undo:

    @QtCore.pyqtSlot(str)
    def on_js_obj_drag_start(self, mesh_id):
        js.SetupScene.save_state("js_drag_translate")

    # DELETING / RESETTING

    def clear_all(self):
        """ Resets the entire scene & the undo utility. """
        while self.list_widget.count() > 0:
            self.list_widget.takeItem(0)

        for mesh in self.meshes:
            js.SetupScene.remove_mesh(mesh)

        js.SetupScene.remove_texture("walls")
        js.SetupScene.remove_texture("carpet")
        self.meshes = []
        self.selected_mesh = None
        self.undo_utility.reset()

    def delete_mesh(self, mesh_id):
        self.selected_mesh = None
        if mesh_id in self.meshes:
            index = self.meshes.index(mesh_id)
            del self.meshes[index]
            self.list_widget.takeItem(index)
        js.SetupScene.remove_mesh(mesh_id)

    # MESH SELECTION

    def mesh_selection_changed(self, b=0):
        """ Callback for when the selection in the list of scene objects
            changes.
        """
        selected = self.list_widget.selectedIndexes()
        if len(selected) > 0:
            self.select_mesh(self.meshes[selected[0].row()], False)
        else:
            self.de_select_meshes(False)

    def select_mesh(self, obj_id, update_list=True, from_click=False):
        """ Sets the mesh as selected in the scene (gives it an outine)
            & in the list of objects.

            update_list: if the selection change came from the list widget,
                         it should not be updated redundantly (=False)
        """
        was_selected = self.selected_mesh == obj_id
        # = short for "the item that was selected was the item that was already
        # selected"

        self.selected_mesh = obj_id
        for mesh in self.meshes:
            if mesh == obj_id:
                continue

            js.SetupScene.remove_highlight_from_mesh(mesh)

        if update_list and not was_selected:
            if obj_id in self.meshes:
                # remove any selection:
                selection_model = self.list_widget.selectionModel()
                selection_model.clear()
                # add new selection:
                selected_index = self.meshes.index(obj_id)
                new_selection = self.list_widget.indexFromItem(
                    self.list_widget.item(selected_index))
                selection_model.select(new_selection,
                                       QtCore.QItemSelectionModel.Select)

        js.SetupScene.highlight_mesh(obj_id, from_click)

    def de_select_meshes(self, from_js=True):
        if from_js:
            selection_model = self.list_widget.selectionModel()
            selection_model.clear()
        self.selected_mesh = None

        for mesh in self.meshes:
            js.SetupScene.remove_highlight_from_mesh(mesh)

    @QtCore.pyqtSlot(str)
    def on_object_clicked(self, obj_id):
        if obj_id in self.meshes:
            self.select_mesh(obj_id, True, True)
        else:  # == None; None does not work from JS
            self.de_select_meshes()

    @QtCore.pyqtSlot(str, str, str)
    def on_mesh_highlighted(self, obj_id, scale, y_rotation):
        self.last_scale_factor = float(scale)
        self.last_angle_y_rotation = float(y_rotation)

        self.mesh_rotation = [0, float(y_rotation), 0]
        self.mesh_scale = [float(scale), float(scale), float(scale)]

    # CURSOR AND CLICKS

    def set_cursor_position(self, x, y, absolute=True):
        if absolute:
            self.cursor().setPos(x, y)
        else:
            self.cursor().setPos(self.win.centralWidget.pos().x() + x,
                                 self.win.centralWidget.pos().y() + y)

    def get_cursor_position(self, absolute=True):
        if absolute:
            return self.cursor().pos()
        else:
            cursor_pos = self.cursor().pos()
            # trial and error
            y_fix = self.win.style().pixelMetric(
                QtWidgets.QStyle.PM_TitleBarHeight) * 1.5 + 1
            return QtCore.QPoint(cursor_pos.x() - self.win.pos().x(),
                                 cursor_pos.y() - self.win.pos().y() - y_fix)

    def simulate_click(self):
        rel_cursor = self.get_cursor_position(False)
        abs_cursor = self.get_cursor_position(True)

        for ev_type in (QtGui.QMouseEvent.MouseButtonPress,
                        QtGui.QMouseEvent.MouseButtonRelease):
            self.simulate_left_mouse_event(ev_type, rel_cursor, abs_cursor)

    def simulate_mouse_press(self):
        rel_cursor = self.get_cursor_position(False)
        abs_cursor = self.get_cursor_position(True)

        self.simulate_left_mouse_event(QtGui.QMouseEvent.MouseButtonPress,
                                       rel_cursor, abs_cursor)

    def simulate_mouse_release(self):
        rel_cursor = self.get_cursor_position(False)
        abs_cursor = self.get_cursor_position(True)

        self.simulate_left_mouse_event(QtGui.QMouseEvent.MouseButtonRelease,
                                       rel_cursor, abs_cursor)

    def simulate_left_mouse_event(self, ev_type, rel_cursor, abs_cursor):
        clicked_child = self.win.childAt(rel_cursor)
        if clicked_child is None:
            clicked_child = self.win
        global_child_coords = clicked_child.mapToGlobal(QtCore.QPoint(0, 0))
        pos = QtCore.QPoint(abs_cursor.x() - global_child_coords.x(),
                            abs_cursor.y() - global_child_coords.y())
        event = QtGui.QMouseEvent(ev_type,
                                  pos,
                                  abs_cursor,
                                  QtCore.Qt.LeftButton,
                                  QtCore.Qt.LeftButton,
                                  QtCore.Qt.NoModifier)
        self.app.postEvent(clicked_child, event)

    def simulate_camera_event(self, type_, key):
        event = QtGui.QKeyEvent(type_, key, QtCore.Qt.NoModifier)

        self.app.postEvent(self.wv, event)

    # NEW, SAVE, LOAD, UNDO, REDO

    def on_new_action(self):
        x, y, ok = um.InputDialog.get_new_room_xz_dimensions()

        if ok:
            self.clear_all()
            js.SetupScene.create_new_scene(x, y)

    def on_save_action(self):
        js.SetupScene.save_state("save")

    def on_load_action(self):
        scene_json = um.FileDialog.load_json_from_file()

        if scene_json != '':
            self.load_state(scene_json)

    @QtCore.pyqtSlot(str, str)
    def save_state_result(self, scene_json, identifier):
        """ Callback for when JS successfully saved the scene.

            identifier: same string that was given to the JS component
                        to mark why the state was saved. E.g., if it is
                        "undo", that means it was created to be able to
                        redo the scene & it should not be added to the
                        undo list.
        """
        scene_obj = json.loads(scene_json)

        scene_obj["selection"] = self.selected_mesh if \
            (self.selected_mesh is not None) else "None"

        scene_json = json.dumps(scene_obj)

        if identifier == "undo":
            self.undo_utility.set_first_state_at_undo(scene_json)
            self.undo()
        elif identifier == "save":
            um.FileDialog.save_json_to_file(scene_json)
        else:
            self.undo_utility.add_action(identifier, scene_json)

    def load_state(self, scene_json):
        """ Load the state in scene_json (JSON String) while completely
            discarding the current state. Cannot be undone.
        """
        self.clear_all()
        as_data = json.loads(scene_json)

        js.SetupScene.redo_scene(as_data["room"]["x"], as_data["room"]["y"])

        for mesh in as_data["meshes"]:
            self.request_add_mesh(mesh["fileName"], mesh["type"], mesh["id"],
                                  json.dumps({
                                    "pos": mesh["pos"],
                                    "rot": mesh["rot"],
                                    "scale": mesh["scale"]
                                    }), True)

        self.load_selection(as_data)

        self.load_floor_and_walls(as_data)

    def load_changed_state(self, current_state, next_state):
        """ Loads the "next_state" (JSON Object / dicts and lists) from the
            current state. Is faster than load_state & can be undone; use this
            method for "undo" and "redo" (when there are likely to be few
            changes between the states & undo must be possible).
        """

        # delete meshes if they are not in the next state
        for mesh in current_state["meshes"]:
            found_mesh = False
            for other_mesh in next_state["meshes"]:
                if other_mesh["id"] == mesh["id"]:
                    found_mesh = True
                    break
            if not found_mesh:
                self.delete_mesh(mesh["id"])

        # transform meshes for the next state / create them, if they don't
        # exist yet
        for mesh in next_state["meshes"]:
            found_mesh = False
            for previous_state in current_state["meshes"]:
                if previous_state["id"] == mesh["id"]:
                    found_mesh = True
                    self.load_transformations_for_mesh(mesh, previous_state)
                    break

            if not found_mesh:
                self.request_add_mesh(mesh["fileName"], mesh["type"],
                                      mesh["id"], json.dumps({
                                        "pos": mesh["pos"],
                                        "rot": mesh["rot"],
                                        "scale": mesh["scale"]
                                      }), True)

        self.load_selection(next_state)

        self.load_floor_and_walls(next_state)

    def load_selection(self, next_state):
        if next_state["selection"] is not "None":
            self.select_mesh(next_state["selection"])
        else:
            self.de_select_meshes()

    def load_floor_and_walls(self, next_state):
        for texture_type in ("walls", "floor"):
            if texture_type in next_state:
                self.request_change_texture(
                    next_state[texture_type]["fileName"],
                    next_state[texture_type]["textureName"],
                    next_state[texture_type]["type"], False)
            else:
                if texture_type == "floor":
                    js.SetupScene.remove_texture("carpet")
                else:
                    js.SetupScene.remove_texture(texture_type)

    def load_transformations_for_mesh(self, mesh, previous_state):
        pos_data_new = mesh["pos"]
        pos_data_old = previous_state["pos"]
        js.SetupScene.translate_mesh_by_id(
            mesh["id"], pos_data_new[0] - pos_data_old[0],
            pos_data_new[1] - pos_data_old[1],
            pos_data_new[2] - pos_data_old[2])

        rot_data = mesh["rot"]
        js.SetupScene.rotate_mesh_by_id(mesh["id"], rot_data[0], rot_data[1],
                                        rot_data[2])

        scale_data = mesh["scale"]
        js.SetupScene.scale_mesh_by_id(
            mesh["id"], scale_data[0], scale_data[1], scale_data[2], False)

    def request_undo(self):
        js.SetupScene.save_state("undo")

    def undo(self):
        undone_state = self.undo_utility.undo()
        current_state = self.undo_utility.current_state(True)
        if undone_state is not None:
            # self.load_state(undone_state["state"])
            self.load_changed_state(json.loads(current_state["state"]),
                                    json.loads(undone_state["state"]))

    def redo(self):
        redone_state = self.undo_utility.redo()
        current_state = self.undo_utility.current_state(False)
        if redone_state is not None:
            # self.load_state(redone_state["state"])
            self.load_changed_state(json.loads(current_state["state"]),
                                    json.loads(redone_state["state"]))

    # MISCELLANY

    @QtCore.pyqtSlot(str)
    def on_js_console_log(self, log):
        """
        function for debugging purposes

        :param log:
        :return:
        """
        print(log)

    def explain_controls(self):
        msg_box = QtWidgets.QMessageBox()
        pixmap = QtGui.QPixmap()
        pixmap.load("assets/img/wiimote_explain.png")
        # some 2:3 ratio that fits on most screens...
        pixmap = pixmap.scaled(534, 801)
        msg_box.setWindowTitle("WiiMote Controls - Info")
        msg_box.setIconPixmap(pixmap)
        msg_box.setDefaultButton(QtWidgets.QMessageBox.Ok)
        msg_box.show()
        msg_box.exec_()

    def eventFilter(self, source, event):
        """ Causes selection tables to lose focus (if they have the focus)
            and handles ctrl+z & ctrl+y
        """
        if event.type() == QtGui.QMouseEvent.MouseButtonPress:
            self.mesh_select_table.lose_focus()
            self.texture_select_table.lose_focus()
        elif event.type() == QtGui.QKeyEvent.KeyRelease:
            if event.key() == 75:
                self.simulate_click()
            # z (undo if with ctrl)
            elif (source == self.win and event.key() == 90 and
                  int(event.modifiers()) == QtCore.Qt.ControlModifier):
                self.request_undo()
            # y (redo if with ctrl)
            elif (source == self.win and event.key() == 89 and
                  int(event.modifiers()) == QtCore.Qt.ControlModifier):
                self.redo()
            else:
                pass
                #  print(event.key(), int(event.modifiers()))
        return super(Window, self).eventFilter(source, event)
Beispiel #18
0
class HostWindow(QMainWindow):
    # signals
    SIGTERM = pyqtSignal()
    SIGUSR1 = pyqtSignal()

    # --------------------------------------------------------------------------------------------------------

    def __init__(self):
        QMainWindow.__init__(self)
        gCarla.gui = self

        URI = sys.argv[1]

        # ----------------------------------------------------------------------------------------------------
        # Internal stuff

        self.fCurrentFrame = None
        self.fDocElemement = None
        self.fCanSetValues = False
        self.fNeedsShow = False
        self.fSizeSetup = False
        self.fQuitReceived = False
        self.fWasRepainted = False

        self.fPlugin = get_plugin_info(URI)
        self.fPorts = self.fPlugin['ports']
        self.fPortSymbols = {}
        self.fPortValues = {}

        for port in self.fPorts['control']['input']:
            self.fPortSymbols[port['index']] = (port['symbol'], False)
            self.fPortValues[port['index']] = port['ranges']['default']

        for port in self.fPorts['control']['output']:
            self.fPortSymbols[port['index']] = (port['symbol'], True)
            self.fPortValues[port['index']] = port['ranges']['default']

        # ----------------------------------------------------------------------------------------------------
        # Init pipe

        if len(sys.argv) == 7:
            self.fPipeClient = gCarla.utils.pipe_client_new(
                lambda s, msg: self.msgCallback(msg))
        else:
            self.fPipeClient = None

        # ----------------------------------------------------------------------------------------------------
        # Init Web server

        self.fWebServerThread = WebServerThread(self)
        self.fWebServerThread.start()

        # ----------------------------------------------------------------------------------------------------
        # Set up GUI

        self.setContentsMargins(0, 0, 0, 0)

        self.fWebview = QWebView(self)
        #self.fWebview.setAttribute(Qt.WA_OpaquePaintEvent, False)
        #self.fWebview.setAttribute(Qt.WA_TranslucentBackground, True)
        self.setCentralWidget(self.fWebview)

        page = self.fWebview.page()
        page.setViewportSize(QSize(980, 600))

        mainFrame = page.mainFrame()
        mainFrame.setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
        mainFrame.setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)

        palette = self.fWebview.palette()
        palette.setBrush(QPalette.Base, palette.brush(QPalette.Window))
        page.setPalette(palette)
        self.fWebview.setPalette(palette)

        settings = self.fWebview.settings()
        settings.setAttribute(QWebSettings.DeveloperExtrasEnabled, True)

        self.fWebview.loadFinished.connect(self.slot_webviewLoadFinished)

        url = "http://127.0.0.1:%s/icon.html#%s" % (PORT, URI)
        print("url:", url)
        self.fWebview.load(QUrl(url))

        # ----------------------------------------------------------------------------------------------------
        # Connect actions to functions

        self.SIGTERM.connect(self.slot_handleSIGTERM)

        # ----------------------------------------------------------------------------------------------------
        # Final setup

        self.fIdleTimer = self.startTimer(30)

        if self.fPipeClient is None:
            # testing, show UI only
            self.setWindowTitle("TestUI")
            self.fNeedsShow = True

    # --------------------------------------------------------------------------------------------------------

    def closeExternalUI(self):
        self.fWebServerThread.stopWait()

        if self.fPipeClient is None:
            return

        if not self.fQuitReceived:
            self.send(["exiting"])

        gCarla.utils.pipe_client_destroy(self.fPipeClient)
        self.fPipeClient = None

    def idleStuff(self):
        if self.fPipeClient is not None:
            gCarla.utils.pipe_client_idle(self.fPipeClient)
            self.checkForRepaintChanges()

        if self.fSizeSetup:
            return
        if self.fDocElemement is None or self.fDocElemement.isNull():
            return

        pedal = self.fDocElemement.findFirst(".mod-pedal")

        if pedal.isNull():
            return

        size = pedal.geometry().size()

        if size.width() <= 10 or size.height() <= 10:
            return

        # render web frame to image
        image = QImage(self.fWebview.page().viewportSize(),
                       QImage.Format_ARGB32_Premultiplied)
        image.fill(Qt.transparent)

        painter = QPainter(image)
        self.fCurrentFrame.render(painter)
        painter.end()

        #image.save("/tmp/test.png")

        # get coordinates and size from image
        #x = -1
        #y = -1
        #lastx = -1
        #lasty = -1
        #bgcol = self.fHostColor.rgba()

        #for h in range(0, image.height()):
        #hasNonTransPixels = False

        #for w in range(0, image.width()):
        #if image.pixel(w, h) not in (0, bgcol): # 0xff070707):
        #hasNonTransPixels = True
        #if x == -1 or x > w:
        #x = w
        #lastx = max(lastx, w)

        #if hasNonTransPixels:
        ##if y == -1:
        ##y = h
        #lasty = h

        # set size and position accordingly
        #if -1 not in (x, lastx, lasty):
        #self.setFixedSize(lastx-x, lasty)
        #self.fCurrentFrame.setScrollPosition(QPoint(x, 0))
        #else:

        # TODO that^ needs work
        if True:
            self.setFixedSize(size)

        # set initial values
        self.fCurrentFrame.evaluateJavaScript(
            "icongui.setPortValue(':bypass', 0, null)")

        for index in self.fPortValues.keys():
            symbol, isOutput = self.fPortSymbols[index]
            value = self.fPortValues[index]
            if isOutput:
                self.fCurrentFrame.evaluateJavaScript(
                    "icongui.setOutputPortValue('%s', %f)" % (symbol, value))
            else:
                self.fCurrentFrame.evaluateJavaScript(
                    "icongui.setPortValue('%s', %f, null)" % (symbol, value))

        # final setup
        self.fCanSetValues = True
        self.fSizeSetup = True
        self.fDocElemement = None

        if self.fNeedsShow:
            self.show()

    def checkForRepaintChanges(self):
        if not self.fWasRepainted:
            return

        self.fWasRepainted = False

        if not self.fCanSetValues:
            return

        for index in self.fPortValues.keys():
            symbol, isOutput = self.fPortSymbols[index]

            if isOutput:
                continue

            oldValue = self.fPortValues[index]
            newValue = self.fCurrentFrame.evaluateJavaScript(
                "icongui.getPortValue('%s')" % (symbol, ))

            if oldValue != newValue:
                self.fPortValues[index] = newValue
                self.send(["control", index, newValue])

    # --------------------------------------------------------------------------------------------------------

    @pyqtSlot(bool)
    def slot_webviewLoadFinished(self, ok):
        page = self.fWebview.page()
        page.repaintRequested.connect(self.slot_repaintRequested)

        self.fCurrentFrame = page.currentFrame()
        self.fDocElemement = self.fCurrentFrame.documentElement()

    def slot_repaintRequested(self):
        if self.fCanSetValues:
            self.fWasRepainted = True

    # --------------------------------------------------------------------------------------------------------
    # Callback

    def msgCallback(self, msg):
        msg = charPtrToString(msg)

        if msg == "control":
            index = int(self.readlineblock())
            value = float(self.readlineblock())
            self.dspParameterChanged(index, value)

        elif msg == "program":
            index = int(self.readlineblock())
            self.dspProgramChanged(index)

        elif msg == "midiprogram":
            bank = int(self.readlineblock())
            program = float(self.readlineblock())
            self.dspMidiProgramChanged(bank, program)

        elif msg == "configure":
            key = self.readlineblock()
            value = self.readlineblock()
            self.dspStateChanged(key, value)

        elif msg == "note":
            onOff = bool(self.readlineblock() == "true")
            channel = int(self.readlineblock())
            note = int(self.readlineblock())
            velocity = int(self.readlineblock())
            self.dspNoteReceived(onOff, channel, note, velocity)

        elif msg == "atom":
            index = int(self.readlineblock())
            size = int(self.readlineblock())
            base64atom = self.readlineblock()
            # nothing to do yet

        elif msg == "urid":
            urid = int(self.readlineblock())
            uri = self.readlineblock()
            # nothing to do yet

        elif msg == "uiOptions":
            sampleRate = float(self.readlineblock())
            useTheme = bool(self.readlineblock() == "true")
            useThemeColors = bool(self.readlineblock() == "true")
            windowTitle = self.readlineblock()
            transWindowId = int(self.readlineblock())
            self.uiTitleChanged(windowTitle)

        elif msg == "show":
            self.uiShow()

        elif msg == "focus":
            self.uiFocus()

        elif msg == "hide":
            self.uiHide()

        elif msg == "quit":
            self.fQuitReceived = True
            self.uiQuit()

        elif msg == "uiTitle":
            uiTitle = self.readlineblock()
            self.uiTitleChanged(uiTitle)

        else:
            print("unknown message: \"" + msg + "\"")

    # --------------------------------------------------------------------------------------------------------

    def dspParameterChanged(self, index, value):
        self.fPortValues[index] = value

        if self.fCurrentFrame is not None and self.fCanSetValues:
            symbol, isOutput = self.fPortSymbols[index]

            if isOutput:
                self.fPortValues[index] = value
                self.fCurrentFrame.evaluateJavaScript(
                    "icongui.setOutputPortValue('%s', %f)" % (symbol, value))
            else:
                self.fCurrentFrame.evaluateJavaScript(
                    "icongui.setPortValue('%s', %f, null)" % (symbol, value))

    def dspProgramChanged(self, index):
        return

    def dspMidiProgramChanged(self, bank, program):
        return

    def dspStateChanged(self, key, value):
        return

    def dspNoteReceived(self, onOff, channel, note, velocity):
        return

    # --------------------------------------------------------------------------------------------------------

    def uiShow(self):
        if self.fSizeSetup:
            self.show()
        else:
            self.fNeedsShow = True

    def uiFocus(self):
        if not self.fSizeSetup:
            return

        self.setWindowState((self.windowState() & ~Qt.WindowMinimized)
                            | Qt.WindowActive)
        self.show()

        self.raise_()
        self.activateWindow()

    def uiHide(self):
        self.hide()

    def uiQuit(self):
        self.closeExternalUI()
        self.close()
        app.quit()

    def uiTitleChanged(self, uiTitle):
        self.setWindowTitle(uiTitle)

    # --------------------------------------------------------------------------------------------------------
    # Qt events

    def closeEvent(self, event):
        self.closeExternalUI()
        QMainWindow.closeEvent(self, event)

        # there might be other qt windows open which will block carla-modgui from quitting
        app.quit()

    def timerEvent(self, event):
        if event.timerId() == self.fIdleTimer:
            self.idleStuff()

        QMainWindow.timerEvent(self, event)

    # --------------------------------------------------------------------------------------------------------

    @pyqtSlot()
    def slot_handleSIGTERM(self):
        print("Got SIGTERM -> Closing now")
        self.close()

    # --------------------------------------------------------------------------------------------------------
    # Internal stuff

    def readlineblock(self):
        if self.fPipeClient is None:
            return ""

        return gCarla.utils.pipe_client_readlineblock(self.fPipeClient, 5000)

    def send(self, lines):
        if self.fPipeClient is None or len(lines) == 0:
            return

        gCarla.utils.pipe_client_lock(self.fPipeClient)

        # this must never fail, we need to unlock at the end
        try:
            for line in lines:
                if line is None:
                    line2 = "(null)"
                elif isinstance(line, str):
                    line2 = line.replace("\n", "\r")
                elif isinstance(line, bool):
                    line2 = "true" if line else "false"
                elif isinstance(line, int):
                    line2 = "%i" % line
                elif isinstance(line, float):
                    line2 = "%.10f" % line
                else:
                    print("unknown data type to send:", type(line))
                    return

                gCarla.utils.pipe_client_write_msg(self.fPipeClient,
                                                   line2 + "\n")
        except:
            pass

        gCarla.utils.pipe_client_flush_and_unlock(self.fPipeClient)
# Copyright 2014-2015 Florian Bruhin (The Compiler) <*****@*****.**>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser.  If not, see <http://www.gnu.org/licenses/>.

"""Very simple browser for testing purposes."""

import sys

from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKitWidgets import QWebView

app = QApplication(sys.argv)
wv = QWebView()
wv.load(QUrl(sys.argv[1]))
wv.show()
app.exec_()
Beispiel #20
0
class Browser(QWidget):
    """LilyPond documentation browser widget."""
    def __init__(self, dockwidget):
        super(Browser, self).__init__(dockwidget)
        
        layout = QVBoxLayout(spacing=0)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        
        self.toolbar = tb = QToolBar()
        self.webview = QWebView(contextMenuPolicy=Qt.CustomContextMenu)
        self.chooser = QComboBox(sizeAdjustPolicy=QComboBox.AdjustToContents)
        self.search = SearchEntry(maximumWidth=200)
        
        layout.addWidget(self.toolbar)
        layout.addWidget(self.webview)
        
        ac = dockwidget.actionCollection
        ac.help_back.triggered.connect(self.webview.back)
        ac.help_forward.triggered.connect(self.webview.forward)
        ac.help_home.triggered.connect(self.showHomePage)
        ac.help_print.triggered.connect(self.slotPrint)
        
        self.webview.page().setNetworkAccessManager(lilydoc.network.accessmanager())
        self.webview.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.webview.page().linkClicked.connect(self.openUrl)
        self.webview.page().setForwardUnsupportedContent(True)
        self.webview.page().unsupportedContent.connect(self.slotUnsupported)
        self.webview.urlChanged.connect(self.slotUrlChanged)
        self.webview.customContextMenuRequested.connect(self.slotShowContextMenu)
        
        tb.addAction(ac.help_back)
        tb.addAction(ac.help_forward)
        tb.addSeparator()
        tb.addAction(ac.help_home)
        tb.addAction(ac.help_print)
        tb.addSeparator()
        tb.addWidget(self.chooser)
        tb.addWidget(self.search)
        
        self.chooser.activated[int].connect(self.showHomePage)
        self.search.textEdited.connect(self.slotSearchChanged)
        self.search.returnPressed.connect(self.slotSearchReturnPressed)
        dockwidget.mainwindow().iconSizeChanged.connect(self.updateToolBarSettings)
        dockwidget.mainwindow().toolButtonStyleChanged.connect(self.updateToolBarSettings)
        
        app.settingsChanged.connect(self.readSettings)
        self.readSettings()
        self.loadDocumentation()
        self.showInitialPage()
        app.settingsChanged.connect(self.loadDocumentation)
        app.translateUI(self)
    
    def readSettings(self):
        s = QSettings()
        s.beginGroup("documentation")
        ws = self.webview.page().settings()
        family = s.value("fontfamily", self.font().family(), str)
        size = s.value("fontsize", 16, int)
        ws.setFontFamily(QWebSettings.StandardFont, family)
        ws.setFontSize(QWebSettings.DefaultFontSize, size)
        fixed = textformats.formatData('editor').font
        ws.setFontFamily(QWebSettings.FixedFont, fixed.family())
        ws.setFontSize(QWebSettings.DefaultFixedFontSize, fixed.pointSizeF() * 96 / 72)
        
    def keyPressEvent(self, ev):
        if ev.text() == "/":
            self.search.setFocus()
        else:
            super(Browser, self).keyPressEvent(ev)
        
    def translateUI(self):
        try:
            self.search.setPlaceholderText(_("Search..."))
        except AttributeError:
            pass # not in Qt 4.6
    
    def showInitialPage(self):
        """Shows the preferred start page.
        
        If a local documentation instance already has a suitable version,
        just loads it. Otherwise connects to the allLoaded signal, that is
        emitted when all the documentation instances have loaded their version
        information and then shows the start page (if another page wasn't yet
        loaded).
        
        """
        if self.webview.url().isEmpty():
            docs = lilydoc.manager.docs()
            version = lilypondinfo.preferred().version()
            index = -1
            if version:
                for num, doc in enumerate(docs):
                    if doc.version() is not None and doc.version() >= version:
                        index = num # a suitable documentation is found
                        break
            if index == -1:
                # nothing found (or LilyPond version not available),
                # wait for loading or show the most recent version
                if not lilydoc.manager.loaded():
                    lilydoc.manager.allLoaded.connect(self.showInitialPage)
                    return
                index = len(docs) - 1
            self.chooser.setCurrentIndex(index)
            self.showHomePage()
    
    def loadDocumentation(self):
        """Puts the available documentation instances in the combobox."""
        i = self.chooser.currentIndex()
        self.chooser.clear()
        for doc in lilydoc.manager.docs():
            v = doc.versionString()
            if doc.isLocal():
                t = _("(local)")
            else:
                t = _("({hostname})").format(hostname=doc.url().host())
            self.chooser.addItem("{0} {1}".format(v or _("<unknown>"), t))
        self.chooser.setCurrentIndex(i)
        if not lilydoc.manager.loaded():
            lilydoc.manager.allLoaded.connect(self.loadDocumentation, -1)
            return
        
    def updateToolBarSettings(self):
        mainwin = self.parentWidget().mainwindow()
        self.toolbar.setIconSize(mainwin.iconSize())
        self.toolbar.setToolButtonStyle(mainwin.toolButtonStyle())
        
    def showManual(self):
        """Invoked when the user presses F1."""
        self.slotHomeFrescobaldi() # TEMP
        
    def slotUrlChanged(self):
        ac = self.parentWidget().actionCollection
        ac.help_back.setEnabled(self.webview.history().canGoBack())
        ac.help_forward.setEnabled(self.webview.history().canGoForward())
    
    def openUrl(self, url):
        if url.path().endswith(('.ily', '.lyi', '.ly')):
            self.sourceViewer().showReply(lilydoc.network.get(url))
        else:
            self.webview.load(url)
    
    def slotUnsupported(self, reply):
        helpers.openUrl(reply.url())
    
    def slotSearchChanged(self):
        text = self.search.text()
        if not text.startswith(':'):
            self.webview.page().findText(text, QWebPage.FindWrapsAroundDocument)
    
    def slotSearchReturnPressed(self):
        text = self.search.text()
        if not text.startswith(':'):
            self.slotSearchChanged()
        else:
            pass # TODO: implement full doc search
    
    def sourceViewer(self):
        try:
            return self._sourceviewer
        except AttributeError:
            from . import sourceviewer
            self._sourceviewer = sourceviewer.SourceViewer(self)
            return self._sourceviewer
    
    def showHomePage(self):
        """Shows the homepage of the LilyPond documentation."""
        i = self.chooser.currentIndex()
        if i < 0:
            i = 0
        doc = lilydoc.manager.docs()[i]
        
        url = doc.home()
        if doc.isLocal():
            path = url.toLocalFile()
            langs = lilydoc.network.langs()
            if langs:
                for lang in langs:
                    if os.path.exists(path + '.' + lang + '.html'):
                        path += '.' + lang
                        break
            url = QUrl.fromLocalFile(path + '.html')
        self.webview.load(url)
    
    def slotPrint(self):
        printer = QPrinter()
        dlg = QPrintDialog(printer, self)
        dlg.setWindowTitle(app.caption(_("Print")))
        if dlg.exec_():
            self.webview.print_(printer)
    
    def slotShowContextMenu(self, pos):
        hit = self.webview.page().currentFrame().hitTestContent(pos)
        menu = QMenu()
        if hit.linkUrl().isValid():
            a = self.webview.pageAction(QWebPage.CopyLinkToClipboard)
            a.setIcon(icons.get("edit-copy"))
            a.setText(_("Copy &Link"))
            menu.addAction(a)
            menu.addSeparator()
            a = menu.addAction(icons.get("window-new"), _("Open Link in &New Window"))
            a.triggered.connect((lambda url: lambda: self.slotNewWindow(url))(hit.linkUrl()))
        else:
            if hit.isContentSelected():
                a = self.webview.pageAction(QWebPage.Copy)
                a.setIcon(icons.get("edit-copy"))
                a.setText(_("&Copy"))
                menu.addAction(a)
                menu.addSeparator()
            a = menu.addAction(icons.get("window-new"), _("Open Document in &New Window"))
            a.triggered.connect((lambda url: lambda: self.slotNewWindow(url))(self.webview.url()))
        if menu.actions():
            menu.exec_(self.webview.mapToGlobal(pos))
    
    def slotNewWindow(self, url):
        helpers.openUrl(url)
class Main(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.initUI()

    def initUI(self):
        self.setGeometry(100, 100, 1400, 800)
        self.setWindowTitle("一个属于你的简单基因信息查询软件")
        #self.resize(800,500)

        self.tabs = QtWidgets.QTabWidget()

        self.webtab01 = QWebView()
        self.webtab01.setObjectName("GeneCard")
        self.webtab01.load(QtCore.QUrl("https://www.genecards.org/"))

        self.webtab02 = QWebView()
        self.webtab02.setObjectName("Web-Wiki")
        self.webtab02.load(QtCore.QUrl("https://en.wikipedia.org/wiki/"))

        self.webtab03 = QWebView()
        self.webtab03.setObjectName("ncbi")
        self.webtab03.load(QtCore.QUrl("https://www.ncbi.nlm.nih.gov/gene/"))

        self.webtab04 = QWebView()
        self.webtab04.setObjectName("COSMIC")
        self.webtab04.load(QtCore.QUrl("https://cancer.sanger.ac.uk/cosmic/"))

        self.webtab05 = QWebView()
        self.webtab05.setObjectName("Human Protein Altas")
        self.webtab05.load(QtCore.QUrl("https://www.proteinatlas.org/"))
        #
        self.webtab06 = QWebView()
        self.webtab06.setObjectName("Genetics Home Ref")
        self.webtab06.load(QtCore.QUrl("https://ghr.nlm.nih.gov/gene/"))
        #
        self.webtab07 = QWebView()
        self.webtab07.setObjectName("OMIM")
        self.webtab07.load(QtCore.QUrl("https://omim.org/"))
        #
        #self.webtab12 = QWebView()
        #self.webtab12.setObjectName("Web-谷歌")
        #self.webtab12.load(QtCore.QUrl("https://translate.google.cn/"))
        #
        #self.webtab13 = QWebView()
        #self.webtab13.setObjectName("Web-百度")
        #self.webtab13.load(QtCore.QUrl("http://fanyi.baidu.com/"))
        #
        #self.webtab15 = QWebView()
        #self.webtab15.setObjectName("Web-OzDict")
        #self.webtab15.load(QtCore.QUrl("https://www.onelook.com/"))

        self.tabs.addTab(self.webtab02, "WIKI")
        self.tabs.addTab(self.webtab06, "GeneticsHome")
        self.tabs.addTab(self.webtab03, "NCBI")
        self.tabs.addTab(self.webtab01, "GeneCard")
        self.tabs.addTab(self.webtab04, "COSMIC")
        self.tabs.addTab(self.webtab05, "HPA")
        self.tabs.addTab(self.webtab07, "OMIM")
        #self.tabs.addTab(self.webtab14, "维基百科")
        #self.tabs.addTab(self.webtab05, "UrbanDict")
        #self.tabs.addTab(self.webtab06, "Webster")
        #self.tabs.addTab(self.webtab15, "OneLook")

        self.inputLine = QtWidgets.QLineEdit()
        self.inputLine.setObjectName("inputLineEditor")
        self.inputLine.setFixedHeight(30)
        self.inputLine.textChanged.connect(self.translateText)

        self.outputLine = QtWidgets.QLineEdit()
        self.outputLine.setObjectName("outputLineEditor")
        self.outputLine.setFixedHeight(20)
        self.webtab01.loadStarted.connect(self.initURL)
        #self.outputLine.setText(self.webtab01.url().toString()) 还不太会搞这个的初始化
        self.tabs.currentChanged.connect(self.getURL)
        #self.outputLine..connect(self.getURL)

        centralLayout = QtWidgets.QVBoxLayout()
        centralLayout.addWidget(self.inputLine, 1)
        centralLayout.addWidget(self.outputLine, 2)
        centralLayout.addWidget(self.tabs, 3)

        self.centralWidget = QtWidgets.QWidget()
        self.centralWidget.setLayout(centralLayout)
        self.setCentralWidget(self.centralWidget)

    def getURL(self):
        self.outputLine.setText(self.tabs.currentWidget().url().toString())
        #print(self.tabs.currentIndex())

    def initURL(self):
        self.outputLine.setText(self.webtab01.url().toString())

    def translateText(self):
        word = self.inputLine.text()
        #print(word)
        self.webtab01.load(
            QtCore.QUrl(
                "https://www.genecards.org/Search/Keyword?queryString=" +
                word))
        #self.webtab01.load(QtCore.QUrl("http://www.iciba.com/" + word))
        self.webtab02.load(QtCore.QUrl("https://en.wikipedia.org/wiki/" +
                                       word))
        self.webtab03.load(
            QtCore.QUrl("https://www.ncbi.nlm.nih.gov/gene/?term=" + word))
        self.webtab04.load(
            QtCore.QUrl("https://cancer.sanger.ac.uk/cosmic/search?q=" + word))
        self.webtab05.load(
            QtCore.QUrl("https://www.proteinatlas.org/search/" + word))
        self.webtab06.load(QtCore.QUrl("https://ghr.nlm.nih.gov/gene/" + word))
        self.webtab07.load(
            QtCore.QUrl(
                "https://omim.org/search/?index=entry&sort=score+desc%2C+prefix_sort+desc&start=1&limit=10&search="
                + word))
Beispiel #22
0
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKitWidgets import QWebView
from PyQt5.QtCore import QUrl

app = QApplication([])
view = QWebView()
view.load(QUrl("http://weixin.sogou.com"))
view.show()
app.exec_()


# import sys
# from PyQt5.QtWidgets import *
# from PyQt5.QtCore import *
# from PyQt5.QtWebKitWidgets import QWebPage
# from lxml import etree
# from lxml.etree import XPathEvalError
#
# #use QtWebkit to get the final webpage
# app = QApplication([])
#
#
# def create_tree(html):
#     '''
#     :param html:HTML或者XML字符串
#     :return:tree树形结构对象
#     '''
#     try:
#         root = etree.HTML(html)
#     except ValueError:
#         root = etree.XML(html)
class BrowserController(QObject):
    def __init__(self, parent, fullscreen, sizes):
        """
        This constructor function initializes a layout of the Arius output
        module but doesn`t displays it on the screen.

        Firstly, it creates a new app and detects screens configuration.
        Then, QGridLayout is created and its appearance is configured: margins
        and spaces between elements is set to 0.

        After that, we create three QWebViews: one for our main content view
        and two others for header and footer views.

        Immideately after creating these instances we assign them their heights
        according to percentages given by user and dimensions of the screen.

        Next, we remove scroll bars from top and bottom views and load predefined
        pages into them.

        Then we allow QWebKit to run all extensions it needs to render the page.

        After that, wee set the layout design as a grid of three rows.

        Finally, we create an updater object which will run in another stream and
        a timer instance which checks that stream for new commands
        from the server, and in case if there`s some update handles it.
        """
        super(BrowserController, self).__init__()
        if not fullscreen and not sizes:
            print 'You must initialize windows size'
            raise Exception
        self._fullscreen = fullscreen
        if sizes:
            self._screen_width = sizes[0]
            self._screen_height = sizes[1]
        self._app = QtWidgets.QApplication(sys.argv)
        self._app.setStyle("Fusion")
        if self._fullscreen:
            self._get_screen_height()

        self._layout = QGridLayout()
        self._layout.setSpacing(0)
        self._layout.setContentsMargins(0, 0, 0, 0)

        self._main_browser = QWebView()
        main_page = FakePage(self)
        self._main_browser.setPage(main_page)

        self._top_browser = QWebView()
        self._bottom_browser = QWebView()

        self._top_browser_height = config[
            'output_header_height'] * self._screen_height
        self._bottom_browser_height = config[
            'output_footer_height'] * self._screen_height

        self._top_browser.setMaximumHeight(self._top_browser_height)
        self._top_browser.setMinimumHeight(self._top_browser_height)

        self._bottom_browser.setMaximumHeight(self._bottom_browser_height)
        self._bottom_browser.setMinimumHeight(self._bottom_browser_height)

        self._top_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)
        self._main_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)
        self._main_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff)
        self._bottom_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)

        self._top_browser_load_url(config['flask_server_home'] +
                                   config['output_browser_top_page'])
        self._bottom_browser_load_url(config['flask_server_home'] +
                                      config['output_browser_bottom_page'])

        self._main_browser.settings().setAttribute(
            QWebSettings.DeveloperExtrasEnabled, True)
        self._main_browser.settings().setAttribute(QWebSettings.PluginsEnabled,
                                                   True)
        QWebSettings.setObjectCacheCapacities(0, 0, 0)
        self._main_browser.settings().setAttribute(
            QWebSettings.AcceleratedCompositingEnabled, True)
        self._main_browser.settings().setAttribute(QWebSettings.WebGLEnabled,
                                                   True)

        self._layout.addWidget(self._top_browser, 1, 0)
        self._layout.addWidget(self._main_browser, 2, 0)
        self._layout.addWidget(self._bottom_browser, 3, 0)
        self._parent = parent
        self._parent.load_url.connect(self._load_url)
        self._parent.js_execution.connect(self._execute_js)
        self._parent.zooming.connect(self._zoom)

    def run(self):
        self._main_window = QWidget()  # create a window as a QWidget
        self._main_window.setLayout(self._layout)  # assign a layout to it
        if self._fullscreen:
            self._main_window.showFullScreen()  # set full screen enabled
        else:
            self._main_window.resize(self._screen_width, self._screen_height)
        self._main_window.show()  # and finally, show the window
        # and set a trigger to exit the app, as window is closed
        sys.exit(self._app.exec_())

    def _get_screen_height(self):
        if self._fullscreen:
            output = subprocess.Popen('xrandr | grep "\*" | cut -d" " -f4',
                                      shell=True,
                                      stdout=subprocess.PIPE).communicate()[0]
            output = [int(val) for val in output.split('x')]
            self._screen_height = output[1]
            self._screen_width = output[0]
        else:
            output = [self._width, self._height]
        return output[0], output[1]

    def _zoom(self, factor):
        self._main_browser.page().mainFrame().setZoomFactor(factor)

    def _top_browser_load_url(self, url):
        self._top_browser.load(QUrl(url))

    def _bottom_browser_load_url(self, url):
        self._bottom_browser.load(QUrl(url))

    def _load_url(self, url):
        logger.debug('OPENING URL %s', url)
        self._main_browser.load(QUrl(url))

    def _execute_js(self, string_js):
        logger.debug(string_js)
        self._main_browser.page().mainFrame().evaluateJavaScript(string_js)
Beispiel #24
0
class MainWindow(QMainWindow):
    def __init__(self, url):
        super(MainWindow, self).__init__()

        self.progress = 0

        fd = QFile(":/jquery.min.js")

        if fd.open(QIODevice.ReadOnly | QFile.Text):
            self.jQuery = QTextStream(fd).readAll()
            fd.close()
        else:
            self.jQuery = ''

        QNetworkProxyFactory.setUseSystemConfiguration(True)

        self.view = QWebView(self)
        self.view.load(url)
        self.view.loadFinished.connect(self.adjustLocation)
        self.view.titleChanged.connect(self.adjustTitle)
        self.view.loadProgress.connect(self.setProgress)
        self.view.loadFinished.connect(self.finishLoading)

        self.locationEdit = QLineEdit(self)
        self.locationEdit.setSizePolicy(
            QSizePolicy.Expanding,
            self.locationEdit.sizePolicy().verticalPolicy())
        self.locationEdit.returnPressed.connect(self.changeLocation)

        toolBar = self.addToolBar("Navigation")
        toolBar.addAction(self.view.pageAction(QWebPage.Back))
        toolBar.addAction(self.view.pageAction(QWebPage.Forward))
        toolBar.addAction(self.view.pageAction(QWebPage.Reload))
        toolBar.addAction(self.view.pageAction(QWebPage.Stop))
        toolBar.addWidget(self.locationEdit)

        viewMenu = self.menuBar().addMenu("&View")
        viewSourceAction = QAction("Page Source", self)
        viewSourceAction.triggered.connect(self.viewSource)
        viewMenu.addAction(viewSourceAction)

        effectMenu = self.menuBar().addMenu("&Effect")
        effectMenu.addAction("Highlight all links", self.highlightAllLinks)

        self.rotateAction = QAction(self.style().standardIcon(
            QStyle.SP_FileDialogDetailedView),
                                    "Turn images upside down",
                                    self,
                                    checkable=True,
                                    toggled=self.rotateImages)
        effectMenu.addAction(self.rotateAction)

        toolsMenu = self.menuBar().addMenu("&Tools")
        toolsMenu.addAction("Remove GIF images", self.removeGifImages)
        toolsMenu.addAction("Remove all inline frames",
                            self.removeInlineFrames)
        toolsMenu.addAction("Remove all object elements",
                            self.removeObjectElements)
        toolsMenu.addAction("Remove all embedded elements",
                            self.removeEmbeddedElements)
        self.setCentralWidget(self.view)

    def viewSource(self):
        accessManager = self.view.page().networkAccessManager()
        request = QNetworkRequest(self.view.url())
        reply = accessManager.get(request)
        reply.finished.connect(self.slotSourceDownloaded)

    def slotSourceDownloaded(self):
        reply = self.sender()
        self.textEdit = QTextEdit()
        self.textEdit.setAttribute(Qt.WA_DeleteOnClose)
        self.textEdit.show()
        self.textEdit.setPlainText(QTextStream(reply).readAll())
        self.textEdit.resize(600, 400)
        reply.deleteLater()

    def adjustLocation(self):
        self.locationEdit.setText(self.view.url().toString())

    def changeLocation(self):
        url = QUrl.fromUserInput(self.locationEdit.text())
        self.view.load(url)
        self.view.setFocus()

    def adjustTitle(self):
        if 0 < self.progress < 100:
            self.setWindowTitle("%s (%s%%)" %
                                (self.view.title(), self.progress))
        else:
            self.setWindowTitle(self.view.title())

    def setProgress(self, p):
        self.progress = p
        self.adjustTitle()

    def finishLoading(self):
        self.progress = 100
        self.adjustTitle()
        self.view.page().mainFrame().evaluateJavaScript(self.jQuery)
        self.rotateImages(self.rotateAction.isChecked())

    def highlightAllLinks(self):
        code = """$('a').each(
                    function () {
                        $(this).css('background-color', 'yellow') 
                    } 
                  )"""
        self.view.page().mainFrame().evaluateJavaScript(code)

    def rotateImages(self, invert):
        if invert:
            code = """
                $('img').each(
                    function () {
                        $(this).css('-webkit-transition', '-webkit-transform 2s'); 
                        $(this).css('-webkit-transform', 'rotate(180deg)') 
                    } 
                )"""
        else:
            code = """
                $('img').each(
                    function () { 
                        $(this).css('-webkit-transition', '-webkit-transform 2s'); 
                        $(this).css('-webkit-transform', 'rotate(0deg)') 
                    } 
                )"""

        self.view.page().mainFrame().evaluateJavaScript(code)

    def removeGifImages(self):
        code = "$('[src*=gif]').remove()"
        self.view.page().mainFrame().evaluateJavaScript(code)

    def removeInlineFrames(self):
        code = "$('iframe').remove()"
        self.view.page().mainFrame().evaluateJavaScript(code)

    def removeObjectElements(self):
        code = "$('object').remove()"
        self.view.page().mainFrame().evaluateJavaScript(code)

    def removeEmbeddedElements(self):
        code = "$('embed').remove()"
        self.view.page().mainFrame().evaluateJavaScript(code)
Beispiel #25
0
class Browser(QWidget):
    """LilyPond documentation browser widget."""
    def __init__(self, dockwidget):
        super(Browser, self).__init__(dockwidget)

        layout = QVBoxLayout(spacing=0)
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)

        self.toolbar = tb = QToolBar()
        self.webview = QWebView(contextMenuPolicy=Qt.CustomContextMenu)
        self.chooser = QComboBox(sizeAdjustPolicy=QComboBox.AdjustToContents)
        self.search = SearchEntry(maximumWidth=200)

        layout.addWidget(self.toolbar)
        layout.addWidget(self.webview)

        ac = dockwidget.actionCollection
        ac.help_back.triggered.connect(self.webview.back)
        ac.help_forward.triggered.connect(self.webview.forward)
        ac.help_home.triggered.connect(self.showHomePage)
        ac.help_print.triggered.connect(self.slotPrint)

        self.webview.page().setNetworkAccessManager(
            lilydoc.network.accessmanager())
        self.webview.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.webview.page().linkClicked.connect(self.openUrl)
        self.webview.page().setForwardUnsupportedContent(True)
        self.webview.page().unsupportedContent.connect(self.slotUnsupported)
        self.webview.urlChanged.connect(self.slotUrlChanged)
        self.webview.customContextMenuRequested.connect(
            self.slotShowContextMenu)

        tb.addAction(ac.help_back)
        tb.addAction(ac.help_forward)
        tb.addSeparator()
        tb.addAction(ac.help_home)
        tb.addAction(ac.help_print)
        tb.addSeparator()
        tb.addWidget(self.chooser)
        tb.addWidget(self.search)

        self.chooser.activated[int].connect(self.showHomePage)
        self.search.textEdited.connect(self.slotSearchChanged)
        self.search.returnPressed.connect(self.slotSearchReturnPressed)
        dockwidget.mainwindow().iconSizeChanged.connect(
            self.updateToolBarSettings)
        dockwidget.mainwindow().toolButtonStyleChanged.connect(
            self.updateToolBarSettings)

        app.settingsChanged.connect(self.readSettings)
        self.readSettings()
        self.loadDocumentation()
        self.showInitialPage()
        app.settingsChanged.connect(self.loadDocumentation)
        app.translateUI(self)

    def readSettings(self):
        s = QSettings()
        s.beginGroup("documentation")
        ws = self.webview.page().settings()
        family = s.value("fontfamily", self.font().family(), str)
        size = s.value("fontsize", 16, int)
        ws.setFontFamily(QWebSettings.StandardFont, family)
        ws.setFontSize(QWebSettings.DefaultFontSize, size)
        fixed = textformats.formatData('editor').font
        ws.setFontFamily(QWebSettings.FixedFont, fixed.family())
        ws.setFontSize(QWebSettings.DefaultFixedFontSize,
                       fixed.pointSizeF() * 96 / 72)

    def keyPressEvent(self, ev):
        if ev.text() == "/":
            self.search.setFocus()
        else:
            super(Browser, self).keyPressEvent(ev)

    def translateUI(self):
        try:
            self.search.setPlaceholderText(_("Search..."))
        except AttributeError:
            pass  # not in Qt 4.6

    def showInitialPage(self):
        """Shows the preferred start page.

        If a local documentation instance already has a suitable version,
        just loads it. Otherwise connects to the allLoaded signal, that is
        emitted when all the documentation instances have loaded their version
        information and then shows the start page (if another page wasn't yet
        loaded).

        """
        if self.webview.url().isEmpty():
            docs = lilydoc.manager.docs()
            version = lilypondinfo.preferred().version()
            index = -1
            if version:
                for num, doc in enumerate(docs):
                    if doc.version() is not None and doc.version() >= version:
                        index = num  # a suitable documentation is found
                        break
            if index == -1:
                # nothing found (or LilyPond version not available),
                # wait for loading or show the most recent version
                if not lilydoc.manager.loaded():
                    lilydoc.manager.allLoaded.connect(self.showInitialPage)
                    return
                index = len(docs) - 1
            self.chooser.setCurrentIndex(index)
            self.showHomePage()

    def loadDocumentation(self):
        """Puts the available documentation instances in the combobox."""
        i = self.chooser.currentIndex()
        self.chooser.clear()
        for doc in lilydoc.manager.docs():
            v = doc.versionString()
            if doc.isLocal():
                t = _("(local)")
            else:
                t = _("({hostname})").format(hostname=doc.url().host())
            self.chooser.addItem("{0} {1}".format(v or _("<unknown>"), t))
        self.chooser.setCurrentIndex(i)
        if not lilydoc.manager.loaded():
            lilydoc.manager.allLoaded.connect(self.loadDocumentation, -1)
            return

    def updateToolBarSettings(self):
        mainwin = self.parentWidget().mainwindow()
        self.toolbar.setIconSize(mainwin.iconSize())
        self.toolbar.setToolButtonStyle(mainwin.toolButtonStyle())

    def showManual(self):
        """Invoked when the user presses F1."""
        self.slotHomeFrescobaldi()  # TEMP

    def slotUrlChanged(self):
        ac = self.parentWidget().actionCollection
        ac.help_back.setEnabled(self.webview.history().canGoBack())
        ac.help_forward.setEnabled(self.webview.history().canGoForward())

    def openUrl(self, url):
        if url.path().endswith(('.ily', '.lyi', '.ly')):
            self.sourceViewer().showReply(lilydoc.network.get(url))
        else:
            self.webview.load(url)

    def slotUnsupported(self, reply):
        helpers.openUrl(reply.url())

    def slotSearchChanged(self):
        text = self.search.text()
        if not text.startswith(':'):
            self.webview.page().findText(text,
                                         QWebPage.FindWrapsAroundDocument)

    def slotSearchReturnPressed(self):
        text = self.search.text()
        if not text.startswith(':'):
            self.slotSearchChanged()
        else:
            pass  # TODO: implement full doc search

    def sourceViewer(self):
        try:
            return self._sourceviewer
        except AttributeError:
            from . import sourceviewer
            self._sourceviewer = sourceviewer.SourceViewer(self)
            return self._sourceviewer

    def showHomePage(self):
        """Shows the homepage of the LilyPond documentation."""
        i = self.chooser.currentIndex()
        if i < 0:
            i = 0
        doc = lilydoc.manager.docs()[i]

        url = doc.home()
        if doc.isLocal():
            path = url.toLocalFile()
            langs = lilydoc.network.langs()
            if langs:
                for lang in langs:
                    if os.path.exists(path + '.' + lang + '.html'):
                        path += '.' + lang
                        break
            url = QUrl.fromLocalFile(path + '.html')
        self.webview.load(url)

    def slotPrint(self):
        printer = QPrinter()
        dlg = QPrintDialog(printer, self)
        dlg.setWindowTitle(app.caption(_("Print")))
        if dlg.exec_():
            self.webview.print_(printer)

    def slotShowContextMenu(self, pos):
        hit = self.webview.page().currentFrame().hitTestContent(pos)
        menu = QMenu()
        if hit.linkUrl().isValid():
            a = self.webview.pageAction(QWebPage.CopyLinkToClipboard)
            a.setIcon(icons.get("edit-copy"))
            a.setText(_("Copy &Link"))
            menu.addAction(a)
            menu.addSeparator()
            a = menu.addAction(icons.get("window-new"),
                               _("Open Link in &New Window"))
            a.triggered.connect(
                (lambda url: lambda: self.slotNewWindow(url))(hit.linkUrl()))
        else:
            if hit.isContentSelected():
                a = self.webview.pageAction(QWebPage.Copy)
                a.setIcon(icons.get("edit-copy"))
                a.setText(_("&Copy"))
                menu.addAction(a)
                menu.addSeparator()
            a = menu.addAction(icons.get("window-new"),
                               _("Open Document in &New Window"))
            a.triggered.connect((lambda url: lambda: self.slotNewWindow(url))(
                self.webview.url()))
        if menu.actions():
            menu.exec_(self.webview.mapToGlobal(pos))

    def slotNewWindow(self, url):
        helpers.openUrl(url)
class mainWindow(QMainWindow):
    """ Create main window """
    def __init__(self):
        super(mainWindow, self).__init__()
        uic.loadUi('resources/ui/main.ui', self)

        self.mainPrintMessage("Welcome to pandapower version: " +
                              pp.__version__ + "\nQt vesrion: " + QT_VERSION +
                              "\nGUI version: " + _GUI_VERSION + "\n" +
                              "\nNetwork variable stored in : net")
        self.embedIpythonInterpreter()

        # collections builder setup
        self.lastBusSelected = None
        self.embedCollectionsBuilder()
        self.load_pandapower_network(createSampleNetwork,
                                     "GUI Example Network")
        self.initialiseCollectionsPlot()
        self.ax.xaxis.set_visible(False)
        self.ax.yaxis.set_visible(False)
        self.ax.set_aspect('equal', 'datalim')
        self.ax.autoscale_view(True, True, True)

        self.collectionsDoubleClick = False
        self.tabWidget.setCurrentIndex(0)  #set firtst tab

        # toolbar
        self.actionNew_Network.triggered.connect(self.mainEmptyClicked)
        self.actionLoad.triggered.connect(self.mainLoadClicked)
        self.actionSave.triggered.connect(self.mainSaveClicked)

        self.actionMV_oberrhein.triggered.connect(
            partial(self.load_pandapower_network, pnw.mv_oberrhein,
                    "MV Oberrhein"))
        self.actionCase9.triggered.connect(
            partial(self.load_pandapower_network, pnw.case9, "IEEE Case 9"))

        self.actionAbout.triggered.connect(self.show_license)
        self.actionDocumentation.triggered.connect(self.show_docs)

        #main
        self.actionrunpp.triggered.connect(self.runpp)
        self.actionrunpp.setIcon(QIcon('resources/icons/runpp.png'))

        self.actionrunppOptions.triggered.connect(self.runpp_options)
        self.actionrunppOptions.setIcon(
            QIcon('resources/icons/runpp_options.png'))

        # inspect
        self.inspect_bus.clicked.connect(
            partial(self.show_element_table, "bus"))
        self.inspect_lines.clicked.connect(
            partial(self.show_element_table, "line"))
        self.inspect_load.clicked.connect(
            partial(self.show_element_table, "load"))
        self.inspect_switch.clicked.connect(
            partial(self.show_element_table, "switch"))
        self.inspect_sgen.clicked.connect(
            partial(self.show_element_table, "sgen"))
        self.inspect_ext_grid.clicked.connect(
            partial(self.show_element_table, "ext_grid"))
        self.inspect_trafo.clicked.connect(
            partial(self.show_element_table, "trafo"))
        self.inspect_trafo3w.clicked.connect(
            partial(self.show_element_table, "trafo3w"))
        self.inspect_gen.clicked.connect(
            partial(self.show_element_table, "gen"))
        self.inspect_shunt.clicked.connect(
            partial(self.show_element_table, "shunt"))
        self.inspect_impedance.clicked.connect(
            partial(self.show_element_table, "impedance"))
        self.inspect_ward.clicked.connect(
            partial(self.show_element_table, "ward"))
        self.inspect_xward.clicked.connect(
            partial(self.show_element_table, "xward"))
        self.inspect_dcline.clicked.connect(
            partial(self.show_element_table, "dcline"))
        self.inspect_measurement.clicked.connect(
            partial(self.show_element_table, "measurement"))

        # results
        self.res_bus.clicked.connect(partial(self.show_result_table,
                                             "res_bus"))
        self.res_lines.clicked.connect(
            partial(self.show_result_table, "res_line"))
        self.res_load.clicked.connect(
            partial(self.show_result_table, "res_load"))
        self.res_sgen.clicked.connect(
            partial(self.show_result_table, "res_sgen"))
        self.res_ext_grid.clicked.connect(
            partial(self.show_result_table, "res_ext_grid"))
        self.res_trafo.clicked.connect(
            partial(self.show_result_table, "res_trafo"))
        self.res_trafo3w.clicked.connect(
            partial(self.show_result_table, "res_trafo3w"))
        self.res_gen.clicked.connect(partial(self.show_result_table,
                                             "res_gen"))
        self.res_shunt.clicked.connect(
            partial(self.show_result_table, "res_shunt"))
        self.res_impedance.clicked.connect(
            partial(self.show_result_table, "res_sgen"))
        self.res_ward.clicked.connect(
            partial(self.show_result_table, "res_ward"))
        self.res_xward.clicked.connect(
            partial(self.show_result_table, "res_xward"))
        self.res_dcline.clicked.connect(
            partial(self.show_result_table, "res_dcline"))

        #interpreter
        self.runTests.clicked.connect(self.runPandapowerTests)

        self.show()

    def show_license(self):
        license_text = open("LICENSE", "r")
        self.license = QMessageBox()
        self.license.setIcon(QMessageBox.Information)
        self.license.setWindowTitle("pandapower GUI")
        self.license.setText(license_text.read())
        self.license.show()

    def load_pandapower_network(self, network_function, name):
        net = network_function()
        self.load_network(net, name)

    def show_docs(self):
        self.docs = QWebView()
        self.docs.load(QUrl("https://pandapower.readthedocs.io"))
        self.docs.setWindowTitle("pandapower Documentation")
        self.docs.show()

    def printLineSeperator(self, ch="=", n=40):
        """ prints some characters """
        return ch * n + "\n"

    def mainPrintMessage(self, message):
        #self.main_message.append(self.printLineSeperator())
        self.main_message.append(message)
        self.main_message.append(self.printLineSeperator())

    def embedIpythonInterpreter(self):
        """ embed an IPyton QT Console Interpreter """
        self.ipyConsole = QIPythonWidget(
            customBanner="""Welcome to the console\nType \
                            whos to get list of variables \
                            \n =========== \n""")

        self.interpreter_vbox.addWidget(self.ipyConsole)
        self.ipyConsole.pushVariables({"pp": pp})

    def mainEmptyClicked(self):
        net = pp.create_empty_network()
        self.load_network(net, "Empty Network")

    def mainLoadClicked(self):
        file_to_open = ""
        file_to_open = QFileDialog.getOpenFileName(filter="*.xlsx, *.p")
        if file_to_open[0] != "":
            fn = file_to_open[0]
            if fn.endswith(".xlsx"):
                try:
                    net = pp.from_excel(file_to_open[0], convert=True)
                except:
                    print("couldn't open %s" % fn)
                    return
            elif file_to_open[0].endswith(".p"):
                try:
                    net = pp.from_pickle(file_to_open[0], convert=True)
                except:
                    print("couldn't open %s" % fn)
                    return
            self.load_network(net)

    def load_network(self, net, name):
        self.net = net
        if not "_runpp_options" in self.net:
            self.net._runpp_options = dict()
#        self.ipyConsole.executeCommand("del(net)")
#self.ipyConsole.clearTerminal()
        self.ipyConsole.printText("\n\n" + "-" * 40)
        self.ipyConsole.printText("\nNew net loaded \n")
        self.ipyConsole.printText("-" * 40 + "\n\n")
        self.ipyConsole.pushVariables({"net": self.net})
        self.ipyConsole.executeCommand("net")
        self.initialiseCollectionsPlot()
        self.mainPrintMessage(name + " loaded")
        self.mainPrintMessage(str(self.net))
        self.result_table.clear()
        self.element_table.clear()

    def mainSaveClicked(self):
        #filename = QFileDialog.getOpenFileName()
        filename = QFileDialog.getSaveFileName(self, 'Save net')
        print(filename[0])
        try:
            pp.to_excel(self.net, filename[0])
            self.mainPrintMessage("Saved case to: " + filename[0])
        except:
            self.mainPrintMessage("Case not saved, maybe empty?")

    def runpp(self):
        try:
            pp.runpp(self.net, **self.net._runpp_options)
            self.mainPrintMessage(str(self.net))
        except pp.LoadflowNotConverged:
            self.mainPrintMessage("Power Flow did not Converge!")
        except:
            self.mainPrintMessage("Error occured - empty network?")

    def runpp_options(self):
        try:
            runppOptions(self.net, parent=self)


#            self.options.show()
        except Exception as e:
            print(e)

    def lossesSummary(self):
        """ print the losses in each element that has losses """
        # get total losses
        losses = 0.0
        for i in self.net:
            if 'res' in i:
                if 'pl_kw' in self.net[i]:
                    if not self.net[i]['pl_kw'].empty:
                        print(i)
                        # self.report_message.append(i)
                        self.report_message.append(i)
                        self.report_message.append(
                            self.net[i]['pl_kw'].to_string())
                        print(self.net[i]['pl_kw'])
                        losses += self.net[i]['pl_kw'].sum()
        self.report_message.append("Total Losses (kW)")
        self.report_message.append(str(losses))

        # get total load
        total_load_kw = self.net.res_gen.sum() + self.net.res_sgen.sum() + \
            self.net.res_ext_grid.sum()
        self.report_message.append("Total nett load flowing in network")
        self.report_message.append(str(total_load_kw['p_kw']))

        # losses percentage
        self.report_message.append("% losses")
        loss_pct = losses / total_load_kw['p_kw']
        self.report_message.append(str(abs(loss_pct * 100)))
        self.mainPrintMessage("Losses report generated. Check Report tab.")

    def show_element_table(self, element):
        self.show_table(element, self.element_table)

    def show_result_table(self, element):
        self.show_table(element, self.result_table)

    def show_table(self, element, table_widget):
        table = self.net[element]
        table_widget.setColumnCount(len(table.columns) + 1)
        table_widget.setRowCount(len(table))
        header = ["index"] + table.columns.tolist()
        table_widget.setHorizontalHeaderLabels(header)
        for i, (idx, row) in enumerate(table.iterrows()):
            table_widget.setItem(i, 0, QTableWidgetItem(str(idx)))
            for k, value in enumerate(row.values, 1):
                print(i, k, value)
                table_widget.setItem(i, k, QTableWidgetItem(str(value)))
        table_widget.doubleClicked.connect(
            partial(self.table_doubleclicked, element, table_widget))

    def table_doubleclicked(self, element, table_widget, cell):
        try:
            index = int(table_widget.item(cell.row(), 0).text())
            self.open_element_window(element, index)
        except Exception as e:
            print(e)

    # res
    def res_bus_clicked(self):
        self.res_message.setHtml(str(self.net.res_bus.to_html()))

    def res_lines_clicked(self):
        self.res_message.setHtml(str(self.net.res_line.to_html()))

    # def res_switch_clicked(self):
    #    self.res_message.setHtml(str(self.net.res_switch.to_html()))

    def res_load_clicked(self):
        self.res_message.setHtml(str(self.net.res_load.to_html()))

    def res_sgen_clicked(self):
        self.res_message.setHtml(str(self.net.res_sgen.to_html()))

    def res_ext_grid_clicked(self):
        self.res_message.setHtml(str(self.net.res_ext_grid.to_html()))

    def res_trafo_clicked(self):
        self.res_message.setHtml(str(self.net.res_trafo.to_html()))

    def res_trafo3w_clicked(self):
        self.res_message.setHtml(str(self.net.res_trafo3w.to_html()))

    def res_gen_clicked(self):
        self.res_message.setHtml(str(self.net.res_gen.to_html()))

    def res_shunt_clicked(self):
        self.res_message.setHtml(str(self.net.res_shunt.to_html()))

    def res_ward_clicked(self):
        self.res_message.setHtml(str(self.net.res_ward.to_html()))

    def res_xward_clicked(self):
        self.res_message.setHtml(str(self.net.res_xward.to_html()))

    def res_dcline_clicked(self):
        self.res_message.setHtml(str(self.net.res_dcline.to_html()))

    # interpreter
    def runPandapowerTests(self):
        self.ipyConsole.executeCommand("import pandapower.test as test")
        self.ipyConsole.executeCommand("print('Running tests ...')")
        #self.ipyConsole.executeCommand("test.run_all_tests()")

    # collections
    def initialiseCollectionsPlot(self):
        print("Inialise Collections")
        self.xmin = self.net.bus_geodata.x.min()
        self.xmax = self.net.bus_geodata.x.max()
        self.ymin = self.net.bus_geodata.y.min()
        self.ymax = self.net.bus_geodata.y.max()
        self.scale = max((self.xmax - self.xmin), (self.ymax - self.ymin))
        self.collections = {}
        self.updateBusCollection()
        self.updateLineCollection()
        self.updateTrafoCollections()
        self.updateLoadCollections()
        self.updateExtGridCollections()
        print(self.collections)
        self.drawCollections()

    def drawCollections(self):
        self.ax.clear()
        for name, c in self.collections.items():
            if c is not None:
                self.ax.add_collection(c)
        self.ax.set_xlim((self.xmin * 0.98, self.xmax * 1.02))
        self.ax.set_ylim((self.ymin * 0.98, self.ymax * 1.02))
        self.canvas.draw()
        print("Drew Collections")

    def updateBusCollection(self, redraw=False):
        bc = plot.create_bus_collection(self.net,
                                        size=self.scale * 0.01,
                                        zorder=2,
                                        picker=True,
                                        color="black",
                                        patch_type="rect",
                                        infofunc=lambda x: ("bus", x))
        self.collections["bus"] = bc
        if redraw:
            self.drawCollections()

    def updateExtGridCollections(self, redraw=False):
        eg1, eg2 = plot.create_ext_grid_symbol_collection(
            self.net,
            size=self.scale * 0.05,
            zorder=2,
            picker=True,
            infofunc=lambda x: ("ext_grid", x))
        self.collections["ext_grid1"] = eg1
        self.collections["ext_grid2"] = eg2
        if redraw:
            self.drawCollections()

    def updateLineCollection(self, redraw=False):
        lc = plot.create_line_collection(self.net,
                                         zorder=1,
                                         linewidths=1,
                                         picker=True,
                                         use_line_geodata=False,
                                         color="green",
                                         infofunc=lambda x: ("line", x))
        self.collections["line"] = lc
        if redraw:
            self.drawCollections()

    def updateTrafoCollections(self, redraw=False):
        t1, t2 = plot.create_trafo_symbol_collection(self.net,
                                                     picker=True,
                                                     size=self.scale * 0.02,
                                                     infofunc=lambda x:
                                                     ("trafo", x))
        self.collections["trafo1"] = t1
        self.collections["trafo2"] = t2
        if redraw:
            self.drawCollections()

    def updateLoadCollections(self, redraw=False):
        l1, l2 = plot.create_load_symbol_collection(self.net,
                                                    size=self.scale * 0.02,
                                                    picker=True,
                                                    infofunc=lambda x:
                                                    ("load", x))
        self.collections["load1"] = l1
        self.collections["load2"] = l2
        if redraw:
            self.drawCollections()

    def clearMainCollectionBuilder(self):
        self.ax.clear()
        print("figure cleared")
        self.collections = {}
        self.drawCollections()

    def embedCollectionsBuilder(self):
        self.dpi = 100
        self.fig = plt.Figure()
        self.canvas = FigureCanvas(self.fig)
        self.ax = self.fig.add_subplot(111)
        #        self.ax.set_axis_bgcolor("white")
        # when a button is pressed on the canvas?
        self.canvas.mpl_connect('button_press_event', self.onCollectionsClick)
        #self.canvas.mpl_connect('button_release_event', self.onCollectionsClick)
        self.canvas.mpl_connect('pick_event', self.onCollectionsPick)
        mpl_toolbar = NavigationToolbar(self.canvas, self.main_build_frame)
        self.gridLayout.addWidget(self.canvas)
        self.gridLayout.addWidget(mpl_toolbar)
        self.fig.subplots_adjust(left=0.0,
                                 right=1,
                                 top=1,
                                 bottom=0,
                                 wspace=0.02,
                                 hspace=0.04)
        self.dragged = None

    def onCollectionsClick(self, event):
        print("clicked")
        self.collectionsDoubleClick = event.dblclick
        self.last = "clicked"
        if self.create_bus.isChecked():
            geodata = (event.xdata, event.ydata)
            try:
                self.bus_window = BusWindow(self.net,
                                            self.updateBusCollection,
                                            geodata=geodata)
            except Exception as inst:
                print(inst)

    def onCollectionsPick(self, event):
        if self.collectionsDoubleClick == False:
            QTimer.singleShot(
                200, partial(self.performcollectionsSingleClickActions, event))

    def performcollectionsSingleClickActions(self, event):
        print("picked")
        collection = event.artist
        element, index = collection.info[event.ind[0]]
        print("====", event.ind[0])
        print("====", collection)
        print("single")
        if self.collectionsDoubleClick:
            #ignore second click of collectionsDoubleClick
            if self.last == "doublecklicked":
                self.last = "clicked"
            else:
                self.last = "doublecklicked"
                print("Double Clicked a ", element)
                self.open_element_window(element, index)
        else:
            self.collectionsSingleClickActions(event, element, index)

    def open_element_window(self, element, index):
        if element == "bus":
            print("will build bus")
            self.element_window = BusWindow(self.net,
                                            self.updateBusCollection,
                                            index=index)
        elif element == "line":
            print("will bild line")
            print(index)
            self.element_window = LineWindow(self.net,
                                             self.updateLineCollection,
                                             index=index)
        elif element == "load":
            self.element_window = LoadWindow(self.net,
                                             self.updateLoadCollections,
                                             index=index)
        elif element == "trafo":
            print("trafo doubleclicked")

    def collectionsSingleClickActions(self, event, element, index):
        #what to do when single clicking on an element
        if element != "bus":
            return
        if self.create_line.isChecked():
            if self.lastBusSelected is None:
                self.lastBusSelected = index
            elif self.lastBusSelected != index:
                #pp.create_line(self.net, self.lastBusSelected, index, length_km=1.0, std_type="NAYY 4x50 SE")
                self.build_message.setText(
                    str(self.lastBusSelected) + "-" + str(index))
                self.line_window = LineWindow(self.net,
                                              self.updateLineCollection,
                                              from_bus=self.lastBusSelected,
                                              to_bus=index)
                self.lastBusSelected = None
        elif self.create_trafo.isChecked():
            if self.lastBusSelected is None:
                self.lastBusSelected = index
            elif self.lastBusSelected != index:
                pp.create_transformer(self.net,
                                      self.lastBusSelected,
                                      index,
                                      std_type="0.25 MVA 10/0.4 kV")
                self.lastBusSelected = None
                self.updateTrafoCollections()
                self.drawCollections()
        elif self.create_load.isChecked():
            try:
                self.load_window = LoadWindow(self.net,
                                              self.updateLoadCollections,
                                              bus=index)
            except Exception as e:
                print(e)
            self.lastBusSelected = None
Beispiel #27
0
class HandlerClass:
    def __init__(self, halcomp, widgets, paths):
        self.h = halcomp
        self.w = widgets
        self.PATHS = paths
        self.gcodes = GCodes()

        self.valid = QtGui.QDoubleValidator(-999.999, 999.999, 3)

        KEYBIND.add_call('Key_F12', 'on_keycall_F12')
        KEYBIND.add_call('Key_Pause', 'on_keycall_pause')

        # some global variables
        self.run_time = 0
        self.time_tenths = 0
        self.timerOn = False
        self.home_all = False
        self.max_linear_velocity = INFO.MAX_LINEAR_VELOCITY * 60
        self.system_list = [
            "G54", "G55", "G56", "G57", "G58", "G59", "G59.1", "G59.2", "G59.3"
        ]
        self.slow_jog_factor = 10
        self.reload_tool = 0
        self.last_loaded_program = ""
        self.first_turnon = True
        self.lineedit_list = [
            "work_height", "touch_height", "sensor_height", "laser_x",
            "laser_y", "sensor_x", "sensor_y", "search_vel", "probe_vel",
            "max_probe", "eoffset_count"
        ]
        self.onoff_list = ["frame_program", "frame_dro"]
        self.auto_list = ["chk_eoffsets", "cmb_gcode_history"]
        self.axis_a_list = [
            "label_axis_a", "dro_axis_a", "action_zero_a", "axistoolbutton_a",
            "action_home_a", "widget_jog_angular", "widget_increments_angular",
            "a_plus_jogbutton", "a_minus_jogbutton"
        ]
        self.html = """<html>
<head>
<title>Test page for the download:// scheme</title>
</head>
<body>
<h1>Setup Tab</h1>
<p>If you select a file with .html as a file ending, it will be shown here..</p>
<img src="file://%s" alt="lcnc_swoop" />
<hr />

<a href="http://www.linuxcnc.org/docs/2.8/html/gui/qtdragon.html">QtDragon Documentation link</a>
</body>
</html>
""" % (os.path.join(paths.IMAGEDIR, 'lcnc_swoop.png'))

        STATUS.connect('general', self.dialog_return)
        STATUS.connect('state-on', lambda w: self.enable_onoff(True))
        STATUS.connect('state-off', lambda w: self.enable_onoff(False))
        STATUS.connect('mode-manual', lambda w: self.enable_auto(True))
        STATUS.connect('mode-mdi', lambda w: self.enable_auto(True))
        STATUS.connect('mode-auto', lambda w: self.enable_auto(False))
        STATUS.connect('gcode-line-selected',
                       lambda w, line: self.set_start_line(line))
        STATUS.connect('hard-limits-tripped', self.hard_limit_tripped)
        STATUS.connect('interp-idle', lambda w: self.set_start_line(0))
        STATUS.connect('program-pause-changed',
                       lambda w, state: self.w.spindle_pause.setEnabled(state))
        STATUS.connect('user-system-changed', self.user_system_changed)
        STATUS.connect('file-loaded', self.file_loaded)
        STATUS.connect('homed', self.homed)
        STATUS.connect('all-homed', self.all_homed)
        STATUS.connect('not-all-homed', self.not_all_homed)
        STATUS.connect('periodic', lambda w: self.update_runtimer())
        STATUS.connect('command-running', lambda w: self.start_timer())
        STATUS.connect('command-stopped', lambda w: self.stop_timer())

    def class_patch__(self):
        self.old_fman = FM.load
        FM.load = self.load_code

    def initialized__(self):
        self.init_pins()
        self.init_preferences()
        self.init_widgets()
        self.w.stackedWidget_log.setCurrentIndex(0)
        self.w.stackedWidget.setCurrentIndex(0)
        self.w.stackedWidget_dro.setCurrentIndex(0)
        self.w.spindle_pause.setEnabled(False)
        self.w.btn_dimensions.setChecked(True)
        self.w.page_buttonGroup.buttonClicked.connect(self.main_tab_changed)
        self.w.filemanager.onUserClicked()
        self.w.filemanager_usb.onMediaClicked()

        # hide widgets for A axis if not present
        if "A" not in INFO.AVAILABLE_AXES:
            for i in self.axis_a_list:
                self.w[i].hide()
            self.w.lbl_increments_linear.setText("INCREMENTS")
    # set validators for lineEdit widgets
        for val in self.lineedit_list:
            self.w['lineEdit_' + val].setValidator(self.valid)

    #############################
    # SPECIAL FUNCTIONS SECTION #
    #############################

    def init_pins(self):
        # spindle control pins
        pin = self.h.newpin("spindle_amps", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.spindle_pwr_changed)
        pin = self.h.newpin("spindle_volts", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.spindle_pwr_changed)
        pin = self.h.newpin("spindle_fault", hal.HAL_U32, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.spindle_fault_changed)
        pin = self.h.newpin("modbus-errors", hal.HAL_U32, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.mb_errors_changed)
        # external offset control pins
        self.h.newpin("eoffset_enable", hal.HAL_BIT, hal.HAL_OUT)
        self.h.newpin("eoffset_clear", hal.HAL_BIT, hal.HAL_OUT)
        self.h.newpin("eoffset_count", hal.HAL_S32, hal.HAL_OUT)
        pin = self.h.newpin("eoffset_value", hal.HAL_FLOAT, hal.HAL_IN)
        hal_glib.GPin(pin).connect("value_changed", self.eoffset_changed)

    def init_preferences(self):
        if not self.w.PREFS_:
            self.add_status(
                "CRITICAL - no preference file found, enable preferences in screenoptions widget"
            )
            return
        self.last_loaded_program = self.w.PREFS_.getpref(
            'last_loaded_file', None, str, 'BOOK_KEEPING')
        self.reload_tool = self.w.PREFS_.getpref('Tool to load', 0, int,
                                                 'CUSTOM_FORM_ENTRIES')
        self.w.lineEdit_laser_x.setText(
            str(
                self.w.PREFS_.getpref('Laser X', 100, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_laser_y.setText(
            str(
                self.w.PREFS_.getpref('Laser Y', -20, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_sensor_x.setText(
            str(
                self.w.PREFS_.getpref('Sensor X', 10, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_sensor_y.setText(
            str(
                self.w.PREFS_.getpref('Sensor Y', 10, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_work_height.setText(
            str(
                self.w.PREFS_.getpref('Work Height', 20, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_touch_height.setText(
            str(
                self.w.PREFS_.getpref('Touch Height', 40, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_sensor_height.setText(
            str(
                self.w.PREFS_.getpref('Sensor Height', 40, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_search_vel.setText(
            str(
                self.w.PREFS_.getpref('Search Velocity', 40, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_probe_vel.setText(
            str(
                self.w.PREFS_.getpref('Probe Velocity', 10, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_max_probe.setText(
            str(
                self.w.PREFS_.getpref('Max Probe', 10, float,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.lineEdit_eoffset_count.setText(
            str(
                self.w.PREFS_.getpref('Eoffset count', 0, int,
                                      'CUSTOM_FORM_ENTRIES')))
        self.w.chk_eoffsets.setChecked(
            self.w.PREFS_.getpref('External offsets', False, bool,
                                  'CUSTOM_FORM_ENTRIES'))
        self.w.chk_reload_program.setChecked(
            self.w.PREFS_.getpref('Reload program', False, bool,
                                  'CUSTOM_FORM_ENTRIES'))
        self.w.chk_reload_tool.setChecked(
            self.w.PREFS_.getpref('Reload tool', False, bool,
                                  'CUSTOM_FORM_ENTRIES'))
        self.w.chk_use_keyboard.setChecked(
            self.w.PREFS_.getpref('Use keyboard', False, bool,
                                  'CUSTOM_FORM_ENTRIES'))
        self.w.chk_run_from_line.setChecked(
            self.w.PREFS_.getpref('Run from line', False, bool,
                                  'CUSTOM_FORM_ENTRIES'))
        self.w.chk_use_virtual.setChecked(
            self.w.PREFS_.getpref('Use virtual keyboard', False, bool,
                                  'CUSTOM_FORM_ENTRIES'))
        self.w.chk_alpha_mode.setChecked(
            self.w.PREFS_.getpref('Use alpha display mode', False, bool,
                                  'CUSTOM_FORM_ENTRIES'))
        self.w.chk_inhibit_selection.setChecked(
            self.w.PREFS_.getpref('Inhibit display mouse selection', True,
                                  bool, 'CUSTOM_FORM_ENTRIES'))

    def closing_cleanup__(self):
        if not self.w.PREFS_: return
        self.w.PREFS_.putpref('last_loaded_directory',
                              os.path.dirname(self.last_loaded_program), str,
                              'BOOK_KEEPING')
        self.w.PREFS_.putpref('last_loaded_file', self.last_loaded_program,
                              str, 'BOOK_KEEPING')
        self.w.PREFS_.putpref('Tool to load', STATUS.get_current_tool(), int,
                              'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Laser X',
                              self.w.lineEdit_laser_x.text().encode('utf-8'),
                              float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Laser Y',
                              self.w.lineEdit_laser_y.text().encode('utf-8'),
                              float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Sensor X',
                              self.w.lineEdit_sensor_x.text().encode('utf-8'),
                              float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Sensor Y',
                              self.w.lineEdit_sensor_y.text().encode('utf-8'),
                              float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref(
            'Work Height',
            self.w.lineEdit_work_height.text().encode('utf-8'), float,
            'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref(
            'Touch Height',
            self.w.lineEdit_touch_height.text().encode('utf-8'), float,
            'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref(
            'Sensor Height',
            self.w.lineEdit_sensor_height.text().encode('utf-8'), float,
            'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref(
            'Search Velocity',
            self.w.lineEdit_search_vel.text().encode('utf-8'), float,
            'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Probe Velocity',
                              self.w.lineEdit_probe_vel.text().encode('utf-8'),
                              float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Max Probe',
                              self.w.lineEdit_max_probe.text().encode('utf-8'),
                              float, 'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref(
            'Eoffset count',
            self.w.lineEdit_eoffset_count.text().encode('utf-8'), int,
            'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('External offsets',
                              self.w.chk_eoffsets.isChecked(), bool,
                              'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Reload program',
                              self.w.chk_reload_program.isChecked(), bool,
                              'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Reload tool',
                              self.w.chk_reload_tool.isChecked(), bool,
                              'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use keyboard',
                              self.w.chk_use_keyboard.isChecked(), bool,
                              'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Run from line',
                              self.w.chk_run_from_line.isChecked(), bool,
                              'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use virtual keyboard',
                              self.w.chk_use_virtual.isChecked(), bool,
                              'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Use alpha display mode',
                              self.w.chk_alpha_mode.isChecked(), bool,
                              'CUSTOM_FORM_ENTRIES')
        self.w.PREFS_.putpref('Inhibit display mouse selection',
                              self.w.chk_inhibit_selection.isChecked(), bool,
                              'CUSTOM_FORM_ENTRIES')

    def init_widgets(self):
        self.w.main_tab_widget.setCurrentIndex(0)
        self.w.slider_jog_linear.setMaximum(self.max_linear_velocity)
        self.w.slider_jog_linear.setValue(INFO.DEFAULT_LINEAR_JOG_VEL)
        self.w.slider_jog_angular.setMaximum(INFO.MAX_ANGULAR_JOG_VEL)
        self.w.slider_jog_angular.setValue(INFO.DEFAULT_ANGULAR_JOG_VEL)
        self.w.slider_maxv_ovr.setMaximum(self.max_linear_velocity)
        self.w.slider_maxv_ovr.setValue(self.max_linear_velocity)
        self.w.slider_feed_ovr.setMaximum(INFO.MAX_FEED_OVERRIDE)
        self.w.slider_feed_ovr.setValue(100)
        self.w.slider_rapid_ovr.setMaximum(100)
        self.w.slider_rapid_ovr.setValue(100)
        self.w.slider_spindle_ovr.setMinimum(INFO.MIN_SPINDLE_OVERRIDE)
        self.w.slider_spindle_ovr.setMaximum(INFO.MAX_SPINDLE_OVERRIDE)
        self.w.slider_spindle_ovr.setValue(100)
        self.w.chk_override_limits.setChecked(False)
        self.w.chk_override_limits.setEnabled(False)
        self.w.lbl_maxv_percent.setText("100 %")
        self.w.lbl_max_rapid.setText(str(self.max_linear_velocity))
        self.w.lbl_home_x.setText(
            INFO.get_error_safe_setting('JOINT_0', 'HOME', "50"))
        self.w.lbl_home_y.setText(
            INFO.get_error_safe_setting('JOINT_1', 'HOME', "50"))
        self.w.cmb_gcode_history.addItem("No File Loaded")
        self.w.cmb_gcode_history.wheelEvent = lambda event: None
        self.w.jogincrements_linear.wheelEvent = lambda event: None
        self.w.jogincrements_angular.wheelEvent = lambda event: None
        self.w.gcode_editor.hide()

        #set up gcode list
        self.gcodes.setup_list()
        # clickable frames
        self.w.frame_cycle_start.mousePressEvent = self.btn_start_clicked
        self.w.frame_home_all.mousePressEvent = self.btn_home_all_clicked
        # web view widget for SETUP page
        self.web_view = QWebView()
        self.w.verticalLayout_setup.addWidget(self.web_view)
        self.web_view.setHtml(self.html)
        # check for virtual keyboard enabled
        if self.w.chk_use_virtual.isChecked():
            self.w.btn_keyboard.show()
        else:
            self.w.btn_keyboard.hide()
        TOOLBAR.configure_statusbar(self.w.statusbar, 'message_recall')

    def processed_focus_event__(self, receiver, event):
        if not self.w.chk_use_virtual.isChecked() or STATUS.is_auto_mode():
            return
        if isinstance(receiver, QtWidgets.QLineEdit):
            if not receiver.isReadOnly():
                self.w.btn_keyboard.setChecked(True)
        elif isinstance(receiver, QtWidgets.QTableView):
            self.w.btn_keyboard.setChecked(True)
        elif isinstance(receiver, QtWidgets.QCommonStyle):
            return

    def processed_key_event__(self, receiver, event, is_pressed, key, code,
                              shift, cntrl):
        # when typing in MDI, we don't want keybinding to call functions
        # so we catch and process the events directly.
        # We do want ESC, F1 and F2 to call keybinding functions though
        if code not in (QtCore.Qt.Key_Escape, QtCore.Qt.Key_F1,
                        QtCore.Qt.Key_F2, QtCore.Qt.Key_F12):

            # search for the top widget of whatever widget received the event
            # then check if it's one we want the keypress events to go to
            flag = False
            receiver2 = receiver
            while receiver2 is not None and not flag:
                if isinstance(receiver2, QtWidgets.QDialog):
                    flag = True
                    break
                if isinstance(receiver2, QtWidgets.QLineEdit):
                    flag = True
                    break
                if isinstance(receiver2, MDI_WIDGET):
                    flag = True
                    break
                if isinstance(receiver2, GCODE):
                    flag = True
                    break
                if isinstance(receiver2, TOOL_TABLE):
                    flag = True
                    break
                if isinstance(receiver2, OFFSET_VIEW):
                    flag = True
                    break
                receiver2 = receiver2.parent()

            if flag:
                if isinstance(receiver2, GCODE):
                    # if in manual do our keybindings - otherwise
                    # send events to gcode widget
                    if STATUS.is_man_mode() == False:
                        if is_pressed:
                            receiver.keyPressEvent(event)
                            event.accept()
                        return True
                elif is_pressed:
                    receiver.keyPressEvent(event)
                    event.accept()
                    return True
                else:
                    event.accept()
                    return True

        if event.isAutoRepeat(): return True
        # ok if we got here then try keybindings
        try:
            KEYBIND.call(self, event, is_pressed, shift, cntrl)
            event.accept()
            return True
        except NameError as e:
            if is_pressed:
                LOG.debug('Exception in KEYBINDING: {}'.format(e))
                self.add_status('Exception in KEYBINDING: {}'.format(e))
        except Exception as e:
            if is_pressed:
                LOG.debug('Exception in KEYBINDING:', exc_info=e)
                print 'Error in, or no function for: %s in handler file for-%s' % (
                    KEYBIND.convert(event), key)
        event.accept()
        return True

    #########################
    # CALLBACKS FROM STATUS #
    #########################

    def spindle_pwr_changed(self, data):
        # this calculation assumes the voltage is line to neutral
        # and that the synchronous motor spindle has a power factor of 0.9
        power = self.h['spindle_volts'] * self.h[
            'spindle_amps'] * 2.7  # 3 x V x I x PF
        amps = "{:1.1f}".format(self.h['spindle_amps'])
        pwr = "{:1.1f}".format(power)
        self.w.lbl_spindle_amps.setText(amps)
        self.w.lbl_spindle_power.setText(pwr)

    def spindle_fault_changed(self, data):
        fault = hex(self.h['spindle_fault'])
        self.w.lbl_spindle_fault.setText(fault)

    def mb_errors_changed(self, data):
        errors = self.h['modbus-errors']
        self.w.lbl_mb_errors.setText(str(errors))

    def eoffset_changed(self, data):
        eoffset = "{:2.3f}".format(self.h['eoffset_value'])
        self.w.lbl_eoffset_value.setText(eoffset)

    def dialog_return(self, w, message):
        rtn = message.get('RETURN')
        name = message.get('NAME')
        plate_code = bool(message.get('ID') == '_touchplate_')
        sensor_code = bool(message.get('ID') == '_toolsensor_')
        wait_code = bool(message.get('ID') == '_wait_resume_')
        if plate_code and name == 'MESSAGE' and rtn is True:
            self.touchoff('touchplate')
        elif sensor_code and name == 'MESSAGE' and rtn is True:
            self.touchoff('sensor')
        elif wait_code and name == 'MESSAGE':
            self.h['eoffset_clear'] = False

    def user_system_changed(self, obj, data):
        sys = self.system_list[int(data) - 1]
        self.w.offset_table.selectRow(int(data) + 3)
        self.w.actionbutton_rel.setText(sys)

    def file_loaded(self, obj, filename):
        if filename is not None:
            self.add_status("Loaded file {}".format(filename))
            self.w.progressBar.setValue(0)
            self.last_loaded_program = filename
        else:
            self.add_status("Filename not valid")

    def percent_loaded_changed(self, fraction):
        if fraction < 0:
            self.w.progressBar.setValue(0)
            self.w.progressBar.setFormat('Progress')
        else:
            self.w.progressBar.setValue(fraction)
            self.w.progressBar.setFormat('Loading: {}%'.format(fraction))

    def percent_completed_changed(self, fraction):
        self.w.progressBar.setValue(fraction)
        if fraction < 0:
            self.w.progressBar.setValue(0)
            self.w.progressBar.setFormat('Progress')
        else:
            self.w.progressBar.setFormat('Completed: {}%'.format(fraction))

    def homed(self, obj, joint):
        i = int(joint)
        axis = INFO.GET_NAME_FROM_JOINT.get(i).lower()
        try:
            self.w["dro_axis_{}".format(axis)].setProperty('homed', True)
            self.w["dro_axis_{}".format(axis)].setStyle(
                self.w["dro_axis_{}".format(axis)].style())
        except:
            pass

    def all_homed(self, obj):
        self.home_all = True
        self.w.lbl_home_all.setText("ALL\nHOMED")
        if self.first_turnon is True:
            self.first_turnon = False
            if self.w.chk_reload_tool.isChecked():
                command = "M61 Q{}".format(self.reload_tool)
                ACTION.CALL_MDI(command)
            if self.last_loaded_program is not None and self.w.chk_reload_program.isChecked(
            ):
                if os.path.isfile(self.last_loaded_program):
                    self.w.cmb_gcode_history.addItem(self.last_loaded_program)
                    self.w.cmb_gcode_history.setCurrentIndex(
                        self.w.cmb_gcode_history.count() - 1)
                    ACTION.OPEN_PROGRAM(self.last_loaded_program)
                    self.w.manual_mode_button.setChecked(True)

    def not_all_homed(self, obj, list):
        self.home_all = False
        self.w.lbl_home_all.setText("HOME\nALL")
        for i in INFO.AVAILABLE_JOINTS:
            if str(i) in list:
                axis = INFO.GET_NAME_FROM_JOINT.get(i).lower()
                try:
                    self.w["dro_axis_{}".format(axis)].setProperty(
                        'homed', False)
                    self.w["dro_axis_{}".format(axis)].setStyle(
                        self.w["dro_axis_{}".format(axis)].style())
                except:
                    pass

    def hard_limit_tripped(self, obj, tripped, list_of_tripped):
        self.add_status("Hard limits tripped")
        self.w.chk_override_limits.setEnabled(tripped)
        if not tripped:
            self.w.chk_override_limits.setChecked(False)

    def update_runtimer(self):
        if self.timerOn is False or STATUS.is_auto_paused(): return
        self.time_tenths += 1
        if self.time_tenths == 10:
            self.time_tenths = 0
            self.run_time += 1
            hours, remainder = divmod(self.run_time, 3600)
            minutes, seconds = divmod(remainder, 60)
            self.w.lbl_runtime.setText("{:02d}:{:02d}:{:02d}".format(
                hours, minutes, seconds))

    def start_timer(self):
        if STATUS.is_auto_running():
            self.run_time = 0
            self.timerOn = True

    def stop_timer(self):
        self.timerOn = False

    #######################
    # CALLBACKS FROM FORM #
    #######################

    # main button bar
    def main_tab_changed(self, btn):
        if STATUS.is_auto_mode():
            self.add_status("Cannot switch pages while in AUTO mode")
            self.w.btn_main.setChecked(True)
            return
        index = btn.property("index")
        if index is None: return
        self.w.main_tab_widget.setCurrentIndex(index)
        if index == TAB_MAIN:
            self.w.btn_keyboard.setChecked(False)
            self.w.stackedWidget.setCurrentIndex(0)
        elif index == TAB_FILE:
            self.w.stackedWidget.setCurrentIndex(1)
        elif index == TAB_OFFSETS:
            self.w.stackedWidget.setCurrentIndex(2)
        elif index == TAB_TOOL:
            self.w.stackedWidget.setCurrentIndex(3)
        else:
            self.w.stackedWidget.setCurrentIndex(0)

    # gcode frame
    def cmb_gcode_history_clicked(self):
        if self.w.cmb_gcode_history.currentIndex() == 0: return
        filename = self.w.cmb_gcode_history.currentText().encode('utf-8')
        if filename == self.last_loaded_program:
            self.add_status("Selected program is already loaded")
        else:
            ACTION.OPEN_PROGRAM(filename)

    # program frame
    def btn_start_clicked(self, obj):
        if self.w.main_tab_widget.currentIndex() != 0:
            return
        if not STATUS.is_auto_mode():
            self.add_status("Must be in AUTO mode to run a program")
            return
        start_line = int(self.w.lbl_start_line.text().encode('utf-8'))
        self.add_status("Started program from line {}".format(start_line))
        self.run_time = 0
        if start_line == 1:
            ACTION.RUN(start_line)
        else:
            # instantiate preset dialog
            info = '<b>Running from Line: {} <\b>'.format(start_line)
            mess = {
                'NAME': 'RUNFROMLINE',
                'TITLE': 'Preset Dialog',
                'ID': '_RUNFROMLINE',
                'MESSAGE': info,
                'LINE': start_line
            }
            ACTION.CALL_DIALOG(mess)

    def btn_reload_file_clicked(self):
        if self.last_loaded_program:
            self.w.progressBar.setValue(0)
            self.add_status("Loaded program file {}".format(
                self.last_loaded_program))
            ACTION.OPEN_PROGRAM(self.last_loaded_program)

    # DRO frame
    def btn_home_all_clicked(self, obj):
        if self.home_all is False:
            ACTION.SET_MACHINE_HOMING(-1)
        else:
            ACTION.SET_MACHINE_UNHOMED(-1)

    def btn_home_clicked(self):
        joint = self.w.sender().property('joint')
        axis = INFO.GET_NAME_FROM_JOINT.get(joint).lower()
        if self.w["dro_axis_{}".format(axis)].property('homed') is True:
            ACTION.SET_MACHINE_UNHOMED(joint)
        else:
            ACTION.SET_MACHINE_HOMING(joint)

    # tool frame
    def disable_pause_buttons(self, state):
        self.w.action_pause.setEnabled(not state)
        self.w.action_step.setEnabled(not state)
        if state:
            # set external offsets to lift spindle
            self.h['eoffset_enable'] = self.w.chk_eoffsets.isChecked()
            fval = float(self.w.lineEdit_eoffset_count.text())
            self.h['eoffset_count'] = int(fval)
        else:
            self.h['eoffset_count'] = 0
            self.h['eoffset_clear'] = True
            # instantiate warning box
            info = "Wait for spindle at speed signal before resuming"
            mess = {
                'NAME': 'MESSAGE',
                'ICON': 'WARNING',
                'ID': '_wait_resume_',
                'MESSAGE': 'CAUTION',
                'MORE': info,
                'TYPE': 'OK'
            }
            ACTION.CALL_DIALOG(mess)

    # override frame
    def slow_button_clicked(self, state):
        slider = self.w.sender().property('slider')
        current = self.w[slider].value()
        max = self.w[slider].maximum()
        if state:
            self.w.sender().setText("SLOW")
            self.w[slider].setMaximum(max / self.slow_jog_factor)
            self.w[slider].setValue(current / self.slow_jog_factor)
            self.w[slider].setPageStep(10)
        else:
            self.w.sender().setText("FAST")
            self.w[slider].setMaximum(max * self.slow_jog_factor)
            self.w[slider].setValue(current * self.slow_jog_factor)
            self.w[slider].setPageStep(100)

    def slider_maxv_changed(self, value):
        maxpc = (float(value) / self.max_linear_velocity) * 100
        self.w.lbl_maxv_percent.setText("{:3.0f} %".format(maxpc))

    def slider_rapid_changed(self, value):
        rapid = (float(value) / 100) * self.max_linear_velocity
        self.w.lbl_max_rapid.setText("{:4.0f}".format(rapid))

    def btn_maxv_100_clicked(self):
        self.w.slider_maxv_ovr.setValue(self.max_linear_velocity)

    def btn_maxv_50_clicked(self):
        self.w.slider_maxv_ovr.setValue(self.max_linear_velocity / 2)

    # file tab
    def btn_gcode_edit_clicked(self, state):
        if not STATUS.is_on_and_idle():
            return
        if state:
            self.w.filemanager.hide()
            self.w.widget_file_copy.hide()
            self.w.gcode_editor.show()
            self.w.gcode_editor.editMode()
        else:
            self.w.filemanager.show()
            self.w.widget_file_copy.show()
            self.w.gcode_editor.hide()
            self.w.gcode_editor.readOnlyMode()

    def btn_load_file_clicked(self):
        fname = self.w.filemanager.getCurrentSelected()
        if fname[1] is True:
            self.load_code(fname[0])

    def btn_copy_file_clicked(self):
        if self.w.sender() == self.w.btn_copy_right:
            source = self.w.filemanager_usb.getCurrentSelected()
            target = self.w.filemanager.getCurrentSelected()
        elif self.w.sender() == self.w.btn_copy_left:
            source = self.w.filemanager.getCurrentSelected()
            target = self.w.filemanager_usb.getCurrentSelected()
        else:
            return
        if source[1] is False:
            self.add_status("Specified source is not a file")
            return
        if target[1] is True:
            destination = os.path.join(os.path.dirname(target[0]),
                                       os.path.basename(source[0]))
        else:
            destination = os.path.join(target[0], os.path.basename(source[0]))
        try:
            copyfile(source[0], destination)
            self.add_status("Copied file from {} to {}".format(
                source[0], destination))
        except Exception as e:
            self.add_status("Unable to copy file. %s" % e)

    # offsets tab
    def btn_goto_sensor_clicked(self):
        x = float(self.w.lineEdit_sensor_x.text())
        y = float(self.w.lineEdit_sensor_y.text())
        if not STATUS.is_metric_mode():
            x = x / 25.4
            y = y / 25.4
        ACTION.CALL_MDI("G90")
        ACTION.CALL_MDI_WAIT("G53 G0 Z0")
        command = "G53 G0 X{:3.4f} Y{:3.4f}".format(x, y)
        ACTION.CALL_MDI_WAIT(command, 10)

    def btn_ref_laser_clicked(self):
        x = float(self.w.lineEdit_laser_x.text())
        y = float(self.w.lineEdit_laser_y.text())
        if not STATUS.is_metric_mode():
            x = x / 25.4
            y = y / 25.4
        self.add_status("Laser offsets set")
        command = "G10 L20 P0 X{:3.4f} Y{:3.4f}".format(x, y)
        ACTION.CALL_MDI(command)

    # tool tab
    def btn_m61_clicked(self):
        checked = self.w.tooloffsetview.get_checked_list()
        if len(checked) > 1:
            self.add_status("Select only 1 tool to load")
        elif checked:
            self.add_status("Loaded tool {}".format(checked[0]))
            ACTION.CALL_MDI("M61 Q{}".format(checked[0]))
        else:
            self.add_status("No tool selected")

    def btn_touchoff_clicked(self):
        if STATUS.get_current_tool() == 0:
            self.add_status("Cannot touchoff with no tool loaded")
            return
        if not STATUS.is_all_homed():
            self.add_status("Must be homed to perform tool touchoff")
            return
        # instantiate dialog box
        sensor = self.w.sender().property('sensor')
        info = "Ensure tooltip is within {} mm of tool sensor and click OK".format(
            self.w.lineEdit_max_probe.text())
        mess = {
            'NAME': 'MESSAGE',
            'ID': sensor,
            'MESSAGE': 'TOOL TOUCHOFF',
            'MORE': info,
            'TYPE': 'OKCANCEL'
        }
        ACTION.CALL_DIALOG(mess)

    # status tab
    def btn_clear_status_clicked(self):
        STATUS.emit('update-machine-log', None, 'DELETE')

    def btn_save_status_clicked(self):
        text = self.w.machinelog.toPlainText()
        filename = self.w.lbl_clock.text().encode('utf-8')
        filename = 'status_' + filename.replace(' ', '_') + '.txt'
        self.add_status("Saving Status file to {}".format(filename))
        with open(filename, 'w') as f:
            f.write(text)

    def btn_dimensions_clicked(self, state):
        self.w.gcodegraphics.show_extents_option = state
        self.w.gcodegraphics.clear_live_plotter()

    def chk_override_limits_checked(self, state):
        if state:
            print("Override limits set")
            ACTION.SET_LIMITS_OVERRIDE()
        else:
            print("Override limits not set")

    def chk_run_from_line_checked(self, state):
        if not state:
            self.w.lbl_start_line.setText('1')

    def chk_alpha_mode_clicked(self, state):
        self.w.gcodegraphics.set_alpha_mode(state)

    def chk_inhibit_display_selection_clicked(self, state):
        self.w.gcodegraphics.set_inhibit_selection(state)

    # settings tab
    def chk_use_virtual_changed(self, state):
        if state:
            self.w.btn_keyboard.show()
        else:
            self.w.btn_keyboard.hide()

    #####################
    # GENERAL FUNCTIONS #
    #####################
    def load_code(self, fname):
        if fname is None: return
        if fname.endswith(".ngc") or fname.endswith(".py"):
            self.w.cmb_gcode_history.addItem(fname)
            self.w.cmb_gcode_history.setCurrentIndex(
                self.w.cmb_gcode_history.count() - 1)
            ACTION.OPEN_PROGRAM(fname)
            self.add_status("Loaded program file : {}".format(fname))
            self.w.main_tab_widget.setCurrentIndex(TAB_MAIN)
        elif fname.endswith(".html"):
            self.web_view.load(QtCore.QUrl.fromLocalFile(fname))
            self.add_status("Loaded HTML file : {}".format(fname))
            self.w.main_tab_widget.setCurrentIndex(TAB_SETUP)
            self.w.btn_setup.setChecked(True)
        else:
            self.add_status("Unknown or invalid filename")

    def disable_spindle_pause(self):
        self.h['eoffset_count'] = 0
        if self.w.spindle_pause.isChecked():
            self.w.spindle_pause.setChecked(False)

    def touchoff(self, selector):
        if selector == 'touchplate':
            z_offset = float(self.w.lineEdit_touch_height.text())
        elif selector == 'sensor':
            z_offset = float(self.w.lineEdit_sensor_height.text()) - float(
                self.w.lineEdit_work_height.text())
        else:
            self.add_alarm("Unknown touchoff routine specified")
            return
        self.add_status("Touchoff to {} started".format(selector))
        max_probe = self.w.lineEdit_max_probe.text()
        search_vel = self.w.lineEdit_search_vel.text()
        probe_vel = self.w.lineEdit_probe_vel.text()
        ACTION.CALL_MDI("G21 G49")
        ACTION.CALL_MDI("G10 L20 P0 Z0")
        ACTION.CALL_MDI("G91")
        command = "G38.2 Z-{} F{}".format(max_probe, search_vel)
        if ACTION.CALL_MDI_WAIT(command, 10) == -1:
            ACTION.CALL_MDI("G90")
            return
        if ACTION.CALL_MDI_WAIT("G1 Z4.0"):
            ACTION.CALL_MDI("G90")
            return
        ACTION.CALL_MDI("G4 P0.5")
        command = "G38.2 Z-4.4 F{}".format(probe_vel)
        if ACTION.CALL_MDI_WAIT(command, 10) == -1:
            ACTION.CALL_MDI("G90")
            return
        command = "G10 L20 P0 Z{}".format(z_offset)
        ACTION.CALL_MDI_WAIT(command)
        command = "G1 Z10 F{}".format(search_vel)
        ACTION.CALL_MDI_WAIT(command)
        ACTION.CALL_MDI("G90")

    def kb_jog(self, state, joint, direction, fast=False, linear=True):
        if not STATUS.is_man_mode() or not STATUS.machine_is_on():
            self.add_status('Machine must be ON and in Manual mode to jog')
            return
        if linear:
            distance = STATUS.get_jog_increment()
            rate = STATUS.get_jograte() / 60
        else:
            distance = STATUS.get_jog_increment_angular()
            rate = STATUS.get_jograte_angular() / 60
        if state:
            if fast:
                rate = rate * 2
            ACTION.JOG(joint, direction, rate, distance)
        else:
            ACTION.JOG(joint, 0, 0, 0)

    def add_status(self, message):
        self._m = message
        print message
        self.w.statusbar.showMessage(self._m, 5000)
        STATUS.emit('update-machine-log', self._m, 'TIME')

    def enable_auto(self, state):
        for widget in self.auto_list:
            self.w[widget].setEnabled(state)
        if state is True:
            self.w.jogging_frame.show()
            if self.w.chk_use_virtual.isChecked():
                self.w.btn_keyboard.show()
        else:
            self.w.jogging_frame.hide()
            self.w.btn_main.setChecked(True)
            self.w.btn_keyboard.setChecked(False)
            self.w.btn_keyboard.hide()
            self.w.main_tab_widget.setCurrentIndex(TAB_MAIN)
            self.w.stackedWidget.setCurrentIndex(0)

    def enable_onoff(self, state):
        if state:
            self.add_status("Machine ON")
        else:
            self.add_status("Machine OFF")
        self.w.spindle_pause.setChecked(False)
        self.h['eoffset_count'] = 0
        for widget in self.onoff_list:
            self.w[widget].setEnabled(state)

    def set_start_line(self, line):
        if line == 0:
            self.w.lbl_start_line.setText('1')
        elif self.w.chk_run_from_line.isChecked():
            self.w.lbl_start_line.setText(str(line))
        else:
            self.w.lbl_start_line.setText('1')

    def use_keyboard(self):
        if self.w.chk_use_keyboard.isChecked():
            return True
        else:
            self.add_status('Keyboard shortcuts are disabled')
            return False

    #####################
    # KEY BINDING CALLS #
    #####################

    def on_keycall_ESTOP(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_ESTOP_STATE(True)

    def on_keycall_POWER(self, event, state, shift, cntrl):
        if state:
            ACTION.SET_MACHINE_STATE(False)

    def on_keycall_ABORT(self, event, state, shift, cntrl):
        if state:
            ACTION.ABORT()

    def on_keycall_HOME(self, event, state, shift, cntrl):
        if state and not STATUS.is_all_homed() and self.use_keyboard():
            ACTION.SET_MACHINE_HOMING(-1)

    def on_keycall_pause(self, event, state, shift, cntrl):
        if state and STATUS.is_auto_mode() and self.use_keyboard():
            ACTION.PAUSE()

    def on_keycall_XPOS(self, event, state, shift, cntrl):
        if self.use_keyboard() and not self.w.btn_keyboard.isChecked():
            self.kb_jog(state, 0, 1, shift)

    def on_keycall_XNEG(self, event, state, shift, cntrl):
        if self.use_keyboard() and not self.w.btn_keyboard.isChecked():
            self.kb_jog(state, 0, -1, shift)

    def on_keycall_YPOS(self, event, state, shift, cntrl):
        if self.use_keyboard() and not self.w.btn_keyboard.isChecked():
            self.kb_jog(state, 1, 1, shift)

    def on_keycall_YNEG(self, event, state, shift, cntrl):
        if self.use_keyboard() and not self.w.btn_keyboard.isChecked():
            self.kb_jog(state, 1, -1, shift)

    def on_keycall_ZPOS(self, event, state, shift, cntrl):
        if self.use_keyboard() and not self.w.btn_keyboard.isChecked():
            self.kb_jog(state, 2, 1, shift)

    def on_keycall_ZNEG(self, event, state, shift, cntrl):
        if self.use_keyboard() and not self.w.btn_keyboard.isChecked():
            self.kb_jog(state, 2, -1, shift)

    def on_keycall_APOS(self, event, state, shift, cntrl):
        if self.use_keyboard() and not self.w.btn_keyboard.isChecked():
            self.kb_jog(state, 3, 1, shift, False)

    def on_keycall_ANEG(self, event, state, shift, cntrl):
        if self.use_keyboard() and not self.w.btn_keyboard.isChecked():
            self.kb_jog(state, 3, -1, shift, False)

    def on_keycall_F12(self, event, state, shift, cntrl):
        if state:
            STYLEEDITOR.load_dialog()

    ##############################
    # required class boiler code #
    ##############################
    def __getitem__(self, item):
        return getattr(self, item)

    def __setitem__(self, item, value):
        return setattr(self, item, value)
class QUnFrameWindow(QWidget):
    """
    无边框窗口类
    """
    def __init__(self):
        super(QUnFrameWindow, self).__init__(None,Qt.FramelessWindowHint) # 设置为顶级窗口,无边框
        # self._padding =8 # 设置边界宽度为8
        #self.setAttribute(Qt.WA_TranslucentBackground)
        self.SHADOW_WIDTH = 8
        self.initLayout() # 设置框架布局
        #self.setMinimumSize(900,700)
        self.setMouseTracking(True) # 设置widget鼠标跟踪
        self.initDrag() # 设置鼠标跟踪判断默认值
        self.center()
        self.__dir = os.path.dirname(os.path.abspath(__file__))



    #绘制边框阴影
    def drawShadow(self,painter):
        #print('ddddddddddddddddddd')
        #绘制左上角、左下角、右上角、右下角、上、下、左、右边框

        self.pixmaps=[self.__dir+'/shadow/shadow_left_top.png',self.__dir+'/shadow/shadow_left_bottom.png',self.__dir+'/shadow/shadow_right_top.png',self.__dir+'/shadow/shadow_right_bottom.png',self.__dir+'/shadow/shadow_top.png',self.__dir+'/shadow/shadow_bottom.png',self.__dir+'/shadow/shadow_left.png',self.__dir+'/shadow/shadow_right.png']
        painter.drawPixmap(0, 0, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[0]))   #左上角
        painter.drawPixmap(self.width()-self.SHADOW_WIDTH, 0, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[2]))   #右上角
        painter.drawPixmap(0,self.height()-self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[1]))   #左下角
        painter.drawPixmap(self.width()-self.SHADOW_WIDTH, self.height()-self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[3]))  #右下角
        painter.drawPixmap(0, self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.height()-2*self.SHADOW_WIDTH, QPixmap(self.pixmaps[6]).scaled(self.SHADOW_WIDTH, self.height()-2*self.SHADOW_WIDTH)) #左
        painter.drawPixmap(self.width()-self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.height()-2*self.SHADOW_WIDTH, QPixmap(self.pixmaps[7]).scaled(self.SHADOW_WIDTH, self.height()- 2*self.SHADOW_WIDTH)) #右
        painter.drawPixmap(self.SHADOW_WIDTH, 0, self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[4]).scaled(self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH)) #上
        painter.drawPixmap(self.SHADOW_WIDTH, self.height()-self.SHADOW_WIDTH, self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[5]).scaled(self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH))   #下


    def paintEvent(self, event):
        painter = QPainter(self)

        self.drawShadow(painter)
        painter.setPen(Qt.NoPen)
        painter.setBrush(Qt.white)
        painter.drawRect(QRect(self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.width() - 2 * self.SHADOW_WIDTH,
                               self.height() - 2 * self.SHADOW_WIDTH))


    def initDrag(self):
        # 设置鼠标跟踪判断扳机默认值
        self._move_drag = False


    def initLayout(self):
        # 设置框架布局


        self.setAttribute(Qt.WA_TranslucentBackground, True)
        # self.setWindowIcon(QIcon('logo.ico'))

        self.gridLayout = QGridLayout(self)
        self.gridLayout.setContentsMargins(8,8,8,8)
        self.gridLayout.setSpacing(0)
        self.gridLayout.setObjectName("gridLayout")


        #添加竖排layout
        self.verticalLayout =QVBoxLayout()
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.gridLayout.addLayout(self.verticalLayout,0,0,0,0)


        self.label = QTitleLabel()
        self.label.setScaledContents(False)
        # self.label.setPixmap(QPixmap("title.png"))

        #
        # sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        # sizePolicy.setHorizontalStretch(0)
        # sizePolicy.setVerticalStretch(0)
        # sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
        # self.label.setSizePolicy(sizePolicy)


        self.label.setFixedHeight(108)
        self.label.setContentsMargins(0,0,0,0)
        self.label.setMouseTracking(True)

        self.verticalLayout.addWidget(self.label)
        #在横排layput中添加按钮


        #在上方横排下排生成一个横排放浏览器
        self.horizontalLayout = QHBoxLayout()
        self.horizontalLayout.setContentsMargins(0,0,0,0)#浏览器右下方留出拖拽空间
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout.addLayout(self.horizontalLayout)


        #生成一个浏览器组件,添加到下方的横排layout
        self.webEngineView = QWebView()
        self.webEngineView.load(QUrl('file:///C:/Users/zhongcun/Desktop/project/app/mainWin/login/web/login.html'))

        self.webEngineView.setObjectName('webEngineView')

                         #---------------------------------------------------
        # self.webEngineView.page().setWebChannel(channeller)

        self.webEngineView.setContentsMargins(0,0,0,0)

        self.webEngineView.setMaximumSize(QSize(10000, 10000))
        self.webEngineView.setMouseTracking(True)
        self.horizontalLayout.addWidget(self.webEngineView)


    def setCloseButton(self, bool):
        # 给widget定义一个setCloseButton函数,为True时设置一个关闭按钮
        if bool == True:
            self._CloseButton = QTitleButton(b'\xef\x81\xb2'.decode("utf-8"), self)
            self._CloseButton.setObjectName("CloseButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式
            self._CloseButton.setToolTip("关闭")
            self._CloseButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)
            self._CloseButton.setFixedHeight(36)

            #self._CloseButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度
            self._CloseButton.clicked.connect(self.close) # 按钮信号连接到关闭窗口的槽函数


    def setMinConfigButtons(self, bool):
        # 给widget定义一个setMinMaxButtons函数,为True时设置一组最小化最大化按钮
        if bool == True:
            self._MinimumButton = QTitleButton(b'\xef\x80\xb0'.decode("utf-8"), self)
            self._MinimumButton.setObjectName("MinMaxButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式
            self._MinimumButton.setToolTip("最小化")
            self._MinimumButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)
            self._MinimumButton.setFixedHeight(36)  # 设置按钮高度为标题栏高度
            #self._MinimumButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度
            self._MinimumButton.clicked.connect(self.showMinimized) # 按钮信号连接到最小化窗口的槽函数
            self._ConfigButton = QTitleButton(b'\xef\x81\x80'.decode("utf-8"), self)
            self._ConfigButton.setObjectName("MinMaxButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式
            self._ConfigButton.setToolTip("设置")
            self._ConfigButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)
            self._ConfigButton.setFixedHeight(36)


    def resizeEvent(self, QResizeEvent):

        try:
            self._CloseButton.move(self.width() - self._CloseButton.width()-16, 16)
        except:
            pass
        try:
            self._MinimumButton.move(self.width() - (self._CloseButton.width() + 1) * 2 -16+2, 16)
        except:
            pass
        try:
            self._ConfigButton.move(self.width() - (self._CloseButton.width() + 1) * 3 -16+3, 16)
        except:
            pass

    def mousePressEvent(self, event):

        # 重写鼠标点击的事件

        if (event.button() == Qt.LeftButton) and (event.y() < self.label.height()+16):
            # 鼠标左键点击标题栏区域
            self._move_drag = True
            self.move_DragPosition = event.globalPos() - self.pos()
            event.accept()

    def mouseMoveEvent(self, QMouseEvent):

        if (Qt.LeftButton and self._move_drag):
            # 标题栏拖放窗口位置
            self.move(QMouseEvent.globalPos() - self.move_DragPosition)
            #window.setContentsMargins(0,0,0,0) #动态调整阴影
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        # 鼠标释放后,各扳机复位
        self._move_drag = False


    #窗口居中
    def center(self):
        qr = self.frameGeometry()  # 获得主窗口的一个矩形特定几何图形。这包含了窗口的框架。
        cp = QDesktopWidget().availableGeometry().center()  # 算出相对于显示器的绝对值。
        # 并且从这个绝对值中,我们获得了屏幕中心点。
        qr.moveCenter(cp)  # 矩形已经设置好了它的宽和高。现在我们把矩形的中心设置到屏幕的中间去。
        # 矩形的大小并不会改变。
        self.move(qr.topLeft())  # 移动了应用窗口的左上方的点到qr矩形的左上方的点,因此居中显示在我们的屏幕


    def closeEvent(self, event):
        # try:
        #     reply = QMessageBox.question(self, '提示',
        #                                  "确认退出?", QMessageBox.Yes, QMessageBox.No)
        #     print(reply == QMessageBox.Yes)
        #     if reply == QMessageBox.Yes:
                event.ignore()
                # self.setVisible(False)
                print('---------')
                self.setVisible(False)
class BrowserController(QObject):

    def __init__(self, parent, fullscreen, sizes):
        """
        This constructor function initializes a layout of the Arius output
        module but doesn`t displays it on the screen.

        Firstly, it creates a new app and detects screens configuration.
        Then, QGridLayout is created and its appearance is configured: margins
        and spaces between elements is set to 0.

        After that, we create three QWebViews: one for our main content view
        and two others for header and footer views.

        Immideately after creating these instances we assign them their heights
        according to percentages given by user and dimensions of the screen.

        Next, we remove scroll bars from top and bottom views and load predefined
        pages into them.

        Then we allow QWebKit to run all extensions it needs to render the page.

        After that, wee set the layout design as a grid of three rows.

        Finally, we create an updater object which will run in another stream and
        a timer instance which checks that stream for new commands
        from the server, and in case if there`s some update handles it.
        """
        super(BrowserController, self).__init__()
        if not fullscreen and not sizes:
            print 'You must initialize windows size'
            raise Exception
        self._fullscreen = fullscreen
        if sizes:
            self._screen_width = sizes[0]
            self._screen_height = sizes[1]
        self._app = QtWidgets.QApplication(sys.argv)
        self._app.setStyle("Fusion")
        if self._fullscreen:
            self._get_screen_height()

        self._layout = QGridLayout()
        self._layout.setSpacing(0)
        self._layout.setContentsMargins(0, 0, 0, 0)

        self._main_browser = QWebView()
        main_page = FakePage(self)
        self._main_browser.setPage(main_page)

        self._top_browser = QWebView()
        self._bottom_browser = QWebView()

        self._top_browser_height = config['output_header_height'] * self._screen_height
        self._bottom_browser_height = config['output_footer_height'] * self._screen_height

        self._top_browser.setMaximumHeight(self._top_browser_height)
        self._top_browser.setMinimumHeight(self._top_browser_height)

        self._bottom_browser.setMaximumHeight(self._bottom_browser_height)
        self._bottom_browser.setMinimumHeight(self._bottom_browser_height)

        self._top_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)
        self._main_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)
        self._main_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff)
        self._bottom_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)

        self._top_browser_load_url(
            config['flask_server_home'] + config['output_browser_top_page'])
        self._bottom_browser_load_url(
            config['flask_server_home'] + config['output_browser_bottom_page'])

        self._main_browser.settings().setAttribute(
            QWebSettings.DeveloperExtrasEnabled, True)
        self._main_browser.settings().setAttribute(QWebSettings.PluginsEnabled, True)
        QWebSettings.setObjectCacheCapacities(0, 0, 0)
        self._main_browser.settings().setAttribute(
            QWebSettings.AcceleratedCompositingEnabled, True)
        self._main_browser.settings().setAttribute(QWebSettings.WebGLEnabled, True)

        self._layout.addWidget(self._top_browser, 1, 0)
        self._layout.addWidget(self._main_browser, 2, 0)
        self._layout.addWidget(self._bottom_browser, 3, 0)
        self._parent = parent
        self._parent.load_url.connect(self._load_url)
        self._parent.js_execution.connect(self._execute_js)
        self._parent.zooming.connect(self._zoom)

    def run(self):
        self._main_window = QWidget()  # create a window as a QWidget
        self._main_window.setLayout(self._layout)  # assign a layout to it
        if self._fullscreen:
            self._main_window.showFullScreen()  # set full screen enabled
        else:
            self._main_window.resize(self._screen_width, self._screen_height)
        self._main_window.show()  # and finally, show the window
        # and set a trigger to exit the app, as window is closed
        sys.exit(self._app.exec_())

    def _get_screen_height(self):
        if self._fullscreen:
            output = subprocess.Popen('xrandr | grep "\*" | cut -d" " -f4',
                                      shell=True, stdout=subprocess.PIPE).communicate()[0]
            output = [int(val) for val in output.split('x')]
            self._screen_height = output[1]
            self._screen_width = output[0]
        else:
            output = [self._width, self._height]
        return output[0], output[1]

    def _zoom(self, factor):
        self._main_browser.page().mainFrame().setZoomFactor(factor)

    def _top_browser_load_url(self, url):
        self._top_browser.load(QUrl(url))

    def _bottom_browser_load_url(self, url):
        self._bottom_browser.load(QUrl(url))

    def _load_url(self, url):
        logger.debug('OPENING URL %s', url)
        self._main_browser.load(QUrl(url))

    def _execute_js(self, string_js):
        logger.debug(string_js)
        self._main_browser.page().mainFrame().evaluateJavaScript(string_js)
Beispiel #30
0
class DrawLotteryView(QObject):
    def __init__(self, parent):
        super(DrawLotteryView, self).__init__()
        self.pwindow = parent   #获取父窗口指针

        self.states = QStateMachine()

        sinitinfo = QState()
        sltypeinfo = QState()
        sprizeinfo = QState()
        svnumberwindow = QState()
        sdrawlottery = QState()
        sfinal = QState()

        sinitinfo.addTransition(self.on_nextstep_event, sltypeinfo)
        sltypeinfo.addTransition(self.on_nextstep_event, sprizeinfo)
        sprizeinfo.addTransition(self.on_nextstep_event, svnumberwindow)
        svnumberwindow.addTransition(self.on_nextstep_event, sdrawlottery)
        sdrawlottery.addTransition(self.on_nextstep_event, sfinal)
        sfinal.addTransition(self.on_final_event, sinitinfo)

        sinitinfo.entered.connect(self.initinfo)
        sltypeinfo.entered.connect(self.viewltypeinfo)
        sprizeinfo.entered.connect(self.viewprizeinfo)
        svnumberwindow.entered.connect(self.viewnumberwindow)
        sdrawlottery.entered.connect(self.drawlottery)
        sfinal.entered.connect(self.final)

        self.states.addState(sinitinfo)
        self.states.addState(sltypeinfo)
        self.states.addState(sprizeinfo)
        self.states.addState(svnumberwindow)
        self.states.addState(sdrawlottery)
        self.states.addState(sfinal)
        self.states.setInitialState(sinitinfo)

        self.states.start()

    def show(self):
        #It is IMPERATIVE that all forward slashes are scrubbed out, otherwise QTWebKit seems to be
        # easily confused
        # kickOffHTML = 'file:///' + join(dirname(__file__).replace('\\', '/'), "www/test02.html").replace('\\', '/')
        # kickOffHTML = 'file:///' + join(dirname(__file__).replace('\\', '/'), "www/test02.html").replace('\\', '/')
        kickOffHTML = 'file:///' + QDir().absolutePath() + SysConfig().getlotterywindowspath() + 'index.html'
        # kickOffHTML = 'http://get.webgl.org/'
        # kickOffHTML = 'http://www.airtightinteractive.com/demos/js/nebula/'

        #This is basically a browser instance
        # self.gweb = QGraphicsWebView()
        self.web = QWebView()
        self.web.setMinimumSize(1024,680)
        self.web.setWindowFlags(Qt.FramelessWindowHint) #无边框
        self.web.setContextMenuPolicy(0)    #关闭右键

        #Unlikely to matter but prefer to be waiting for callback then try to catch
        # it in time.
        self.web.loadFinished.connect(self.onLoad)
        self.web.load(QUrl(kickOffHTML))
        self.web.show()
        # self.scene = QGraphicsScene()
        # self.scene.addItem(self.gweb)
        # self.view = QGraphicsView()
        # self.view.setScene(self.scene)
        # self.view.show()

    def onLoad(self):
        #如果mywebinterface未初始化,则初始化mywebinterface
        # if getattr(self, "mywebinterface", False) == False:
        #     self.mywebinterface = WebInterface()

        #This is the body of a web browser tab
        self.myPage = self.web.page()
        self.myPage.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
        self.myPage.settings().setAttribute(QWebSettings.JavascriptEnabled, True)
        self.myPage.settings().setAttribute(QWebSettings.WebGLEnabled, True)
        self.myPage.settings().setAttribute(QWebSettings.AcceleratedCompositingEnabled, True)

        #This is the actual context/frame a webpage is running in.
        # Other frames could include iframes or such.
        self.myFrame = self.myPage.mainFrame()
        # ATTENTION here's the magic that sets a bridge between Python to HTML
        self.myFrame.addToJavaScriptWindowObject("mywebinterface", self)
        #Tell the HTML side, we are open for business
        self.myFrame.evaluateJavaScript("ApplicationIsReady()")

    def initinfo(self):
        # print('initinfo')
        cltypes = self.pwindow.getcurrentqueue()
        if cltypes == None:
            self.isfinished = True
        else:
            self.isfinished = False
            self.currentltype = cltypes['ltype']
            self.currentnumber = cltypes['number'] #当前奖项需要抽取的数量
            self.drawcount = int(self.currentnumber)  #当前抽奖序列的人数,需要重复抽奖的次数
            self.isdrawing = False    #当前是否为抽奖状态

    @pyqtSlot()
    def nextstep(self):
        if self.isfinished:
            # print('close this window')
            self.on_message_event.emit('当前抽奖序列已抽取完毕!<br>按退出按钮退出!')
        else:
            if self.isdrawing and self.drawcount > 0:
                self.drawlottery()
            else:
                # print('nextstep')
                self.on_nextstep_event.emit()

    @pyqtSlot()
    def exitwindow(self):
        # print('exit window')
        self.web.close()

    def viewltypeinfo(self):
        # print('viewltypeinfo')
        self.on_viewltypeinfo_event.emit(self.currentltype, int(self.currentnumber))

    def viewprizeinfo(self):
        # print('return prizeinfo')
        ls = SysConfig().getprizeitempicandnote(self.currentltype)
        icon = ls[0]
        notes = ls[1]
        self.on_viewprizeinfo_event.emit(icon, notes)

    def viewnumberwindow(self):
        # print('return viewnumberwindow')
        self.on_viewnumberwindow_event.emit()

    def drawlottery(self):
        # print('return drawlottery')
        progress = str(int(self.currentnumber)-self.drawcount+1) + '/' + self.currentnumber
        self.on_viewprogress_event.emit(progress)
        try:
            dl = DAllList().getwininfo()
            sid = dl[0][2] + dl[0][5] + dl[0][6] + dl[0][7]
            name = dl[1]
            DAllList().setwininfo(self.currentltype,dl[0])
        except:
            sid = '0000'
            name = 'error, retry'
            self.drawcount = 0
            self.isdrawing = False
            self.on_drawlottery_event.emit(sid, name)
            pass
        self.on_drawlottery_event.emit(sid, name)
        self.drawcount -= 1
        if self.drawcount == 0:
            self.isdrawing = False
        else:
            self.isdrawing = True

    def final(self):
        print('final')
        self.on_final_event.emit()

    @pyqtSlot()
    def changesize(self):
        # print('changesize')
        if self.web.isFullScreen():
            self.web.showNormal()
        else:
            self.web.showFullScreen()

    on_nextstep_event = pyqtSignal()
    on_viewltypeinfo_event = pyqtSignal(str, int)
    on_viewprizeinfo_event = pyqtSignal(str, str)
    on_viewluckguyinfo_event = pyqtSignal(str, str)
    on_viewnumberwindow_event = pyqtSignal()
    on_drawlottery_event = pyqtSignal(str, str)
    on_final_event = pyqtSignal()
    on_message_event = pyqtSignal(str)
    on_viewprogress_event = pyqtSignal(str)


# app = QApplication(sys.argv)
#
# myWebApp = DrawLotteryView()
# myWebApp.show()
#
# exit(app.exec_())
Beispiel #31
0
class OutputInterface:

    def __init__(self, fullscreen=False, sizes=None):
        """
        This constructor function initializes a layout of the Arius output
        module but doesn`t displays it on the screen.

        Firstly, it creates a new app and detects screens configuration.
        Then, QGridLayout is created and its appearance is configured: margins
        and spaces between elements is set to 0.

        After that, we create three QWebViews: one for our main content view
        and two others for header and footer views.

        Immideately after creating these instances we assign them their heights
        according to percentages given by user and dimensions of the screen.

        Next, we remove scroll bars from top and bottom views and load predefined
        pages into them.

        Then we allow QWebKit to run all extensions it needs to render the page.

        After that, wee set the layout design as a grid of three rows.

        Finally, we create an updater object which will run in another stream and
        a timer instance which checks that stream for new commands
        from the server, and in case if there`s some update handles it.
        """
        if not fullscreen and not sizes:
            print 'You must initialize windows size'
            raise Exception
        self._fullscreen = fullscreen
        if sizes:
            self._screen_width = sizes[0]
            self._screen_height = sizes[1]
        self._app = QtWidgets.QApplication(sys.argv)
        self._app.setStyle("Fusion")
        if self._fullscreen:
            self._get_screen_height()

        self._layout = QGridLayout()  # create a main view of an app
        self._layout.setSpacing(0)  # and do some design settings
        self._layout.setContentsMargins(0, 0, 0, 0)

        self._main_browser = QWebView()  # create a main content view
        # and initialize zoom factor variable which will be used to control
        # zoom
        main_page = FakeBrowser(self)
        self._main_browser.setPage(main_page)
        self._zoom_factor = 1

        self._top_browser = QWebView()  # and create top and bottom views
        self._bottom_browser = QWebView()

        self._top_browser_height = config[
            'output_header_height'] * self._screen_height  # calculate views sizes
        self._bottom_browser_height = config[
            'output_footer_height'] * self._screen_height

        self._top_browser.setMaximumHeight(
            self._top_browser_height)  # and assign them to the views
        self._top_browser.setMinimumHeight(self._top_browser_height)

        self._bottom_browser.setMaximumHeight(self._bottom_browser_height)
        self._bottom_browser.setMinimumHeight(self._bottom_browser_height)

        self._top_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)  # remove the scroll bars
        self._main_browser.page().mainFrame().setScrollBarPolicy(QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)
        self._main_browser.page().mainFrame().setScrollBarPolicy(QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff)
        self._bottom_browser.page().mainFrame().setScrollBarPolicy(
            QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff)

        self._top_browser_load_url(
            config['flask_server_home'] + config['output_browser_top_page'])  # load default design
        self._bottom_browser_load_url(
            config['flask_server_home'] + config['output_browser_bottom_page'])

        self._main_browser.settings().setAttribute(
            QWebSettings.DeveloperExtrasEnabled, True)  # enable console
        self._main_browser.settings().setAttribute(
            QWebSettings.PluginsEnabled, True)  # enable plugins
        QWebSettings.setObjectCacheCapacities(0, 0, 0)  # disable caching
        self._main_browser.settings().setAttribute(
            QWebSettings.AcceleratedCompositingEnabled, True)
        self._main_browser.settings().setAttribute(
            QWebSettings.WebGLEnabled, True)

        self._layout.addWidget(self._top_browser, 1, 0)  # set views positions
        self._layout.addWidget(self._main_browser, 2, 0)
        self._layout.addWidget(self._bottom_browser, 3, 0)

        # create a RLock object to syncronyze threads.
        self._lock = threading.RLock()
        # and create an updater object
        self._updater = OutputUpdater(self._lock)

        self._updater.start()  # which is ran in another non-blocking stream

        self.timeoutTimer = QTimer()  # create a timer to check for commands
        tCallback = functools.partial(
            self._handle_command)  # set a timer`s function
        self.timeoutTimer.timeout.connect(tCallback)
        self.timeoutTimer.start(
            config['output_update_frequency'])  # and start it

        # as no data is displayed on the main view - curent content type is
        # None
        self._cur_filetype = None

        # text to speech speaker
        self._speaker = None
        # audioplayer
        self._player = Player()

    def run(self):
        """
        This method is called to show the output module window
        after initializing all views in __init__.
        """
        self._main_window = QWidget()  # create a window as a QWidget
        self._main_window.setLayout(self._layout)  # assign a layout to it
        if self._fullscreen:
            self._main_window.showFullScreen()  # set full screen enabled
        else:
            self._main_window.resize(self._screen_width, self._screen_height)
        self._main_window.show()  # and finally, show the window
        # and set a trigger to exit the app, as window is closed
        sys.exit(self._app.exec_())
        logger.info('Finished')

    def _get_screen_height(self):
        """
        This method is used to get dimensions of user`s screen.
        To do this is uses system utilite 'xrandr' via subprocess module,
        which is not very nice way, however we didn`t find
        anything better.
        """
        if self._fullscreen:
            output = subprocess.Popen('xrandr | grep "\*" | cut -d" " -f4',
                                      shell=True, stdout=subprocess.PIPE).communicate()[0]
            output = [int(val) for val in output.split('x')]
            # logger.debug('Screen dimensions are: {} x {}'.format(output[0], output[1]))
            self._screen_height = output[1]
            self._screen_width = output[0]
        else:
            output = [self._width, self._height]
        return output[0], output[1]

    def _handle_command(self):
        """
        This is a method called by an updater timer each given interval of time.
        It checks updater object and in case if there`s some new command it proceeds it.
        """
        command = self._updater.get_state()  # get a new command
        if command[0] != 'none' and command[0] != None:  # if there`s a command, handle it
            logger.info('Handling command {}'.format(command))

            # self._updater.reset()  # clear the updater object command buffer

            # Commands for opening all types of content are handled by
            # calling of _load_content method with specified content type.

            # start music play if it was stopped

            if command[0] == 'OPEN_PDF':
                self._player.play()
                self._load_content('local_pdf', command[1])
            elif command[0] == 'OPEN_URL':
                self._player.play()
                self._load_content('external_url', command[1])
            elif command[0] == 'OPEN_LOCAL_PAGE':
                self._player.play()
                self._load_content('local_url', command[1])
            elif command[0] == 'OPEN_VIDEO':
                self._player.stop()
                self._load_content('local_video', command[1])

            # Command to open a system scren (e.g. {'type': 'OPEN_SCREEN', 'command':'OPEN_IDLE'})
            # will be proceeded by sending a 'command' to a _load_screen method, which does futher
            # work.

            elif command[0] == 'OPEN_SCREEN':
                self._player.play()
                self._load_screen(command[1])

            # Zoom commands are handled each with its own method.

            elif command[0] == 'ZOOM_IN':
                self._main_browser_zoom_in()
            elif command[0] == 'ZOOM_OUT':
                self._main_browser_zoom_out()
            elif command[0] == 'NO_ZOOM':
                self._main_browser_reset_zoom()

            # as well as scroll.

            elif command[0] == 'SCROLL_DOWN':
                self._main_browser_scroll_down()
            elif command[0] == 'SCROLL_UP':
                self._main_browser_scroll_up()

            elif command[0] == 'SCROLL_LEFT':
                self._main_browser_scroll_left()
            elif command[0] == 'SCROLL_RIGHT':
                self._main_browser_scroll_right()
            elif command[0] == 'CONTINIOUS_SCROLL_UP':
                pass
            elif command[0] == 'CONTINIOUS_SCROLL_DOWN':
                pass
            elif command[0] == 'STOP_SCROLL':
                pass
            # Following two commands are responsible for playing
            # video and pausing it. As a second part of the command
            # name of the video file should be given.

            elif command[0] == 'PLAY':
                self._player.stop()
                self._video_play()
            elif command[0] == 'PAUSE':
                self._video_pause()

            # These two commands are used for increasing or
            # decreasing video volume.

            elif command[0] == 'VOLUME_UP':
                self._volume_up()
            elif command[0] == 'VOLUME_DOWN':
                self._volume_down()

            # and these two are for text-to-speech
            # The 'command' body should be a text you
            # you want to hear.

            elif command[0] == "SPEAK":
                print 'SPEAK'
                self._player.play()
                self._speak_text(command[1])
            elif command[0] == "STOP_SPEAK":
                self._player.play()
                self._speak_stop()
            elif command[0] == 'NEXT_PAGE':
                self._main_browser_next_page()
            elif command[0] == 'PREV_PAGE':
                self._main_browser_prev_page()

            elif command[0] == 'MUTE':
                self._mute()
            elif command[0] == 'UNMUTE':
                self._unmute()
            else:
                logger.info('command not recognized {}'.format(command))
        else:
            pass

    def _load_screen(self, screen_type):
        """
        This method is responsible for opening system
        Arius screens. It receives a type of screen,
        server wants to open and then displays it on
        the main content view.
        """
        self._main_browser_reset_zoom()  # set zoom level to 1 in case if previous page was zoomed
        # this a default path to the arius server
        url = 'http://' + config['flask_server_address'] + \
            ':' + config['flask_server_port']
        if screen_type == 'IDLE':  # and here in depend of type of the required screen
            # we set the last path of the URL to the exact screen
            url = url + config['flask_server_idle_address']
        elif screen_type == 'ERROR':
            url = url + config['flask_server_error_address']
        elif screen_type == 'SEARCH':
            url = url + config['flask_server_search_address']
        elif screen_type == 'SPEAKING':
            url = url + config['flask_server_speaking_address']
        else:  # and if the target screen wasn`t recognized we can also handle it
            logger.info('WRONG SCREEN TYPE: {}'.format(screen_type))
        logger.debug(
            'Opening {} screen on following address {}'.format(screen_type, url))
        self._main_browser.load(QUrl(url))

    def _custom_ua(self, url):
        """
        This function returns a custom user agent data
        which is stored in config.py file as 'output_user_agent'
        """
        return config['output_user_agent']

    def _load_content(self, content_type, content):
        """
        This method is for displaying some content of
        such types: local web pages, remote web pages,
        local pdf`s, local videos.

        It should be called like in the following example
        to work correctly:
        self._load_content('local_video', 'some_video.mp4')
        """
        self._main_browser_reset_zoom()  # reset zoom
        if content_type == 'local_url':
            source = config['flask_server_home'] + \
                config['flask_server_local_page_client'] + \
                content  # simply get the file from flask-server by its relative path-id
            # specify type of currently opened file for zoom and scroll methods
            self._cur_filetype = "webpage"
        elif content_type == 'external_url':
            self._cur_filetype = "webpage"
            # no needs required as, link should be given in
            # 'http://yoursite.com/yourpage'
            source = content
        elif content_type == 'local_pdf':
            # to render PDF`s we use PDF.js, so we open its page and send it a
            # path for the target file.
            source = config['flask_server_home'] + \
                config['flask_server_local_page_client'] + \
                content
            self._cur_filetype = "pdf"
        elif content_type == 'local_video':
            # in case of opening local videos we need to modify the path to the video in the source code of
            # the videoplayer, so don`t die after reading this code. It works just in the same style as other
            # filetypes, but in a very weird way.
            source = config['flask_server_home'] + \
                config['flask_server_video_addr_client'] + content
            logger.info('Opening video at {}'.format(source))
            self._cur_filetype = "video"
        # Set a custom user agent to avoid message about deprecated version of
        # browser

        self._main_browser.page().userAgentForUrl = self._custom_ua

        logger.info('Loading data on address: {}'.format(source))

        # Create a request to be able to set user-agent data. Without
        # it, it`s impossible to customize request data.
        request = QNetworkRequest()
        request.setUrl(QUrl(source))
        request.setRawHeader("USER-AGENT", config['output_user_agent'])

        # and finally load the result
        self._main_browser.load(request)

    def _top_browser_load_url(self, url):
        """
        This method just loads a given URL in the top content view.
        URL must contain protocol and the address.
        e.g. http://placehold.it/400x200
        or
        file://data/somepage.html
        """
        logger.info('Loading {} to the top content view.'.format(url))
        self._top_browser.load(QUrl(url))

    def _bottom_browser_load_url(self, url):
        """
        This method just loads a given URL in the bottom content view.
        URL must contain protocol and the address.
        e.g. http://placehold.it/400x200
        or
        file:
        """
        logger.info('Loading {} to the bottom content view.'.format(url))
        self._bottom_browser.load(QUrl(url))

    def _main_browser_scroll_down(self):
        """
        This method is called to smoothly scroll the page down. In
        dependence of the current content type if provides different
        implementations of scroll, but generally it gives the same result.
        """
        logger.debug('Scrolling main content view down')
        scroll_js = open("scroll.js", "r").read()
        self._main_browser.page().mainFrame().evaluateJavaScript(scroll_js)
        if self._cur_filetype == "pdf":
            self._main_browser.page().mainFrame().evaluateJavaScript("smooth_vscroll_by(PDFViewerApplication.pdfViewer.container, 300, 1000);")
        elif self._cur_filetype == "webpage":
            self._main_browser.page().mainFrame().evaluateJavaScript("smooth_vscroll_by(document.body, 300, 1000);")

    def _main_browser_scroll_up(self):
        """
        This method is called to smoothly scroll the page up. In
        dependence of the current content type if provides different
        implementations of scroll, but generally it gives the same result.
        """
        logger.debug('Scrolling main content view down')
        scroll_js = open("scroll.js", "r").read()
        self._main_browser.page().mainFrame().evaluateJavaScript(scroll_js)
        if self._cur_filetype == "pdf":
            self._main_browser.page().mainFrame().evaluateJavaScript("smooth_vscroll_by(PDFViewerApplication.pdfViewer.container, -300, 1000);")
        elif self._cur_filetype == "webpage":
            self._main_browser.page().mainFrame().evaluateJavaScript("smooth_vscroll_by(document.body, -300, 1000);")

    def _main_browser_scroll_left(self):
        """
        This method is called to smoothly scroll the page left. In
        dependence of the current content type if provides different
        implementations of scroll, but generally it gives the same result.
        """
        logger.debug('Scrolling main content view left')
        scroll_js = open("scroll.js", "r").read()
        self._main_browser.page().mainFrame().evaluateJavaScript(scroll_js)
        if self._cur_filetype == "pdf":
            self._main_browser.page().mainFrame().evaluateJavaScript("smooth_hscroll_by(PDFViewerApplication.pdfViewer.container, -100, 1000);")
        elif self._cur_filetype == "webpage":
            self._main_browser.page().mainFrame().evaluateJavaScript("smooth_hscroll_by(document.body, -100, 1000);")

    def _main_browser_scroll_right(self):
        """
        This method is called to smoothly scroll the page right. In
        dependence of the current content type if provides different
        implementations of scroll, but generally it gives the same result.
        """
        logger.debug('Scrolling main content view right')
        scroll_js = open("scroll.js", "r").read()
        self._main_browser.page().mainFrame().evaluateJavaScript(scroll_js)
        if self._cur_filetype == "pdf":
            self._main_browser.page().mainFrame().evaluateJavaScript("smooth_hscroll_by(PDFViewerApplication.pdfViewer.container, 100, 1000);")
        elif self._cur_filetype == "webpage":
            self._main_browser.page().mainFrame().evaluateJavaScript("smooth_hscroll_by(document.body, 100, 1000);")

    def _main_browser_zoom_in(self):
        """
        This methoud simply zooms main content view in. It works
        well with all content types.
        """
        logger.debug('Zooming main content view in')
        if self._cur_filetype == "pdf":
            string_js = """PDFViewerApplication.zoomIn();"""
            self._main_browser.page().mainFrame().evaluateJavaScript(string_js)
        elif self._cur_filetype == "webpage":

            self._zoom_factor += .1
            self._main_browser.page().mainFrame().setZoomFactor(self._zoom_factor)

    def _main_browser_reset_zoom(self):
        """
        This method sets zoom level of the main content view to the default level.
        It should be called before loading a new page or in order to cancel any zoom
        changes.
        """
        logger.debug('Resetting zoom in the main content view')
        if self._cur_filetype == "pdf":
            string_js = 'PDFViewerApplication.pdfViewer.currentScaleValue = "page-width"'
            self._main_browser.page().mainFrame().evaluateJavaScript(string_js)
        elif self._cur_filetype == "webpage":
            self._zoom_factor = 1
            self._main_browser.page().mainFrame().setZoomFactor(self._zoom_factor)

    def _main_browser_zoom_out(self):
        """
        This methoud simply zooms main content view out. It works
        well with all content types.
        """
        logger.debug('Zooming main content view out')
        if self._cur_filetype == "pdf":
            string_js = """PDFViewerApplication.zoomOut();"""
            self._main_browser.page().mainFrame().evaluateJavaScript(string_js)
        elif self._cur_filetype == "webpage":
            self._zoom_factor -= .1
            self._main_browser.page().mainFrame().setZoomFactor(self._zoom_factor)

    def _main_browser_next_page(self):
        logger.debug('Next page')
        script_js = """PDFViewerApplication.page++;"""
        self._main_browser.page().mainFrame().evaluateJavaScript(script_js)

    def _main_browser_prev_page(self):
        logger.debug('Previous page')
        script_js = """PDFViewerApplication.page--;"""
        self._main_browser.page().mainFrame().evaluateJavaScript(script_js)

    def _speak_text(self, input_text):
        """
        This method is used to provide text-to-speech syntesizer for voice output.
        As a back-end of this method Mary TTS is used.
        Voices can be configured through config.py quit easy.
        """
        logger.info('Speaking following text {}'.format(input_text))
        if self._speaker is None:  # if there wasn`t no tts requests before, create a TTS client
            self._speaker = Speaker(config['default_voice'], config[
                                    "marytts_host"], config["marytts_port"])
        # otherwise just stop previous speaking session (if Arius isn`t
        # speaking at the moment, nothing will crash)
        else:
            self._speaker.stop()
        # and send given text as a tts request.
        self._speaker.speak(input_text)

    def _speak_stop(self):
        """
        This method simply stops current voice output.
        """
        logger.info('Stop speaking')
        self._speaker.stop()

    def _video_play(self):
        """
        This method is used to begin playing video on the current page.
        It should be run only if current content type is 'video'.
        """
        logger.debug('Playing video')
        if self._cur_filetype == 'video':
            script_js = """video=document.getElementById("arius_videoplayer"); video.play()"""
            self._main_browser.page().mainFrame().evaluateJavaScript(script_js)

    def _video_pause(self):
        """
        This method is used to pause currently playing video on the page.
        It should be run only if current content type is 'video'.
        """
        logger.debug('Video paused')
        if self._cur_filetype == 'video':
            script_js = """video=document.getElementById("arius_videoplayer"); video.pause()"""
            self._main_browser.page().mainFrame().evaluateJavaScript(script_js)

    def _volume_up(self):
        """
        This method is used to increase volume.
        It should be run only if current content type is 'video'.
        """
        logger.debug('Increasing volume')
        if self._cur_filetype == 'video':
            script_js = """video=document.getElementById("arius_videoplayer"); video.volume+=0.2;"""
            self._main_browser.page().mainFrame().evaluateJavaScript(script_js)

    def _volume_down(self):
        """
        This method is used to decrease volume.
        It should be run only if current content type is 'video'.
        """
        logger.debug('Decreasing volume')
        if self._cur_filetype == 'video':
            script_js = """video=document.getElementById("arius_videoplayer"); video.volume-=0.2;"""
            self._main_browser.page().mainFrame().evaluateJavaScript(script_js)

    def _mute(self):
        if self._player:
            self._player.mute()
        if self._speaker:
            self._speaker.mute()

    def _unmute(self):
        if self._player:
            self._player.unmute()
        if self._speaker:
            self._speaker.unmute()
# Copyright 2014 Florian Bruhin (The Compiler) <*****@*****.**>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser.  If not, see <http://www.gnu.org/licenses/>.

"""Very simple browser for testing purposes."""

import sys

from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKitWidgets import QWebView

app = QApplication(sys.argv)
wv = QWebView()
wv.load(QUrl(sys.argv[1]))
wv.show()
app.exec_()
Beispiel #33
0
        # Enable extra tools for developers
        from PyQt5.QtWebKit import QWebSettings
        web.page().settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)

        # Enable right click on page
        web.page().mainFrame().evaluateJavaScript("var debug=true;")


    # Html and js
    Pyjs = Pyjs()
    Pyjs.debug = debug
    html = QUrl("file://" + os.getcwd() + "/static/index.html")

    # Load html and js
    web.load(html)
    web.page().mainFrame().addToJavaScriptWindowObject("Pyjs", Pyjs)

    # Show webview
    web.show()

    # Quit application
    ret = app.exec_()
    ### Execute before quit ###

    # Save window config
    config.set('window', 'width', str(web.frameGeometry().width()))
    config.set('window', 'height', str(web.frameGeometry().height()))
    config.set('window', 'x', str(web.geometry().x()))
    config.set('window', 'y', str(web.geometry().y()))
    with open(configFilePath, 'w') as file:
class ExperimentManagerUI(QtWidgets.QMainWindow):
    """
    QT User interface
    """
    def __init__(self):
        """
        Initialize Experiment Manager UI
        """

        super(ExperimentManagerUI, self).__init__()
        self.fs = os.sep
        self._initConf()
        self._initHomeApp()
        self._initLogging()
        self._initDefaultValues()
        self._initUI()
        self._initWidgets()

    def _initConf(self):
        """
        Initialize config file
        """

        self.conf_default_io           = config['default_io']
        self.conf_experimentmanager_ui = config['experimentmanager_ui']
        self.conf_ui                   = config['ui']

    def _initHomeApp(self):
        """
        Initializes paths of the application
        """

        self.homeFolder = os.path.expanduser("~")

        homeAppFolderName         = self.conf_default_io['homeAppFolderName']
        homeAppLogFolder          = self.conf_default_io['homeAppLogFolder']
        homeDataFolderName        = self.conf_default_io['homeDataFolderName']

        homeExperimentFolderName  = self.conf_experimentmanager_ui['homeExperimentFolderName']
        dataTarFileName           = self.conf_experimentmanager_ui['dataTarFileName']

        self.homeAppFolder        = os.path.join(self.homeFolder, homeAppFolderName)
        self.homeAppLogFolder     = os.path.join(self.homeAppFolder, homeAppLogFolder)
        self.homeDataFolder       = os.path.join(self.homeFolder, homeDataFolderName)

        self.homeExperimentFolder = os.path.join(self.homeDataFolder, homeExperimentFolderName)
        self.homeDataLogFolder    = os.path.join(self.homeDataFolder, 'logs')

        self.dataTarFile = getResourceLoc(dataTarFileName)

        if not os.path.exists(self.homeAppFolder):
            os.mkdir(self.homeAppFolder)
        if not os.path.exists(self.homeAppLogFolder):
            os.mkdir(self.homeAppLogFolder)
        if not os.path.exists(self.homeDataFolder):
            os.mkdir(self.homeDataFolder)
        if not os.path.exists(self.homeDataLogFolder):
            os.mkdir(self.homeDataLogFolder)
        if not os.path.exists(self.homeExperimentFolder):
            with tarfile.open(self.dataTarFile, "r:gz") as dataTar:
                dataTar.extractall(path=self.homeDataFolder)

    def _initLogging(self):
        """
        Initializes paths of the application
        """
        fileName = 'errors_' + windowTitle.replace(' ', '-').lower() + '.log'
        errorLogPath = os.path.join(self.homeAppLogFolder, fileName)
        if debug:
            level = logging.DEBUG
        else:
            level = logging.ERROR
        configureLogging(errorLogPath, level)

    def _initDefaultValues(self):
        """
        Initialize default values
        """

        # Load resource paths
        self.uiPath       = getResourceLoc(self.conf_experimentmanager_ui['uiPath'])
        self.icoPath      = getResourceLoc(self.conf_experimentmanager_ui['icoPath'])
        self.helpimgPath  = getResourceLoc(self.conf_ui['helpimgPath'])
        self.aboutimgPath = getResourceLoc(self.conf_ui['aboutimgPath'])
        self.labelimgPath = getResourceLoc(self.conf_experimentmanager_ui['labelimgPath'])

        # set commands
        self.opensesamerunCommandAuto = findOpensesamerun()
        self.settingsExtension = self.conf_experimentmanager_ui['settingsExtension']
        self.defaultName       = 'default.' + self.settingsExtension
        self.extFilterSettings = self.settingsExtension + " (*." + self.settingsExtension + ")"
        self.extFilterAll      = "All Files" + " (*)"

        # default folders
        self.destinationFolder          = ""
        self._lastSelectedDestDir       = ""
        self._lastSelectedSourceDir     = ""
        self.pythonCommandManual        = ""
        self.opensesamerunCommandManual = ""

        # default text
        self.windowTitle = self.conf_experimentmanager_ui['windowTitle']
        self.StatusBoxHeight = int(self.conf_experimentmanager_ui['StatusBoxHeight'])

        # default folder
        self.sourceFolder = self.homeExperimentFolder
        print(self.sourceFolder)

        # default widget values
        self.defaultResolutionHorizontalInteger = int(self.conf_experimentmanager_ui['defaultResolutionHorizontalInteger'])
        self.defaultResolutionVerticalInteger   = int(self.conf_experimentmanager_ui['defaultResolutionVerticalInteger'])
        self.extensionList                      = list(self.conf_experimentmanager_ui['extensionList'])


    def _initUI(self):
        """
        Initializes the UI and sets button actions
        """

        # icons
        self.helpIcon   = QtGui.QIcon(self.helpimgPath)
        self.aboutIcon  = QtGui.QIcon(self.aboutimgPath)
        self.windowIcon = QtGui.QIcon(self.icoPath)

        # images
        self.pixmap = QtGui.QPixmap(self.labelimgPath)

        # Load and setup UI
        uic.loadUi(self.uiPath, self)

        self.windowHorizontalResolution = self.width()

        if verbose:
            self.windowVerticalResolution  = self.height()
        else:
            self.windowVerticalResolution  = self.height() - self.StatusBoxHeight

        # set default window values
        self.setWindowIcon(self.windowIcon)
        self.setFixedSize(self.windowHorizontalResolution,self.windowVerticalResolution)
        self.setWindowTitle(self.windowTitle)
        self.center()

        # set icons
        self.docButton.setIcon(self.helpIcon)
        self.aboutButton.setIcon(self.aboutIcon)

        # set default values
        self.srcCheckBox.setChecked(False)
        self.inputFolderLocation.setText(self.sourceFolder)
        self.fullscreenCheckBox.setChecked(True)
        self.customResolutionCheckBox.setChecked(False)
        self.resolutionHorizontalSpinBox.setValue(self.defaultResolutionHorizontalInteger)
        self.resolutionVerticalSpinBox.setValue(self.defaultResolutionVerticalInteger)

        # set statusbox
        self.statusBox.setReadOnly(True)
        self.statusBox.hide()

        # show/hide default widgets
        self.pythonLabel.hide()
        self.pythonLineEdit.hide()
        self.pythonButton.hide()
        self.resolutionHorizontalLabel.hide()
        self.resolutionHorizontalSpinBox.hide()
        self.resolutionVerticalLabel.hide()
        self.resolutionVerticalSpinBox.hide()

        # set Gui image
        self.image.setPixmap(self.pixmap)

        # set context menu
        self.experimentListWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.experimentListWidget.customContextMenuRequested.connect(self.listItemRightClicked)

        if not self.opensesamerunCommandAuto:
            self.opensesamerunLabel.show()
            self.opensesamerunLineEdit.show()
            self.opensesamerunButton.show()
            self.opensesameNotFoundLabel.show()

        else:
            self.opensesamerunLabel.hide()
            self.opensesamerunLineEdit.hide()
            self.opensesamerunButton.hide()
            self.opensesameNotFoundLabel.hide()

        # Set button actions
        self.inputFolderButton.clicked.connect(self.selectInputFolderLocation)
        self.logFolderButton.clicked.connect(self.selectLogFolderDestination)
        self.startButton.clicked.connect(self.startExperiments)
        self.docButton.clicked.connect(self.showDocWindow)
        self.aboutButton.clicked.connect(self.showAboutWindow)
        self.restoreSettingsButton.clicked.connect(self.selectOpenSettingsFile)
        self.saveSettingsButton.clicked.connect(self.selectSaveSettingsFile)
        self.opensesamerunButton.clicked.connect(self.selectOpensesamerunFile)
        self.pythonButton.clicked.connect(self.selectPythonFile)
        self.createOpenButton.clicked.connect(self.addOpenQuestion)
        self.createMCButton.clicked.connect(self.addMCQuestion)
        self.refreshButton.clicked.connect(self.refreshWidgets)
        self.resetButton.clicked.connect(self.resetButtonClicked)

        # set checkbox actions
        self.srcCheckBox.stateChanged.connect(self.updaterunFromSource)
        self.customResolutionCheckBox.stateChanged.connect(self.updateCustomResolution)

        if verbose:
            self.statusBox.show()
        else:
            pass

        if verbose and not debug:
            # Redirect console output to textbox in UI, printing stdout in black
            # and stderr in red
            sys.stdout = OutLog(self.statusBox, sys.stdout, QtGui.QColor(0,0,0))
            if not hasattr(sys,'frozen'):
                sys.stderr = OutLog(self.statusBox, sys.stderr, QtGui.QColor(255,0,0))
            else:
                sys.stderr = OutLog(self.statusBox, None, QtGui.QColor(255,0,0))
            print("")
        else:
            pass

    def _initWidgets(self):

        # set empty strings, lists and dicts
        self.currentLangString = ''
        self.langList = []
        self.languageComboBoxItemList = []
        self.experimentFileListDict = {}
        self.widgetItemObjectListDict = {}
        self.widgetItemNameListDict = {}

        self.experimentListWidget.clear()
        self.languageComboBox.clear()
        self.refreshWidgets()

    def startExperiments(self):
        """
        Starts the sanity checks and if passed then the execution of experiments.
        """

        if not self.sourceFolder:
            errorMessage = "Please select a source folder containing the experiment files."
            print(errorMessage, file=sys.stderr)
            self.showErrorMessage(errorMessage)
            return
        elif not self.destinationFolder :
            errorMessage = "Please select a log folder."
            print(errorMessage, file=sys.stderr)
            self.showErrorMessage(errorMessage)
        elif not self.subjectLineEdit.text().strip().isdigit():
            errorMessage = "Please enter an integer as subject number."
            print(errorMessage, file=sys.stderr)
            self.showErrorMessage(errorMessage)
            return
        elif not self.srcCheckBox.isChecked() and not self.opensesamerunCommandAuto and not self.opensesamerunCommandManual:
            error_message = "Please specify the path to the opensesamerun executable."
            print(error_message, file=sys.stderr)
            self.showErrorMessage(error_message)
            return
        elif self.srcCheckBox.isChecked() and not self.opensesamerunCommandManual:
            error_message = "Please specify the path to the opensesamerun source file."
            print(error_message, file=sys.stderr)
            self.showErrorMessage(error_message)
            return
        elif self.srcCheckBox.isChecked() and not self.pythonCommandManual:
            error_message = "Please specify the path to the python 2 executable."
            print(error_message, file=sys.stderr)
            self.showErrorMessage(error_message)
            return

        else:

            selectedSubjectNr = self.subjectLineEdit.displayText().strip()

            if self.srcCheckBox.isChecked():
                self.opensesamerunCommand = self.opensesamerunCommandManual
                self.pythonCommand  = self.pythonCommandManual
            else:
                if self.opensesamerunCommandAuto:
                    self.opensesamerunCommand = self.opensesamerunCommandAuto
                    self.pythonCommand = ''
                else:
                    self.opensesamerunCommand = self.opensesamerunCommandManual
                    self.pythonCommand  = ''

            fullscreen = self.fullscreenCheckBox.isChecked()
            customResolution = self.customResolutionCheckBox.isChecked()

            if customResolution:
                resolutionHorizontal = str(self.resolutionHorizontalSpinBox.value())
                resolutionVertical   = str(self.resolutionVerticalSpinBox.value())
            else:
                resolutionHorizontal = None
                resolutionVertical   = None


            [selectedExperimentList, selectedLanguage] = self.getSelectedExperimentData()

            if not selectedExperimentList:
                errorMessage = "No experiments selected, please select at least one experiment."
                print(errorMessage, file=sys.stderr)
                self.showErrorMessage(errorMessage)
                return
            else:
                pass

            logFileExists = None
            logDestinationFilePathList = []
            for experiment in selectedExperimentList:
                strippedExperiment = experiment
                logDestinationFolder = os.path.join(self.destinationFolder, selectedLanguage, strippedExperiment)
                logDestinationFile = 'subject-' + selectedSubjectNr + '.csv'
                logDestinationFilePath = os.path.join(logDestinationFolder, logDestinationFile)
                logDestinationFilePathList.append(logDestinationFilePath)

                try:
                    os.makedirs(logDestinationFolder)
                except OSError as exc: # Python >2.5
                    if exc.errno == errno.EEXIST and os.path.isdir(logDestinationFolder):
                        pass
                    else: raise

                if  os.path.isfile(logDestinationFilePath):
                    logFileExists = True
                else:
                    pass

            if logFileExists:
                overwriteCheck = self.confirmOverwriteEvent()
                if not overwriteCheck:
                    return
                else:
                    pass
            elif not logFileExists:
                overwriteCheck = True
            else:
                overwriteCheck = False
                return

            if overwriteCheck:
                print("Starting Experiment...")
                finishedExperiment = ExperimentManager(self.pythonCommand, self.opensesamerunCommand,
                                                       self.sourceFolder, logDestinationFilePathList,
                                                       selectedSubjectNr, selectedLanguage, selectedExperimentList,
                                                       fullscreen, customResolution,resolutionHorizontal, resolutionVertical)

                if finishedExperiment:
                    print("Output saved to " + self.destinationFolder)
                    print("Ready.")
                    return
                else:
                    errorMessage = "Error: Could not start the experiments! Did you select the correct opensesamerun and Python File?"
                    print(errorMessage, file=sys.stderr)
                    self.showErrorMessage(errorMessage)
                    return
            else:
                errorMessageList = []
                self.showErrorMessage(''.join(errorMessageList))
                return


    def listItemRightClicked(self, QPos):
        """
        Add right click context menu to the ListWidget
        """
        self.listMenu= QtWidgets.QMenu()
        renameItem = self.listMenu.addAction("Rename Questionnaire on disk")
        removeItem = self.listMenu.addAction("Delete Questionnaire from disk")

        if self.experimentListWidget.count() == 0:
            renameItem.setDisabled(True)
            removeItem.setDisabled(True)

        renameItem.triggered.connect(self.renameItemClicked)
        removeItem.triggered.connect(self.removeItemClicked)

        parentPosition = self.experimentListWidget.mapToGlobal(QtCore.QPoint(0, 0))
        self.listMenu.move(parentPosition + QPos)

        self.listMenu.show()

    def renameItemClicked(self):
        """
        Create right click rename method
        """
        if self.experimentListWidget.count() == 0:
            return

        currentWidget       = self.experimentListWidget.currentItem()
        currentItemName     = self.experimentListWidget.currentItem().text()
        currentItemLanguage = self.languageComboBox.currentText()

        fileExistsCheck = True
        go = True
        noChange = False

        while fileExistsCheck and go and not noChange:

            destItemValueTuple = self.renameEvent(currentItemName)
            go = destItemValueTuple[1]
            destItemName = destItemValueTuple[0]

            srcFilePath  = os.path.join(self.sourceFolder, currentItemLanguage, currentItemName)
            destFilePath = os.path.join(self.sourceFolder, currentItemLanguage, destItemName)

            if srcFilePath ==  destFilePath:
                noChange = True

            fileExistsCheck = os.path.exists(destFilePath)

            if fileExistsCheck and not noChange and go:
                errorMessage = "A questionnaire with that filename already exists, please select another name"
                self.showErrorMessage(errorMessage)

        if go and not fileExistsCheck:

            try:
                self.renameQuestionnaire(srcFilePath, destFilePath)
            except Exception:
                errorMessage = 'Access denied, cannot rename experiment, do you have the correct permissions?'
                self.showErrorMessage(errorMessage)
                return

            currentWidget.setText(destItemName)

            expindex = self.experimentFileListDict[currentItemLanguage].index(currentItemName)
            self.experimentFileListDict[currentItemLanguage][expindex] = destItemName

            nameindex = self.widgetItemNameListDict[currentItemLanguage].index(currentItemName)
            self.widgetItemNameListDict[currentItemLanguage][nameindex] = destItemName

    def removeItemClicked(self):
        """
        Create right click remove item method
        """
        if self.experimentListWidget.count() == 0:
            return

        currentWidget = self.experimentListWidget.currentItem()
        currentItemName = currentWidget.text()
        currentItemLanguage = self.languageComboBox.currentText()

        if self.confirmDeleteEvent():

            try:
                self.removeQuestionnaire(currentItemName, currentItemLanguage)
            except Exception:
                errorMessage = 'Access denied, cannot delete experiment, do you have the correct permissions?'
                self.showErrorMessage(errorMessage)
                return

            widgetIndex = self.experimentListWidget.row(currentWidget)
            self.experimentListWidget.takeItem(widgetIndex)

            self.experimentFileListDict[currentItemLanguage].remove(currentItemName)
            self.widgetItemObjectListDict[currentItemLanguage].remove(currentWidget)
            self.widgetItemNameListDict[currentItemLanguage].remove(currentItemName)

    def renameQuestionnaire(self,srcFilePath,destFilePath):
        """
        Rename item on disk
        """
        if  os.path.isfile(srcFilePath) and not os.path.exists(destFilePath):
            os.rename(srcFilePath, destFilePath)

    def removeQuestionnaire(self,fileName,lang):
        """
        Remove item from disk
        """
        filePath = os.path.join(self.sourceFolder, lang, fileName)
        if  os.path.isfile(filePath):
            os.remove(filePath)

    def isWritable(self, path):
        """
        Check if path is writable by creating a temp file
        """
        try:
            testfile = tempfile.TemporaryFile(dir = path)
            testfile.close()
            return True
        except Exception:
            return False

    def resetButtonClicked(self):
        """
        Reset the listwidget to initial state
        """
        answer = self.confirmResetEvent()
        if answer:
            self._initWidgets()
        else:
            pass

    def renameEvent(self,original):
        """
        Confirm box renaming item on disk
        """
        reply = QtWidgets.QInputDialog.getText(self, "Please enter the new name.", "Filename:", QtWidgets.QLineEdit.Normal, original)
        return reply

    def addMCQuestion(self):
        """
        Start the MC questionnaire creator with write check
        """
        if self.isWritable(self.sourceFolder):
            self.mc = QuestionnaireCreatorUI(self.languageComboBox.currentText(),self.langList,self.sourceFolder,'mc')
            reply = self.mc.exec_()

            if reply:
                [widgetItemName, lang] = self.mc.getValues()
                self.processQuestion(widgetItemName, lang)
            else:
                pass

        else:
            errorMessage = 'Access denied, cannot write in questionnaire folder, please change questionnaire folder.'
            self.showErrorMessage(errorMessage)

    def addOpenQuestion(self):
        """
        Start the open questionnaire creator with write check
        """
        if self.isWritable(self.sourceFolder):
            self.open = QuestionnaireCreatorUI(self.languageComboBox.currentText(),self.langList,self.sourceFolder,'open')
            reply = self.open.exec_()

            if reply:
                [widgetItemName, lang] = self.open.getValues()
                self.processQuestion(widgetItemName, lang)
            else:
                pass
        else:
            errorMessage = 'Access denied, cannot write in questionnaire folder, please change questionnaire folder.'
            self.showErrorMessage(errorMessage)

    def processQuestion(self,widgetItemName, lang):
        """
        Add the questionnaire to the dicts and widgets
        """
        listWidgetItem = self.createListWidgetItem(widgetItemName)

        if lang not in self.widgetItemNameListDict:
            self.widgetItemNameListDict[lang] = []
        if lang not in self.widgetItemObjectListDict:
            self.widgetItemObjectListDict[lang] = []
        if lang not in self.experimentFileListDict:
            self.experimentFileListDict[lang] = []
        else:
            pass

        self.widgetItemNameListDict[lang].append(widgetItemName)
        self.widgetItemObjectListDict[lang].append(listWidgetItem)
        self.experimentFileListDict[lang].append(widgetItemName)

        if lang == self.languageComboBox.currentText():
            self.experimentListWidget.addItem(listWidgetItem)
        else:
            pass

    def startRestoreSettings(self, settingsFilePath):
        """
        Restore settings from ini file
        """
        if os.path.isfile(settingsFilePath):
            self.settingsRestore = QtCore.QSettings(settingsFilePath, QtCore.QSettings.IniFormat)
            self.refreshWidgets()
            self.restoreSettings()
        else:
            errorMessage = "File not found, nothing to restore."
            print(errorMessage, file=sys.stderr)
            self.showErrorMessage(errorMessage)

    def startSaveSettings(self, settingsFilePath):
        """
        Save settings to ini file
        """
        self.settingsSave = QtCore.QSettings(settingsFilePath, QtCore.QSettings.IniFormat)
        self.saveSettings()

    def selectSaveSettingsFile(self):
        """
        Save settings file dialog
        """
        selectedSettingsDest = QtWidgets.QFileDialog.getSaveFileName(self,"Save output as..", self.defaultName, self.extFilterSettings)
        # Prevent erasing previous entry on cancel press
        if selectedSettingsDest[0]:
            self.startSaveSettings(selectedSettingsDest[0])

    def selectOpenSettingsFile(self):
        """
        Open settings file dialog
        """
        selectedSettingsLocation = QtWidgets.QFileDialog.getOpenFileName(self,"Open File..", self.defaultName, self.extFilterSettings)
        # Prevent erasing previous entry on cancel press
        if selectedSettingsLocation[0]:
            self.startRestoreSettings(selectedSettingsLocation[0])

    def selectOpensesamerunFile(self):
        """
        Set file to write output to
        """
        selectedOpensesamerunLocation = QtWidgets.QFileDialog.getOpenFileName(self,"Open File..", self.homeFolder, self.extFilterAll)
        # Prevent erasing previous entry on cancel press
        if selectedOpensesamerunLocation[0]:
            self.opensesamerunCommandManual = selectedOpensesamerunLocation[0]
            self.opensesamerunLineEdit.setText(os.path.normpath(self.opensesamerunCommandManual))

    def selectPythonFile(self):
        """
        Set file to write output to
        """
        selectedPythonLocation = QtWidgets.QFileDialog.getOpenFileName(self,"Open File..", self.homeFolder, self.extFilterAll)
        # Prevent erasing previous entry on cancel press
        if selectedPythonLocation[0]:
            self.pythonCommandManual = selectedPythonLocation[0]
            self.pythonLineEdit.setText(os.path.normpath(self.pythonCommandManual))

    def selectInputFolderLocation(self):
        """
        Select folder to read csv files from
        """
        selectedFolder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select Directory", directory=self.inputFolderLocation.text())
        # Prevent erasing previous entry on cancel press
        if selectedFolder:
            self.sourceFolder = selectedFolder
            self.inputFolderLocation.setText(os.path.normpath(self.sourceFolder))
            self._initWidgets()

    def selectLogFolderDestination(self):
        """
        Set file to write output to
        """
        selectedDest = QtWidgets.QFileDialog.getExistingDirectory(self, "Select Directory", directory=self.logFolderDestination.text())
        # Prevent erasing previous entry on cancel press
        if selectedDest:
            self.destinationFolder = selectedDest
            self.logFolderDestination.setText(os.path.normpath(self.destinationFolder))

    def refreshWidgets(self):
        """
        Refresh widgets
        """
        try: self.languageComboBox.currentIndexChanged.disconnect(self.updateListWidget)
        except Exception: pass

        self.emptyListWidget()
        self.updateDirs()
        self.updateListWidgetItems()
        self.updateComboBoxItems()
        self.fillListWidget()

        self.languageComboBox.currentIndexChanged.connect(self.updateListWidget)

    def updateDirs(self):
        """
        Process and update directories
        """
        langList = list(self.langList)

        for item in sorted(os.listdir(self.sourceFolder)):
            languageDir = os.path.join(self.sourceFolder, item)
            if os.path.isfile(languageDir):
                pass
            else:
                if item not in langList:
                    self.langList.append(item)
                    self.experimentFileListDict[item] = []
                else:
                    pass

                expFileList = []
                for extension in self.extensionList:
                    expFileList.extend(glob.glob(languageDir + self.fs + '*' + extension))

                expFileList = sorted(expFileList)

                for expFilePath in expFileList:
                    expFile = os.path.basename(expFilePath)
                    if os.path.isfile(expFilePath):
                        if expFile not in self.experimentFileListDict[item]:
                            self.experimentFileListDict[item].append(expFile)
                        else:
                            pass
                    else:
                        pass

        for lang in langList:
            languageDir = os.path.join(self.sourceFolder, lang)

            if not os.path.isdir(languageDir):
                self.langList.remove(lang)
                del self.experimentFileListDict[lang]
            else:
                for expFile in self.experimentFileListDict[lang]:
                    filePath = os.path.join(languageDir, expFile)
                    if not os.path.isfile(filePath):
                        self.experimentFileListDict[lang].remove(expFile)
                    else:
                        pass

    def updateComboBoxItems(self):
        """
        Process and update the languageComboBox
        """
        comboBoxItemList = list(self.languageComboBoxItemList)

        for lang in self.langList:
            if lang not in comboBoxItemList:
                self.languageComboBox.addItem(lang)
                self.languageComboBoxItemList.append(lang)
            else:
                pass

        for lang in comboBoxItemList:
            if lang not in self.langList:

                if self.languageComboBox.currentText() == lang:
                    index1 = self.languageComboBox.findText(self.langList[0],QtCore.Qt.MatchExactly)
                    self.languageComboBox.setCurrentIndex(index1)
                else:
                    pass

                self.languageComboBoxItemList.remove(lang)
                index = self.languageComboBox.findText(lang,QtCore.Qt.MatchExactly)
                self.languageComboBox.removeItem(index)
            else:
                pass

    def updateListWidgetItems(self):
        """
        Process and update the ListWidget items
        """
        widgetItemNameListDictKeys =  list(self.widgetItemNameListDict)

        for lang in self.langList:
            expnameList = self.experimentFileListDict[lang]
            if lang not in widgetItemNameListDictKeys:
                self.widgetItemNameListDict[lang] = []
                self.widgetItemObjectListDict[lang] = []

            else:
                pass

            for index in range(len(expnameList)):
                widgetItemName = expnameList[index]
                if widgetItemName not in self.widgetItemNameListDict[lang]:
                    listWidgetItem = self.createListWidgetItem(widgetItemName)
                    self.widgetItemNameListDict[lang].append(widgetItemName)
                    self.widgetItemObjectListDict[lang].append(listWidgetItem)
                else:
                    pass

        for lang in widgetItemNameListDictKeys:

            if lang not in self.langList:
                del self.widgetItemNameListDict[lang]
                del self.widgetItemObjectListDict[lang]

            else:
                for widgetItemName in self.widgetItemNameListDict[lang]:
                    if widgetItemName not in self.experimentFileListDict[lang]:
                        widgetIndex = self.widgetItemNameListDict[lang].index(widgetItemName)
                        del self.widgetItemObjectListDict[lang][widgetIndex]
                        del self.widgetItemNameListDict[lang][widgetIndex]
                    else:
                        pass

    def createListWidgetItem(self, widgetItem):
        """
        Create a ListWidget item
        """
        listWidgetItem = QtWidgets.QListWidgetItem(widgetItem)
        listWidgetItem.setCheckState(QtCore.Qt.Checked)
        listWidgetItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsDragEnabled)

        return listWidgetItem

    def updateListWidget(self):
        """
        Update the ListWidget
        """
        self.emptyListWidget()
        self.fillListWidget()

    def emptyListWidget(self):
        """
        Empty the ListWidget
        """
        nrListWidgetItems = self.experimentListWidget.count()
        if not self.currentLangString == '' or not nrListWidgetItems  == 0:
            lang = self.currentLangString

            widgetList = list(self.widgetItemObjectListDict[lang])
            widgetNameList = list(self.widgetItemNameListDict[lang])


            self.widgetItemNameListDict[lang] = []
            self.widgetItemObjectListDict[lang] = []

            for index in range(nrListWidgetItems):
                listWidgetItem = self.experimentListWidget.takeItem(0)
                widgetIndex = widgetList.index(listWidgetItem)

                self.widgetItemNameListDict[lang].append(widgetNameList[widgetIndex])
                self.widgetItemObjectListDict[lang].append(listWidgetItem)

    def fillListWidget(self):
        """
        Fill the ListWidget
        """
        lang = self.languageComboBox.currentText()
        if not lang == '':
            listWidgetItemList = list(self.widgetItemObjectListDict[lang])

            for row in range(len(listWidgetItemList)):
                self.experimentListWidget.insertItem(row,listWidgetItemList[row])
                #self.experimentListWidget.item(row).setCheckState(QtCore.Qt.Checked)

        self.currentLangString = self.languageComboBox.currentText()

    def getSelectedExperimentData(self):
        """
        Get the language and experiment list from the widgets
        """
        selectedExperimentList = []
        selectedLanguage = self.languageComboBox.currentText()

        nWidgets = self.experimentListWidget.count()
        for index in range(nWidgets):
            listWidgetItem = self.experimentListWidget.item(index)
            if listWidgetItem.checkState() == 2:
                selectedExperimentList.append(listWidgetItem.text())

        return [selectedExperimentList, selectedLanguage]

    def updaterunFromSource(self):
        """
        Get the language and experiment list from the widgets
        """
        if self.srcCheckBox.isChecked():
            self.pythonLabel.show()
            self.pythonLineEdit.show()
            self.pythonButton.show()
            self.opensesamerunLabel.show()
            self.opensesamerunLineEdit.show()
            self.opensesamerunButton.show()
        else:
            self.pythonLabel.hide()
            self.pythonLineEdit.hide()
            self.pythonButton.hide()
            if not self.opensesamerunCommandAuto:
                self.opensesamerunLabel.show()
                self.opensesamerunLineEdit.show()
                self.opensesamerunButton.show()
            else:
                self.opensesamerunLabel.hide()
                self.opensesamerunLineEdit.hide()
                self.opensesamerunButton.hide()

    def updateCustomResolution(self):
        """
        Get the language and experiment list from the widgets
        """
        if self.customResolutionCheckBox.isChecked():
            self.resolutionHorizontalLabel.show()
            self.resolutionHorizontalSpinBox.show()
            self.resolutionVerticalLabel.show()
            self.resolutionVerticalSpinBox.show()
        else:
            self.resolutionHorizontalLabel.hide()
            self.resolutionHorizontalSpinBox.hide()
            self.resolutionVerticalLabel.hide()
            self.resolutionVerticalSpinBox.hide()

    def saveSettings(self):
        """
        Save GUI values to ini file
        """
        [selectedExperimentList, selectedLanguage] = self.getSelectedExperimentData()

        self.settingsSave.setValue('srcCheckBox', self.srcCheckBox.isChecked())
        self.settingsSave.setValue('customResolutionCheckBox', self.customResolutionCheckBox.isChecked())
        self.settingsSave.setValue('fullscreenCheckBox', self.fullscreenCheckBox.isChecked())
        self.settingsSave.setValue('sourceFolder', self.sourceFolder)
        self.settingsSave.setValue('destinationFolder', self.destinationFolder)
        self.settingsSave.setValue('pythonCommandManual', self.pythonCommandManual)
        self.settingsSave.setValue('opensesamerunCommandManual', self.opensesamerunCommandManual)
        self.settingsSave.setValue('resolutionHorizontalSpinBox', self.resolutionHorizontalSpinBox.value())
        self.settingsSave.setValue('resolutionVerticalSpinBox', self.resolutionVerticalSpinBox.value())
        self.settingsSave.setValue('languageComboBox', selectedLanguage)
        self.settingsSave.setValue('selectedExperimentList', selectedExperimentList)


    def restoreSettings(self):
        """
        Restore GUI values from ini file
        """

        errorMessageList = []
        errorMessageExperimentList = []

        srcCheckBox = self.settingsRestore.value('srcCheckBox')
        self.srcCheckBox.setChecked(stringToBool(srcCheckBox))

        fullscreenCheckBox = self.settingsRestore.value('fullscreenCheckBox')
        self.fullscreenCheckBox.setChecked(stringToBool(fullscreenCheckBox))

        customResolutionCheckBox = self.settingsRestore.value('customResolutionCheckBox')
        self.customResolutionCheckBox.setChecked(stringToBool(customResolutionCheckBox))

        resolutionHorizontalSpinBox = int(self.settingsRestore.value('resolutionHorizontalSpinBox'))
        self.resolutionHorizontalSpinBox.setValue(resolutionHorizontalSpinBox)

        resolutionVerticalSpinBox = int(self.settingsRestore.value('resolutionVerticalSpinBox'))
        self.resolutionVerticalSpinBox.setValue(resolutionVerticalSpinBox)


        sourceFolder = self.settingsRestore.value('sourceFolder')
        if sourceFolder:
            if os.path.isdir(sourceFolder):
                self.sourceFolder = sourceFolder
                self.inputFolderLocation.setText(os.path.normpath(sourceFolder))
                self._initWidgets()
            else:
                errorMessageList.append('- Experiment folder not found! Using current experiment folder\n')
        else:
            pass


        destinationFolder = self.settingsRestore.value('destinationFolder')
        if destinationFolder:
            if os.path.isdir(destinationFolder):
                self.destinationFolder = destinationFolder
                self.logFolderDestination.setText(os.path.normpath(destinationFolder))
            else:
                errorMessageList.append('- Log folder not found! Using current log folder\n')
        else:
            pass


        pythonCommandManual = self.settingsRestore.value('pythonCommandManual')
        if pythonCommandManual:
            if os.path.isfile(pythonCommandManual):
                self.pythonCommandManual = pythonCommandManual
                self.pythonLineEdit.setText(os.path.normpath(pythonCommandManual))
            else:
                errorMessageList.append('- Python file not found! Using current Python file\n')
        else:
            pass


        opensesamerunCommandManual = self.settingsRestore.value('opensesamerunCommandManual')
        if opensesamerunCommandManual:
            if os.path.isfile(opensesamerunCommandManual):
                self.opensesamerunCommandManual = opensesamerunCommandManual
                self.opensesamerunLineEdit.setText(os.path.normpath(opensesamerunCommandManual))
            else:
                errorMessageList.append('- Opensesamerun File not found! Using current Opensesamerun File\n')
        else:
            pass


        languageComboBox = self.settingsRestore.value('languageComboBox')
        if languageComboBox:
            index = self.languageComboBox.findText(languageComboBox)
            if index == -1:
                errorMessageList.append('- Language not found in current language folder! Cannot restore language and experiments.\n')
                self.showErrorMessage(''.join(errorMessageList))
                return
            else:
                self.languageComboBox.setCurrentIndex(index)
        else:
            errorMessageList.append('- No language present in restore file! Cannot restore language and experiments.\n')
            self.showErrorMessage(''.join(errorMessageList))
            return


        selectedExperimentList = self.settingsRestore.value('selectedExperimentList')
        if selectedExperimentList:
            nWidgets = self.experimentListWidget.count()
            for index in range(nWidgets):
                self.experimentListWidget.item(index).setCheckState(QtCore.Qt.Unchecked)

            counter = 0
            for selectedExperiment in selectedExperimentList:
                try:
                    [listWidgetItem] = self.experimentListWidget.findItems(selectedExperiment,QtCore.Qt.MatchExactly)
                    currentIndex = self.experimentListWidget.row(listWidgetItem)
                    targetWidget = self.experimentListWidget.takeItem(currentIndex)
                    targetWidget.setCheckState(QtCore.Qt.Checked)
                    self.experimentListWidget.insertItem(counter,targetWidget)
                    counter += 1
                except Exception:
                    errorMessageExperimentList.append('- ' + selectedExperiment + ' not found in data, not restoring this item.\n')
        else:
            errorMessageList.append('- No experiments present in restore file! Cannot restore experiments.\n')
            self.showErrorMessage(''.join(errorMessageList))
            return

        if errorMessageList:
            self.showErrorMessage(''.join(errorMessageList))
        else:
            pass

        if errorMessageExperimentList:
            self.showErrorMessage(''.join(errorMessageExperimentList))
        else:
            pass

    def center(self):
        """
        Centers the main app window on the screen
        """
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def confirmDeleteEvent(self):
        """
        Confirm box deleting item from disk
        """
        message = "Are you sure to delete this questionnaire from disk?"

        reply = self.confirmEvent(message)
        return reply

    def confirmResetEvent(self):
        """
        Confirm box deleting item from disk
        """
        message = "Are you sure you want to reset the experiment selection and order?"

        reply = self.confirmEvent(message)
        return reply

    def confirmOverwriteEvent(self):
        """
        Confirm box deleting item from disk
        """
        message =  "Log file(s) already exists, do you want to overwrite the log file(s)?"

        reply = self.confirmEvent(message)
        return reply

    def confirmEvent(self, message):
        """
        Confirm box overwriting (log) files
        """
        reply = QtWidgets.QMessageBox.question(self, 'Message',
            message, QtWidgets.QMessageBox.Yes |
            QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
        if reply == QtWidgets.QMessageBox.Yes:
            reply = True
        else:
            reply = False
        return reply

    def showDocWindow(self):
        """
        Shows documentation window (with help and licensing info)
        """

        title = "Documentation"
        htmlFile = "helpfile.html"

        self.docWindow = QWebView()
        self.docWindow.closeEvent = self.closeDocWindow
        self.docWindow.setWindowTitle(title)
        self.docWindow.setWindowIcon(self.helpIcon)
        self.docWindow.load(QtCore.QUrl.fromLocalFile(getResourceLoc(htmlFile)))
        self.docWindow.show()

    def closeDocWindow(self,source):
        """
        Callback function of the docWindow QWebView item.
        Destroys reference to doc window after its closed
        """
        del(self.docWindow)

    def showAboutWindow(self):
        """
        Shows about window
        """
        about ="About"

        msgBox = QtWidgets.QMessageBox(self)
        msgBox.setWindowIcon(self.aboutIcon)
        msgBox.about(self, about, aboutString)

    def showErrorMessage(self, message):
        """
        Shows error message
        """
        error ="Error"

        msgBox = QtWidgets.QMessageBox(self)
        msgBox.about(self, error, message)

    def closeEvent(self, event):
        """
        Confirm closing the main window
        """
        message = "Are you sure to quit?"

        reply = self.confirmEvent(message)

        if reply:
            event.accept()
        else:
            event.ignore()
class Platform(QWidget):
    def __init__(self):
        super(Platform, self).__init__()
        self._desktop = QApplication.instance().desktop()
        self.__dir = os.path.dirname(os.path.dirname(
            os.path.abspath(__file__)))
        self.__WebContent()
        self.__initPosition()
        self.__connectJs()
        print("启动desk")

    def __WebContent(self):
        self.resize(self._desktop.screenGeometry().width() / 5,
                    self._desktop.availableGeometry().height())
        self.verticalLayout = QtWidgets.QVBoxLayout(self)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.webView = QWebView()
        # BASE_DIR = os.path.dirname(os.path.dirname(__file__))
        # new = os.path.join(BASE_DIR, 'web')
        #
        # new_file_name = os.path.join(new, 'noticeContent.html')
        # fname = 'file:///'+new_file_name
        # print(fname)
        # self.webView.load(QUrl('file:///C:/Users/Administrator/Desktop/app/mainWin/desk/web/desk.html'))
        print('file:///' + self.__dir + '/web/desk.html')
        self.webView.load(QUrl('file:///' + self.__dir + '/web/desk.html'))
        # self.webView.load(QUrl(fname))
        self.verticalLayout.addWidget(self.webView)
        # self.webView.loadFinished.connect(self.test)

    def onClose(self):
        #点击关闭按钮时
        self.isShow = False
        QTimer.singleShot(100, self.closeAnimation)  #启动弹回动画

    def __initPosition(self):
        # 隐藏任务栏|去掉边框|顶层显示
        self.setWindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint
                            | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)

        # 是否在显示标志
        self.isShow = True

        # 桌面
        # self._desktop = QApplication.instance().desktop()
        # 窗口初始开始位置
        self._startPos = QPoint(
            self._desktop.screenGeometry().width(),
            self._desktop.availableGeometry().height() - self.height())
        print(self._startPos)
        # 窗口弹出结束位置
        self._endPos = QPoint(
            self._desktop.screenGeometry().width() - self.width(),
            self._desktop.availableGeometry().height() - self.height())
        print(self._endPos)
        # 初始化位置到右侧
        self.move(self._startPos)

        # 动画
        self.animation = QPropertyAnimation(self, b"pos")

        self.hide()  # 先隐藏
        super(Platform, self).show()

    def __connectJs(self):

        connector = ConnectJs(self)
        self.webView.page().mainFrame().javaScriptWindowObjectCleared.connect(
            lambda: self.webView.page().mainFrame(
            ).addToJavaScriptWindowObject('pyNotice', connector))

    def add(self, content=""):
        if content:
            self.__notice_list.insert(0, content)
            self.webView.page().mainFrame().evaluateJavaScript(
                "pyNoticeAdd(%s)" % str(content))

    def show(self, title="", content=""):
        # 显示动画
        self.isShow = True
        self.animation.setStartValue(self.pos())
        self.animation.setEndValue(self._endPos)
        self.animation.start()

    def closeAnimation(self):

        self.isShow = False
        self.animation.setStartValue(self.pos())
        self.animation.setEndValue(self._startPos)
        self.animation.start()
Beispiel #36
0
class Spdom(WizardWidget):
    drag_label = "Spatial Domain <spdom>"
    acceptable_tags = ['spdom', 'bounding']
    ui_class = UI_spdom.Ui_fgdc_spdom

    def __init__(self, root_widget=None):

        self.east = 180
        self.west = -180
        self.north = 90
        self.south = -90
        self.valid = True

        super(self.__class__, self).__init__()
        self.schema = 'bdp'
        self.root_widget = root_widget

        self.after_load = False
        self.in_xml_load = False
        self.has_rect = True

        self.completer = QCompleter()
        self.ui.fgdc_descgeog.setCompleter(self.completer)

        self.model = QStringListModel()
        self.completer.setModel(self.model)
        self.completer.setCaseSensitivity(0)

        fname = utils.get_resource_path("spatial/BNDCoords.csv")
        self.bnds_df = pd.read_csv(fname)
        self.model.setStringList(self.bnds_df['Name'])

        self.completer.popup().clicked.connect(self.on_completer_activated)
        self.completer.popup().selectionModel().selectionChanged.connect(
            self.on_completer_activated)
        # self.completer.popup().activated.connect(self.on_completer_activated)

    def build_ui(self):
        """
        Build and modify this widget's GUI

        Returns
        -------
        None
        """
        self.ui = self.ui_class()
        self.ui.setupUi(self)

        if platform.system() == 'Darwin':
            map_fname = utils.get_resource_path('leaflet/map_mac.html')
        else:
            map_fname = utils.get_resource_path('leaflet/map.html')

        try:
            self.view = QWebView()
            self.view.page().mainFrame().addToJavaScriptWindowObject(
                "Spdom", self)
            self.view.setUrl(QUrl.fromLocalFile(map_fname))
            self.frame = self.view.page().mainFrame()
            self.view.load(
                QUrl.fromLocalFile(QtCore.QDir.current().filePath(map_fname)))
        except AttributeError:
            self.view = QWebView()
            self.view.load(
                QUrl.fromLocalFile(QtCore.QDir.current().filePath(map_fname)))
            channel = QWebChannel(self.view.page())

            jstr = """
            var spdom;

            new QWebChannel(qt.webChannelTransport, function (channel) {
                spdom = channel.objects.spdom;
            });"""

            self.view.page().setWebChannel(channel)
            self.evaluate_js(jstr)
            channel.registerObject("spdom", self)

        self.ui.verticalLayout_3.addWidget(self.view)

        # setup drag-drop functionality for this widget and all it's children.
        self.setup_dragdrop(self)
        self.add_rect()
        self.raise_()

    def connect_events(self):
        self.ui.fgdc_eastbc.editingFinished.connect(self.coord_updated)
        self.ui.fgdc_westbc.editingFinished.connect(self.coord_updated)
        self.ui.fgdc_northbc.editingFinished.connect(self.coord_updated)
        self.ui.fgdc_southbc.editingFinished.connect(self.coord_updated)

    def on_completer_activated(self, model_index):

        try:
            cur_descgeog = model_index.data()
        except AttributeError:
            try:
                cur_descgeog = model_index.indexes()[0].data()
            except:
                return

        try:
            if self.bnds_df['Name'].str.contains(cur_descgeog).any():
                self.ui.fgdc_eastbc.setText(
                    str(
                        float(self.bnds_df[self.bnds_df['Name'] ==
                                           cur_descgeog]['east'])))
                self.ui.fgdc_westbc.setText(
                    str(
                        float(self.bnds_df[self.bnds_df['Name'] ==
                                           cur_descgeog]['west'])))
                self.ui.fgdc_northbc.setText(
                    str(
                        float(self.bnds_df[self.bnds_df['Name'] ==
                                           cur_descgeog]['north'])))
                self.ui.fgdc_southbc.setText(
                    str(
                        float(self.bnds_df[self.bnds_df['Name'] ==
                                           cur_descgeog]['south'])))
                self.add_rect()
                self.update_map()
        except:
            pass
            # this is a convenience function.
            # If anything at all happens pass silently

    def complete_name(self):
        self.view.page().runJavaScript('addRect();', js_callback)

    def coord_updated(self):

        good_coords = self.all_good_coords()

        try:
            cur_name = self.sender().objectName()
            if 'fgdc' not in cur_name:
                return
            cur_value = self.sender().text()
        except AttributeError:
            cur_name = ''
            cur_value = ''

        try:
            cur_value = float(cur_value)
        except ValueError:
            pass

        msg = ''
        if type(cur_value) != float and cur_value != '':
            msg = 'number entered must be numeric only'
        elif cur_value == '':
            msg = ''
        elif cur_name in ['fgdc_westbc', 'fgdc_eastbc'] \
                and -180 >= cur_value >= 180:
            msg = 'East or West coordinate must be within -180 and 180'
        elif cur_name in ['fgdc_southbc', 'fgdc_northbc'] \
                and -90 >= cur_value >= 90:
            msg = 'North and South coordinates must be within -90 and 90'
        elif cur_name == 'fgdc_southbc':
            try:
                north = float(self.ui.fgdc_northbc.text())
                if north <= cur_value:
                    msg = 'North coordinate must be greater than South coordinate'
            except ValueError:
                pass
        elif cur_name == 'fgdc_northbc':
            try:
                south = float(self.ui.fgdc_southbc.text())
                if south >= cur_value:
                    msg = 'North coordinate must be greater than South coordinate'
            except ValueError:
                pass

        if msg:
            QMessageBox.warning(self, "Problem bounding coordinates", msg)

        if good_coords:
            self.add_rect()
        else:
            self.remove_rect()
            return

        self.update_map()

    def update_map(self):
        jstr = """east = {eastbc};
        west = {westbc};
        south = {southbc};
        north = {northbc};
        updateMap();
        fitMap();
        """.format(
            **{
                'eastbc': self.ui.fgdc_eastbc.text(),
                'westbc': self.ui.fgdc_westbc.text(),
                'northbc': self.ui.fgdc_northbc.text(),
                'southbc': self.ui.fgdc_southbc.text(),
            })
        self.evaluate_js(jstr)

    def add_rect(self):
        jstr = """addRect();"""
        self.evaluate_js(jstr)

    def remove_rect(self):
        if self.has_rect:
            self.has_rect = False
            jstr = """removeRect()"""
            self.evaluate_js(jstr)

    def evaluate_js(self, jstr):
        """

        :param jstr:
        :return:
        """
        try:
            self.frame.evaluateJavaScript(jstr)
        except:
            self.view.page().runJavaScript(jstr, js_callback)

    @pyqtSlot(float, float)
    def on_ne_move(self, lat, lng):
        if self.in_xml_load:
            n, e = lat, lng
            s = float(self.ui.fgdc_southbc.text())
            w = float(self.ui.fgdc_westbc.text())
            bounds = spatial_utils.format_bounding((w, e, n, s))

            self.ui.fgdc_eastbc.setText(bounds[1])
            self.ui.fgdc_northbc.setText(bounds[2])

    @pyqtSlot(float, float)
    def on_nw_move(self, lat, lng):
        if self.in_xml_load:
            n, w = lat, lng
            s = float(self.ui.fgdc_southbc.text())
            e = float(self.ui.fgdc_eastbc.text())
            bounds = spatial_utils.format_bounding((w, e, n, s))

            self.ui.fgdc_westbc.setText(bounds[0])
            self.ui.fgdc_northbc.setText(bounds[2])

    @pyqtSlot(float, float)
    def on_se_move(self, lat, lng):
        if self.in_xml_load:
            s, e = lat, lng
            n = float(self.ui.fgdc_northbc.text())
            w = float(self.ui.fgdc_westbc.text())
            bounds = spatial_utils.format_bounding((w, e, n, s))

            self.ui.fgdc_eastbc.setText(bounds[1])
            self.ui.fgdc_southbc.setText(bounds[3])

    @pyqtSlot(float, float)
    def on_sw_move(self, lat, lng):
        if self.in_xml_load:
            s, w = lat, lng
            n = float(self.ui.fgdc_northbc.text())
            e = float(self.ui.fgdc_eastbc.text())
            bounds = spatial_utils.format_bounding((w, e, n, s))

            self.ui.fgdc_westbc.setText(bounds[0])
            self.ui.fgdc_southbc.setText(bounds[3])

    def switch_schema(self, schema):
        self.schema = schema
        if schema == 'bdp':
            self.ui.fgdc_descgeog.show()
            self.ui.descgeog_label.show()
            self.ui.descgeog_star.show()
        else:
            self.ui.fgdc_descgeog.hide()
            self.ui.descgeog_label.hide()
            self.ui.descgeog_star.hide()

    def all_good_coords(self):
        try:
            if -180 > float(self.ui.fgdc_westbc.text()) > 180:
                return False
            if -180 > float(self.ui.fgdc_eastbc.text()) > 180:
                return False
            if -90 > float(self.ui.fgdc_southbc.text()) > 90:
                return False
            if -90 > float(self.ui.fgdc_northbc.text()) > 90:
                return False
            if float(self.ui.fgdc_northbc.text()) <= float(
                    self.ui.fgdc_southbc.text()):
                return False
            return True
        except:
            return False

    def clear_widget(self):
        super(self.__class__, self).clear_widget()

        # self.view.page().mainFrame().addToJavaScriptWindowObject("Spdom", self)
        # map_fname = utils.get_resource_path('leaflet/map.html')
        # self.view.setUrl(QUrl.fromLocalFile(map_fname))

    def showEvent(self, e):
        if not self.after_load:
            self.add_rect()
            self.update_map()
            jstr = "sw_marker.openPopup();"
            self.evaluate_js(jstr)
            self.after_load = True

    def to_xml(self):
        spdom = xml_node('spdom')

        if self.schema == 'bdp':
            descgeog = xml_node('descgeog',
                                text=self.ui.fgdc_descgeog.text(),
                                parent_node=spdom)

        bounding = xml_node('bounding', parent_node=spdom)
        westbc = xml_node('westbc',
                          text=self.ui.fgdc_westbc.text(),
                          parent_node=bounding)
        eastbc = xml_node('eastbc',
                          text=self.ui.fgdc_eastbc.text(),
                          parent_node=bounding)
        northbc = xml_node('northbc',
                           text=self.ui.fgdc_northbc.text(),
                           parent_node=bounding)
        southbc = xml_node('southbc',
                           text=self.ui.fgdc_southbc.text(),
                           parent_node=bounding)

        if self.original_xml is not None:
            boundalt = xml_utils.search_xpath(self.original_xml,
                                              'bounding/boundalt')
            if boundalt is not None:
                spdom.append(deepcopy(boundalt))

            dsgpoly_list = xml_utils.search_xpath(self.original_xml,
                                                  'dsgpoly',
                                                  only_first=False)
            for dsgpoly in dsgpoly_list:
                spdom.append(deepcopy(dsgpoly))

        return spdom

    def from_xml(self, spdom):
        self.in_xml_load = False
        self.original_xml = spdom
        self.clear_widget()
        utils.populate_widget(self, spdom)

        contents = xml_utils.node_to_dict(spdom, add_fgdc=False)
        if 'bounding' in contents:
            contents = contents['bounding']

        try:
            if self.all_good_coords():
                self.add_rect()
                self.update_map()
            else:
                self.remove_rect()
        except KeyError:
            self.remove_rect()
        self.in_xml_load = True
Beispiel #37
0
class HostWindow(QMainWindow):
    # signals
    SIGTERM = pyqtSignal()
    SIGUSR1 = pyqtSignal()

    # --------------------------------------------------------------------------------------------------------

    def __init__(self):
        QMainWindow.__init__(self)
        gCarla.gui = self

        URI = sys.argv[1]

        # ----------------------------------------------------------------------------------------------------
        # Internal stuff

        self.fCurrentFrame = None
        self.fDocElemement = None
        self.fCanSetValues = False
        self.fNeedsShow    = False
        self.fSizeSetup    = False
        self.fQuitReceived = False
        self.fWasRepainted = False

        self.fPlugin      = get_plugin_info(URI)
        self.fPorts       = self.fPlugin['ports']
        self.fPortSymbols = {}
        self.fPortValues  = {}

        for port in self.fPorts['control']['input'] + self.fPorts['control']['output']:
            self.fPortSymbols[port['index']] = port['symbol']
            self.fPortValues [port['index']] = port['ranges']['default']

        # ----------------------------------------------------------------------------------------------------
        # Init pipe

        if len(sys.argv) == 7:
            self.fPipeClient = gCarla.utils.pipe_client_new(lambda s,msg: self.msgCallback(msg))
        else:
            self.fPipeClient = None

        # ----------------------------------------------------------------------------------------------------
        # Init Web server

        self.fWebServerThread = WebServerThread(self)
        self.fWebServerThread.start()

        # ----------------------------------------------------------------------------------------------------
        # Set up GUI

        self.setContentsMargins(0, 0, 0, 0)

        self.fWebview = QWebView(self)
        #self.fWebview.setAttribute(Qt.WA_OpaquePaintEvent, False)
        #self.fWebview.setAttribute(Qt.WA_TranslucentBackground, True)
        self.setCentralWidget(self.fWebview)

        page = self.fWebview.page()
        page.setViewportSize(QSize(980, 600))

        mainFrame = page.mainFrame()
        mainFrame.setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
        mainFrame.setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)

        palette = self.fWebview.palette()
        palette.setBrush(QPalette.Base, palette.brush(QPalette.Window))
        page.setPalette(palette)
        self.fWebview.setPalette(palette)

        settings = self.fWebview.settings()
        settings.setAttribute(QWebSettings.DeveloperExtrasEnabled, True)

        self.fWebview.loadFinished.connect(self.slot_webviewLoadFinished)

        url = "http://127.0.0.1:%s/icon.html#%s" % (PORT, URI)
        print("url:", url)
        self.fWebview.load(QUrl(url))

        # ----------------------------------------------------------------------------------------------------
        # Connect actions to functions

        self.SIGTERM.connect(self.slot_handleSIGTERM)

        # ----------------------------------------------------------------------------------------------------
        # Final setup

        self.fIdleTimer = self.startTimer(30)

        if self.fPipeClient is None:
            # testing, show UI only
            self.setWindowTitle("TestUI")
            self.fNeedsShow = True

    # --------------------------------------------------------------------------------------------------------

    def closeExternalUI(self):
        self.fWebServerThread.stopWait()

        if self.fPipeClient is None:
            return

        if not self.fQuitReceived:
            self.send(["exiting"])

        gCarla.utils.pipe_client_destroy(self.fPipeClient)
        self.fPipeClient = None

    def idleStuff(self):
        if self.fPipeClient is not None:
            gCarla.utils.pipe_client_idle(self.fPipeClient)
            self.checkForRepaintChanges()

        if self.fSizeSetup:
            return
        if self.fDocElemement is None or self.fDocElemement.isNull():
            return

        pedal = self.fDocElemement.findFirst(".mod-pedal")

        if pedal.isNull():
            return

        size = pedal.geometry().size()

        if size.width() <= 10 or size.height() <= 10:
            return

        # render web frame to image
        image = QImage(self.fWebview.page().viewportSize(), QImage.Format_ARGB32_Premultiplied)
        image.fill(Qt.transparent)

        painter = QPainter(image)
        self.fCurrentFrame.render(painter)
        painter.end()

        #image.save("/tmp/test.png")

        # get coordinates and size from image
        #x = -1
        #y = -1
        #lastx = -1
        #lasty = -1
        #bgcol = self.fHostColor.rgba()

        #for h in range(0, image.height()):
            #hasNonTransPixels = False

            #for w in range(0, image.width()):
                #if image.pixel(w, h) not in (0, bgcol): # 0xff070707):
                    #hasNonTransPixels = True
                    #if x == -1 or x > w:
                        #x = w
                    #lastx = max(lastx, w)

            #if hasNonTransPixels:
                ##if y == -1:
                    ##y = h
                #lasty = h

        # set size and position accordingly
        #if -1 not in (x, lastx, lasty):
            #self.setFixedSize(lastx-x, lasty)
            #self.fCurrentFrame.setScrollPosition(QPoint(x, 0))
        #else:

        # TODO that^ needs work
        if True:
            self.setFixedSize(size)

        # set initial values
        self.fCurrentFrame.evaluateJavaScript("icongui.setPortValue(':bypass', 0, null)")

        for index in self.fPortValues.keys():
            symbol = self.fPortSymbols[index]
            value  = self.fPortValues[index]
            self.fCurrentFrame.evaluateJavaScript("icongui.setPortValue('%s', %f, null)" % (symbol, value))

        # final setup
        self.fCanSetValues = True
        self.fSizeSetup    = True
        self.fDocElemement = None

        if self.fNeedsShow:
            self.show()

    def checkForRepaintChanges(self):
        if not self.fWasRepainted:
            return

        self.fWasRepainted = False

        if not self.fCanSetValues:
            return

        for index in self.fPortValues.keys():
            symbol   = self.fPortSymbols[index]
            oldValue = self.fPortValues[index]
            newValue = self.fCurrentFrame.evaluateJavaScript("icongui.getPortValue('%s')" % (symbol,))

            if oldValue != newValue:
                self.fPortValues[index] = newValue
                self.send(["control", index, newValue])

    # --------------------------------------------------------------------------------------------------------

    @pyqtSlot(bool)
    def slot_webviewLoadFinished(self, ok):
        page = self.fWebview.page()
        page.repaintRequested.connect(self.slot_repaintRequested)

        self.fCurrentFrame = page.currentFrame()
        self.fDocElemement = self.fCurrentFrame.documentElement()

    def slot_repaintRequested(self):
        if self.fCanSetValues:
            self.fWasRepainted = True

    # --------------------------------------------------------------------------------------------------------
    # Callback

    def msgCallback(self, msg):
        msg = charPtrToString(msg)

        if msg == "control":
            index = int(self.readlineblock())
            value = float(self.readlineblock())
            self.dspParameterChanged(index, value)

        elif msg == "program":
            index = int(self.readlineblock())
            self.dspProgramChanged(index)

        elif msg == "midiprogram":
            bank    = int(self.readlineblock())
            program = float(self.readlineblock())
            self.dspMidiProgramChanged(bank, program)

        elif msg == "configure":
            key   = self.readlineblock()
            value = self.readlineblock()
            self.dspStateChanged(key, value)

        elif msg == "note":
            onOff    = bool(self.readlineblock() == "true")
            channel  = int(self.readlineblock())
            note     = int(self.readlineblock())
            velocity = int(self.readlineblock())
            self.dspNoteReceived(onOff, channel, note, velocity)

        elif msg == "atom":
            index      = int(self.readlineblock())
            size       = int(self.readlineblock())
            base64atom = self.readlineblock()
            # nothing to do yet

        elif msg == "urid":
            urid = int(self.readlineblock())
            uri  = self.readlineblock()
            # nothing to do yet

        elif msg == "uiOptions":
            sampleRate     = float(self.readlineblock())
            useTheme       = bool(self.readlineblock() == "true")
            useThemeColors = bool(self.readlineblock() == "true")
            windowTitle    = self.readlineblock()
            transWindowId  = int(self.readlineblock())
            self.uiTitleChanged(windowTitle)

        elif msg == "show":
            self.uiShow()

        elif msg == "focus":
            self.uiFocus()

        elif msg == "hide":
            self.uiHide()

        elif msg == "quit":
            self.fQuitReceived = True
            self.uiQuit()

        elif msg == "uiTitle":
            uiTitle = self.readlineblock()
            self.uiTitleChanged(uiTitle)

        else:
            print("unknown message: \"" + msg + "\"")

    # --------------------------------------------------------------------------------------------------------

    def dspParameterChanged(self, index, value):
        self.fPortValues[index] = value

        if self.fCurrentFrame is not None and self.fCanSetValues:
            symbol = self.fPortSymbols[index]
            self.fCurrentFrame.evaluateJavaScript("icongui.setPortValue('%s', %f, null)" % (symbol, value))

    def dspProgramChanged(self, index):
        return

    def dspMidiProgramChanged(self, bank, program):
        return

    def dspStateChanged(self, key, value):
        return

    def dspNoteReceived(self, onOff, channel, note, velocity):
        return

    # --------------------------------------------------------------------------------------------------------

    def uiShow(self):
        if self.fSizeSetup:
            self.show()
        else:
            self.fNeedsShow = True

    def uiFocus(self):
        if not self.fSizeSetup:
            return

        self.setWindowState((self.windowState() & ~Qt.WindowMinimized) | Qt.WindowActive)
        self.show()

        self.raise_()
        self.activateWindow()

    def uiHide(self):
        self.hide()

    def uiQuit(self):
        self.closeExternalUI()
        self.close()
        app.quit()

    def uiTitleChanged(self, uiTitle):
        self.setWindowTitle(uiTitle)

    # --------------------------------------------------------------------------------------------------------
    # Qt events

    def closeEvent(self, event):
        self.closeExternalUI()
        QMainWindow.closeEvent(self, event)

        # there might be other qt windows open which will block carla-modgui from quitting
        app.quit()

    def timerEvent(self, event):
        if event.timerId() == self.fIdleTimer:
            self.idleStuff()

        QMainWindow.timerEvent(self, event)

    # --------------------------------------------------------------------------------------------------------

    @pyqtSlot()
    def slot_handleSIGTERM(self):
        print("Got SIGTERM -> Closing now")
        self.close()

    # --------------------------------------------------------------------------------------------------------
    # Internal stuff

    def readlineblock(self):
        if self.fPipeClient is None:
            return ""

        return gCarla.utils.pipe_client_readlineblock(self.fPipeClient, 5000)

    def send(self, lines):
        if self.fPipeClient is None or len(lines) == 0:
            return

        gCarla.utils.pipe_client_lock(self.fPipeClient)

        # this must never fail, we need to unlock at the end
        try:
            for line in lines:
                if line is None:
                    line2 = "(null)"
                elif isinstance(line, str):
                    line2 = line.replace("\n", "\r")
                elif isinstance(line, bool):
                    line2 = "true" if line else "false"
                elif isinstance(line, int):
                    line2 = "%i" % line
                elif isinstance(line, float):
                    line2 = "%.10f" % line
                else:
                    print("unknown data type to send:", type(line))
                    return

                gCarla.utils.pipe_client_write_msg(self.fPipeClient, line2 + "\n")
        except:
            pass

        gCarla.utils.pipe_client_flush_and_unlock(self.fPipeClient)
Beispiel #38
0
#!/usr/bin/python

import os

from PyQt5.QtCore import QUrl
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtWebKitWidgets import QWebView
from PyQt5.QtWidgets import QApplication

app = QApplication(['mockup'])
view = QWebView()
settings = view.settings()
settings.setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
view.load(QUrl.fromLocalFile(os.path.realpath('mockup.html')))
view.show()
app.exec_()
Beispiel #39
0
class DrrrWindow(ShadowsWindow):
    def __init__(self):
        super(DrrrWindow, self).__init__()
        self.setWindowTitle("Drrr Chat Room")
        self.setWindowIcon(QIcon('./img/drrr.ico'))

        # w = WebView()
        # w.show()
        self.getSetting()

        self.WebView = QWebView()
        # self.WebView.load(QUrl("file:///E:/Project/DrrrPC/img/index.html"))
        self.WebView.setZoomFactor(0.8)

        self.WebView.loadStarted.connect(self.loadStarted)
        self.WebView.loadFinished.connect(self.loadFinished)
        self.WebView.loadProgress.connect(self.loading)

        # self.connect(self.WebView, SIGNAL("loadStarted(bool)"), self.loadStarted)
        # self.connect(self.WebView, SIGNAL("loadFinished(bool)"), self.loadFinished)
        # self.connect(self.WebView, SIGNAL("loadProgress(int)"), self.loading)

        self.cookieJar = QNetworkCookieJar()
        self.WebView.page().networkAccessManager().setCookieJar(self.cookieJar)
        # self.WebView.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.WebView.page().linkClicked.connect(self.linkClicked)
        self.WebView.page().contentsChanged.connect(self.contentsChanged)
        # self.WebView.page().networkAccessManager().setHeader(QNetworkRequest.ContentTypeHeader, QVariant("text/html; charset=GBK"))

        self.WebView.page().javaScriptAlert = self._javascript_alert                
        self.WebView.page().javaScriptConsoleMessage = self._javascript_console_message
        self.WebView.page().javaScriptConfirm = self._javascript_confirm
        self.WebView.page().javaScriptPrompt = self._javascript_prompt

        # NetworkAccessManager
        # self.NetworkAccessManager = QNetworkAccessManager()
        # self.WebView.page().setNetworkAccessManager(self.NetworkAccessManager)
        # self.NetworkAccessManager.finished.connect(self.NetworkAccessManagerReplyFinished)        
        # self.NetworkAccessManager.get(QNetworkRequest(QUrl("http://www.baidu.com")))        

        self.old_manager = self.WebView.page().networkAccessManager()
        self.new_manager = NetworkAccessManager(self.old_manager)
        self.WebView.page().setNetworkAccessManager(self.new_manager)

        self.titlebar = titleBar()
        self.statusBar = StatusWindow()

        # 中心窗口布局
        self.contentLayout = QVBoxLayout()
        self.contentWidget = QWidget()
        self.contentWidget.gridLayout = QtWidgets.QGridLayout(self.contentWidget)
        self.contentWidget.gridLayout.addLayout(self.contentLayout, 0, 0, 1, 1)
        self.contentLayout.addWidget(self.WebView)
        self.contentWidget.gridLayout.setContentsMargins(0,0,0,0)
        self.contentLayout.setContentsMargins(1,0,1,0)
        self.contentWidget.setStyleSheet("""
            border-left:    1px solid black;
            border-right:   1px solid black;
            """)

        # self.titlebar.titlebarBotton = QPushButton(self.titlebar)
        # self.titlebar.titlebarBotton.setText('Push ME')
        # self.titlebar.titlebarBotton.clicked.connect(self.getData)

        self.main_layout = QVBoxLayout()
        self.main_layout.addWidget(self.titlebar)
        self.main_layout.addWidget(self.contentWidget)
        self.main_layout.addWidget(self.statusBar)
        self.main_layout.setSpacing(0)

        # 窗口属性
        self.setWindowFlags(Qt.Widget | QtCore.Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground,True)
        
        self.widget = QWidget()
        self.setCentralWidget(self.widget)
        self.widget.setLayout(self.main_layout)
        self.widget.setMouseTracking(True)        
        # self.resize(500,650)
        self.resize(650,650)
        # self.setMaximumHeight(660)
        self.center()

        # 功能性功能开始
        self.titlebar.min_button.clicked.connect(self.hideIt)
        self.titlebar.max_button.clicked.connect(self.MaxAndNormal)
        self.titlebar.close_button.clicked.connect(self.closeIt)

        # notice sound
        # self.player = 

        self.WebView.setHtml(WaitingHTML)
        self.show()
        self.WebView.setStyleSheet("""
            QWebView {
                background-color:black
            }        
            QWebView::QScrollBar:Vertical {
                background-color:black
            }
            """)
        self.WebView.load(QUrl("http://drrr.com/"))

    def center(self,screenNum=0):
        '''多屏居中支持'''
        self.desktop = QApplication.desktop()
        screen = self.desktop.availableGeometry(screenNum)
        size = self.geometry()
        self.normalGeometry2 = QtCore.QRect((screen.width()-size.width())/2+screen.left(),
                         (screen.height()-size.height())/2,
                         size.width(),size.height())
        self.setGeometry((screen.width()-size.width())/2+screen.left(),
                         (screen.height()-size.height())/2,
                         size.width(),size.height())

    def keyPressEvent(self,event):
        # F11全屏切换
        if event.key()==QtCore.Qt.Key_F11:
            self.MaxAndNormal()
        if event.key()==QtCore.Qt.Key_F4:
            self.WebView.page().mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)

    def getData(self):
        # print self.bbb == None
        # print str(self.bbb)
        pass
        
    @QtCore.pyqtSlot(str)
    def play(self,content):
        # ["bubble","userin","userout"]
        print content
        QtMultimedia.QSound.play("./img/"+content+".wav")

    def readyRead(self):
        pass
        # print self.NetworkAccessManager.readAll()

    def NetworkAccessManagerReplyFinished(self,response):
        # NO USE
        # print response.readAll()
        # print response.header(QNetworkRequest.ContentTypeHeader)
        # print response.url()
        # self.bbb = response.readAll()
        response.deleteLater()

    def contentsChanged(self):
        # print 'contentsChanged'
        pass

    def _javascript_alert(self, webframe, message):
        print '_javascript_alert'
        
    def _javascript_console_message(self, message, line, sourceid):
        print "_javascript_console_message"

    def _javascript_confirm(self, webframe, message):
        print "_javascript_confirm"
        return QWebPage.javaScriptConfirm(self.WebView.page(), webframe, message)

    def _javascript_prompt(self, webframe, message, defaultvalue, result):
        print "_javascript_prompt"

    def linkClicked(self,url):
        print url

    def getSetting(self):
        '''获取应用设置'''
        self.settings = QtCore.QSettings("DrrrChatRoom.ini", QtCore.QSettings.IniFormat)

    def loadStarted(self):
        if 'http://drrr.com/' == str(self.WebView.url().toString()):
            frame = self.WebView.page().mainFrame()
            name = frame.findFirstElement("input#form-name.home-name-input")
            username = name.evaluateJavaScript("this.value")
            print username
            language = frame.findFirstElement("#form-language-select")
            language = language.evaluateJavaScript("this.value")
            print language
            frame.evaluateJavaScript("""
                var iconFun = function(){
                    var elementsLI = document.getElementsByTagName('li')
                    var length = document.getElementsByTagName('li').length;
                    for(var i = 0; i < length ; ++i){
                        if(elementsLI[i].getElementsByTagName('div')[0].className.indexOf("active")>=0){
                            var icon = elementsLI[i].getElementsByTagName('input')[0].value;
                        }                    
                    }
                    return icon
                    };                                
                """)
            icon = frame.evaluateJavaScript("""iconFun()""")

            print icon

            if username:self.settings.setValue('username',username)
            if language:self.settings.setValue("language",language)
            if icon:
                # self.settings.setValue("icon",icon)
                pass
            else:
                if self.settings.value('icon', None):
                    icon = self.settings.value('icon',None)
                    frame.findFirstElement('input[value="'+icon+'"]').evaluateJavaScript("this.click()")
           

        if "http://drrr.com/room/?ajax=1" in str(self.WebView.url().toString()):
            # print "quit room"
            pass
        print 'requestedUrl:' + self.WebView.page().mainFrame().requestedUrl().toString()
    
    def loadFinished(self, flag):
        self.statusBar.status.setText(u"Connected")

        # http://drrr.com/
        if 'http://drrr.com/' == str(self.WebView.url().toString()):
            frame = self.WebView.page().mainFrame()
            name = frame.findFirstElement("input#form-name.home-name-input")
            if self.settings.value('username', None):
                name.setAttribute('value',self.settings.value('username', None)) 
            language = frame.findFirstElement("#form-language-select")
            if self.settings.value('language', None):
                language.evaluateJavaScript('''
                    sel = document.getElementById("form-language-select");
                    for(var i = 0, j = sel.options.length; i < j; ++i) {
                        if(sel.options[i].value === "'''+self.settings.value('language', "zh-CN")+'''") {
                           sel.selectedIndex = i;
                           break;
                        }
                    }
                    ''')
                # language.setAttribute('value',self.settings.value('language', None))
            if self.settings.value('icon', None):
                icon = self.settings.value('icon',None)
                frame.findFirstElement('input[value="'+icon+'"]').evaluateJavaScript("this.click()")

        # http://drrr.com/create_room/
        if 'http://drrr.com/room/' in str(self.WebView.url().toString()):
            frame = self.WebView.page().mainFrame()
            frame.addToJavaScriptWindowObject("drrrWindow", self)
            frame.evaluateJavaScript('''
                var volumeFun = function(b){
                    return b
                    }
                ''')
            frame.evaluateJavaScript('''
                var playFun = function(a){
                    this.volume = volumeFun;
                    drrrWindow.play(a);
                    return this
                    };
                ''')
            frame.evaluateJavaScript('''sound.play = playFun''')
                                            
    def loading(self, percent):
        self.statusBar.status.setText("Loading %d%%" % percent)

    def quit(self):
        sys.exit(0)
        # QtCore.QCoreApplication.instance().quit()

    def closeIt(self):
        self.animation = QtCore.QPropertyAnimation(self,"windowOpacity")
        self.animation.finished.connect(QtCore.QCoreApplication.instance().quit)
        self.animation.finished.connect(self.quit)
        self.animation.setDuration(300)
        self.animation.setStartValue(1)
        self.animation.setEndValue(0)
        self.animation.start()

    def hideIt(self):
        self.animation = QtCore.QPropertyAnimation(self,"windowOpacity")
        self.animation.finished.connect(self.showMinimized2)
        self.animation.setDuration(300)
        self.animation.setStartValue(1)
        self.animation.setEndValue(0)
        self.animation.start()
    
    def leaveEvent(self,event):
        self.setCursor(QtCore.Qt.ArrowCursor)

    def keyPressEvent(self,event):
        # F11全屏切换
        if event.key()==QtCore.Qt.Key_F11:
            self.MaxAndNormal2()

    def MaxAndNormal2(self):
        '''全屏与正常大小间切换函数'''
        if self.showNormal3():
            self.showFullScreen3()
            self.titlebar.hide()
            self.statusBar.hide()
        else:
            self.titlebar.show()
            self.statusBar.show()            

    def MaxAndNormal(self):
        '''最大化与正常大小间切换函数'''
        if self.showNormal3():
            self.showFullScreen3()


    def showEvent(self,event):
        self.animation = QtCore.QPropertyAnimation(self,"windowOpacity")
        self.animation.setDuration(300)
        self.animation.setStartValue(0)
        self.animation.setEndValue(1)
        self.animation.start()

    def showNormal2(self):
        self.showNormal()
        self.animationEndFlag = 1 # 动画停止

    def showNormal3(self):
        if self.isFullScreen():
            self.main_layout.setContentsMargins(10,7,10,7)
            self.animation = QtCore.QPropertyAnimation(self,"geometry")
            self.animation.setDuration(180)
            self.animation.setEndValue(self.normalGeometry2)
            self.animation.setStartValue(self.desktop.availableGeometry(self.desktop.screenNumber(self.widget)))
            self.animation.finished.connect(self.showNormal2)
            self.animationEndFlag = 0
            self.animation.start()
            return 0
        return 1

    def showFullScreen2(self):
        self.animationEndFlag = 1 # 动画停止
        self.showFullScreen()

    def showFullScreen3(self):
        if not self.isFullScreen():
            self.main_layout.setContentsMargins(0,0,0,0)
            self.animation = QtCore.QPropertyAnimation(self,"geometry")
            self.animation.setDuration(180)
            self.animation.setStartValue(self.geometry())
            self.animation.setEndValue(self.desktop.availableGeometry(self.desktop.screenNumber(self.widget)))
            self.animation.finished.connect(self.showFullScreen2)
            self.animationEndFlag = 0
            self.animation.start()

    def showMinimized2(self):
        self.setWindowOpacity(1)
        self.showMinimized()
class EbookScramblePreviewDlg(QDialog):
    def __init__(self, ebook, orig, is_scrambled, fmap, parent=None):
        QDialog.__init__(self, parent=parent)

        self.setWindowFlags(Qt.Window)

        self.orig = orig
        self.ebook = ebook
        self.revfmap = {v: k for (k, v) in iteritems(fmap)}

        # create widgets
        lay = QVBoxLayout()
        self.setLayout(lay)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Close)

        self.webview_orig = Webview()
        self.webview_scram = Webview()
        settings = self.webview_orig.settings()
        if hasattr(settings, 'setUserStyleSheetUrl'):
            # QWebView from QtWebKit
            style = 'body {%s}' % CSSBG
            cssurl = 'data:text/css;charset=utf-8;base64,'
            cssurl += as_base64_unicode(style)
            self.webview_orig.settings().setUserStyleSheetUrl(QUrl(cssurl))
            self.webview_scram.settings().setUserStyleSheetUrl(QUrl(cssurl))
        elif hasattr(self.webview_orig, 'setStyleSheet'):
            # QWebEngineView from QtWebEngine
            # setStyleSheet doesn't seem to work at the moment
            self.webview_orig.setStyleSheet('Webview {%s}' % CSSBG)
            self.webview_scram.setStyleSheet('Webview {%s}' % CSSBG)

        dummytext = '<body><p>*** Text content could not be displayed ...</p></body>'
        self.webview_orig.setHtml(dummytext)
        self.webview_scram.setHtml(dummytext)

        self.htmlList_orig = QListWidget()
        self.htmlList_scram = QListWidget()
        self.htmlList_orig.setMinimumWidth(300)
        self.htmlList_scram.setMinimumWidth(300)

        gpbox1 = QGroupBox()
        lay1 = QHBoxLayout()
        gpbox1.setLayout(lay1)
        lay1.addWidget(self.htmlList_orig)

        gpbox3 = QGroupBox()
        lay3 = QHBoxLayout()
        gpbox3.setLayout(lay3)
        lay3.addWidget(self.htmlList_scram)

        gpbox2 = QGroupBox('Original text content:')
        lay2 = QHBoxLayout()
        gpbox2.setLayout(lay2)
        lay2.addWidget(self.webview_orig)

        gpbox4 = QGroupBox('Original text content:')
        lay4 = QHBoxLayout()
        gpbox4.setLayout(lay4)
        lay4.addWidget(self.webview_scram)

        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(gpbox1)
        splitter.addWidget(gpbox2)
        splitter.addWidget(gpbox3)
        splitter.addWidget(gpbox4)

        lay.addWidget(splitter)
        lay.addWidget(buttonBox)

        # create connect signals/slots
        buttonBox.rejected.connect(self.reject)
        self.htmlList_scram.currentRowChanged.connect(
            self.htmlList_currentRowChanged)
        self.htmlList_scram.itemDoubleClicked.connect(
            self.htmlList_itemDoubleClicked)

        self.htmlList_orig.setEnabled(False)
        self.htmlnames_scram = get_textnames(self.ebook)
        self.htmlnames_orig = tuple(
            [self.revfmap.get(an, an) for an in self.htmlnames_scram])

        gpbox1.setTitle('Original HTML files: %s' % len(self.htmlnames_orig))
        gpbox3.setTitle('Original HTML files: %s' % len(self.htmlnames_scram))
        self.htmlList_orig.clear()
        self.htmlList_orig.addItems(self.htmlnames_orig)
        self.htmlList_scram.clear()
        self.htmlList_scram.addItems(self.htmlnames_scram)

        if not self.revfmap:
            gpbox1.setVisible(False)

        msg = '%s Preview: Original' % CAPTION
        if not is_scrambled:
            self.setWindowTitle(msg)
            gpbox1.setVisible(False)
            gpbox2.setVisible(False)
        else:
            self.setWindowTitle(msg + ' vs. Scrambled')
            gpbox3.setTitle('Scrambled HTML files: %s' %
                            len(self.htmlnames_scram))
            gpbox4.setTitle('Scrambled text content:')

        self.htmlList_scram.setCurrentRow(0)

    def htmlList_currentRowChanged(self, row):
        if row < 0: return
        name = self.htmlList_scram.currentItem().text()
        self.htmlList_orig.setCurrentRow(row)
        self.webview_refresh(name)

    def htmlList_itemDoubleClicked(self, item):
        name = item.text()
        self.webview_refresh(name)

    def webview_refresh(self, name):
        name_orig = self.revfmap.get(name, name)

        abspath_orig = self.orig.name_to_abspath(name_orig)
        abspath = self.ebook.name_to_abspath(name)

        if isinstance(self.webview_orig, QTextBrowser):
            self.webview_orig.setSource(QUrl.fromLocalFile(abspath_orig))
            self.webview_scram.setSource(QUrl.fromLocalFile(abspath))
        else:
            self.webview_orig.load(QUrl.fromLocalFile(abspath_orig))
            self.webview_scram.load(QUrl.fromLocalFile(abspath))
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton, QAction
from PyQt5.QtCore import *
from PyQt5.QtWebKitWidgets import QWebView, QWebPage

app = QApplication(sys.argv)

browser = QWebView()
browser.load(QUrl("https://www.google.com"))
browser.show()

app.exec_()
Beispiel #42
0
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKitWidgets import QWebView
from PyQt5.QtCore import QUrl

app = QApplication([])
view = QWebView()
view.load(QUrl("http://weixin.sogou.com"))
view.show()
app.exec_()

# import sys
# from PyQt5.QtWidgets import *
# from PyQt5.QtCore import *
# from PyQt5.QtWebKitWidgets import QWebPage
# from lxml import etree
# from lxml.etree import XPathEvalError
#
# #use QtWebkit to get the final webpage
# app = QApplication([])
#
#
# def create_tree(html):
#     '''
#     :param html:HTML或者XML字符串
#     :return:tree树形结构对象
#     '''
#     try:
#         root = etree.HTML(html)
#     except ValueError:
#         root = etree.XML(html)
#     tree = etree.ElementTree(root)
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtWebKitWidgets import QWebView


def parse_args():
    """Parse commandline arguments."""
    parser = argparse.ArgumentParser()
    parser.add_argument('url', help='The URL to open')
    parser.add_argument('--plugins', '-p', help='Enable plugins',
                        default=False, action='store_true')
    return parser.parse_known_args()[0]


if __name__ == '__main__':
    args = parse_args()
    app = QApplication(sys.argv)
    wv = QWebView()

    wv.loadStarted.connect(lambda: print("Loading started"))
    wv.loadProgress.connect(lambda p: print("Loading progress: {}%".format(p)))
    wv.loadFinished.connect(lambda: print("Loading finished"))

    if args.plugins:
        wv.settings().setAttribute(QWebSettings.PluginsEnabled, True)

    wv.load(QUrl.fromUserInput(args.url))
    wv.show()

    app.exec_()
Beispiel #44
0
class MainWindow(QMainWindow):
    def __init__(self, url):
        super(MainWindow, self).__init__()

        self.progress = 0

        fd = QFile(":/jquery.min.js")

        if fd.open(QIODevice.ReadOnly | QFile.Text):
            self.jQuery = QTextStream(fd).readAll()
            fd.close()
        else:
            self.jQuery = ''

        QNetworkProxyFactory.setUseSystemConfiguration(True)

        self.view = QWebView(self)
        self.view.load(url)
        self.view.loadFinished.connect(self.adjustLocation)
        self.view.titleChanged.connect(self.adjustTitle)
        self.view.loadProgress.connect(self.setProgress)
        self.view.loadFinished.connect(self.finishLoading)

        self.locationEdit = QLineEdit(self)
        self.locationEdit.setSizePolicy(QSizePolicy.Expanding,
                self.locationEdit.sizePolicy().verticalPolicy())
        self.locationEdit.returnPressed.connect(self.changeLocation)

        toolBar = self.addToolBar("Navigation")
        toolBar.addAction(self.view.pageAction(QWebPage.Back))
        toolBar.addAction(self.view.pageAction(QWebPage.Forward))
        toolBar.addAction(self.view.pageAction(QWebPage.Reload))
        toolBar.addAction(self.view.pageAction(QWebPage.Stop))
        toolBar.addWidget(self.locationEdit)

        viewMenu = self.menuBar().addMenu("&View")
        viewSourceAction = QAction("Page Source", self)
        viewSourceAction.triggered.connect(self.viewSource)
        viewMenu.addAction(viewSourceAction)

        effectMenu = self.menuBar().addMenu("&Effect")
        effectMenu.addAction("Highlight all links", self.highlightAllLinks)

        self.rotateAction = QAction(
                self.style().standardIcon(QStyle.SP_FileDialogDetailedView),
                "Turn images upside down", self, checkable=True,
                toggled=self.rotateImages)
        effectMenu.addAction(self.rotateAction)

        toolsMenu = self.menuBar().addMenu("&Tools")
        toolsMenu.addAction("Remove GIF images", self.removeGifImages)
        toolsMenu.addAction("Remove all inline frames",
                self.removeInlineFrames)
        toolsMenu.addAction("Remove all object elements",
                self.removeObjectElements)
        toolsMenu.addAction("Remove all embedded elements",
                self.removeEmbeddedElements)
        self.setCentralWidget(self.view)

    def viewSource(self):
        accessManager = self.view.page().networkAccessManager()
        request = QNetworkRequest(self.view.url())
        reply = accessManager.get(request)
        reply.finished.connect(self.slotSourceDownloaded)

    def slotSourceDownloaded(self):
        reply = self.sender()
        self.textEdit = QTextEdit()
        self.textEdit.setAttribute(Qt.WA_DeleteOnClose)
        self.textEdit.show()
        self.textEdit.setPlainText(QTextStream(reply).readAll())
        self.textEdit.resize(600, 400)
        reply.deleteLater()

    def adjustLocation(self):
        self.locationEdit.setText(self.view.url().toString())

    def changeLocation(self):
        url = QUrl.fromUserInput(self.locationEdit.text())
        self.view.load(url)
        self.view.setFocus()

    def adjustTitle(self):
        if 0 < self.progress < 100:
            self.setWindowTitle("%s (%s%%)" % (self.view.title(), self.progress))
        else:
            self.setWindowTitle(self.view.title())

    def setProgress(self, p):
        self.progress = p
        self.adjustTitle()

    def finishLoading(self):
        self.progress = 100
        self.adjustTitle()
        self.view.page().mainFrame().evaluateJavaScript(self.jQuery)
        self.rotateImages(self.rotateAction.isChecked())

    def highlightAllLinks(self):
        code = """$('a').each(
                    function () {
                        $(this).css('background-color', 'yellow') 
                    } 
                  )"""
        self.view.page().mainFrame().evaluateJavaScript(code)

    def rotateImages(self, invert):
        if invert:
            code = """
                $('img').each(
                    function () {
                        $(this).css('-webkit-transition', '-webkit-transform 2s'); 
                        $(this).css('-webkit-transform', 'rotate(180deg)') 
                    } 
                )"""
        else:
            code = """
                $('img').each(
                    function () { 
                        $(this).css('-webkit-transition', '-webkit-transform 2s'); 
                        $(this).css('-webkit-transform', 'rotate(0deg)') 
                    } 
                )"""

        self.view.page().mainFrame().evaluateJavaScript(code)

    def removeGifImages(self):
        code = "$('[src*=gif]').remove()"
        self.view.page().mainFrame().evaluateJavaScript(code)

    def removeInlineFrames(self):
        code = "$('iframe').remove()"
        self.view.page().mainFrame().evaluateJavaScript(code)

    def removeObjectElements(self):
        code = "$('object').remove()"
        self.view.page().mainFrame().evaluateJavaScript(code)

    def removeEmbeddedElements(self):
        code = "$('embed').remove()"
        self.view.page().mainFrame().evaluateJavaScript(code)
Beispiel #45
0
class HTMLViewer(vip_base):
    def cb_initialize_plugin(self):

        # ---------------------------
        # Read configuration
        # ---------------------------
        self.config = self.pl_get_current_config_ref()
        content = self.config['content']['value']
        isUrl = self.config['isUrl']['value']

        # --------------------------------
        # Create Widget
        # --------------------------------
        self.WebView = QWebView()

        # This call is important, because the background structure needs to know the used widget!
        # In the background the qmidiwindow will becreated and the widget will be added
        self.pl_set_widget_for_internal_usage(self.WebView)
        print(isUrl)
        if isUrl == '1':
            url = QtCore.QUrl(content)
            self.WebView.load(url)
        else:
            self.WebView.setHtml(content)
        self.WebView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.WebView.customContextMenuRequested.connect(self.show_context_menu)

        return True

    def show_context_menu(self, pos):
        gloPos = self.WebView.mapToGlobal(pos)
        self.cmenu = self.pl_create_control_context_menu()
        self.cmenu.exec_(gloPos)

    def cb_pause(self):
        # will be called, when plugin gets paused
        # can be used to get plugin in a defined state before pause
        # e.a.
        pass

    def cb_resume(self):
        # will be called when plugin gets resumed
        # can be used to wake up the plugin from defined pause state
        # e.a. reopen communication ports, files etc.
        pass

    def cb_execute(self, Data=None, block_name=None, plugin_uname=None):
        # Do main work here!
        # If this plugin is an IOP plugin, then there will be no Data parameter because it wont get data
        # If this plugin is a DPP, then it will get Data with data

        # param: Data is a Data hash and block_name is the block_name of Data origin
        # Data is a hash, so use ist like:  Data[CORE_TIME_SIGNAL] = [t1, t2, ...] where CORE_TIME_SIGNAL is a signal_name
        # hash signal_name: value

        # Data could have multiple types stored in it e.a. Data['d1'] = int, Data['d2'] = []

        pass

    def cb_set_parameter(self, name, value):
        # attetion: value is a string and need to be processed !
        # if name == 'irgendeinParameter':
        #   do that .... with value
        pass

    def cb_quit(self):
        # do something before plugin will close, e.a. close connections ...
        pass

    def cb_get_plugin_configuration(self):
        #
        # Implement a own part of the config
        # config is a hash of hass object
        # config_parameter_name : {}
        # config[config_parameter_name]['value']  NEEDS TO BE IMPLEMENTED
        # configs can be marked as advanced for create dialog
        # http://utilitymill.com/utility/Regex_For_Range

        config = {
            "content": {
                'value': """<p> Insert your html code here </p>""",
                'display_text': 'HTML Content',
                'advanced': 'HTLM',
                'tooltip': 'Plain html code to be displayed'
            },
            "isUrl": {
                'value': "0",
                'display_text': "Content==Url?",
                'tooltip':
                "Set to 1 if the content is an url that should be loaded",
                'advanced': 'HTML'
            },
        }

        return config

    def cb_plugin_meta_updated(self):
        """
        Whenever the meta information is updated this function is called (if implemented).

        :return:
        """

        #dplugin_info = self.dplugin_info
        pass
class QuestionnaireProcessorUI(QtWidgets.QMainWindow):
    """
    QT User interface
    """
    def __init__(self):
        """
        Initialize Questionnaire Processor UI
        """

        super(QuestionnaireProcessorUI, self).__init__()

        self._initConf()
        self._initHomeApp()
        self._initLogging()
        self._initDefaultValues()
        self._initUI()

    def _initConf(self):
        """
        Initialize config file
        """

        self.conf_default_io                = config['default_io']
        self.conf_questionnaireprocessor_ui = config['questionnaireprocessor_ui']
        self.conf_ui                        = config['ui']
        self.conf_default_input             = config['default_input']
        self.conf_format                    = config['format']

    def _initHomeApp(self):
        """
        Initializes paths of the application
        """

        self.homeFolder = os.path.expanduser("~")

        homeAppFolderName         = self.conf_default_io['homeAppFolderName']
        homeAppLogFolder          = self.conf_default_io['homeAppLogFolder']

        self.homeAppFolder        = os.path.join(self.homeFolder, homeAppFolderName)
        self.homeAppLogFolder     = os.path.join(self.homeAppFolder, homeAppLogFolder)

        if not os.path.exists(self.homeAppFolder):
            os.mkdir(self.homeAppFolder)
        if not os.path.exists(self.homeAppLogFolder):
            os.mkdir(self.homeAppLogFolder)

    def _initLogging(self):
        """
        Initializes paths of the application
        """
        fileName = 'errors_' + windowTitle.replace(' ', '-').lower() + '.log'
        errorLogPath = os.path.join(self.homeAppLogFolder, fileName)
        if debug:
            level = logging.DEBUG
        else:
            level = logging.ERROR
        configureLogging(errorLogPath, level)

    def _initDefaultValues(self):
        """
        Initializes default values
        """

        # Load resources
        self.idKey                   = self.conf_default_input['idKey']
        self.responseKey             = self.conf_default_input['responseKey']
        self.categoryKey             = self.conf_default_input['categoryKey']
        self.answerKey               = self.conf_default_input['answerKey']
        self.scoreKey                = self.conf_default_input['scoreKey']

        ## remove illegal characters
        self.illegalCharacterList = self.conf_format['illegalCharacterList']

        self.defaultIdentityList  = self.conf_default_input['defaultIdList']
        self.defaultCategoryList  = self.conf_default_input['defaultCategoryList']
        self.defaultAnswerString  = self.conf_default_input['defaultAnswerString']
        self.defaultScoreList     = self.conf_default_input['defaultScoreList']

        # Load resource paths
        self.uiPath       = getResourceLoc(self.conf_questionnaireprocessor_ui['uiPath'])
        self.icoPath      = getResourceLoc(self.conf_questionnaireprocessor_ui['icoPath'])
        self.helpimgPath  = getResourceLoc(self.conf_ui['helpimgPath'])
        self.aboutimgPath = getResourceLoc(self.conf_ui['aboutimgPath'])
        self.labelimgPath = getResourceLoc(self.conf_questionnaireprocessor_ui['labelimgPath'])

        # default folders
        self.sourceFolder = ""
        self.destinationFolder = ""
        self._lastSelectedDestDir = ""
        self._lastSelectedSourceDir = ""

        # default text
        self.windowTitle = self.conf_questionnaireprocessor_ui['windowTitle']
        self.StatusBoxHeight = int(self.conf_questionnaireprocessor_ui['StatusBoxHeight'])



    def _initUI(self):
        """
        Initializes the UI, sets button actions and default values
        """

        # icons
        self.helpIcon  = QtGui.QIcon(self.helpimgPath)
        self.aboutIcon = QtGui.QIcon(self.aboutimgPath)
        self.windowIcon = QtGui.QIcon(self.icoPath)

        # images
        self.pixmap = QtGui.QPixmap(self.labelimgPath)

        # Load and setup UI
        uic.loadUi(self.uiPath, self)

        self.windowHorizontalResolution = self.width()

        if verbose:
            self.windowVerticalResolution  = self.height()
        else:
            self.windowVerticalResolution  = self.height() - self.StatusBoxHeight

        # set default window values
        self.setWindowIcon(self.windowIcon)
        self.setFixedSize(self.windowHorizontalResolution,self.windowVerticalResolution)
        self.setWindowTitle(self.windowTitle)
        self.center()

        # set icons
        self.docButton.setIcon(self.helpIcon)
        self.aboutButton.setIcon(self.aboutIcon)

        # set default values
        self.idColumnLineEdit.setText(self.idKey)
        self.responseColumnLineEdit.setText(self.responseKey)
        self.categoryColumnLineEdit.setText(self.categoryKey)
        self.answerOptionColumnLineEdit.setText(self.answerKey)
        self.answerScoreColumnLineEdit.setText(self.scoreKey)
        self.idCustomPlainTextEdit.setPlainText('\n'.join(self.defaultIdentityList))
        self.categoryCustomPlainTextEdit.setPlainText('\n'.join(self.defaultCategoryList))
        self.answerCustomLineEdit.setText(self.defaultAnswerString)
        self.scoreCustomPlainTextEdit.setPlainText('\n'.join(self.defaultScoreList))
        self.caseInsensitiveCheckBox.setChecked(True)

        # set statusbox
        self.statusBox.setReadOnly(True)
        self.statusBox.hide()

        # set GUI image
        self.image.setPixmap(self.pixmap)

        ## hide custom column elements
        self.idColumnLabel.hide()
        self.idColumnLineEdit.hide()
        self.responseColumnLabel.hide()
        self.responseColumnLineEdit.hide()
        self.categoryColumnLabel.hide()
        self.categoryColumnLineEdit.hide()
        self.answerOptionColumnLabel.hide()
        self.answerOptionColumnLineEdit.hide()
        self.answerScoreColumnLabel.hide()
        self.answerScoreColumnLineEdit.hide()
        #self.line_2.hide()

        ## hide custom score elements
        self.idCustomLabel.hide()
        self.idCustomPlainTextEdit.hide()
        self.categoryCustomLabel.hide()
        self.categoryCustomPlainTextEdit.hide()
        self.answerCustomLabel.hide()
        self.answerCustomLineEdit.hide()
        self.scoreCustomLabel.hide()
        self.scoreCustomPlainTextEdit.hide()
        self.customExperimentCheckBox.hide()

        # Set button actions
        self.inputFolderButton.clicked.connect(self.selectInputFolderLocation)
        self.outputFolderButton.clicked.connect(self.selectOutputFolderDestination)
        self.processButton.clicked.connect(self.startAnalysis)
        self.docButton.clicked.connect(self.showDocWindow)
        self.aboutButton.clicked.connect(self.showAboutWindow)

        # Set checkbox actions
        self.customColumnCheckBox.stateChanged.connect(self.updateCustomColumnWidgets)
        self.customExperimentCheckBox.stateChanged.connect(self.updateCustomExperimentWidgets)

        if verbose:
            self.statusBox.show()
            self.label.hide()
        else:
            pass

        if verbose and not debug:

            # Redirect console output to textbox in UI, printing stdout in black
            # and stderr in red
            sys.stdout = OutLog(self.statusBox, sys.stdout, QtGui.QColor(0,0,0))
            if not hasattr(sys,'frozen'):
                sys.stderr = OutLog(self.statusBox, sys.stderr, QtGui.QColor(255,0,0))
            else:
                sys.stderr = OutLog(self.statusBox, None, QtGui.QColor(255,0,0))
            print("")
        else:
            pass

    def startAnalysis(self):
        """
        Starts sanity checks and if passed starts the analyze operation.
        """

        # check if sourceFolder is selected
        if self.sourceFolder == "":
            errorMessage = "Please select a source folder containing the data files to merge."
            print(errorMessage, file=sys.stderr)
            self.showErrorMessage(errorMessage)
            return
        # check if destinationFolder is selected
        elif self.destinationFolder == "":

            errorMessage = "Please specify a folder to save the results."
            print(errorMessage, file=sys.stderr)
            self.showErrorMessage(errorMessage)
            return

        else:
            print("Starting Analyze operation...")

            # set the default keys
            responseKey  = self.responseKey
            idKey        = self.idKey
            categoryKey  = self.categoryKey
            answerKey    = self.answerKey
            scoreKey     = self.scoreKey

            idList       = None
            categoryList = None
            answerList   = None
            scoreList    = None

            caseInsensitiveComparison = self.caseInsensitiveCheckBox.isChecked()

            if not self.customColumnCheckBox.isChecked():

                # calculate score automatically
                custom = False
                analyzedDataset = QuestionnaireProcessor(self.sourceFolder, self.destinationFolder, responseKey, idKey, categoryKey, 
                                                         answerKey, scoreKey, idList, categoryList, answerList, scoreList, custom, 
                                                         caseInsensitiveComparison, self)

                if analyzedDataset:
                    print("Output saved to " + self.destinationFolder)
                    print("Ready.")
                else:
                    pass


            elif self.customColumnCheckBox.isChecked() and not self.customExperimentCheckBox.isChecked():

                # calculate score with the given column keys
                responseKey = self.responseColumnLineEdit.text()
                idKey       = self.idColumnLineEdit.text()
                categoryKey = self.categoryColumnLineEdit.text()
                answerKey   = self.answerOptionColumnLineEdit.text()
                scoreKey    = self.answerScoreColumnLineEdit.text()

                custom = False

                ## check for illegal character
                stringCheck = None

                checkStringList = [responseKey, idKey, categoryKey, answerKey, scoreKey]

                for index in range(len(checkStringList)):
                    for illegalCharacter in self.illegalCharacterList:
                        if illegalCharacter in checkStringList[index]:
                            checkStringList[index] = checkStringList[index].replace(illegalCharacter, '')
                            stringCheck = True
                        else:
                            pass

                if stringCheck:

                    errorMessage = "The following characters are not allowed and have been stripped: double-quote (\") and backslash (\\)"
                    print(errorMessage, file=sys.stderr)
                    self.showErrorMessage(errorMessage)

                    self.responseColumnLineEdit.setText(checkStringList[0])
                    self.idColumnLineEdit.setText(checkStringList[1])
                    self.categoryColumnLineEdit.setText(checkStringList[2])
                    self.answerOptionColumnLineEdit.setText(checkStringList[3])
                    self.answerScoreColumnLineEdit.setText(checkStringList[4])

                    return

                else:
                    pass

                if responseKey != "" and idKey != "" and categoryKey != "" and answerKey != "" and scoreKey != "":

                    analyzedDataset = QuestionnaireProcessor(self.sourceFolder, self.destinationFolder, responseKey, idKey, categoryKey, 
                                                             answerKey, scoreKey, idList, categoryList, answerList, scoreList, custom, 
                                                             caseInsensitiveComparison, self)

                    if analyzedDataset:
                        print("Output saved to " + self.destinationFolder)
                        print("Ready.")
                    else:
                        pass
                else:
                    ## show error message if checks failed
                    errorMessage = "Not all column names are defined."
                    print(errorMessage, file=sys.stderr)
                    self.showErrorMessage(errorMessage)
                    return

            # calculate score with the custom given experiment data
            elif self.customColumnCheckBox.isChecked() and self.customExperimentCheckBox.isChecked():

                # set custom bool
                custom = True

                # get values from the widgets
                responseKey    = self.responseColumnLineEdit.text()
                idKey          = self.idColumnLineEdit.text()
                idString       = self.idCustomPlainTextEdit.toPlainText()
                answerString   = self.answerCustomLineEdit.text()
                categoryString = self.categoryCustomPlainTextEdit.toPlainText()
                scoreString    = self.scoreCustomPlainTextEdit.toPlainText()

                ## String Checks
                stringCheck = None

                checkStringList = [responseKey,idKey,idString, answerString, categoryString, scoreString]

                for index in range(len(checkStringList)):
                    for illegalCharacter in self.illegalCharacterList:
                        if illegalCharacter in checkStringList[index]:
                            checkStringList[index] = checkStringList[index].replace(illegalCharacter, '')
                            stringCheck = True
                        else:
                            pass

                if stringCheck:

                    errorMessage = "The following characters are not allowed and have been stripped: double-quote (\"), backslash (\\) and tab"
                    print(errorMessage, file=sys.stderr)
                    self.showErrorMessage(errorMessage)

                    self.responseColumnLineEdit.setText(checkStringList[0])
                    self.idColumnLineEdit.setText(checkStringList[1])
                    self.idCustomPlainTextEdit.setPlainText(checkStringList[2])
                    self.answerCustomLineEdit.setText(checkStringList[3])
                    self.categoryCustomPlainTextEdit.setPlainText(checkStringList[4])
                    self.scoreCustomPlainTextEdit.setPlainText(checkStringList[5])

                    return

                else:
                    pass


                ## split string to list and remove last enter
                idList       = (idString[:-1] if idString.endswith('\n') else idString).split('\n')
                categoryList = (categoryString[:-1] if categoryString.endswith('\n') else categoryString).split('\n')
                scoreList    = (scoreString[:-1] if scoreString.endswith('\n') else scoreString).split('\n')

                ## clean up items
                idList       = removeJunk(idList)
                categoryList = cleanUpStringList(categoryList,';')
                scoreList    = cleanUpStringList(scoreList,';')
                answerString = cleanUpString(answerString,';')

                ## make answer list for counting
                answerItemList = answerString.split(';')

                ## determine number of elements
                ncategory = len(categoryList)
                nscore    = len(scoreList)
                nid       = len(idList)
                nanswers  = len(answerItemList)

                ## replicate answer option to a list with length ntrials
                answerList = []
                for index in range(len(idList)):
                    answerList.append(answerString)

                ## number check
                nScoreItemList = []
                checkList = []
                for item in scoreList:
                    scoreItemList = item.split(';')
                    nScoreItemList.append(len(scoreItemList))
                    checkList.append(all(element.isdigit()==True for element in scoreItemList))

                numberCheck = all(item==True for item in checkList)

                ## check if all score lines have equal number of elements (seperated by ;) and is equal to
                ## the number of elements of answers
                uniqueScoreItemList = list(set(nScoreItemList))
                if len(uniqueScoreItemList)==1:

                    uniqueItems = uniqueScoreItemList[0]
                    if uniqueItems == nanswers:
                        scoreCheck = True
                    else:
                        scoreCheck = False
                else:
                    scoreCheck = False

                ## combine checks and show error if applicable
                if nid == ncategory == nscore and scoreCheck and numberCheck:
                    analyzedDataset = QuestionnaireProcessor(self.sourceFolder, self.destinationFolder, responseKey, idKey, categoryKey,
                                                             answerKey, scoreKey, idList, categoryList, answerList, scoreList, custom,
                                                             caseInsensitiveComparison, self)

                    if analyzedDataset:
                        print("Output saved to " + self.destinationFolder)
                        print("Ready.")
                    else:
                        pass
                else:
                    ## show error messages if checks failed
                    errorMessageList = []

                    if not (nid == ncategory == nscore and scoreCheck):
                        errorMessageList.append('- Not all fields have the correct number of elements\n')
                    if not numberCheck:
                        errorMessageList.append('- Field \"score\" should contain only integers seperated by \";\", found other characters\n')

                    self.showErrorMessage(''.join(errorMessageList))
                    return
            else:
                pass

    def updateCustomColumnWidgets(self):
        """
        Show custom column widgets when checkbox is checked else hide
        """
        if self.customColumnCheckBox.isChecked() :
            self.idColumnLabel.show()
            self.idColumnLineEdit.show()
            self.responseColumnLabel.show()
            self.responseColumnLineEdit.show()
            self.categoryColumnLabel.show()
            self.categoryColumnLineEdit.show()
            self.answerOptionColumnLabel.show()
            self.answerOptionColumnLineEdit.show()
            self.answerScoreColumnLabel.show()
            self.answerScoreColumnLineEdit.show()
            #self.line_2.show()

            self.customExperimentCheckBox.show()

            self.updateCustomExperimentWidgets()

        else:
            self.idColumnLabel.hide()
            self.idColumnLineEdit.hide()
            self.responseColumnLabel.hide()
            self.responseColumnLineEdit.hide()
            self.categoryColumnLabel.hide()
            self.categoryColumnLineEdit.hide()
            self.answerOptionColumnLabel.hide()
            self.answerOptionColumnLineEdit.hide()
            self.answerScoreColumnLabel.hide()
            self.answerScoreColumnLineEdit.hide()
            #self.line_2.hide()

            self.customExperimentCheckBox.hide()
            self.idCustomLabel.hide()
            self.idCustomPlainTextEdit.hide()
            self.categoryCustomLabel.hide()
            self.categoryCustomPlainTextEdit.hide()
            self.answerCustomLabel.hide()
            self.answerCustomLineEdit.hide()
            self.scoreCustomLabel.hide()
            self.scoreCustomPlainTextEdit.hide()
            self.customExperimentCheckBox.hide()

    def updateCustomExperimentWidgets(self):
        """
        Show custom experiment widgets (and hide some column widget elements)
        when checkbox is checked else hide
        """
        if self.customExperimentCheckBox.isChecked():
            self.idCustomLabel.show()
            self.idCustomPlainTextEdit.show()
            self.categoryCustomLabel.show()
            self.categoryCustomPlainTextEdit.show()
            self.answerCustomLabel.show()
            self.answerCustomLineEdit.show()
            self.scoreCustomLabel.show()
            self.scoreCustomPlainTextEdit.show()

            self.categoryColumnLabel.hide()
            self.categoryColumnLineEdit.hide()
            self.answerOptionColumnLabel.hide()
            self.answerOptionColumnLineEdit.hide()
            self.answerScoreColumnLabel.hide()
            self.answerScoreColumnLineEdit.hide()

        else:
            self.idCustomLabel.hide()
            self.idCustomPlainTextEdit.hide()
            self.categoryCustomLabel.hide()
            self.categoryCustomPlainTextEdit.hide()
            self.answerCustomLabel.hide()
            self.answerCustomLineEdit.hide()
            self.scoreCustomLabel.hide()
            self.scoreCustomPlainTextEdit.hide()

            self.categoryColumnLabel.show()
            self.categoryColumnLineEdit.show()
            self.answerOptionColumnLabel.show()
            self.answerOptionColumnLineEdit.show()
            self.answerScoreColumnLabel.show()
            self.answerScoreColumnLineEdit.show()

    def selectInputFolderLocation(self):
        """
        Select folder to read csv files from
        """
        selectedFolder = QtWidgets.QFileDialog.getExistingDirectory(self, "Select Directory", directory=self.inputFolderLocation.text())
        # Prevent erasing previous entry on cancel press
        if selectedFolder:
            self.sourceFolder = selectedFolder
            self.inputFolderLocation.setText(os.path.normpath(self.sourceFolder))
            self.progressBar.setValue(0)

    def selectOutputFolderDestination(self):
        """
        Set folder to write output to
        """
        selectedDest = QtWidgets.QFileDialog.getExistingDirectory(self,"Save output in..", directory=self.outputFolderDestination.text())
        # Prevent erasing previous entry on cancel press
        if selectedDest:
            self.destinationFolder = selectedDest
            self.outputFolderDestination.setText(os.path.normpath(self.destinationFolder))
            self.progressBar.setValue(0)

    def center(self):
        """
        Centers the main app window on the screen
        """
        qr = self.frameGeometry()
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def showDocWindow(self):
        """
        Shows documentation window (with help and licensing info)
        """

        title = "Documentation"
        htmlFile = "helpfile.html"

        self.docWindow = QWebView()
        self.docWindow.closeEvent = self.closeDocWindow
        self.docWindow.setWindowTitle(title)
        self.docWindow.setWindowIcon(self.helpIcon)
        self.docWindow.load(QtCore.QUrl.fromLocalFile(getResourceLoc(htmlFile)))
        self.docWindow.show()

    def closeDocWindow(self,source):
        """
        Callback function of the docWindow QWebView item.
        Destroys reference to doc window after its closed
        """
        del(self.docWindow)

    def showAboutWindow(self):
        """
        Shows about window
        """
        about ="About"

        msgBox = QtWidgets.QMessageBox(self)
        msgBox.setWindowIcon(self.aboutIcon)
        msgBox.about(self, about, aboutString)

    def showErrorMessage(self, message):
        """
        Shows error message
        """
        error ="Error"

        msgBox = QtWidgets.QMessageBox(self)
        msgBox.about(self, error, message)

    def confirmEvent(self, message):
        """
        Confirm box
        """
        reply = QtWidgets.QMessageBox.question(self, 'Message',
            message, QtWidgets.QMessageBox.Yes |
            QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
        if reply == QtWidgets.QMessageBox.Yes:
            reply = True
        else:
            reply = False
        return reply

    def closeEvent(self, event):
        """
        Confirm closing the main window
        """
        message = "Are you sure to quit?"

        reply = self.confirmEvent(message)

        if reply:
            event.accept()
        else:
            event.ignore()
Beispiel #47
0
class Application(QApplication):
    _active_task = None
    _exit_timer = None
    _expects = None
    _expects_active = False
    _expects_if_timeout = None
    _expects_timer = None
    _frame_data = None
    _frame_data_lock = None
    _frame_timer = None
    _handlers = None
    _queue = None
    _trigger_delay_timer = None
    _visible = True

    log_event = pyqtSignal(int, str, str)
    name = ''

    def __init__(self, name, settings):
        super(Application, self).__init__([])

        self.name = name
        self.settings = settings

        self.web_view = QWebView()

        self._exit_timer = QTimer(self)
        self._exit_timer.setSingleShot(True)
        self._exit_timer.setInterval(1000)

        self._expects = []
        self._expects_if_timeout = []
        self._expects_timer = QTimer(self)
        self._expects_timer.setSingleShot(True)
        self._expects_timer.timeout.connect(self._on_expects_timeout)
        self._frame_data = {}
        self._frame_data_lock = Lock()
        self._frame_timer = QTimer(self)
        self._frame_timer.start(3000)
        self._queue = Queue()
        self._trigger_delay_timer = QTimer(self)
        self._trigger_delay_timer.setSingleShot(True)
        self._visible = int(self.settings['application.visible'])

        self.web_page = WebPage(self.web_view)
        self.web_page.log_event.connect(self.log_event)
        self.web_page.frameCreated.connect(self._on_frame_created)
        self._on_frame_created(self.web_page.mainFrame())
        #self.web_page.networkAccessManager().finished.connect(
        #        self._on_http_response)

        self.web_view.setPage(self.web_page)

        st = self.web_page.settings()
        st.setAttribute(st.AutoLoadImages,
                        int(self.settings['application.settings.load_images']))
        st.setAttribute(
            st.JavaEnabled,
            int(self.settings['application.settings.java_enabled']))
        st.setAttribute(
            st.PluginsEnabled,
            int(self.settings['application.settings.plugins_enabled']))

        self.clear_handlers()

        # redirect qt related messages
        try:
            qInstallMessageHandler(self._pyqt5_null_message_handler)
        except NameError:
            qInstallMsgHandler(self._pyqt4_null_message_handler)

    def start(self):
        self.process_next_queue()
        if self._visible:
            self.web_view.show()
        return self.exec_()

    def add_queue(self, task, publish=False):
        self._queue.put(task)

    def process_next_queue(self):
        self._on_next_queue_trigger(self)

    def get_frame_related_data(self, frame):
        """
        There is a pool of reusable frame data, because browser's frames were
        easily created and destroyed.
        """
        with self._frame_data_lock:
            frame_data = self._frame_data.get(str(frame.objectName()))
        return frame_data

    def set_expects(self, expects):
        self._expects_active = True

        newlist = make_list(expects)
        for item in newlist:
            for key in item:
                if not key in ('path', 'hash', 'host', 'selector_exists',
                               'selector_not_exists', 'trigger',
                               'trigger_args', 'trigger_delay',
                               'trigger_wait_pageload', 'custom'):

                    self.warn('"%s" is not a valid expect field.' % key)

            item['selector_exists'] = make_list(item.get('selector_exists'))
            item['selector_not_exists'] = make_list(
                item.get('selector_not_exists'))

        self._expects = newlist

    def set_timeout_expects(self, timeout, expects):
        self._expects_timer.start(timeout * 1000)
        self._expects_if_timeout = make_list(expects)

    def set_upload_files(self, filenames):
        self.web_page.upload_files = make_list(filenames)

    def add_handler(self, name, value):
        self._handlers[name] = value

    def clear_handlers(self):
        # clear handlers registration
        self._handlers = {
            'core.next_queue': self._on_next_queue_trigger,
            'core.page_not_found': self._on_page_not_found_trigger
        }

    def load(self, url):
        self.web_view.load(QUrl(url))

    def info(self, message):
        self.log_event.emit(INFO, message, 'default')

    def debug(self, message):
        self.log_event.emit(DEBUG, message, 'default')

    def error(self, message):
        self.log_event.emit(ERROR, message, 'default')

    def warn(self, message):
        self.log_event.emit(WARNING, message, 'default')

    def exit(self, return_code):
        self.web_view.hide()
        self._expects_active = False
        self.web_view.stop()
        self._exit_timer.timeout.connect(
            partial(super(Application, self).exit, return_code))

        self._exit_timer.start(1000)

    def _url_matched_expectation(self, expect, scheme, netloc, path, query,
                                 segment):

        if 'host' in expect and not re.match(expect['host'], netloc):
            self.debug('%s location.host: "%s" "%s"' %
                       (expect['trigger'], expect['host'], netloc))
            return False

        if 'path' in expect and not re.match(expect['path'], path):
            self.debug('%s location.pathname: "%s" "%s"' %
                       (expect['trigger'], expect['path'], path))
            return False

        if 'hash' in expect and not re.match(expect['hash'], segment):
            self.debug('%s location.hash: "%s" "%s"' %
                       (expect['trigger'], expect['hash'], segment))
            return False

        return True

    def process_expectations(self, expect, frame, urlparts):
        if not self._url_matched_expectation(expect, *urlparts):
            return

        document = frame.documentElement()

        for selector in expect.get('selector_exists', []):
            if document.findFirst(selector).isNull():
                self.debug('%s selector_exists: %s' %
                           (expect['trigger'], selector))
                return

        for selector in expect.get('selector_not_exists', []):
            if not document.findFirst(selector).isNull():
                self.debug('%s selector_not_exists: %s' %
                           (expect['trigger'], selector))
                return

        if 'custom' in expect and not expect['custom'](self, frame, *urlparts):
            return

        self.debug('%s triggered.' % expect['trigger'])
        self._expects_active = False

        trigger_delay = expect.get('trigger_delay', 0)
        if trigger_delay:
            try:
                self._trigger_delay_timer.timeout.disconnect()
            except Exception as e:
                pass

            self._trigger_delay_timer.timeout.connect(
                partial(self.trigger,
                        frame=frame,
                        trigger_name=expect['trigger'],
                        trigger_args=expect.get('trigger_args', [])))

            self._trigger_delay_timer.start(trigger_delay * 1000)
        else:
            self.trigger(frame, expect['trigger'],
                         expect.get('trigger_args', []))

    def trigger(self, frame, trigger_name, trigger_args):
        if self._trigger_delay_timer.isActive():
            self._trigger_delay_timer.stop()

        trigger_args = dict((str(key), trigger_args[key]) for \
                key in trigger_args)

        if trigger_name in self._handlers:
            self._handlers[trigger_name](self, frame, **trigger_args)
        else:
            self.error('No handler for trigger %s.' % trigger_name)
            self.exit(-1)

    @staticmethod
    def _on_page_not_found_trigger(app, frame):
        app.error('PageNotFound: %s.' % frame.baseUrl().toString())
        app.exit(-1)

    @staticmethod
    def _on_next_queue_trigger(app, frame=None):
        if not app._active_task is None:
            app._queue.task_done()

        try:
            app._active_task = task = app._queue.get(timeout=15)
        except Empty:
            app.info('No more task in the queue.')
            app.web_view.close()
            app.exit(0)
            return

        expects = make_list(task['expects'])
        for expect in expects:
            expect['trigger_wait_pageload'] = True

        app.set_expects(expects)
        app.load(task['goto'])

    def _on_expects_timeout(self):
        self.debug('No expectations were fulfilled after a periode.')
        self.set_expects(self._expects_if_timeout or [])
        self.web_page.triggerAction(QWebPage.Stop)

    def _on_frame_created(self, frame):
        """ Called when QWebPage created a QWebFrame """
        frame_name = 'frame-' + uuid4().hex
        frame.setObjectName(frame_name)
        frame_data = {
            ENUM_FRAME_DATA_ACTIVE:
            False,
            ENUM_FRAME_DATA_TIMER_CALLBACK:
            partial(self._on_frame_timer, frame=frame),
            ENUM_FRAME_DATA_TIMER_COUNTER:
            0,
        }

        with self._frame_data_lock:
            self._frame_data[frame_name] = frame_data

        self._frame_timer.timeout.connect(
            frame_data[ENUM_FRAME_DATA_TIMER_CALLBACK])

        frame.destroyed.connect(self._on_frame_destroyed)
        #frame.javaScriptWindowObjectCleared.connect(partial(
        #        self._on_frame_reset, frame=frame))
        frame.loadFinished.connect(partial(self._on_frame_loaded, frame=frame))

    def _on_frame_destroyed(self, frame):
        """ Called when QWebFrame was destroyed """
        frame_name = str(frame.objectName())
        with self._frame_data_lock:
            frame_data = self._frame_data.get(frame_name)
            if frame_data is None:
                return

            del self._frame_data[frame_name]
            self._frame_timer.timeout.disconnect(
                frame_data[ENUM_FRAME_DATA_TIMER_CALLBACK])

    def _on_frame_loaded(self, success, frame=None):
        self._on_frame_reset(frame)

    def _on_frame_reset(self, frame=None):
        """
        Called when the javascript `window` object were destroyed, usually just
        before page reload.
        """
        if frame is None:
            # this happens if the frame was forced stop, probably, not sure
            self.error('Problem while loading the page.')
            self.exit(-1)
            return
        self.debug('DOMContentLoaded ' + frame.baseUrl().toString())

        frame.evaluateJavaScript("""
            window.bot = {
                click: function(el) {
                    if (el.click) {
                        el.click()
                    }
                    else if (el.fireEvent) {
                        el.fireEvent('onclick');
                    }
                    else {
                        var evt = document.createEvent('Events');
                        evt.initEvent('click', true, false);
                        el.dispatchEvent(evt);
                    }
                },
            };
        """)

        frame_data = self.get_frame_related_data(frame)
        frame_data[ENUM_FRAME_DATA_TIMER_COUNTER] = 0
        frame_data[ENUM_FRAME_DATA_ACTIVE] = True

    def _on_frame_timer(self, frame):
        if not self._expects_active:
            # we have obsolete expects
            return

        frame_data = self.get_frame_related_data(frame)
        if frame_data is None:
            return

        if not frame_data[ENUM_FRAME_DATA_ACTIVE]:
            # the frame hasn't been fully loaded
            return

        wait_pageload = False

        urlparts = urlsplit(str(frame.baseUrl().toString()))
        for expect in self._expects:
            # is it an obsolete frame
            if expect.get('trigger_wait_pageload', False) and \
                    frame_data[ENUM_FRAME_DATA_TIMER_COUNTER] > 0:

                wait_pageload = True
                continue

            self.process_expectations(expect, frame, urlparts)
            if not self._expects_active:
                # one of the triggers has been activated
                break

        if not wait_pageload:
            frame_data[ENUM_FRAME_DATA_TIMER_COUNTER] += 1

    def _pyqt4_null_message_handler(self, msgtype, msg):
        """ Nuke Qt related error messages """
        self.log_event.emit(DEBUG, str(msg), 'qt')

    def _pyqt5_null_message_handler(self, msgtype, msgctx, msg):
        """ Nuke Qt related error messages """
        self.log_event.emit(DEBUG, str(msg), 'qt')

    def _on_http_response(self, response):
        error = response.error()
        if error == QNetworkReply.NoError:
            return

        url = str(response.url().toString())
        scheme, netloc, path, query, segment = urlsplit(url)
        filename, ext = os.path.splitext(path)

        if len(ext) and ext[1:] in ('gif', 'css', 'js', 'png', 'jpg', 'jpeg',
                                    'ico'):

            return

        status_code = int(
            response.attribute(
                QNetworkRequest.HttpStatusCodeAttribute).toInt())

        for expect in self._expects:
            if self._url_matched_expectation(expect, scheme, netloc, path,
                                             query, segment):

                self.log_event.emit(WARNING, '%s: %s' % (status_code, url),
                                    'http')

                break
        else:
            self.log_event.emit(DEBUG, '%s: %s' % (status_code, url), 'http')
Beispiel #48
0
class HTMLViewer(vip_base):


    def cb_initialize_plugin(self):

        # ---------------------------
        # Read configuration
        # ---------------------------
        self.config = self.pl_get_current_config_ref()
        content = self.config['content']['value']
        isUrl   = self.config['isUrl']['value']



        # --------------------------------
        # Create Widget
        # --------------------------------
        self.WebView = QWebView()


        # This call is important, because the background structure needs to know the used widget!
        # In the background the qmidiwindow will becreated and the widget will be added
        self.pl_set_widget_for_internal_usage( self.WebView )
        print(isUrl)
        if isUrl == '1':
            url = QtCore.QUrl(content)
            self.WebView.load(url)
        else:
            self.WebView.setHtml(content)
        self.WebView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.WebView.customContextMenuRequested.connect(self.show_context_menu)

        return True

    def show_context_menu(self, pos):
        gloPos = self.WebView.mapToGlobal(pos)
        self.cmenu = self.pl_create_control_context_menu()
        self.cmenu.exec_(gloPos)

    def cb_pause(self):
        # will be called, when plugin gets paused
        # can be used to get plugin in a defined state before pause
        # e.a.
        pass

    def cb_resume(self):
        # will be called when plugin gets resumed
        # can be used to wake up the plugin from defined pause state
        # e.a. reopen communication ports, files etc.
        pass

    def cb_execute(self, Data=None, block_name = None, plugin_uname = None):
        # Do main work here!
        # If this plugin is an IOP plugin, then there will be no Data parameter because it wont get data
        # If this plugin is a DPP, then it will get Data with data

        # param: Data is a Data hash and block_name is the block_name of Data origin
        # Data is a hash, so use ist like:  Data[CORE_TIME_SIGNAL] = [t1, t2, ...] where CORE_TIME_SIGNAL is a signal_name
        # hash signal_name: value

        # Data could have multiple types stored in it e.a. Data['d1'] = int, Data['d2'] = []

        pass

    def cb_set_parameter(self, name, value):
        # attetion: value is a string and need to be processed !
        # if name == 'irgendeinParameter':
        #   do that .... with value
        pass

    def cb_quit(self):
        # do something before plugin will close, e.a. close connections ...
        pass


    def cb_get_plugin_configuration(self):
        #
        # Implement a own part of the config
        # config is a hash of hass object
        # config_parameter_name : {}
        # config[config_parameter_name]['value']  NEEDS TO BE IMPLEMENTED
        # configs can be marked as advanced for create dialog
        # http://utilitymill.com/utility/Regex_For_Range

        config = {
            "content": {
                'value': """<p> Insert your html code here </p>""",
                'display_text' : 'HTML Content',
                'advanced' : '0',
                'tooltip' : 'Plain html code to be displayed'
            },
            "isUrl": {
                'value': "0",
                'display_text': "Content==Url?",
                'tooltip': "Set to 1 if the content is an url that should be loaded",
                'advanced' : '0'
            },
        }

        return config

    def cb_plugin_meta_updated(self):
        """
        Whenever the meta information is updated this function is called (if implemented).

        :return:
        """

        #dplugin_info = self.dplugin_info
        pass
Beispiel #49
0
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtPrintSupport import QPrinter
from PyQt5.QtWebKit import *
from PyQt5.QtWebKitWidgets import QWebView
from PyQt5.QtWidgets import QApplication

app = QApplication(sys.argv)

web = QWebView()
# web.load(QUrl("http://www.google.com"))
# web.show()
# sourceHtml = open("../template/umaficha/ficha.html").read()
local_url = QUrl.fromLocalFile("../template/umaficha/ficha.html")
web.load(local_url)

printer = QPrinter()
printer.setPageSize(QPrinter.A4)
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName("file.pdf")


def convertIt():
    web.print_(printer)
    print("Pdf generated")
    QApplication.exit()


if __name__ == "__main__":
    convertIt()