Example #1
0
    def _page_loaded(self, success):
        if self.develop and self.display:
            if self.inspector is None:
                self.inspector = QWebInspector()

            self.inspector.setPage(self.page)
            self.inspector.show()

        scripts = [
            'atoms.js',
            'htmlutils.js',
        ]

        if self.jquery_namespace:
            scripts.append('jquery-1.9.1.min.js', )

        for script in scripts:
            self.evaluate_js_file(os.path.dirname(__file__) + '/javascripts/' + script)

        if self.jquery_namespace:
            self.evaluate("%s=jQuery.noConflict();" % self.jquery_namespace)

        self._loaded = True
        # self.cache.clear()
        logger.debug("Page load finished")
Example #2
0
 def show_inspector(self, event=None):
     """Show the web inspector."""
     if not self.inspector:
         inspect = QWebInspector()
         inspect.setPage(self.page())
         self.inspector = inspect
     self.inspector.show()
Example #3
0
 def __init__(self, parent=None):
     QWebView.__init__(self, parent)
     self.inspector = QWebInspector(self)
     w = QApplication.instance().desktop().availableGeometry(self).width()
     self._size_hint = QSize(int(w/3), int(w/2))
     self._page = WebPage(self)
     self.setPage(self._page)
     self.inspector.setPage(self._page)
     self.clear()
Example #4
0
 def toggle_inspector():
     if self._inspector:
         self._inspector.setVisible(not self._inspector.isVisible())
     else:
         # create the inspector "on demand"
         page.settings().setAttribute(
             QWebSettings.DeveloperExtrasEnabled, True)
         self._inspector = QWebInspector(self)
         self._inspector.setPage(page)
         self.splitter.addWidget(self._inspector)
Example #5
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        vbox = QVBoxLayout(self)
        self._webInspector = QWebInspector(self)
        vbox.addWidget(self._webInspector)
        self.btnDock = QPushButton(translations.TR_UNDOCK)
        vbox.addWidget(self.btnDock)

        ExplorerContainer.register_tab(translations.TR_TAB_WEB_INSPECTOR, self)
        IDE.register_service('web_inspector', self)
Example #6
0
class WebView(QWebView):

    def __init__(self, parent=None):
        QWebView.__init__(self, parent)
        self.inspector = QWebInspector(self)
        w = QApplication.instance().desktop().availableGeometry(self).width()
        self._size_hint = QSize(int(w/3), int(w/2))
        settings = self.page().settings()
        apply_settings(settings, config().parse())
        settings.setMaximumPagesInCache(0)
        settings.setAttribute(settings.JavaEnabled, False)
        settings.setAttribute(settings.PluginsEnabled, False)
        settings.setAttribute(settings.PrivateBrowsingEnabled, True)
        settings.setAttribute(settings.JavascriptCanOpenWindows, False)
        settings.setAttribute(settings.JavascriptCanAccessClipboard, False)
        settings.setAttribute(settings.LinksIncludedInFocusChain, False)
        settings.setAttribute(settings.DeveloperExtrasEnabled, True)
        settings.setDefaultTextEncoding('utf-8')

        self.page().setNetworkAccessManager(NetworkAccessManager(self))
        self.page().setLinkDelegationPolicy(self.page().DelegateAllLinks)

        self.clear()

    def sizeHint(self):
        return self._size_hint

    def refresh(self):
        self.pageAction(self.page().Reload).trigger()

    @dynamic_property
    def scroll_pos(self):
        def fget(self):
            mf = self.page().mainFrame()
            return (mf.scrollBarValue(Qt.Horizontal), mf.scrollBarValue(Qt.Vertical))
        def fset(self, val):
            mf = self.page().mainFrame()
            mf.setScrollBarValue(Qt.Horizontal, val[0])
            mf.setScrollBarValue(Qt.Vertical, val[1])
        return property(fget=fget, fset=fset)

    def clear(self):
        self.setHtml('<p>')

    def inspect(self):
        self.inspector.parent().show()
        self.inspector.parent().raise_()
        self.pageAction(self.page().InspectElement).trigger()

    def contextMenuEvent(self, ev):
        menu = QMenu(self)
        menu.addAction(actions['reload-preview'])
        menu.addAction(QIcon(I('debug.png')), _('Inspect element'), self.inspect)
        menu.exec_(ev.globalPos())
Example #7
0
    def toggleInspector(self):
        if self.__inspector_window is None:
            self.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
            web_inspector = QWebInspector()
            web_inspector.setPage(self.page())

            self.__inspector_window = QMainWindow(self)
            self.__inspector_window.setCentralWidget(web_inspector)
            self.__inspector_window.resize(900, 600)
            self.__inspector_window.setVisible(False)

        self.__inspector_window.setVisible(not self.__inspector_window.isVisible())
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     vbox = QVBoxLayout(self)
     self._webInspector = QWebInspector(self)
     vbox.addWidget(self._webInspector)
     self.btnDock = QPushButton(self.tr("Undock"))
     vbox.addWidget(self.btnDock)
Example #9
0
    def _page_loaded(self, success):
        if self.develop and self.display:
            if self.inspector is None:
                self.inspector = QWebInspector()

            self.inspector.setPage(self.page)
            self.inspector.show()

        scripts = [
            'atoms.js',
            'htmlutils.js',
        ]

        if self.jquery_namespace:
            scripts.append('jquery-1.9.1.min.js', )

        for script in scripts:
            self.evaluate_js_file(os.path.dirname(__file__) + '/javascripts/' + script)

        if self.jquery_namespace:
            self.evaluate(u"%s=jQuery.noConflict();" % self.jquery_namespace)

        self._loaded = True
        # self.cache.clear()
        logger.debug("Page load finished")
 def toggle_inspector():
     if self._inspector:
         self._inspector.setVisible(not self._inspector.isVisible())
     else:
         # create the inspector "on demand"
         page.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
         self._inspector = QWebInspector(self)
         self._inspector.setPage(page)
         self.splitter.addWidget(self._inspector)
Example #11
0
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        vbox = QVBoxLayout(self)
        self._webInspector = QWebInspector(self)
        vbox.addWidget(self._webInspector)
        self.btnDock = QPushButton(translations.TR_UNDOCK)
        vbox.addWidget(self.btnDock)

        ExplorerContainer.register_tab(translations.TR_TAB_WEB_INSPECTOR, self)
Example #12
0
 def __init__(self, parent=None):
     QWebView.__init__(self, parent)
     self.inspector = QWebInspector(self)
     w = QApplication.instance().desktop().availableGeometry(self).width()
     self._size_hint = QSize(int(w/3), int(w/2))
     self._page = WebPage(self)
     self.setPage(self._page)
     self.inspector.setPage(self._page)
     self.clear()
Example #13
0
    def __init__(self, parent=None):
        '''
        Constructor
        '''
        QtGui.QWidget.__init__(self, parent)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Clear all of the tabs on the widget
        while self.ui.javascriptTabs.count() > 0:
            self.ui.javascriptTabs.removeTab(0)

        # Document filename
        self.docxFile = ''
        self.document = None

        # Create one new one
        newTab = ScriptEditor()
        self.ui.javascriptTabs.addTab(newTab, 'untitled')

        # Connect all of my signals
        self.ui.actionNew_Script.triggered.connect(self.newScript)
        self.ui.actionOpen_Docx.triggered.connect(self.openDocx)
        self.ui.actionOpen_Javascript.triggered.connect(self.openScript)
        self.ui.actionSave_Current.triggered.connect(self.saveCurrentScript)
        self.ui.actionSave_All.triggered.connect(self.saveAllScripts)

        self.ui.javascriptTabs.tabCloseRequested.connect(self.onTabClose)

        self.ui.resetButton.clicked.connect(self.resetDocx)
        self.ui.inspectorButton.clicked.connect(self.openInspector)

        self.ui.run1Button.clicked.connect(self.runScript1)
        self.ui.run2Button.clicked.connect(self.runScript2)
        self.ui.run3Button.clicked.connect(self.runScript3)

        # For my web inspector
        self.ui.documentView.settings().setAttribute(
            QWebSettings.DeveloperExtrasEnabled, True)
        self.webInspector = QWebInspector()
Example #14
0
    def __init__(self, parent, page):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('Inspect book code'))
        self.setWindowIcon(QIcon(I('debug.png')))
        l = QVBoxLayout()
        self.setLayout(l)

        self.inspector = QWebInspector(self)
        self.inspector.setPage(page)
        l.addWidget(self.inspector)

        self.bb = bb = QDialogButtonBox(QDialogButtonBox.Close)
        l.addWidget(bb)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)

        self.resize(self.sizeHint())

        geom = gprefs.get('viewer_inspector_geom', None)
        if geom is not None:
            self.restoreGeometry(geom)
Example #15
0
class WebView(QWebView):
    def __init__(self, parent=None):
        QWebView.__init__(self, parent)
        self.inspector = QWebInspector(self)
        w = QApplication.instance().desktop().availableGeometry(self).width()
        self._size_hint = QSize(int(w / 3), int(w / 2))
        self._page = WebPage(self)
        self.setPage(self._page)
        self.inspector.setPage(self._page)
        self.clear()

    def sizeHint(self):
        return self._size_hint

    def refresh(self):
        self.pageAction(self.page().Reload).trigger()

    @dynamic_property
    def scroll_pos(self):
        def fget(self):
            mf = self.page().mainFrame()
            return (mf.scrollBarValue(Qt.Horizontal),
                    mf.scrollBarValue(Qt.Vertical))

        def fset(self, val):
            mf = self.page().mainFrame()
            mf.setScrollBarValue(Qt.Horizontal, val[0])
            mf.setScrollBarValue(Qt.Vertical, val[1])

        return property(fget=fget, fset=fset)

    def clear(self):
        self.setHtml(
            _('''
            <h3>Live preview</h3>

            <p>Here you will see a live preview of the HTML file you are currently editing.
            The preview will update automatically as you make changes.

            <p style="font-size:x-small; color: gray">Note that this is a quick preview
            only, it is not intended to simulate an actual ebook reader. Some
            aspects of your ebook will not work, such as, page breaks,
            page margins and embedded fonts that use font name aliasing.

            '''))

    def inspect(self):
        self.inspector.parent().show()
        self.inspector.parent().raise_()
        self.pageAction(self.page().InspectElement).trigger()

    def contextMenuEvent(self, ev):
        menu = QMenu(self)
        ca = self.pageAction(QWebPage.Copy)
        if ca.isEnabled():
            menu.addAction(ca)
        menu.addAction(actions['reload-preview'])
        menu.addAction(QIcon(I('debug.png')), _('Inspect element'),
                       self.inspect)
        menu.exec_(ev.globalPos())
Example #16
0
class WebInspector(QDialog):

    def __init__(self, parent, page):
        QDialog.__init__(self, parent)
        self.setWindowTitle(_('Inspect book code'))
        self.setWindowIcon(QIcon(I('debug.png')))
        l = QVBoxLayout()
        self.setLayout(l)

        self.inspector = QWebInspector(self)
        self.inspector.setPage(page)
        l.addWidget(self.inspector)

        self.bb = bb = QDialogButtonBox(QDialogButtonBox.Close)
        l.addWidget(bb)
        bb.accepted.connect(self.accept)
        bb.rejected.connect(self.reject)

        self.resize(self.sizeHint())

        geom = gprefs.get('viewer_inspector_geom', None)
        if geom is not None:
            self.restoreGeometry(geom)

    def save_geometry(self):
        gprefs['viewer_inspector_geom'] = bytearray(self.saveGeometry())

    def closeEvent(self, ev):
        self.save_geometry()
        return QDialog.closeEvent(self, ev)

    def accept(self):
        self.save_geometry()
        QDialog.accept(self)

    def reject(self):
        self.save_geometry()
        QDialog.reject(self)
Example #17
0
class WebView(QWebView):

    def __init__(self, parent=None):
        QWebView.__init__(self, parent)
        self.inspector = QWebInspector(self)
        w = QApplication.instance().desktop().availableGeometry(self).width()
        self._size_hint = QSize(int(w/3), int(w/2))
        self._page = WebPage(self)
        self.setPage(self._page)
        self.inspector.setPage(self._page)
        self.clear()

    def sizeHint(self):
        return self._size_hint

    def refresh(self):
        self.pageAction(self.page().Reload).trigger()

    @dynamic_property
    def scroll_pos(self):
        def fget(self):
            mf = self.page().mainFrame()
            return (mf.scrollBarValue(Qt.Horizontal), mf.scrollBarValue(Qt.Vertical))
        def fset(self, val):
            mf = self.page().mainFrame()
            mf.setScrollBarValue(Qt.Horizontal, val[0])
            mf.setScrollBarValue(Qt.Vertical, val[1])
        return property(fget=fget, fset=fset)

    def clear(self):
        self.setHtml(_(
            '''
            <h3>Live preview</h3>

            <p>Here you will see a live preview of the HTML file you are currently editing.
            The preview will update automatically as you make changes.

            <p style="font-size:x-small; color: gray">Note that this is a quick preview
            only, it is not intended to simulate an actual ebook reader. Some
            aspects of your ebook will not work, such as, page breaks,
            page margins and embedded fonts that use font name aliasing.

            '''))

    def inspect(self):
        self.inspector.parent().show()
        self.inspector.parent().raise_()
        self.pageAction(self.page().InspectElement).trigger()

    def contextMenuEvent(self, ev):
        menu = QMenu(self)
        ca = self.pageAction(QWebPage.Copy)
        if ca.isEnabled():
            menu.addAction(ca)
        menu.addAction(actions['reload-preview'])
        menu.addAction(QIcon(I('debug.png')), _('Inspect element'), self.inspect)
        menu.exec_(ev.globalPos())
Example #18
0
class WebInspector(QWidget):

    def __init__(self, parent):
        QWidget.__init__(self, parent)
        vbox = QVBoxLayout(self)
        self._webInspector = QWebInspector(self)
        vbox.addWidget(self._webInspector)
        self.btnDock = QPushButton(translations.TR_UNDOCK)
        vbox.addWidget(self.btnDock)

        ExplorerContainer.register_tab(translations.TR_TAB_WEB_INSPECTOR, self)

    def refresh_inspector(self):
        self._webInspector.hide()
        self._webInspector.show()

    def set_inspection_page(self, page):
        self._webInspector.setPage(page)
        self._webInspector.setVisible(True)
Example #19
0
class WebInspector(QWidget):
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        vbox = QVBoxLayout(self)
        self._webInspector = QWebInspector(self)
        vbox.addWidget(self._webInspector)
        self.btnDock = QPushButton(translations.TR_UNDOCK)
        vbox.addWidget(self.btnDock)

        ExplorerContainer.register_tab(translations.TR_TAB_WEB_INSPECTOR, self)
        IDE.register_service('web_inspector', self)

    def refresh_inspector(self):
        self._webInspector.hide()
        self._webInspector.show()

    def set_inspection_page(self, page):
        self._webInspector.setPage(page)
        self._webInspector.setVisible(True)
Example #20
0
class WebInspector(QWidget):
    """WebInspector widget class"""
    def __init__(self, parent):
        QWidget.__init__(self, parent)
        vbox = QVBoxLayout(self)
        self._webInspector = QWebInspector(self)
        vbox.addWidget(self._webInspector)
        self.btnDock = QPushButton(translations.TR_UNDOCK)
        vbox.addWidget(self.btnDock)

        ExplorerContainer.register_tab(translations.TR_TAB_WEB_INSPECTOR, self)
        IDE.register_service('web_inspector', self)

    def refresh_inspector(self):
        """Refresh WebInspector widget by hiding and showing"""
        self._webInspector.hide()
        self._webInspector.show()

    def set_inspection_page(self, page):
        """Method to load an argument page object on the WebInspector"""
        self._webInspector.setPage(page)
        self._webInspector.setVisible(True)
Example #21
0
    def __init__(self, parent=None):
        QWebView.__init__(self, parent)
        self.inspector = QWebInspector(self)
        w = QApplication.instance().desktop().availableGeometry(self).width()
        self._size_hint = QSize(int(w/3), int(w/2))
        settings = self.page().settings()
        apply_settings(settings, config().parse())
        settings.setMaximumPagesInCache(0)
        settings.setAttribute(settings.JavaEnabled, False)
        settings.setAttribute(settings.PluginsEnabled, False)
        settings.setAttribute(settings.PrivateBrowsingEnabled, True)
        settings.setAttribute(settings.JavascriptCanOpenWindows, False)
        settings.setAttribute(settings.JavascriptCanAccessClipboard, False)
        settings.setAttribute(settings.LinksIncludedInFocusChain, False)
        settings.setAttribute(settings.DeveloperExtrasEnabled, True)
        settings.setDefaultTextEncoding('utf-8')

        self.page().setNetworkAccessManager(NetworkAccessManager(self))
        self.page().setLinkDelegationPolicy(self.page().DelegateAllLinks)

        self.clear()
Example #22
0
class WebInspector(QWidget):
    """WebInspector widget class"""

    def __init__(self, parent):
        QWidget.__init__(self, parent)
        vbox = QVBoxLayout(self)
        self._webInspector = QWebInspector(self)
        vbox.addWidget(self._webInspector)
        self.btnDock = QPushButton(translations.TR_UNDOCK)
        vbox.addWidget(self.btnDock)

        ExplorerContainer.register_tab(translations.TR_TAB_WEB_INSPECTOR, self)
        IDE.register_service('web_inspector', self)

    def refresh_inspector(self):
        """Refresh WebInspector widget by hiding and showing"""
        self._webInspector.hide()
        self._webInspector.show()

    def set_inspection_page(self, page):
        """Method to load an argument page object on the WebInspector"""
        self._webInspector.setPage(page)
        self._webInspector.setVisible(True)
Example #23
0
class WebView(QWebView):

    def __init__(self, parent=None):
        QWebView.__init__(self, parent)
        self.inspector = QWebInspector(self)
        w = QApplication.instance().desktop().availableGeometry(self).width()
        self._size_hint = QSize(int(w/3), int(w/2))
        self._page = WebPage(self)
        self.setPage(self._page)
        self.inspector.setPage(self._page)
        self.clear()

    def sizeHint(self):
        return self._size_hint

    def refresh(self):
        self.pageAction(self.page().Reload).trigger()

    @dynamic_property
    def scroll_pos(self):
        def fget(self):
            mf = self.page().mainFrame()
            return (mf.scrollBarValue(Qt.Horizontal), mf.scrollBarValue(Qt.Vertical))
        def fset(self, val):
            mf = self.page().mainFrame()
            mf.setScrollBarValue(Qt.Horizontal, val[0])
            mf.setScrollBarValue(Qt.Vertical, val[1])
        return property(fget=fget, fset=fset)

    def clear(self):
        self.setHtml('<p>')

    def inspect(self):
        self.inspector.parent().show()
        self.inspector.parent().raise_()
        self.pageAction(self.page().InspectElement).trigger()

    def contextMenuEvent(self, ev):
        menu = QMenu(self)
        menu.addAction(actions['reload-preview'])
        menu.addAction(QIcon(I('debug.png')), _('Inspect element'), self.inspect)
        menu.exec_(ev.globalPos())
Example #24
0
	def __init__(self, urls, parent=None):
		KParts.MainWindow.__init__(self, parent)
		
		QWebSettings.globalSettings().setAttribute(
			QWebSettings.DeveloperExtrasEnabled, True)
		
		self.setWindowIcon(KIcon('text-editor'))
		
		self.kate = KTextEditor.EditorChooser.editor()
		self.editor = self.kate.createDocument(self).createView(self)
		doc = self.editor.document()
		self.editor.setContextMenu(self.editor.defaultContextMenu())
		
		sizegrip = create_grip(self.editor)
		sizegrip.show() #TODO: only show on windowstate change
		
		self.renderer = Renderer(self)
		
		@doc.textChanged.connect
		def _start_markdown(doc=None, old_range=None, new_range=None):
			"""Runs the renderer if it’s not currently rendering"""
			if not self.renderer.isRunning():
				self.renderer.start()
		
		@self.renderer.finished.connect
		def _stop_markdown():
			"""
			Replaces the preview HTML with the newly rendered one
			and restores the scroll position
			"""
			url = self.editor.document().url().resolved(QUrl('.'))
			self.preview.setHtml(self.renderer.html, url) #baseurl für extenes zeug
			self.preview.page().mainFrame().setScrollPosition(self.renderer.scrollpos)
		
		self.editor.document().documentNameChanged.connect(self.refresh_document)
		
		self.guiFactory().addClient(self.editor)
		self.setCentralWidget(self.editor)
		
		self.toolbar = KToolBar(i18n('Markdowner Toolbar'), self)
		self.toolbar.setWindowTitle(self.toolbar.objectName())
		self.preview_button = self.toolbar.addAction(KIcon('document-preview'), i18n('Show Preview'))
		self.preview_button.setCheckable(True)
		
		self.preview = QWebView()
		self.preview.settings().setUserStyleSheetUrl(base64css())
		self.preview.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
		self.preview.linkClicked.connect(self.intercept_link)
		
		with self.setup_dock(self.preview, i18n('Preview'), Qt.RightDockWidgetArea) as dock:
			page = self.preview.page()
			palette = page.palette()
			palette.setBrush(QPalette.Base, Qt.transparent)
			page.setPalette(palette)
			
			self.preview.setAttribute(Qt.WA_TranslucentBackground)
			self.preview.setAttribute(Qt.WA_OpaquePaintEvent, False)
			
			dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
			dock.visibilityChanged.connect(self.preview_button.setChecked)
			self.preview_button.triggered.connect(dock.setVisible)
		
		inspector = QWebInspector()
		with self.setup_dock(inspector, i18n('Inspector'), Qt.BottomDockWidgetArea) as dock:
			inspector.setPage(self.preview.page())
			dock.hide()
			inspect_action = self.preview.page().action(QWebPage.InspectElement)
			inspect_action.triggered.connect(dock.show)
		
		if len(urls) != 0:
			self.editor.document().openUrl(urls[0])
		
		#TODO: spellcheck
		self.setAutoSaveSettings()
		self.kate.readConfig(self.autoSaveConfigGroup().config())
Example #25
0
class MainWindow(QtGui.QMainWindow):
    '''
    classdocs
    '''
    def __init__(self, parent=None):
        '''
        Constructor
        '''
        QtGui.QWidget.__init__(self, parent)

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Clear all of the tabs on the widget
        while self.ui.javascriptTabs.count() > 0:
            self.ui.javascriptTabs.removeTab(0)

        # Document filename
        self.docxFile = ''
        self.document = None

        # Create one new one
        newTab = ScriptEditor()
        self.ui.javascriptTabs.addTab(newTab, 'untitled')

        # Connect all of my signals
        self.ui.actionNew_Script.triggered.connect(self.newScript)
        self.ui.actionOpen_Docx.triggered.connect(self.openDocx)
        self.ui.actionOpen_Javascript.triggered.connect(self.openScript)
        self.ui.actionSave_Current.triggered.connect(self.saveCurrentScript)
        self.ui.actionSave_All.triggered.connect(self.saveAllScripts)

        self.ui.javascriptTabs.tabCloseRequested.connect(self.onTabClose)

        self.ui.resetButton.clicked.connect(self.resetDocx)
        self.ui.inspectorButton.clicked.connect(self.openInspector)

        self.ui.run1Button.clicked.connect(self.runScript1)
        self.ui.run2Button.clicked.connect(self.runScript2)
        self.ui.run3Button.clicked.connect(self.runScript3)

        # For my web inspector
        self.ui.documentView.settings().setAttribute(
            QWebSettings.DeveloperExtrasEnabled, True)
        self.webInspector = QWebInspector()

    def newScript(self):
        print 'Adding new script...'
        newTab = ScriptEditor()
        self.ui.javascriptTabs.addTab(newTab, newTab.label)

    def openDocx(self):
        print 'Opening document...'

        dir = os.path.normpath(os.path.join(os.getcwd(), '../tests'))

        newFile = QtGui.QFileDialog.getOpenFileName(caption='Open Docx...',
                                                    directory=dir,
                                                    filter='(*.docx)')
        if len(newFile) > 0:
            self.docxFile = str(newFile)
            url = os.path.join(os.getcwd(), '../import')
            baseUrl = QUrl.fromLocalFile(url)
            self.document = DocxDocument(str(self.docxFile))
            self.ui.documentView.setHtml(self.document.getMainPage(), baseUrl)

        print 'Done!'

    def openScript(self):
        print 'Opening script...'

        dir = os.path.normpath(os.path.join(os.getcwd(), '../docx'))

        newFile = QtGui.QFileDialog.getOpenFileName(
            caption='Open JavaScript...', directory=dir)

        if len(newFile) > 0:
            newTab = ScriptEditor(filename=str(newFile))
            self.ui.javascriptTabs.addTab(newTab, newTab.label)
            self.ui.javascriptTabs.setCurrentIndex(
                self.ui.javascriptTabs.count() - 1)

    def saveScript(self, index):
        # Check to see if it is modified. If not, don't do anything
        current = self.ui.javascriptTabs.widget(index)

        if current.modified:
            if len(current.filename) > 0:
                f = open(current.filename, 'w')
                f.write(current.editor.text())
                f.close()

                current.modified = False

                return True
            else:
                newFile = QtGui.QFileDialog.getSaveFileName()

                if len(newFile) > 0:
                    f.open(newFile, 'w')
                    f.write(current.editor.text())
                    f.close()

                    current.filename = newFile
                    current.modified = False

                    return True
                else:
                    return False

    def saveCurrentScript(self):
        print 'Saving current script...'
        index = self.ui.javascriptTabs.currentIndex()
        self.saveScript(index)
        self.resetDocx(None)

    def saveAllScripts(self):
        print 'Saving all scripts...'
        for i in range(self.ui.javascriptTabs.count()):
            self.saveScript(i)
        self.resetDocx(None)

    def onTabClose(self, index):
        print 'Tab closing:', index

        if self.ui.javascriptTabs.widget(index).modified:
            quit_msg = "Do you want to save?"
            reply = QtGui.QMessageBox.question(self, 'Save Script?', quit_msg,
                                               QtGui.QMessageBox.Yes,
                                               QtGui.QMessageBox.No)

            if reply == QtGui.QMessageBox.Yes:
                saved = self.saveScript(index)
                if saved:
                    self.ui.javascriptTabs.removeTab(index)
            else:
                self.ui.javascriptTabs.removeTab(index)
        else:
            self.ui.javascriptTabs.removeTab(index)

    def resetDocx(self, e):
        print 'Resetting document...'
        if len(self.docxFile) > 0:
            content = self.document.getMainPage()
            baseUrl = QUrl.fromLocalFile(os.path.join(os.getcwd(),
                                                      '../import'))
            self.ui.documentView.setHtml(content, baseUrl)

    def openInspector(self, e):
        self.webInspector.setPage(self.ui.documentView.page())
        self.webInspector.setVisible(True)

    def runScript1(self):
        print 'Running 1:', str(self.ui.commandLine1.text())
        self.ui.documentView.page().mainFrame().evaluateJavaScript(
            self.ui.commandLine1.text())

    def runScript2(self):
        print 'Running 2:', str(self.ui.commandLine2.text())
        self.ui.documentView.page().mainFrame().evaluateJavaScript(
            self.ui.commandLine2.text())

    def runScript3(self):
        print 'Running 3:', str(self.ui.commandLine3.text())
        self.ui.documentView.page().mainFrame().evaluateJavaScript(
            self.ui.commandLine3.text())

    def quit(self):
        self.close()
Example #26
0
    def _page_loaded(self, success):
        if self.develop and self.display:
            if self.inspector is None:
                self.inspector = QWebInspector()

            self.inspector.setPage(self.page)
            self.inspector.show()

        selenium_scripts = ['atoms.js',
                            'htmlutils.js',
                            'selenium-logging.js',

                            'find_matching_child.js',
                            'selenium-api.js',
                            'selenium-api-override.js',

                            'selenium-browserbot.js',
                            'selenium-browserdetect.js',
                            'selenium-commandhandlers.js',
                            'xmlextras.js', ]

        for script in selenium_scripts:
            # js_file = open(os.path.dirname(__file__) + '/../selenium-scripts/' + script).read()
            # self.main_frame.evaluateJavaScript(js_file)
            self.evaluate_js_file(os.path.dirname(__file__) + '/../selenium-scripts/' + script)

        self.evaluate(
            """

            selenium=Selenium.createForWindow(window);
            GCrawlerFactory = new CommandHandlerFactory();
            GCrawlerFactory.registerAll(selenium);

            function do_selenium_command(command,target,value)
            {

                var command=new SeleniumCommand(command,target,value, false);
                var handler=GCrawlerFactory.getCommandHandler(command.command);
                if (handler)
                {
                    command.target = selenium.preprocessParameter(command.target);
                    command.value = selenium.preprocessParameter(command.value);

                try
                {
                    handler.execute(selenium, command);
                }catch(e)
                {
                    if (e.isSeleniumError)
                        e.message;
                }

                }else
                {
                    'Do not hava command '+command.command;
                }
            }

""")

        self.loaded = True
        # self.cache.clear()
        logger.debug("Page load finished")
Example #27
0
class GRobot(object):
    _loop = None
    _liveRobot = 0
    _app = None
    _kill_loop=None
    exit_lock = RLock()

    def __init__(self, user_agent=default_user_agent, operate_timeout=10, loading_timeout=60, log_level=logging.WARNING,
                 display=False, viewport_size=(1024, 768), accept_language='en,*', ignore_ssl_errors=True,
                 cache_dir=os.path.join(tempfile.gettempdir(), "GRobot"),
                 image_enabled=True, plugins_enabled=False, java_enabled=False, javascript_enabled=True,
                 plugin_path=None, develop=False, proxy=None, sleep=0.5, jquery_namespace='GRobot'):
        """GRobot manages a QWebPage.
    
        @param user_agent: The default User-Agent header.
        @param operate_timeout: Operation timeout.
        @param loading_timeout: The page loading timeout.
        @param log_level: The optional logging level.
        @param display: A boolean that tells GRobot to displays UI.
        @param viewport_size: A tupple that sets initial viewport size.
        @param accept_language: Set the webkit accept language. 
        @param ignore_ssl_errors: A boolean that forces ignore ssl errors.
        @param cache_dir: A directory path where to store cache datas.
        @param image_enabled: Enable images.
        @param plugins_enabled: Enable plugins (like Flash).
        @param java_enabled: Enable Java JRE.
        @param javascript_enabled: Enable Javascript.
        @param plugin_path: Array with paths to plugin directories (default ['/usr/lib/mozilla/plugins'])
        @param develop: Enable the Webkit Inspector.
        @param proxy: Set a Socks5,HTTP{S} Proxy
        @param sleep: Sleep `sleep` second,after operate
        @param jquery_namespace: Set the jQuery namespace.
        """

        GRobot.exit_lock.acquire()

        if GRobot._kill_loop:
            gevent.kill(GRobot._kill_loop)
            GRobot._kill_loop=None

        logger.setLevel(log_level)

        plugin_path = plugin_path or ['/usr/lib/mozilla/plugins', ]

        GRobot._liveRobot += 1

        self.develop = develop
        self.inspector = None
        self.plugin = False
        self.exitLoop = False
        self._deleted = False

        self.set_proxy(proxy)

        self.sleep = sleep
        self.jquery_namespace = jquery_namespace
        self.popup_messages = None
        self.accept_language = accept_language

        self._loaded = True

        self._confirm_expected = None
        self._prompt_expected = None
        self._upload_file = None
        self._alert = None

        self.http_resources = []

        self.user_agent = user_agent

        self.loading_timeout = loading_timeout
        self.operate_timeout = operate_timeout

        self.ignore_ssl_errors = ignore_ssl_errors

        if not sys.platform.startswith('win') and not 'DISPLAY' in os.environ \
            and not hasattr(GRobot, 'xvfb'):
            try:
                os.environ['DISPLAY'] = ':99'
                GRobot.xvfb = subprocess.Popen(['Xvfb', ':99'])
            except OSError:
                raise Exception('Xvfb is required to a GRobot run oustside ' + \
                                'an X instance')

        self.display = display

        if not GRobot._app:
            GRobot._app = QApplication.instance() or QApplication(['GRobot'])
            if plugin_path:
                for p in plugin_path:
                    GRobot._app.addLibraryPath(p)

        self.page = GRobotWebPage(self, GRobot._app)

        QtWebKit.QWebSettings.setMaximumPagesInCache(0)
        QtWebKit.QWebSettings.setObjectCacheCapacities(0, 0, 0)
        QtWebKit.QWebSettings.globalSettings().setAttribute(QtWebKit.QWebSettings.LocalStorageEnabled, True)

        self.page.setForwardUnsupportedContent(True)

        # Page signals
        self.page.loadFinished.connect(self._page_loaded)
        self.page.loadStarted.connect(self._page_load_started)
        self.page.unsupportedContent.connect(self._unsupported_content)

        self.manager = self.page.networkAccessManager()

        #TODO:Think about how to handle the network accessible signal
        #self.manager.networkAccessibleChanged.connect()

        self.manager.finished.connect(self._request_ended)
        self.manager.sslErrors.connect(self._on_manager_ssl_errors)

        # Cache
        self.cache = QNetworkDiskCache()
        self.cache.setCacheDirectory(cache_dir)

        self.manager.setCache(self.cache)

        # Cookie jar
        self.cookie_jar = QNetworkCookieJar()
        self.manager.setCookieJar(self.cookie_jar)

        # User Agent
        self.page.setUserAgent(self.user_agent)

        self.page.networkAccessManager().authenticationRequired \
            .connect(self._authenticate)
        self.page.networkAccessManager().proxyAuthenticationRequired \
            .connect(self._authenticate)

        self.main_frame = self.page.mainFrame()

        self.webview = None

        self.viewport_size = viewport_size

        self.webview = QtWebKit.QWebView()
        self.webview.setPage(self.page)

        self.webview.show() if display else self.webview.hide()

        self.set_viewport_size(*viewport_size)

        self.page.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, plugins_enabled)
        self.page.settings().setAttribute(QtWebKit.QWebSettings.JavaEnabled, java_enabled)
        self.page.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, self.develop)

        self.enable_image = image_enabled
        self.enable_javascript = javascript_enabled

        #always open link in current window instead of new window
        self.page.setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.page.linkClicked.connect(self._link_clicked)

        #start the qt main loop
        GRobot._loop = QtMainLoop(GRobot._app)
        GRobot._loop.start()
        GRobot.exit_lock.release()

    @property
    def popup_messages(self):
        return self._popup_messages

    @popup_messages.setter
    def popup_messages(self, value):
        self._popup_messages = str(value)


    @property
    def url(self):
        return str(self.main_frame.url().toString())



    def content(self):
        """Returns current frame HTML as a string."""
        return str(self.main_frame.toHtml())

    @property
    def cookies(self):
        """Returns all cookies."""
        return self.cookie_jar.allCookies()


    @property
    def enable_image(self):
        """Disable the page images can speed up page loading.

        """
        return self._enable_image

    @enable_image.setter
    def enable_image(self, value):
        self.page.settings().setAttribute(QWebSettings.AutoLoadImages, value)
        self._enable_image = value

    #TODO:It seems not work?
    # @enable_image.deleter
    # def enable_image(self):
    #     raise NotImplemented

    @property
    def enable_javascript(self):
        """Disable the page javascript can speed up page loading.

        """
        return self._enable_javascript

    @enable_javascript.setter
    def enable_javascript(self, value):
        self.page.settings().setAttribute(QWebSettings.JavascriptEnabled, value)
        self._enable_javascript = value


    def open(self, address, method='get', headers=None, auth=None, body=None,
             default_popup_response=None):
        """Opens a web page.

        @param address: The resource URL.
        @param method: The Http method.
        @param headers: An optional dict of extra request hearders.
        @param auth: An optional tupple of HTTP auth (username, password).
        @param body: An optional string containing a payload.
        @param default_popup_response: the default response for any confirm/
        alert/prompt popup from the Javascript (replaces the need for the with
        blocks)
        """

        headers = headers or {}

        body = body or QByteArray()
        try:
            method = getattr(QNetworkAccessManager,
                             "%sOperation" % method.capitalize())
        except AttributeError:
            raise Exception("Invalid http method %s" % method)
        request = QNetworkRequest(QUrl(address))
        request.CacheLoadControl = 0
        for header in headers:
            request.setRawHeader(header, headers[header])
        self._auth = auth
        self._auth_attempt = 0  # Avoids reccursion
        self.page.mainFrame().load(request, method, body)
        self._loaded = False

        if default_popup_response is not None:
            self._prompt_expected = (default_popup_response, None)
            self._confirm_expected = (default_popup_response, None)

        return self.wait_for_page_loaded()

    def set_viewport_size(self, width, height):
        """Sets the page viewport size.

        @param width: An integer that sets width pixel count.
        @param height: An integer that sets height pixel count.
        """

        if self.display:
            self.webview.resize(QSize(width, height))
        self.page.setViewportSize(QSize(width, height))


    def set_proxy(self, proxy=None):
        """Set the proxy or using system configuration as None,supported socks5 http{s}.

        @param proxy: Example:socks5://username:[email protected]:7070
        """
        proxy_type = None
        if proxy:
            parse = urlparse(proxy)
            scheme = parse.scheme
            hostname = parse.hostname
            port = parse.port
            username = parse.username or ''
            password = parse.password or ''

            if scheme == 'socks5':
                proxy_type = QNetworkProxy.Socks5Proxy
            elif scheme in ('http', 'https'):
                proxy_type = QNetworkProxy.HttpProxy

        if proxy_type:
            self.page.networkAccessManager().setProxy(
                QNetworkProxy(proxy_type, hostname, port, username, password)
            )
        else:
            QNetworkProxyFactory.setUseSystemConfiguration(True)

    def first_element_position(self, selector):
        try:
            return self.elements_position(selector)[0]
        except IndexError:
            logger.warning("Can't locate selector " + selector)
            return None


    def elements_position(self, selector):
        """Get the position of elements whose match selector

        @param selector:
        @return: position of QPoint
        """
        attr, pattern, val = self.parser_selector(selector, attr='identifier')

        strip = lambda v: v.strip()

        if pattern:
            val = locals()[pattern](val)


        def identifier(query):
            return id(query) or name(query)

        def name(query):
            return css("*[name='%s']" % query)

        def id(query):
            return css('#' + query)

        def link(query):
            return xpath("//a[text()='%s']" % query.replace("\'", "\\'"))

        def css(query):
            result = []
            for ele in self.main_frame.findAllElements(query):
                if not ele.isNull():
                    result.append(ele.geometry().center())
            return result

        def xpath(query):
            positions = self.evaluate("""
            function GetAbsoluteLocationEx(element)
            {
                if ( arguments.length != 1 || element == null )
                {
                    return null;
                }
                var elmt = element;
                var offsetTop = elmt.offsetTop;
                var offsetLeft = elmt.offsetLeft;
                var offsetWidth = elmt.offsetWidth;
                var offsetHeight = elmt.offsetHeight;
                while( elmt = elmt.offsetParent )
                {
                      // add this judge
                    if ( elmt.style.position == 'absolute' || elmt.style.position == 'relative'
                        || ( elmt.style.overflow != 'visible' && elmt.style.overflow != '' ) )
                    {
                        break;
                    }
                    offsetTop += elmt.offsetTop;
                    offsetLeft += elmt.offsetLeft;
                }
                return { absoluteTop: offsetTop, absoluteLeft: offsetLeft,
                    offsetWidth: offsetWidth, offsetHeight: offsetHeight };
            }
            result=[];
            for (var r = document.evaluate('%s', document, null, 5, null), n; n = r.iterateNext();) {
            pos=GetAbsoluteLocationEx(n)
            result.push([pos.absoluteLeft+pos.offsetWidth/2.0,pos.absoluteTop+pos.offsetHeight/2.0]);
            }
            result
            """ % query.replace("\'", "\\'"))

            return [QPoint(*tuple(x)) for x in positions]

        return locals()[attr](val)


    def _move_page_center_to(self, qpoint):
        size = self.page.viewportSize()
        self.main_frame.setScrollPosition(qpoint - QPoint(size.width(), size.height()) / 2)


    def reload(self):
        """Reload page.

        @return:
        """

        self.trigger_action('Reload', expect_loading=True)

    def back(self):
        self.trigger_action('Back')

    def forward(self):
        self.trigger_action('Forward')


    @can_load_page
    def trigger_action(self, action):
        """Trigger QWebPage::WebAction

        @param action:
        """
        self.page.triggerAction(getattr(QWebPage, action))


    def parser_selector(self, selector, attr=None, pattern=None, val=None):
        index = selector.find('=')

        if index <= 0:
            val = selector
        else:
            attr = selector[:index]
            value_ = selector[index + 1:]
            index = value_.find(':')

            if index > 0:
                pattern = value_[:index]

            val = value_[index + 1:]

        return attr, pattern, val


    @can_load_page
    @have_a_break
    def click(self, selector):
        qpoint = self.first_element_position(selector)
        if qpoint:
            return self.qpoint_to_tuple(self._click_position(qpoint))

    @can_load_page
    @have_a_break
    def test(self):
        return self.qpoint_to_tuple(QPoint(1, 2))


    @can_load_page
    def _click_position(self, qpoint):
        self._move_page_center_to(qpoint)
        self.webview.repaint()
        pos = qpoint - self.main_frame.scrollPosition()

        self._move_to_position(pos)
        QTest.mouseClick(self.webview, Qt.LeftButton, pos=pos)
        gevent.sleep(1)
        return pos


    def qpoint_to_tuple(self, qpoint):
        return qpoint.x(), qpoint.y()

    @have_a_break
    def move_to(self, selector):
        qpoint = self.first_element_position(selector)
        if qpoint:
            self._move_to_position(qpoint)
            return qpoint_to_tuple(qpoint)

    def move_at(self, x, y):
        return self._move_to_position(QPoint(x, y))

    def _move_to_position(self, qpoint):
        QTest.mouseMove(self.webview, pos=qpoint)
        return qpoint

    @can_load_page
    @have_a_break
    def click_at(self, x, y):
        return self._click_position(QPoint(x, y))


    @have_a_break
    def key_clicks(self, selector, text):
        if selector:
            self.click(selector)
        QTest.keyClicks(self.webview, text, delay=50)

    @have_a_break
    def type(self, selector, text):
        position = self.click(selector)

        ele = self._hit_element_from(QPoint(*position))

        ele.setFocus()
        ele.evaluateJavaScript(
            """
            core.events.setValue(this, '%s')
            """ % (text.replace("\n", "\\n").replace("\'", "\\'"))
        )
        logger.debug('type %s %s' % (selector, text))


    def _hit_element_from(self, position):
        return self.main_frame.hitTestContent(position).element()

    def first_element(self, selector):
        position = self.first_element_position(selector)
        if position:
            return self.main_frame.hitTestContent(position).element(), position


    def wait_forever(self):
        self.wait_for(lambda: False, time_for_stop=-1)

    @have_a_break
    def check(self, selector, checked=True):
        ele, position = self.first_element(selector)
        if ele and ele.tagName() == 'INPUT':
            if ele.attribute('type') in ['checkbox', 'radio']:
                ele_checked = ele.attribute('checked') == 'checked' or False
                if ele_checked != checked:
                    self._click_position(position)
            else:
                raise ValueError("%s is not a checkbox or radio" % selector)

    @have_a_break
    def select(self, selector, value):

        def _select(query, select_by, select):
            select.evaluateJavaScript("""
            triggerEvent(this, 'focus', false);
            var changed = false;
            var optionToSelect = '%s';
            for (var i = 0; i < this.options.length; i++) {
                var option = this.options[i];
                if (option.selected && option.%s != optionToSelect) {
                    option.selected = false;
                    changed = true;
                }
                else if (!option.selected && option.%s == optionToSelect) {
                    option.selected = true;
                    changed = true;
                }
            }

            if (changed) {
                triggerEvent(this, 'change', true);
            }
            """ % ( query.replace("\'", "\\'"), select_by, select_by))

        def _add_selection(query, select_by, select, selected):
            select.evaluateJavaScript("""
            triggerEvent(this, 'focus', false);
            var optionToSelect = '%s';
            for (var i = 0; i < this.options.length; i++) {
                var option = this.options[i];
                if (option.%s == optionToSelect)
                {
                    option.selected = %s;
                    triggerEvent(this, 'change', true);
                }

            }
            """ % ( query.replace("\'", "\\'"), select_by, selected and 'true' or 'false'))

        ele, position = self.first_element(selector)

        if ele and ele.tagName() == 'SELECT':
            ele.setFocus()

            if ele.attribute('multiple') == 'multiple':
                assert isinstance(value, list)
                for value_, selected in value:
                    attr, pattern, val = self.parser_selector(value_, attr='text')
                    _add_selection(val, attr, ele, selected)
            else:
                attr, pattern, val = self.parser_selector(value, attr='text')
                _select(val, attr, ele)


    def choose_file(self, selector, file):
        self._upload_file = file
        self.click(selector)
        self._upload_file = None


    def capture(self, selector=None):
        """Capture the images of selector.

        @param selector: Css selector.
        @return: Images
        """

        elements = self.main_frame.documentElement().findAll(selector)
        imgs = []

        for element in elements:
            geo = element.geometry()
            img = QImage(geo.width(), geo.height(), QImage.Format_ARGB32)
            painter = QPainter(img)
            element.render(painter)
            painter.end()
            imgs.append(img)

        return imgs

    def capture_to(self, path, selector=None):
        """Capture the images of selector to files.

        @param path: File path with index suffix.
        @param selector: Css selector.
        @return: The paths of saving.
        """

        _, ext = os.path.splitext(path)
        ext = ext[1:]

        imgs = self.capture(selector)
        result = []
        for index, img in enumerate(imgs):
            filepath = '%s.%s' % (path, index)
            if img.save(filepath, ext.upper()):
                result.append(filepath)

        return result

    def capture_to_buf(self, selector=None):
        """capture the images of selector to StringIO

        @param selector: Css selector.
        @return: The StringIO list.
        """

        images = self.capture(selector)
        result = []

        for image in images:
            ba = QByteArray()
            buf = QBuffer(ba)
            buf.open(QIODevice.ReadWrite)
            image.save(buf, 'jpg')
            stream = StringIO(str(buf.buffer()))
            result.append(stream)

        return result


    @can_load_page
    def evaluate(self, script):
        """Evaluates script in page frame.

        @param script: The script to evaluate.
        """
        result = self.main_frame.evaluateJavaScript("%s" % script)
        # if isinstance(result,QString):
        #     result=unicode(result)
        return result

    def evaluate_js_file(self, path, encoding='utf-8'):
        """Evaluates javascript file at given path in current frame.
        Raises native IOException in case of invalid file.

        @param path: The path of the file.
        @param encoding: The file's encoding.
        """
        self.evaluate(codecs.open(path, encoding=encoding).read())

    def __del__(self):
        """Depend on the CG of Python.
        """
        self.exit()


    def delete_cookies(self):
        """Deletes all cookies."""
        self.cookie_jar.setAllCookies([])

    def exists(self, selector):
        """Checks if element exists for given selector.

        @param string: The element selector.
        """
        return not self.main_frame.findFirstElement(selector).isNull()


        #TODO: Still not work.

    #     def remove_css(self):
    #         """Remore the css,speed up page loading.
    #
    #         @return:
    #         """
    #
    #         return self.evaluate("""var targetelement="link";//determine element type to create nodelist from
    # var targetattr="href"//determine corresponding attribute to test for
    # var allsuspects=document.getElementsByTagName(targetelement)
    # for (var i=allsuspects.length; i>=0; i--){ //search backwards within nodelist for matching elements to remove
    # if (allsuspects[i] && allsuspects[i].getAttribute(targetattr)!=null )
    # allsuspects[i].parentNode.removeChild(allsuspects[i]); //remove element by calling parentNode.removeChild()
    # }
    #         """)


    def filter_resources(self, pattern):
        """Filter resources with pattern.

        @param pattern: Match pattern.
        @param resources:
        @return: @raise:
        """
        if isinstance(pattern, str):
            is_match = lambda x: pattern == x
        elif isinstance(pattern, _pattern_type):
            is_match = lambda x: pattern.match(x)
        elif hasattr(pattern, '__call__'):
            is_match = pattern
        else:
            raise TypeError('pattern must be one of str,re.compile,callable')
        return filter(lambda x: is_match(x.request_url), self.http_resources)[:]


    def save(self, path):
        """Save current page content to the path.
        
        @param path: The path to save.
        """
        f = open(path, 'w')
        f.write(self.content().encode('utf-8'))
        f.close()

    def global_exists(self, global_name):
        """Checks if javascript global exists.

        @param global_name: The name of the global.
        """
        return self.evaluate('!(typeof %s === "undefined");' %
                             global_name)


    def load_cookies( self, cookie_storage, keep_old=False ):
        """load from cookielib's CookieJar or Set-Cookie3 format text file.

        @param cookie_storage: file location string on disk or CookieJar instance.
        @param keep_old: Don't reset, keep cookies not overridden.
        """

        def toQtCookieJar( PyCookieJar, QtCookieJar ):
            allCookies = QtCookieJar.cookies if keep_old else []
            for pc in PyCookieJar:
                qc = toQtCookie(pc)
                allCookies.append(qc)
            QtCookieJar.setAllCookies(allCookies)

        def toQtCookie(PyCookie):
            qc = QNetworkCookie(PyCookie.name, PyCookie.value)
            qc.setSecure(PyCookie.secure)
            if PyCookie.path_specified:
                qc.setPath(PyCookie.path)
            if PyCookie.domain != "":
                qc.setDomain(PyCookie.domain)
            if PyCookie.expires != 0:
                t = QDateTime()
                t.setTime_t(PyCookie.expires)
                qc.setExpirationDate(t)
                # not yet handled(maybe less useful):
            #   py cookie.rest / QNetworkCookie.setHttpOnly()
            return qc

        if cookie_storage.__class__.__name__ == 'str':
            cj = LWPCookieJar(cookie_storage)
            cj.load()
            toQtCookieJar(cj, self.cookie_jar)
        elif cookie_storage.__class__.__name__.endswith('CookieJar'):
            toQtCookieJar(cookie_storage, self.cookie_jar)
        else:
            raise ValueError('unsupported cookie_storage type.')


    def save_cookies(self, cookie_storage):
        """Save to cookielib's CookieJar or Set-Cookie3 format text file.

        @param cookie_storage: file location string or CookieJar instance.
        """

        def toPyCookieJar(QtCookieJar, PyCookieJar):
            for c in QtCookieJar.allCookies():
                PyCookieJar.set_cookie(toPyCookie(c))

        def toPyCookie(QtCookie):
            port = None
            port_specified = False
            secure = QtCookie.isSecure()
            name = str(QtCookie.name())
            value = str(QtCookie.value())
            v = str(QtCookie.path())
            path_specified = bool(v != "")
            path = v if path_specified else None
            v = str(QtCookie.domain())
            domain_specified = bool(v != "")
            domain = v
            domain_initial_dot = v.startswith('.') if domain_specified else None
            v = int(QtCookie.expirationDate().toTime_t())
            # Long type boundary on 32bit platfroms; avoid ValueError
            expires = 2147483647 if v > 2147483647 else v
            rest = {}
            discard = False
            return Cookie(0, name, value, port, port_specified, domain
                , domain_specified, domain_initial_dot, path, path_specified
                , secure, expires, discard, None, None, rest)

        if cookie_storage.__class__.__name__ == 'str':
            cj = LWPCookieJar(cookie_storage)
            toPyCookieJar(self.cookie_jar, cj)
            cj.save()
        elif cookie_storage.__class__.__name__.endswith('CookieJar'):
            toPyCookieJar(self.cookie_jar, cookie_storage)
        else:
            raise ValueError('unsupported cookie_storage type.')


    def wait_for_confirm(self, confirm=True, callback=None):
        """Statement that tells GRobot how to deal with javascript confirm().

        @param confirm: A bollean that confirm.
        @param callable: A callable that returns a boolean for confirmation.
        """

        self._robot._confirm_expected = (confirm, callback)
        self._robot.wait_for(lambda: self._robot._confirm_expected is None)
        return self.popup_messages


    def wait_for_text(self, text, time_for_stop=None):
        """Waits until given text appear on main frame.

        @param text: The text to wait for.
        @return:
        """

        logger.debug("Wait for text %s" % text)

        self.wait_for(lambda: text in self.content(),
                      "Can\'t find '%s' in current frame" % text, time_for_stop=time_for_stop)

        return self.wait_for_page_loaded()

    def wait_for_xpath(self, expression, time_for_stop=None):
        self.wait_for(lambda: XPath(self.content()).execute(expression),
                      "Can't find xpath=%s in current frame" % expression, time_for_stop=time_for_stop)
        return self.wait_for_page_loaded()


    def wait_for_selector(self, selector):
        """Waits until selector match an element on the frame.

        @param selector: The selector to wait for.
        """
        self.wait_for(lambda: self.exists(selector),
                      'Can\'t find element matching "%s"' % selector)

    def wait_for_page_loaded(self, time_for_stop=None):
        """Waits until page is loaded, assumed that a page as been requested.

        """
        return self.wait_for(lambda: self._loaded,
                             'Unable to load requested page', time_for_stop=time_for_stop)

    def wait_for(self, condition, timeout_message='', time_for_stop=None):
        """Waits until condition is True.

        @param condition: A callable that returns the condition.
        @param timeout_message: The exception message on timeout.-1 means never timeout.
        """

        if self._loaded:
            time_for_stop = time_for_stop or self.operate_timeout
        else:
            time_for_stop = time_for_stop or self.loading_timeout

        started_at = time.time()
        while not condition():
            if time_for_stop != -1 and time.time() > (started_at + time_for_stop):
                if self._loaded:
                    raise OperateTimeout(timeout_message)
                else:
                    # raise LoadingTimeout, timeout_message
                    self.trigger_action('Stop') #QWebPage::Stop
                    self._loaded = True
                    logger.warning("Page loading timeout.Force to stop the page")
                    break

            gevent.sleep(2)

    def wait_for_alert(self):
        """Waits for main frame alert().
        """
        self.wait_for(lambda: self._alert is not None,
                      'User has not been alerted.')
        msg, self._alert = self._alert, None
        return msg

    def _release_last_resources(self):
        """Releases last loaded resources.

        :return: The released resources.
        """
        last_resources, self.http_resources = self.http_resources[:], []
        return last_resources


    def _page_loaded(self, success):
        if self.develop and self.display:
            if self.inspector is None:
                self.inspector = QWebInspector()

            self.inspector.setPage(self.page)
            self.inspector.show()

        scripts = [
            'atoms.js',
            'htmlutils.js',
        ]

        if self.jquery_namespace:
            scripts.append('jquery-1.9.1.min.js', )

        for script in scripts:
            self.evaluate_js_file(os.path.dirname(__file__) + '/javascripts/' + script)

        if self.jquery_namespace:
            self.evaluate("%s=jQuery.noConflict();" % self.jquery_namespace)

        self._loaded = True
        # self.cache.clear()
        logger.debug("Page load finished")

    def _page_load_started(self):
        logger.debug("Start load page")

        self._loaded = False

    def _unsupported_content(self, reply):
        """Adds an HttpResource object to http_resources with unsupported
        content.

        @param reply: The QNetworkReply object.
        """

        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute):
            self.http_resources.append(HttpResource(reply, self.cache,
                                                    reply.readAll()))

    def _link_clicked(self, href):
        """Contorl the page link clicked event,forbid open new window.

        @param href: The href attribute of a tag.
        """

        self.main_frame.load(href)

    def _request_ended(self, reply):
        """Adds an HttpResource object to http_resources.

        @param reply: The QNetworkReply object.
        """

        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute):
            self.http_resources.append(HttpResource(reply, self.cache))

    def _authenticate(self, mix, authenticator):
        """Called back on basic / proxy http auth.

        @param mix: The QNetworkReply or QNetworkProxy object.
        @param authenticator: The QAuthenticator object.
        """
        if self._auth_attempt == 0:
            username, password = self._auth
            authenticator.setUser(username)
            authenticator.setPassword(password)
            self._auth_attempt += 1

    def _on_manager_ssl_errors(self, reply, errors):
        """Ingore all the ssl error

        @param reply:
        @param errors:
        """
        url = str(reply.url().toString())
        if self.ignore_ssl_errors:
            reply.ignoreSslErrors()
        else:
            logger.warning('SSL certificate error: %s' % url)


    def exit(self):
        """Destroy the Qt main event loop.

        """
        GRobot.exit_lock.acquire()
        if not self._deleted:
            if self.inspector:
                self.inspector.close()
                sip.delete(self.inspector)

            if self.display:
                self.webview.close()
                sip.delete(self.webview)

            if self.page and not sip.isdeleted(self.page):
                sip.delete(self.page)

            GRobot._liveRobot -= 1

            if GRobot._liveRobot == 0 and GRobot._loop is not None:
                GRobot._kill_loop=gevent.spawn_later(20,self.kill_loop)


            self._deleted = True

        GRobot.exit_lock.release()

    def kill_loop(self):
        GRobot._loop.stop()
        GRobot._loop = None
        GRobot._app = None
        if hasattr(self, 'xvfb'):
            GRobot.xvfb.terminate()
class SynopticWidget(QtGui.QWidget):

    """
    A Qt widget displaying a SVG synoptic in a webview.

    This widget does not have a "backend", so it's intended
    to be subclassed to add control system specific behavior.
    See TaurusSynopticWidget for a TANGO implementation.
    """

    subscribe = QtCore.pyqtSignal(str)

    def __init__(self, url=None, parent=None, *args, **kwargs):
        super(SynopticWidget, self).__init__(parent)
        self.subscribe.connect(self._handle_subscriptions)
        self._url = url
        self._setup_ui(url)

    def _setup_ui(self, url=None, section=None):
        self.hbox = hbox = QtGui.QHBoxLayout(self)
        self.hbox.setContentsMargins(0, 0, 0, 0)
        self.hbox.layout().setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.hbox)
        if url:
            self.set_url(url, section)

    def set_url(self, url, section=None):
        # TODO: probably breaks things if the url is already set
        self._url = url
        self.splitter = QtGui.QSplitter(self)
        self.splitter.setOrientation(QtCore.Qt.Vertical)
        self.hbox.addWidget(self.splitter)
        view = self._create_view(url, section)
        self._setup_inspector(view)
        self.splitter.addWidget(view)
        print "set_url", url

    def _create_view(self, html=None, section=None):
        "Create the webview that will display the synoptic itself"
        view = QWebView(self)

        # This is supposedly an optimisation. Disable if there are
        # graphical artifacts or something.
        view.settings().TiledBackingStoreEnabled = True
        view.setRenderHint(QtGui.QPainter.TextAntialiasing, False)

        page = LoggingWebPage()
        view.setPage(page)
        view.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)

        # setup the JS interface
        frame = view.page().mainFrame()
        self.js = JSInterface(frame)
        self.js.subscription.connect(self.subscribe)

        # mouse interaction signals
        self.clicked = self.js.leftclicked
        self.rightClicked = self.js.rightclicked
        self.hovered = self.js.hovered
        self.clicked.connect(self._on_click)
        self.rightClicked.connect(self._on_rightclick)
        self.hovered.connect(self._on_hover)

        # Inject JSInterface into the JS global namespace as "Backend"
        def addBackend():
            frame.addToJavaScriptWindowObject('Backend', self.js)
        view.connect(frame, QtCore.SIGNAL("javaScriptWindowObjectCleared()"), addBackend)

        # load the page
        # need to set the "base URL" for the webview to find the
        # resources (js, css).
        base_url = QtCore.QUrl().fromLocalFile(
            os.path.abspath(os.path.dirname(__file__)) + "/web/")

        # some ugly magic to get the path to the SVG file right. It
        # needs to be absolute because local paths go to the base URL.
        abspath = os.path.dirname(os.path.abspath(html))
        with open(html) as f:
            text = f.read().replace("${path}", abspath)  # TODO: use template
            view.setHtml(text, base_url)

        return view

    def _setup_inspector(self, view):

        """Create a WebInspector widget connected to the WebView. This allows inspecting
        the DOM, debugging javascript, logging, etc. Can be toggled using F12."""

        self._inspector = None
        page = view.page()

        def toggle_inspector():
            if self._inspector:
                self._inspector.setVisible(not self._inspector.isVisible())
            else:
                # create the inspector "on demand"
                page.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
                self._inspector = QWebInspector(self)
                self._inspector.setPage(page)
                self.splitter.addWidget(self._inspector)

        shortcut = QtGui.QShortcut(self)
        shortcut.setKey(QtCore.Qt.Key_F12)
        shortcut.activated.connect(toggle_inspector)

    def _handle_subscriptions(self, models):
        # we get the subscribed models as a comma separated list from Qt,
        # let's deliver something neater.
        if models:
            self.handle_subscriptions(str(models).split("\n"))
        else:
            self.handle_subscriptions([])

    def handle_subscriptions(self, models):
        # This noop needs to be overridden in order for subscriptions
        # to actually do anything!
        # "models" is a list of models that are currently visible
        # in the synoptic.
        pass

    def _on_click(self, kind, name):
        # this is a workaround for a strange behavior; under some circumstances
        # we get QStrings here, and sometimes unicode. Investigate!
        self.on_click(str(kind), str(name))

    def on_click(self, kind, name):
        """Default behavior on click. Override to change!"""
        if kind == "section":
            self.zoom_to(kind, name)
        elif kind == "model":
            self.select(kind, [name])

    def _on_rightclick(self, kind, name):
        # see _on_click()
        self.on_rightclick(str(kind), str(name))

    def on_rightclick(self, kind, name):
        "Placeholder; override me!"
        pass

    def _on_hover(self, section, models):
        # we get a comma separated string of concatenated models here.
        splitmodels = str(models).split("\n") if models else []
        self.on_hover(section, splitmodels)

    def on_hover(self, section, models):
        "Show a basic 'tooltip' when the mouse pointer is over an item."
        # Override this to add more interesting behavior
        if section:
            self.js.evaluate("synoptic.showTooltip();")
            self.js.evaluate("synoptic.setTooltipHTML('%s')" % section)
        elif models:
            self.js.evaluate("synoptic.showTooltip();")
            self.js.evaluate("synoptic.setTooltipHTML('%s')" % models[0])
        else:
            self.js.evaluate("synoptic.hideTooltip();")

    # # # 'Public' API # # #

    def zoom_to(self, kind, name):
        "Move the view so that the given object is visible"
        self.js.evaluate("synoptic.zoomTo(%r, %r)" % (str(kind), str(name)))

    def select(self, kind, names, replace=True):
        """Set a list of items as 'selected'. By default unselects all
        previously selected things first.
        """
        print "select", kind, names
        if replace:
            self.js.evaluate("synoptic.unselectAll()")
        if names:
            for name in names:
                self.js.evaluate("synoptic.select(%r, %r)" %
                                 (str(kind), [str(name)]))

    def unselect_all(self):
        self.js.evaluate("synoptic.unselectAll();")
Example #29
0
class GRobot(object):
    _loop = None
    _liveRobot = 0
    _app = None
    exit_lock = RLock()

    def __init__(self, user_agent=default_user_agent, operate_timeout=10, loading_timeout=60, log_level=logging.WARNING,
                 display=False, viewport_size=(1024, 768), accept_language='en,*', ignore_ssl_errors=True,
                 cache_dir=os.path.join(tempfile.gettempdir(), "GRobot"),
                 image_enabled=True, plugins_enabled=False, java_enabled=False, javascript_enabled=True,
                 plugin_path=None, develop=False, proxy=None, sleep=0.5, jquery_namespace='GRobot'):
        """GRobot manages a QWebPage.
    
        @param user_agent: The default User-Agent header.
        @param operate_timeout: Operation timeout.
        @param loading_timeout: The page loading timeout.
        @param log_level: The optional logging level.
        @param display: A boolean that tells GRobot to displays UI.
        @param viewport_size: A tupple that sets initial viewport size.
        @param accept_language: Set the webkit accept language. 
        @param ignore_ssl_errors: A boolean that forces ignore ssl errors.
        @param cache_dir: A directory path where to store cache datas.
        @param image_enabled: Enable images.
        @param plugins_enabled: Enable plugins (like Flash).
        @param java_enabled: Enable Java JRE.
        @param javascript_enabled: Enable Javascript.
        @param plugin_path: Array with paths to plugin directories (default ['/usr/lib/mozilla/plugins'])
        @param develop: Enable the Webkit Inspector.
        @param proxy: Set a Socks5,HTTP{S} Proxy
        @param sleep: Sleep `sleep` second,after operate
        @param jquery_namespace: Set the jQuery namespace.
        """

        GRobot.exit_lock.acquire()
        logger.setLevel(log_level)

        plugin_path = plugin_path or ['/usr/lib/mozilla/plugins', ]

        GRobot._liveRobot += 1

        self.develop = develop
        self.inspector = None
        self.plugin = False
        self.exitLoop = False

        self.set_proxy(proxy)

        self.sleep = sleep
        self.jquery_namespace = jquery_namespace
        self.popup_messages = None
        self.accept_language = accept_language

        self._loaded = True

        self._confirm_expected = None
        self._prompt_expected = None
        self._upload_file = None
        self._alert = None

        self.http_resources = []

        self.user_agent = user_agent

        self.loading_timeout = loading_timeout
        self.operate_timeout = operate_timeout

        self.ignore_ssl_errors = ignore_ssl_errors

        if not sys.platform.startswith('win') and not 'DISPLAY' in os.environ \
            and not hasattr(GRobot, 'xvfb'):
            try:
                os.environ['DISPLAY'] = ':99'
                GRobot.xvfb = subprocess.Popen(['Xvfb', ':99'])
            except OSError:
                raise Exception('Xvfb is required to a GRobot run oustside ' + \
                                'an X instance')

        self.display = display

        if not GRobot._app:
            GRobot._app = QApplication.instance() or QApplication(['GRobot'])
            if plugin_path:
                for p in plugin_path:
                    GRobot._app.addLibraryPath(p)

        self.page = GRobotWebPage(self, GRobot._app)

        QtWebKit.QWebSettings.setMaximumPagesInCache(0)
        QtWebKit.QWebSettings.setObjectCacheCapacities(0, 0, 0)
        QtWebKit.QWebSettings.globalSettings().setAttribute(QtWebKit.QWebSettings.LocalStorageEnabled, True)

        self.page.setForwardUnsupportedContent(True)

        # Page signals
        self.page.loadFinished.connect(self._page_loaded)
        self.page.loadStarted.connect(self._page_load_started)
        self.page.unsupportedContent.connect(self._unsupported_content)

        self.manager = self.page.networkAccessManager()

        #TODO:Think about how to handle the network accessible signal
        #self.manager.networkAccessibleChanged.connect()

        self.manager.finished.connect(self._request_ended)
        self.manager.sslErrors.connect(self._on_manager_ssl_errors)

        # Cache
        self.cache = QNetworkDiskCache()
        self.cache.setCacheDirectory(cache_dir)

        self.manager.setCache(self.cache)

        # Cookie jar
        self.cookie_jar = QNetworkCookieJar()
        self.manager.setCookieJar(self.cookie_jar)

        # User Agent
        self.page.setUserAgent(self.user_agent)

        self.page.networkAccessManager().authenticationRequired \
            .connect(self._authenticate)
        self.page.networkAccessManager().proxyAuthenticationRequired \
            .connect(self._authenticate)

        self.main_frame = self.page.mainFrame()

        self.webview = None

        self.viewport_size = viewport_size

        self.webview = QtWebKit.QWebView()
        self.webview.setPage(self.page)

        self.webview.show() if display else self.webview.hide()

        self.set_viewport_size(*viewport_size)

        self.page.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, plugins_enabled)
        self.page.settings().setAttribute(QtWebKit.QWebSettings.JavaEnabled, java_enabled)
        self.page.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, self.develop)

        self.enable_image = image_enabled
        self.enable_javascript = javascript_enabled

        #always open link in current window instead of new window
        self.page.setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
        self.page.linkClicked.connect(self._link_clicked)

        #start the qt main loop
        GRobot._loop = QtMainLoop(GRobot._app)
        GRobot._loop.start()
        GRobot.exit_lock.release()

    @property
    def popup_messages(self):
        return self._popup_messages

    @popup_messages.setter
    def popup_messages(self, value):
        self._popup_messages = unicode(value)


    @property
    def url(self):
        return unicode(self.main_frame.url().toString())


    @property
    def content(self):
        """Returns current frame HTML as a string."""
        return unicode(self.page.currentFrame().toHtml())

    @property
    def cookies(self):
        """Returns all cookies."""
        return self.cookie_jar.allCookies()


    @property
    def enable_image(self):
        """Disable the page images can speed up page loading.

        """
        return self._enable_image

    @enable_image.setter
    def enable_image(self, value):
        self.page.settings().setAttribute(QWebSettings.AutoLoadImages, value)
        self._enable_image = value

    #TODO:It seems not work?
    # @enable_image.deleter
    # def enable_image(self):
    #     raise NotImplemented

    @property
    def enable_javascript(self):
        """Disable the page javascript can speed up page loading.

        """
        return self._enable_javascript

    @enable_javascript.setter
    def enable_javascript(self, value):
        self.page.settings().setAttribute(QWebSettings.JavascriptEnabled, value)
        self._enable_javascript = value


    def open(self, address, method='get', headers=None, auth=None, body=None,
             default_popup_response=None):
        """Opens a web page.

        @param address: The resource URL.
        @param method: The Http method.
        @param headers: An optional dict of extra request hearders.
        @param auth: An optional tupple of HTTP auth (username, password).
        @param body: An optional string containing a payload.
        @param default_popup_response: the default response for any confirm/
        alert/prompt popup from the Javascript (replaces the need for the with
        blocks)
        """

        headers = headers or {}

        body = body or QByteArray()
        try:
            method = getattr(QNetworkAccessManager,
                             "%sOperation" % method.capitalize())
        except AttributeError:
            raise Exception("Invalid http method %s" % method)
        request = QNetworkRequest(QUrl(address))
        request.CacheLoadControl = 0
        for header in headers:
            request.setRawHeader(header, headers[header])
        self._auth = auth
        self._auth_attempt = 0  # Avoids reccursion
        self.page.mainFrame().load(request, method, body)
        self._loaded = False

        if default_popup_response is not None:
            self._prompt_expected = (default_popup_response, None)
            self._confirm_expected = (default_popup_response, None)

        return self.wait_for_page_loaded()

    def set_viewport_size(self, width, height):
        """Sets the page viewport size.

        @param width: An integer that sets width pixel count.
        @param height: An integer that sets height pixel count.
        """

        if self.display:
            self.webview.resize(QSize(width, height))
        self.page.setViewportSize(QSize(width, height))


    def set_proxy(self, proxy=None):
        """Set the proxy or using system configuration as None,supported socks5 http{s}.

        @param proxy: Example:socks5://username:[email protected]:7070
        """
        proxy_type = None
        if proxy:
            parse = urlparse(proxy)
            scheme = parse.scheme
            hostname = parse.hostname
            port = parse.port
            username = parse.username or ''
            password = parse.password or ''

            if scheme == 'socks5':
                proxy_type = QNetworkProxy.Socks5Proxy
            elif scheme in ('http', 'https'):
                proxy_type = QNetworkProxy.HttpProxy

        if proxy_type:
            self.page.networkAccessManager().setProxy(
                QNetworkProxy(proxy_type, hostname, port, username, password)
            )
        else:
            QNetworkProxyFactory.setUseSystemConfiguration(True)

    def first_element_position(self, selector):
        try:
            return self.elements_position(selector)[0]
        except IndexError:
            logger.warning("Can't locate selector " + selector)
            return None


    def elements_position(self, selector):
        """Get the position of elements whose match selector

        @param selector:
        @return: position of QPoint
        """
        attr, pattern, val = self.parser_selector(selector, attr='identifier')

        strip = lambda v: v.strip()

        if pattern:
            val = locals()[pattern](val)


        def identifier(query):
            return id(query) or name(query)

        def name(query):
            return css("*[name='%s']" % query)

        def id(query):
            return css('#' + query)

        def link(query):
            return xpath(u"//a[@text()='%s']" % query.replace("\'", "\\'"))

        def css(query):
            result = []
            for ele in self.main_frame.findAllElements(query):
                if not ele.isNull():
                    result.append(ele.geometry().center())
            return result

        def xpath(query):
            positions = self.evaluate(u"""
            function GetAbsoluteLocationEx(element)
            {
                if ( arguments.length != 1 || element == null )
                {
                    return null;
                }
                var elmt = element;
                var offsetTop = elmt.offsetTop;
                var offsetLeft = elmt.offsetLeft;
                var offsetWidth = elmt.offsetWidth;
                var offsetHeight = elmt.offsetHeight;
                while( elmt = elmt.offsetParent )
                {
                      // add this judge
                    if ( elmt.style.position == 'absolute' || elmt.style.position == 'relative'
                        || ( elmt.style.overflow != 'visible' && elmt.style.overflow != '' ) )
                    {
                        break;
                    }
                    offsetTop += elmt.offsetTop;
                    offsetLeft += elmt.offsetLeft;
                }
                return { absoluteTop: offsetTop, absoluteLeft: offsetLeft,
                    offsetWidth: offsetWidth, offsetHeight: offsetHeight };
            }
            result=[];
            for (var r = document.evaluate('%s', document, null, 5, null), n; n = r.iterateNext();) {
            pos=GetAbsoluteLocationEx(n)
            result.push([pos.absoluteLeft+pos.offsetWidth/2.0,pos.absoluteTop+pos.offsetHeight/2.0]);
            }
            result
            """ % query.replace("\'", "\\'"))

            return map(lambda x: QPoint(*tuple(x)), positions)

        return locals()[attr](val)


    def _move_page_center_to(self, qpoint):
        size = self.page.viewportSize()
        self.main_frame.setScrollPosition(qpoint - QPoint(size.width(), size.height()) / 2)


    def reload(self):
        """Reload page.

        @return:
        """

        self.trigger_action('Reload', expect_loading=True)

    def back(self):
        self.trigger_action('Back')

    def forward(self):
        self.trigger_action('Forward')


    @can_load_page
    def trigger_action(self, action):
        """Trigger QWebPage::WebAction

        @param action:
        """
        self.page.triggerAction(getattr(QWebPage, action))


    def parser_selector(self, selector, attr=None, pattern=None, val=None):
        index = selector.find('=')

        if index <= 0:
            val = selector
        else:
            attr = selector[:index]
            value_ = selector[index + 1:]
            index = value_.find(':')

            if index > 0:
                pattern = value_[:index]

            val = value_[index + 1:]

        return attr, pattern, val


    @can_load_page
    @have_a_break
    def click(self, selector):
        qpoint = self.first_element_position(selector)
        if qpoint:
            return self._click_position(qpoint)


    @can_load_page
    def _click_position(self, qpoint):
        self._move_page_center_to(qpoint)
        self.webview.repaint()
        pos = qpoint - self.main_frame.scrollPosition()

        self._move_to_position(pos)
        QTest.mouseClick(self.webview, Qt.LeftButton, pos=pos)
        gevent.sleep(1)
        return pos


    def qpoint_to_tuple(self, qpoint):
        return qpoint.x(), qpoint.y()

    @have_a_break
    def move_to(self, selector):
        qpoint = self.first_element_position(selector)
        if qpoint:
            self._move_to_position(qpoint)
            return qpoint_to_tuple(qpoint)

    def move_at(self, x, y):
        self._move_to_position(QPoint(x, y))

    def _move_to_position(self, qpoint):
        QTest.mouseMove(self.webview, pos=qpoint)
        return qpoint

    @have_a_break
    def click_at(self, x, y):
        self._click_position(QPoint(x, y))

    @have_a_break
    def key_clicks(self, selector, text):
        if selector:
            self.click(selector)
        QTest.keyClicks(self.webview, text, delay=50)

    @have_a_break
    def type(self, selector, text):
        position = self.click(selector)

        ele = self._hit_element_from(position)

        ele.setFocus()
        ele.evaluateJavaScript(
            u"""
            core.events.setValue(this, '%s')
            """ % (text.replace("\n", "\\n").replace("\'", "\\'"))
        )
        logger.debug('type %s %s' % (selector, text))


    def _hit_element_from(self, position):
        return self.main_frame.hitTestContent(position).element()

    def first_element(self, selector):
        position = self.first_element_position(selector)
        if position:
            return self.main_frame.hitTestContent(position).element(), position


    def wait_forever(self):
        self.wait_for(lambda: False, time_for_stop=-1)

    @have_a_break
    def check(self, selector, checked=True):
        ele, position = self.first_element(selector)
        if ele and ele.tagName() == 'INPUT':
            if ele.attribute('type') in ['checkbox', 'radio']:
                ele_checked = ele.attribute('checked') == 'checked' or False
                if ele_checked != checked:
                    self._click_position(position)
            else:
                raise ValueError, "%s is not a checkbox or radio" % selector

    @have_a_break
    def select(self, selector, value):

        def _select(query, select_by, select):
            select.evaluateJavaScript(u"""
            triggerEvent(this, 'focus', false);
            var changed = false;
            var optionToSelect = '%s';
            for (var i = 0; i < this.options.length; i++) {
                var option = this.options[i];
                if (option.selected && option.%s != optionToSelect) {
                    option.selected = false;
                    changed = true;
                }
                else if (!option.selected && option.%s == optionToSelect) {
                    option.selected = true;
                    changed = true;
                }
            }

            if (changed) {
                triggerEvent(this, 'change', true);
            }
            """ % ( query.replace("\'", "\\'"), select_by, select_by))

        def _add_selection(query, select_by, select, selected):
            select.evaluateJavaScript(u"""
            triggerEvent(this, 'focus', false);
            var optionToSelect = '%s';
            for (var i = 0; i < this.options.length; i++) {
                var option = this.options[i];
                if (option.%s == optionToSelect)
                {
                    option.selected = %s;
                    triggerEvent(this, 'change', true);
                }

            }
            """ % ( query.replace("\'", "\\'"), select_by, selected and 'true' or 'false'))

        ele, position = self.first_element(selector)

        if ele and ele.tagName() == 'SELECT':
            ele.setFocus()

            if ele.attribute('multiple') == 'multiple':
                assert isinstance(value, list)
                for value_, selected in value:
                    attr, pattern, val = self.parser_selector(value_, attr='text')
                    _add_selection(val, attr, ele, selected)
            else:
                attr, pattern, val = self.parser_selector(value, attr='text')
                _select(val, attr, ele)


    def choose_file(self, selector, file):
        self._upload_file = file
        self.click(selector)
        self._upload_file = None


    def capture(self, selector=None):
        """Capture the images of selector.

        @param selector: Css selector.
        @return: Images
        """

        elements = self.main_frame.documentElement().findAll(selector)
        imgs = []

        for element in elements:
            geo = element.geometry()
            img = QImage(geo.width(), geo.height(), QImage.Format_ARGB32)
            painter = QPainter(img)
            element.render(painter)
            painter.end()
            imgs.append(img)

        return imgs

    def capture_to(self, path, selector=None):
        """Capture the images of selector to files.

        @param path: File path with index suffix.
        @param selector: Css selector.
        @return: The paths of saving.
        """

        _, ext = os.path.splitext(path)
        ext = ext[1:]

        imgs = self.capture(selector)
        result = []
        for index, img in enumerate(imgs):
            filepath = '%s.%s' % (path, index)
            if img.save(filepath, ext.upper()):
                result.append(filepath)

        return result

    def capture_to_buf(self, selector=None):
        """capture the images of selector to StringIO

        @param selector: Css selector.
        @return: The StringIO list.
        """

        images = self.capture(selector)
        result = []

        for image in images:
            ba = QByteArray()
            buf = QBuffer(ba)
            buf.open(QIODevice.ReadWrite)
            image.save(buf, 'jpg')
            stream = StringIO(str(buf.buffer()))
            result.append(stream)

        return result


    @can_load_page
    def evaluate(self, script):
        """Evaluates script in page frame.

        @param script: The script to evaluate.
        """
        result = self.main_frame.evaluateJavaScript("%s" % script)
        # if isinstance(result,QString):
        #     result=unicode(result)
        return result

    def evaluate_js_file(self, path, encoding='utf-8'):
        """Evaluates javascript file at given path in current frame.
        Raises native IOException in case of invalid file.

        @param path: The path of the file.
        @param encoding: The file's encoding.
        """
        self.evaluate(codecs.open(path, encoding=encoding).read())

    def __del__(self):
        """Depend on the CG of Python.
        """
        self._exit()


    def delete_cookies(self):
        """Deletes all cookies."""
        self.cookie_jar.setAllCookies([])

    def exists(self, selector):
        """Checks if element exists for given selector.

        @param string: The element selector.
        """
        return not self.main_frame.findFirstElement(selector).isNull()


        #TODO: Still not work.

    #     def remove_css(self):
    #         """Remore the css,speed up page loading.
    #
    #         @return:
    #         """
    #
    #         return self.evaluate("""var targetelement="link";//determine element type to create nodelist from
    # var targetattr="href"//determine corresponding attribute to test for
    # var allsuspects=document.getElementsByTagName(targetelement)
    # for (var i=allsuspects.length; i>=0; i--){ //search backwards within nodelist for matching elements to remove
    # if (allsuspects[i] && allsuspects[i].getAttribute(targetattr)!=null )
    # allsuspects[i].parentNode.removeChild(allsuspects[i]); //remove element by calling parentNode.removeChild()
    # }
    #         """)


    def filter_resources(self, pattern):
        """Filter resources with pattern.

        @param pattern: Match pattern.
        @param resources:
        @return: @raise:
        """
        if isinstance(pattern, basestring):
            is_match = lambda x: pattern == x
        elif isinstance(pattern, _pattern_type):
            is_match = lambda x: pattern.match(x)
        elif hasattr(pattern, '__call__'):
            is_match = pattern
        else:
            raise TypeError, 'pattern must be one of str,re.compile,callable'
        return filter(lambda x: is_match(x.request_url), self.http_resources)[:]


    def save(self, path):
        """Save current page content to the path.
        
        @param path: The path to save.
        """
        f = open(path, 'w')
        f.write(self.content.encode('utf-8'))
        f.close()

    def global_exists(self, global_name):
        """Checks if javascript global exists.

        @param global_name: The name of the global.
        """
        return self.evaluate('!(typeof %s === "undefined");' %
                             global_name)


    def load_cookies( self, cookie_storage, keep_old=False ):
        """load from cookielib's CookieJar or Set-Cookie3 format text file.

        @param cookie_storage: file location string on disk or CookieJar instance.
        @param keep_old: Don't reset, keep cookies not overridden.
        """

        def toQtCookieJar( PyCookieJar, QtCookieJar ):
            allCookies = QtCookieJar.cookies if keep_old else []
            for pc in PyCookieJar:
                qc = toQtCookie(pc)
                allCookies.append(qc)
            QtCookieJar.setAllCookies(allCookies)

        def toQtCookie(PyCookie):
            qc = QNetworkCookie(PyCookie.name, PyCookie.value)
            qc.setSecure(PyCookie.secure)
            if PyCookie.path_specified:
                qc.setPath(PyCookie.path)
            if PyCookie.domain != "":
                qc.setDomain(PyCookie.domain)
            if PyCookie.expires != 0:
                t = QDateTime()
                t.setTime_t(PyCookie.expires)
                qc.setExpirationDate(t)
                # not yet handled(maybe less useful):
            #   py cookie.rest / QNetworkCookie.setHttpOnly()
            return qc

        if cookie_storage.__class__.__name__ == 'str':
            cj = LWPCookieJar(cookie_storage)
            cj.load()
            toQtCookieJar(cj, self.cookie_jar)
        elif cookie_storage.__class__.__name__.endswith('CookieJar'):
            toQtCookieJar(cookie_storage, self.cookie_jar)
        else:
            raise ValueError, 'unsupported cookie_storage type.'


    def save_cookies(self, cookie_storage):
        """Save to cookielib's CookieJar or Set-Cookie3 format text file.

        @param cookie_storage: file location string or CookieJar instance.
        """

        def toPyCookieJar(QtCookieJar, PyCookieJar):
            for c in QtCookieJar.allCookies():
                PyCookieJar.set_cookie(toPyCookie(c))

        def toPyCookie(QtCookie):
            port = None
            port_specified = False
            secure = QtCookie.isSecure()
            name = str(QtCookie.name())
            value = str(QtCookie.value())
            v = str(QtCookie.path())
            path_specified = bool(v != "")
            path = v if path_specified else None
            v = str(QtCookie.domain())
            domain_specified = bool(v != "")
            domain = v
            domain_initial_dot = v.startswith('.') if domain_specified else None
            v = long(QtCookie.expirationDate().toTime_t())
            # Long type boundary on 32bit platfroms; avoid ValueError
            expires = 2147483647 if v > 2147483647 else v
            rest = {}
            discard = False
            return Cookie(0, name, value, port, port_specified, domain
                , domain_specified, domain_initial_dot, path, path_specified
                , secure, expires, discard, None, None, rest)

        if cookie_storage.__class__.__name__ == 'str':
            cj = LWPCookieJar(cookie_storage)
            toPyCookieJar(self.cookie_jar, cj)
            cj.save()
        elif cookie_storage.__class__.__name__.endswith('CookieJar'):
            toPyCookieJar(self.cookie_jar, cookie_storage)
        else:
            raise ValueError, 'unsupported cookie_storage type.'


    def wait_for_confirm(self, confirm=True, callback=None):
        """Statement that tells GRobot how to deal with javascript confirm().

        @param confirm: A bollean that confirm.
        @param callable: A callable that returns a boolean for confirmation.
        """

        self._robot._confirm_expected = (confirm, callback)
        self._robot.wait_for(lambda: self._robot._confirm_expected is None)
        return self.popup_messages


    def wait_for_text(self, text, time_for_stop=None):
        """Waits until given text appear on main frame.

        @param text: The text to wait for.
        @return:
        """

        logger.debug("Wait for text %s" % text)

        self.wait_for(lambda: text in self.content,
                      "Can\'t find '%s' in current frame" % text, time_for_stop=time_for_stop)

        return self.wait_for_page_loaded()

    def wait_for_xpath(self, expression, time_for_stop=None):
        self.wait_for(lambda: XPath(self.content).execute(expression),
                      "Can't find xpath=%s in current frame" % expression, time_for_stop=time_for_stop)
        return self.wait_for_page_loaded()


    def wait_for_selector(self, selector):
        """Waits until selector match an element on the frame.

        @param selector: The selector to wait for.
        """
        self.wait_for(lambda: self.exists(selector),
                      'Can\'t find element matching "%s"' % selector)

    def wait_for_page_loaded(self, time_for_stop=None):
        """Waits until page is loaded, assumed that a page as been requested.

        """
        return self.wait_for(lambda: self._loaded,
                             'Unable to load requested page', time_for_stop=time_for_stop)

    def wait_for(self, condition, timeout_message='', time_for_stop=None):
        """Waits until condition is True.

        @param condition: A callable that returns the condition.
        @param timeout_message: The exception message on timeout.-1 means never timeout.
        """

        if self._loaded:
            time_for_stop = time_for_stop or self.operate_timeout
        else:
            time_for_stop = time_for_stop or self.loading_timeout

        started_at = time.time()
        while not condition():
            if time_for_stop != -1 and time.time() > (started_at + time_for_stop):
                if self._loaded:
                    raise OperateTimeout, timeout_message
                else:
                    # raise LoadingTimeout, timeout_message
                    self.trigger_action('Stop') #QWebPage::Stop
                    self._loaded = True
                    logger.warning("Page loading timeout.Force to stop the page")
                    break

            gevent.sleep(2)

    def wait_for_alert(self):
        """Waits for main frame alert().
        """
        self.wait_for(lambda: self._alert is not None,
                      'User has not been alerted.')
        msg, self._alert = self._alert, None
        return msg

    def _release_last_resources(self):
        """Releases last loaded resources.

        :return: The released resources.
        """
        last_resources, self.http_resources = self.http_resources[:], []
        return last_resources


    def _page_loaded(self, success):
        if self.develop and self.display:
            if self.inspector is None:
                self.inspector = QWebInspector()

            self.inspector.setPage(self.page)
            self.inspector.show()

        scripts = [
            'atoms.js',
            'htmlutils.js',
        ]

        if self.jquery_namespace:
            scripts.append('jquery-1.9.1.min.js', )

        for script in scripts:
            self.evaluate_js_file(os.path.dirname(__file__) + '/javascripts/' + script)

        if self.jquery_namespace:
            self.evaluate(u"%s=jQuery.noConflict();" % self.jquery_namespace)

        self._loaded = True
        # self.cache.clear()
        logger.debug("Page load finished")

    def _page_load_started(self):
        logger.debug("Start load page")

        self._loaded = False

    def _unsupported_content(self, reply):
        """Adds an HttpResource object to http_resources with unsupported
        content.

        @param reply: The QNetworkReply object.
        """

        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute):
            self.http_resources.append(HttpResource(reply, self.cache,
                                                    reply.readAll()))

    def _link_clicked(self, href):
        """Contorl the page link clicked event,forbid open new window.

        @param href: The href attribute of a tag.
        """

        self.main_frame.load(href)

    def _request_ended(self, reply):
        """Adds an HttpResource object to http_resources.

        @param reply: The QNetworkReply object.
        """

        if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute):
            self.http_resources.append(HttpResource(reply, self.cache))

    def _authenticate(self, mix, authenticator):
        """Called back on basic / proxy http auth.

        @param mix: The QNetworkReply or QNetworkProxy object.
        @param authenticator: The QAuthenticator object.
        """
        if self._auth_attempt == 0:
            username, password = self._auth
            authenticator.setUser(username)
            authenticator.setPassword(password)
            self._auth_attempt += 1

    def _on_manager_ssl_errors(self, reply, errors):
        """Ingore all the ssl error

        @param reply:
        @param errors:
        """
        url = unicode(reply.url().toString())
        if self.ignore_ssl_errors:
            reply.ignoreSslErrors()
        else:
            logger.warning('SSL certificate error: %s' % url)


    def _exit(self):
        """Destroy the Qt main event loop.

        """
        GRobot.exit_lock.acquire()
        if self.inspector:
            self.inspector.close()
            sip.delete(self.inspector)

        if self.display:
            self.webview.close()
            sip.delete(self.webview)

        if self.page and not sip.isdeleted(self.page):
            sip.delete(self.page)

        GRobot._liveRobot -= 1

        if GRobot._liveRobot == 0 and GRobot._loop is not None:

            GRobot._loop.stop()
            GRobot._loop = None
            GRobot._app = None
            if hasattr(self, 'xvfb'):
                GRobot.xvfb.terminate()
        GRobot.exit_lock.release()
Example #30
0
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_HostWindow()
        self.ui.setupUi(self)

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

        # Current mod-ui title
        #self.fCurrentBundle = ""
        self.fCurrentTitle = ""

        # Next bundle to load (done by startup arguments)
        self.fNextBundle = ""

        # first attempt of auto-start backend doesn't show an error
        self.fFirstBackendInit = True

        # need to call session reconnect after connecting the 1st time
        self.fNeedsSessionReconnect = False

        # Qt idle timer
        self.fIdleTimerId = 0

        # Qt web frame, used for evaluating javascript
        self.fWebFrame = None

        # to be filled with key-value pairs of current settings
        self.fSavedSettings = {}

        # List of pedalboards
        self.fPedalboards = get_all_pedalboards()

        # List of current-pedalboard presets
        self.fPresetMenuList = []

        # Process that runs the backend
        self.fProccessBackend = QProcess(self)
        self.fProccessBackend.setProcessChannelMode(QProcess.MergedChannels)
        self.fProccessBackend.setReadChannel(QProcess.StandardOutput)
        self.fStoppingBackend = False

        # Thread for managing the webserver
        self.fWebServerThread = WebServerThread(self)

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

        self.ui.webview = QWebView(self.ui.swp_webview)
        self.ui.webview.setMinimumWidth(980)
        self.ui.swp_webview.layout().addWidget(self.ui.webview)

        self.ui.webpage = HostWebPage(self)
        self.ui.webpage.setViewportSize(QSize(980, 600))
        self.ui.webview.setPage(self.ui.webpage)

        self.ui.webinspector = QWebInspector(None)
        self.ui.webinspector.resize(800, 600)
        self.ui.webinspector.setPage(self.ui.webpage)
        self.ui.webinspector.setVisible(False)

        self.ui.act_file_connect.setEnabled(False)
        self.ui.act_file_connect.setVisible(False)
        self.ui.act_file_disconnect.setEnabled(False)
        self.ui.act_file_disconnect.setVisible(False)

        self.ui.label_app.setText("MOD Application v%s" % config["version"])

        # disable file menu
        self.ui.act_file_refresh.setEnabled(False)
        self.ui.act_file_inspect.setEnabled(False)

        # disable pedalboard menu
        self.ui.act_pedalboard_new.setEnabled(False)
        self.ui.act_pedalboard_open.setEnabled(False)
        self.ui.act_pedalboard_save.setEnabled(False)
        self.ui.act_pedalboard_save_as.setEnabled(False)
        self.ui.act_pedalboard_share.setEnabled(False)
        self.ui.menu_Pedalboard.setEnabled(False)

        # disable presets menu
        self.ui.act_presets_new.setEnabled(False)
        self.ui.act_presets_save.setEnabled(False)
        self.ui.act_presets_save_as.setEnabled(False)
        self.ui.menu_Presets.setEnabled(False)

        # initial stopped state
        self.slot_backendFinished(-1, -1)

        # Qt needs this so it properly creates & resizes the webview
        self.ui.stackedwidget.setCurrentIndex(1)
        self.ui.stackedwidget.setCurrentIndex(0)

        # FIXME
        #self.ui.act_backend_stop.setVisible(False)
        #self.ui.act_backend_restart.setVisible(False)

        # ----------------------------------------------------------------------------------------------------
        # Set up GUI (special stuff for Mac OS)

        if MACOS:
            self.ui.act_file_quit.setMenuRole(QAction.QuitRole)
            self.ui.act_settings_configure.setMenuRole(QAction.PreferencesRole)
            self.ui.act_help_about.setMenuRole(QAction.AboutRole)
            #self.ui.menu_Settings.setTitle("Panels")
            #self.ui.menu_Help.hide()

        # ----------------------------------------------------------------------------------------------------
        # Load Settings

        self.loadSettings(True)

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

        self.SIGUSR1.connect(self.slot_handleSIGUSR1)
        self.SIGTERM.connect(self.slot_handleSIGTERM)

        self.fProccessBackend.error.connect(self.slot_backendError)
        self.fProccessBackend.started.connect(self.slot_backendStarted)
        self.fProccessBackend.finished.connect(self.slot_backendFinished)
        self.fProccessBackend.readyRead.connect(self.slot_backendRead)

        self.fWebServerThread.running.connect(self.slot_webServerRunning)
        self.fWebServerThread.finished.connect(self.slot_webServerFinished)

        self.ui.act_file_refresh.triggered.connect(self.slot_fileRefresh)
        self.ui.act_file_inspect.triggered.connect(self.slot_fileInspect)

        self.ui.act_settings_configure.triggered.connect(self.slot_configure)

        self.ui.act_help_about.triggered.connect(self.slot_about)
        self.ui.act_help_project.triggered.connect(self.slot_showProject)
        self.ui.act_help_website.triggered.connect(self.slot_showWebsite)

        self.ui.b_start.clicked.connect(self.slot_backendStart)
        self.ui.b_configure.clicked.connect(self.slot_configure)
        self.ui.b_about.clicked.connect(self.slot_about)

        # force our custom refresh
        webReloadAction = self.ui.webpage.action(QWebPage.Reload)
        webReloadAction.triggered.disconnect()
        webReloadAction.triggered.connect(self.slot_fileRefresh)

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

        self.setProperWindowTitle()
        SESSION.setupApp(self._pedal_changed_callback)

        if not "--no-autostart" in sys.argv:
            QTimer.singleShot(0, self.slot_backendStart)

        QTimer.singleShot(1, self.fixWebViewSize)
    def createWidgets(self):
        """
        Create all qt widgets
        """
        self.setWindowTitle(self.tr("Extensive Testing Client - Web Browser"))
        self.setWindowIcon(QIcon(":/main.png"))

        self.dockToolbarWebBrowser = QToolBar(self)
        self.dockToolbarWebBrowser.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)

        browserLayoutGroup = QVBoxLayout()
        browserLayoutGroup.addWidget(self.dockToolbarWebBrowser)

        toolbarBrowserLayoutGroup = QHBoxLayout()

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

        self.webCounter = QLabel("(0%)")

        toolbarBrowserLayoutGroup.addWidget(QLabel("Load URL:"))
        toolbarBrowserLayoutGroup.addWidget(self.webCounter)
        toolbarBrowserLayoutGroup.addWidget(self.locationEdit)

        self.webTitle = QLabel("Title:")

        self.webView = QWebView()

        if QtHelper.str2bool(
                Settings.instance().readValue(key='Server/proxy-web-active')):

            proxy = QNetworkProxy()
            proxy.setType(3)
            # http
            proxy.setHostName(
                Settings.instance().readValue(key='Server/addr-proxy-http'))
            proxy.setPort(
                int(Settings.instance().readValue(
                    key='Server/port-proxy-http')))
            self.webView.page().networkAccessManager().setProxy(proxy)

        if QT_VERSION_STR.startswith("4."):
            self.webInspector = QWebInspector()
            self.webView.settings().setAttribute(
                QWebSettings.DeveloperExtrasEnabled, True)
            self.webInspector.setPage(self.webView.page())

        self.webView.setHtml(
            '<html><head></head><body>No content loaded</body></html>')
        self.webView.settings().setAttribute(QWebSettings.PluginsEnabled, True)
        self.webView.settings().setAttribute(
            QWebSettings.JavascriptCanOpenWindows, True)

        browserLayoutGroup.addLayout(toolbarBrowserLayoutGroup)
        browserLayoutGroup.addWidget(self.webTitle)

        self.webTab = QTabWidget()
        self.webTab.addTab(self.webView, "Web Page")
        if QT_VERSION_STR.startswith("4."):
            self.webTab.addTab(self.webInspector, "Source Inspector")

        browserLayoutGroup.addWidget(self.webTab)

        self.setLayout(browserLayoutGroup)
Example #32
0
    def __init__(self, parent, parentMain, UID):

        # -------------------------------------------------------------------
        QWebPage.__init__(self, parent);

        # -------------------------------------------------------------------
        self.PARENT                                 = parentMain;
        self.UID                                    = UID;
        self.PARENT_TAB                             = parent;
        self.DEBUG                                  = False;
        self.LOG_TAG                                = str(self.__class__.__name__).upper();

        # -------------------------------------------------------------------
        self.L_BTN_CLICK                            = False;
        self.M_BTN_CLICK                            = False;
        self.R_BTN_CLICK                            = False;

        # -------------------------------------------------------------------
        self.PROGRESS_BAR                           = None;

        self.PROGRESS_BAR_PR                        = float( self.PARENT.WIDTH / 100);
        self.PROGRESS_BAR_W                         = 0;

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

        # SEARCH_INPUT
        self.SEARCH_INPUT                           =  QLineEdit("", self.PARENT);
        self.SEARCH_INPUT.setGeometry(0, 615, 400, 30);
        self.SEARCH_INPUT.setStyleSheet("QLineEdit{ background-color: rgba(0,0,0, 180); font-size: 12px; font-family: monospace; color: #fff; padding-left: 10px; border-style: none;}");
        self.connect( self.SEARCH_INPUT, SIGNAL('textChanged(const QString)') , self.FIND_ON_PAGE );
        self.connect( self.SEARCH_INPUT, SIGNAL('returnPressed()') , self.FIND_ON_PAGE );
        #self.SEARCH_INPUT.setReadOnly( True );
        self.SEARCH_INPUT_IS_OPEN                   = False;
        self.SEARCH_INPUT.hide();

        # -------------------------------------------------------------------
        self.AGENTS                                 = [

            # Chrome 41.0.2228.0
            "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
            # Chrome 41.0.2227.1
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36",
            # Chrome 41.0.2227.0
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
            # Chrome 41.0.2226.0
            "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36",
            # Chrome 41.0.2225.0
            "Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
            "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
            # Chrome 41.0.2224.3
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36",
            # Chrome 40.0.2214.93
            "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36",
            # Chrome 37.0.2062.124
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36",
            # Chrome 37.0.2049.0
            "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
            "Mozilla/5.0 (Windows NT 4.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
            # Chrome 36.0.1985.67
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
            # Chrome 36.0.1985.125
            "Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36",
            # Chrome 36.0.1944.0
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36",
            # Chrome 35.0.3319.102
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36",
            # Chrome 35.0.2309.372
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2309.372 Safari/537.36",
            # Chrome 35.0.2117.157
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2117.157 Safari/537.36",
            # Chrome 35.0.1916.47
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36",
            # Chrome 34.0.1866.237
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1866.237 Safari/537.36",
            # Chrome 34.0.1847.137
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F",
            # Chrome 34.0.1847.116
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36",
            "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10",
            

        ];


        # -------------------------------------------------------------------
        self.USER_AGENT                             = self.AGENTS[0];

        self.HEADERS                                = {
            "User-Agent"        : "[USER-AGENT]",
            "Accept"            : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",

            #"Accept-Language"   : "en-US,en;q=0.5",
            #"Referer"           : "https://btc-e.com/",
            #"Connection"        : "keep-alive",
            #"Cache-Control"     : "max-age=0",
            #"Cookie"            : ""

        }

        # -------------------------------------------------------------------
        #self.setContentEditable( True );
        self.setLinkDelegationPolicy( QWebPage.DelegateAllLinks );
        self.setForwardUnsupportedContent( True );
        self.setNetworkAccessManager( self.PARENT.NET_MANAGER );

        self.linkClicked.connect( self.ON_LINK_CLICKED );
        self.linkHovered.connect( self.ON_LINK_HOVERED );
        self.loadProgress.connect( self.ON_PAGE_LOAD_PROGRESS );

        self.downloadRequested.connect( self.PARENT.DOWNLOAD_MANAGER.REQUEST );
        self.unsupportedContent.connect( self.PARENT.DOWNLOAD_MANAGER.REQUEST );

        # -------------------------------------------------------------------
        self.PRINT_ACTION = QAction( self );
        self.PRINT_ACTION.setShortcuts( QKeySequence.Print );
        self.PRINT_ACTION.triggered.connect( self.PRINT );
        self.PARENT.addAction( self.PRINT_ACTION );

        # -------------------------------------------------------------------
        # SETTINGS
       
        self.SETTINGS                               = self.settings();
        self.SETTINGS.setDefaultTextEncoding("utf-8"); # <= [TO-CONFIG.FILE] + ALL FROM BELOW

        #self.SETTINGS.clearIconDatabase();
        #self.SETTINGS.clearMemoryCaches();

        self.SETTINGS.setAttribute( QWebSettings.AutoLoadImages, True );
        self.SETTINGS.setAttribute( QWebSettings.DnsPrefetchEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.JavascriptEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.JavaEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.PluginsEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.PrivateBrowsingEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.JavascriptCanOpenWindows, True ); #
        self.SETTINGS.setAttribute( QWebSettings.JavascriptCanCloseWindows, False ); #
        self.SETTINGS.setAttribute( QWebSettings.JavascriptCanAccessClipboard, True ); #
        self.SETTINGS.setAttribute( QWebSettings.DeveloperExtrasEnabled, True ); #
        self.SETTINGS.setAttribute( QWebSettings.SpatialNavigationEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.LinksIncludedInFocusChain, True );
        self.SETTINGS.setAttribute( QWebSettings.ZoomTextOnly, False );
        self.SETTINGS.setAttribute( QWebSettings.PrintElementBackgrounds, False );
        self.SETTINGS.setAttribute( QWebSettings.OfflineStorageDatabaseEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.OfflineWebApplicationCacheEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.LocalStorageEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.LocalStorageDatabaseEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.LocalContentCanAccessRemoteUrls, True );
        self.SETTINGS.setAttribute( QWebSettings.LocalContentCanAccessFileUrls, True );
        self.SETTINGS.setAttribute( QWebSettings.XSSAuditingEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.AcceleratedCompositingEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.TiledBackingStoreEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.FrameFlatteningEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.SiteSpecificQuirksEnabled, True );

        # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        self.SETTINGS.enablePersistentStorage( self.PARENT.STORAGE_ROOT );
        self.SETTINGS.setLocalStoragePath( self.PARENT.STORAGE_ROOT+"local_storage/" );
        self.SETTINGS.setIconDatabasePath ( self.PARENT.STORAGE_ROOT+"icons_path/" )
        self.SETTINGS.setMaximumPagesInCache ( 10 );

        # FIXME: Create settings config file [TO-CONFIG.FILE]

        self.SETTINGS.setOfflineWebApplicationCachePath( self.PARENT.STORAGE_ROOT+"/cache/" );
        self.SETTINGS.setOfflineWebApplicationCacheQuota ( 25 * 1024 *1024 );

        self.SETTINGS.setOfflineStoragePath( self.PARENT.STORAGE_ROOT );
        self.SETTINGS.setOfflineStorageDefaultQuota ( 25 * 1024 *1024 );
        #self.SETTINGS.setObjectCacheCapacities (int cacheMinDeadCapacity, int cacheMaxDead, int totalCapacity)

        # -------------------------------------------------------------------
        self.INSPECTOR    = QWebInspector( None );

        """
        __init__ (self, QWidget parent = None)
        closeEvent (self, QCloseEvent event)
        bool event (self, QEvent)
        hideEvent (self, QHideEvent event)
        QWebPage page (self)
        resizeEvent (self, QResizeEvent event)
        setPage (self, QWebPage page)
        showEvent (self, QShowEvent event)
        QSize sizeHint (self)
        """

        # -------------------------------------------------------------------
        self.INIT();
Example #33
0
    def __init__(self, iface):
        QDialog.__init__(self)
        self.setupUi(self)
        self.iface = iface

        self.previewUrl = None
        self.layer_search_combo = None
        self.exporter_combo = None

        self.feedback = FeedbackDialog(self)
        self.feedback.setModal(True)

        stgs = QSettings()

        self.restoreGeometry(stgs.value("qgis2web/MainDialogGeometry",
                                        QByteArray(), type=QByteArray))

        if stgs.value("qgis2web/previewOnStartup", Qt.Checked) == Qt.Checked:
            self.previewOnStartup.setCheckState(Qt.Checked)
        else:
            self.previewOnStartup.setCheckState(Qt.Unchecked)
        if (stgs.value("qgis2web/closeFeedbackOnSuccess", Qt.Checked) ==
                Qt.Checked):
            self.closeFeedbackOnSuccess.setCheckState(Qt.Checked)
        else:
            self.closeFeedbackOnSuccess.setCheckState(Qt.Unchecked)
        self.previewFeatureLimit.setText(
            stgs.value("qgis2web/previewFeatureLimit", "1000"))

        self.paramsTreeOL.setSelectionMode(QAbstractItemView.SingleSelection)
        self.preview = None
        if webkit_available:
            widget = QWebView()
            self.preview = widget
            webview = self.preview.page()
            webview.setNetworkAccessManager(QgsNetworkAccessManager.instance())
            self.preview.settings().setAttribute(
                QWebSettings.DeveloperExtrasEnabled, True)
        else:
            widget = QTextBrowser()
            widget.setText(self.tr('Preview is not available since QtWebKit '
                                   'dependency is missing on your system'))
        self.right_layout.insertWidget(0, widget)
        self.populateConfigParams(self)
        self.populate_layers_and_groups(self)
        self.populateLayerSearch()
        self.populateBasemaps()

        writer = WRITER_REGISTRY.createWriterFromProject()
        self.setStateToWriter(writer)

        self.exporter = EXPORTER_REGISTRY.createFromProject()
        self.exporter_combo.setCurrentIndex(
            self.exporter_combo.findText(self.exporter.name()))
        self.exporter_combo.currentIndexChanged.connect(
            self.exporterTypeChanged)

        self.toggleOptions()
        if webkit_available:
            if self.previewOnStartup.checkState() == Qt.Checked:
                self.autoUpdatePreview()
            self.buttonPreview.clicked.connect(self.previewMap)
        else:
            self.buttonPreview.setDisabled(True)
        self.layersTree.model().dataChanged.connect(self.populateLayerSearch)
        self.ol3.clicked.connect(self.changeFormat)
        self.leaflet.clicked.connect(self.changeFormat)
        self.buttonExport.clicked.connect(self.saveMap)
        readme = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                              "README.md")
        helpText = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                "helpFile.md")
        lines = open(readme, 'r').readlines()
        with open(helpText, 'w') as helpFile:
            for ct, line in enumerate(lines):
                if ct > 4:
                    helpFile.write(line)
            helpFile.close()
        self.helpField.setSource(QUrl.fromLocalFile(helpText))
        if webkit_available:
            self.devConsole = QWebInspector(self.verticalLayoutWidget_2)
            self.devConsole.setFixedHeight(0)
            self.devConsole.setObjectName("devConsole")
            self.devConsole.setPage(self.preview.page())
            self.right_layout.insertWidget(1, self.devConsole)
        self.filter = devToggleFilter()
        self.installEventFilter(self.filter)
        self.setModal(False)
Example #34
0
class MainDialog(QDialog, Ui_MainDialog):

    """The main dialog of QGIS2Web plugin."""
    items = {}

    def __init__(self, iface):
        QDialog.__init__(self)
        self.setupUi(self)
        self.iface = iface

        self.previewUrl = None
        self.layer_search_combo = None
        self.exporter_combo = None

        self.feedback = FeedbackDialog(self)
        self.feedback.setModal(True)

        stgs = QSettings()

        self.restoreGeometry(stgs.value("qgis2web/MainDialogGeometry",
                                        QByteArray(), type=QByteArray))

        if stgs.value("qgis2web/previewOnStartup", Qt.Checked) == Qt.Checked:
            self.previewOnStartup.setCheckState(Qt.Checked)
        else:
            self.previewOnStartup.setCheckState(Qt.Unchecked)
        if (stgs.value("qgis2web/closeFeedbackOnSuccess", Qt.Checked) ==
                Qt.Checked):
            self.closeFeedbackOnSuccess.setCheckState(Qt.Checked)
        else:
            self.closeFeedbackOnSuccess.setCheckState(Qt.Unchecked)
        self.previewFeatureLimit.setText(
            stgs.value("qgis2web/previewFeatureLimit", "1000"))

        self.paramsTreeOL.setSelectionMode(QAbstractItemView.SingleSelection)
        self.preview = None
        if webkit_available:
            widget = QWebView()
            self.preview = widget
            webview = self.preview.page()
            webview.setNetworkAccessManager(QgsNetworkAccessManager.instance())
            self.preview.settings().setAttribute(
                QWebSettings.DeveloperExtrasEnabled, True)
        else:
            widget = QTextBrowser()
            widget.setText(self.tr('Preview is not available since QtWebKit '
                                   'dependency is missing on your system'))
        self.right_layout.insertWidget(0, widget)
        self.populateConfigParams(self)
        self.populate_layers_and_groups(self)
        self.populateLayerSearch()
        self.populateBasemaps()

        writer = WRITER_REGISTRY.createWriterFromProject()
        self.setStateToWriter(writer)

        self.exporter = EXPORTER_REGISTRY.createFromProject()
        self.exporter_combo.setCurrentIndex(
            self.exporter_combo.findText(self.exporter.name()))
        self.exporter_combo.currentIndexChanged.connect(
            self.exporterTypeChanged)

        self.toggleOptions()
        if webkit_available:
            if self.previewOnStartup.checkState() == Qt.Checked:
                self.autoUpdatePreview()
            self.buttonPreview.clicked.connect(self.previewMap)
        else:
            self.buttonPreview.setDisabled(True)
        self.layersTree.model().dataChanged.connect(self.populateLayerSearch)
        self.ol3.clicked.connect(self.changeFormat)
        self.leaflet.clicked.connect(self.changeFormat)
        self.buttonExport.clicked.connect(self.saveMap)
        readme = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                              "README.md")
        helpText = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                "helpFile.md")
        lines = open(readme, 'r').readlines()
        with open(helpText, 'w') as helpFile:
            for ct, line in enumerate(lines):
                if ct > 4:
                    helpFile.write(line)
            helpFile.close()
        self.helpField.setSource(QUrl.fromLocalFile(helpText))
        if webkit_available:
            self.devConsole = QWebInspector(self.verticalLayoutWidget_2)
            self.devConsole.setFixedHeight(0)
            self.devConsole.setObjectName("devConsole")
            self.devConsole.setPage(self.preview.page())
            self.right_layout.insertWidget(1, self.devConsole)
        self.filter = devToggleFilter()
        self.installEventFilter(self.filter)
        self.setModal(False)

    def changeFormat(self):
        self.autoUpdatePreview()
        self.toggleOptions()

    def exporterTypeChanged(self):
        new_exporter_name = self.exporter_combo.currentText()
        try:
            self.exporter = [
                e for e in EXPORTER_REGISTRY.getExporters()
                if e.name() == new_exporter_name][0]()
        except:
            pass

    def currentMapFormat(self):
        """
        Returns the currently selected map writer type
        """
        return self.getWriterFactory().type()

    def getWriterFactory(self):
        """
        Returns a factory to create the currently selected map writer
        """
        if self.mapFormat.checkedButton() == self.ol3:
            return OpenLayersWriter
        elif self.mapFormat.checkedButton() == self.leaflet:
            return LeafletWriter

    def createWriter(self):
        """
        Creates a writer object reflecting the current settings
        in the dialog
        """
        writer = self.getWriterFactory()()
        (writer.layers, writer.groups, writer.popup,
         writer.visible, writer.json,
         writer.cluster) = self.getLayersAndGroups()
        writer.params = self.getParameters()
        return writer

    def showErrorMessage(self, error):
        """
        Shows an error message in the preview window
        """
        html = "<html>"
        html += "<head></head>"
        html += "<style>body {font-family: sans-serif;}</style>"
        html += "<body><h1>Error</h1>"
        html += "<p>qgis2web produced an error:</p><code>"
        html += error
        html += "</code></body></html>"
        if self.preview:
            self.preview.setHtml(html)

    def showFeedbackMessage(self, title, message):
        """
        Shows a feedback message in the preview window
        """
        html = "<html>"
        html += "<head></head>"
        html += "<style>body {font-family: sans-serif;}</style>"
        html += "<body><h1>{}</h1>".format(title)
        html += "<p>{}</p>".format(message)
        html += "</body></html>"
        if self.preview:
            self.preview.setHtml(html)

    def toggleOptions(self):
        currentWriter = self.getWriterFactory()
        for param, value in specificParams.iteritems():
            treeParam = self.paramsTreeOL.findItems(param,
                                                    (Qt.MatchExactly |
                                                     Qt.MatchRecursive))[0]
            if currentWriter == OpenLayersWriter:
                if value == "OL3":
                    treeParam.setDisabled(False)
                else:
                    treeParam.setDisabled(True)
            else:
                if value == "OL3":
                    treeParam.setDisabled(True)
                else:
                    treeParam.setDisabled(False)
        for option, value in specificOptions.iteritems():
            treeOptions = self.layersTree.findItems(option,
                                                    (Qt.MatchExactly |
                                                     Qt.MatchRecursive))
            for treeOption in treeOptions:
                if currentWriter == OpenLayersWriter:
                    if value == "OL3":
                        treeOption.setDisabled(False)
                    else:
                        treeOption.setDisabled(True)
                else:
                    if value == "OL3":
                        treeOption.setDisabled(True)
                    else:
                        treeOption.setDisabled(False)

    def createPreview(self):
        writer = self.createWriter()
        return writer.write(self.iface,
                            dest_folder=utils.tempFolder()).index_file

    def shouldAutoPreview(self):
        """
        Returns a tuple, with a bool for whether the preview should
        automatically be generated, and a string for explanations
        as to why the preview cannot be automatically generated
        """
        writer = self.createWriter()
        total_features = 0
        for layer in writer.layers:
            if isinstance(layer, QgsVectorLayer):
                total_features += layer.featureCount()

        if total_features > int(self.previewFeatureLimit.text()):
            # Too many features => too slow!
            return (False, self.tr('<p>A large number of features are '
                                   'present in the map. Generating the '
                                   'preview may take some time.</p>'
                                   '<p>Click Update Preview to generate the '
                                   'preview anyway.</p>'))

        return (True, None)

    def autoUpdatePreview(self):
        """
        Triggered when a preview will be automatically generated, i.e.
        not as a result of the user manually clicking the
        Update Preview button.
        """
        (auto_preview, message) = self.shouldAutoPreview()
        if not auto_preview:
            self.showFeedbackMessage(self.tr('Preview Map'), message)
        else:
            self.previewMap()

    def previewMap(self):
        try:
            preview_file = self.createPreview()
            self.loadPreviewFile(preview_file)
        except Exception as e:
            self.showErrorMessage(
                traceback.format_exc().replace("\n", "<br />"))
            QgsMessageLog.logMessage(traceback.format_exc(), "qgis2web",
                                     level=QgsMessageLog.CRITICAL)

    def saveMap(self):
        writer = self.createWriter()
        write_folder = self.exporter.exportDirectory()
        if not write_folder:
            return

        self.feedback.reset()
        self.feedback.show()
        results = writer.write(self.iface,
                               dest_folder=write_folder,
                               feedback=self.feedback)
        self.feedback.showFeedback('Success')
        if self.closeFeedbackOnSuccess.checkState() == Qt.Checked:
            self.feedback.close()
        result = self.exporter.postProcess(results, feedback=self.feedback)
        if result and (not os.environ.get('CI') and
                       not os.environ.get('TRAVIS')):
            webbrowser.open_new_tab(self.exporter.destinationUrl())

    def populate_layers_and_groups(self, dlg):
        """Populate layers on QGIS into our layers and group tree view."""
        root_node = QgsProject.instance().layerTreeRoot()
        tree_groups = []
        tree_layers = root_node.findLayers()
        self.layers_item = QTreeWidgetItem()
        self.layers_item.setText(0, "Layers and Groups")
        self.layersTree.setColumnCount(3)

        for tree_layer in tree_layers:
            layer = tree_layer.layer()
            if layer.type() != QgsMapLayer.PluginLayer:
                try:
                    if layer.type() == QgsMapLayer.VectorLayer:
                        testDump = layer.rendererV2().dump()
                    layer_parent = tree_layer.parent()
                    if layer_parent.parent() is None:
                        item = TreeLayerItem(self.iface, layer,
                                             self.layersTree, dlg)
                        self.layers_item.addChild(item)
                    else:
                        if layer_parent not in tree_groups:
                            tree_groups.append(layer_parent)
                except:
                    QgsMessageLog.logMessage(traceback.format_exc(),
                                             "qgis2web",
                                             level=QgsMessageLog.CRITICAL)

        for tree_group in tree_groups:
            group_name = tree_group.name()
            group_layers = [
                tree_layer.layer() for tree_layer in tree_group.findLayers()]
            item = TreeGroupItem(group_name, group_layers, self.layersTree)
            self.layers_item.addChild(item)

        self.layersTree.addTopLevelItem(self.layers_item)
        self.layersTree.expandAll()
        self.layersTree.resizeColumnToContents(0)
        self.layersTree.resizeColumnToContents(1)
        for i in xrange(self.layers_item.childCount()):
            item = self.layers_item.child(i)
            if item.checkState(0) != Qt.Checked:
                item.setExpanded(False)

    def populateLayerSearch(self):
        self.layer_search_combo.clear()
        self.layer_search_combo.addItem("None")
        (layers, groups, popup, visible,
         json, cluster) = self.getLayersAndGroups()
        for count, layer in enumerate(layers):
            if layer.type() == layer.VectorLayer:
                options = []
                fields = layer.pendingFields()
                for f in fields:
                    fieldIndex = fields.indexFromName(unicode(f.name()))
                    try:
                        formCnf = layer.editFormConfig()
                        editorWidget = formCnf.widgetType(fieldIndex)
                    except:
                        editorWidget = layer.editorWidgetV2(fieldIndex)
                    if editorWidget == QgsVectorLayer.Hidden \
                            or editorWidget == 'Hidden':
                        continue
                    options.append(unicode(f.name()))
                for option in options:
                    displayStr = unicode(layer.name() + ": " + option)
                    self.layer_search_combo.insertItem(0, displayStr)
                    sln = utils.safeName(layer.name())
                    self.layer_search_combo.setItemData(
                        self.layer_search_combo.findText(displayStr),
                        sln + unicode(count))

    def configureExporter(self):
        self.exporter.configure()

    def populateConfigParams(self, dlg):
        """ Populates the dialog with option items and widgets """
        self.items = defaultdict(dict)
        tree = dlg.paramsTreeOL

        configure_export_action = QAction('...', self)
        configure_export_action.triggered.connect(self.configureExporter)

        params = getParams(configure_exporter_action=configure_export_action)
        for group, settings in params.iteritems():
            item = QTreeWidgetItem()
            item.setText(0, group)
            for param, value in settings.iteritems():
                subitem = self.createOptionItem(tree_widget=tree,
                                                parent_item=item,
                                                parameter=param,
                                                default_value=value)
                item.addChild(subitem)
                self.items[group][param] = subitem
            self.paramsTreeOL.addTopLevelItem(item)
            item.sortChildren(0, Qt.AscendingOrder)
        self.paramsTreeOL.expandAll()
        self.paramsTreeOL.resizeColumnToContents(0)
        self.paramsTreeOL.resizeColumnToContents(1)
        self.layer_search_combo.removeItem(1)

    def createOptionItem(self, tree_widget, parent_item,
                         parameter, default_value):
        """create the tree item corresponding to an option parameter"""
        action = None
        if isinstance(default_value, dict):
            action = default_value['action']
            default_value = default_value['option']

        subitem = TreeSettingItem(parent_item, tree_widget,
                                  parameter, default_value, action)
        if parameter == 'Layer search':
            self.layer_search_combo = subitem.combo
        elif parameter == 'Exporter':
            self.exporter_combo = subitem.combo

        return subitem

    def setStateToWriter(self, writer):
        """
        Sets the dialog state to match the specified writer
        """
        self.selectMapFormat(writer)
        self.setStateToParams(writer.params)
        self.setStateForBasemaps(writer.params["Appearance"]["Base layer"])

    def setStateToParams(self, params):
        """
        Sets the dialog state to match the specified parameters
        """
        for group, settings in self.items.iteritems():
            for param, item in settings.iteritems():
                value = params[group][param]
                item.setValue(value)

    def setStateForBasemaps(self, basemaps):
        """
        Sets the dialog state to match the specified basemaps
        """
        for i in range(self.basemaps.count()):
            self.basemaps.item(i).setSelected(False)

        for basemap in basemaps:
            try:
                self.basemaps.findItems(basemap,
                                        (Qt.MatchExactly))[0].setSelected(True)
            except:
                pass

    def populateBasemaps(self):
        """
        Adds entries for all known basemaps to the dialog
        """
        multiSelect = QAbstractItemView.ExtendedSelection
        self.basemaps.setSelectionMode(multiSelect)
        attrFields = []
        for i in range(len(baselayers)):
            for key in baselayers[i]:
                attrFields.append(key)
        self.basemaps.addItems(attrFields)

    def selectMapFormat(self, writer):
        """
        Updates dialog state to match the specified writer format
        """
        self.ol3.setChecked(isinstance(writer, OpenLayersWriter))
        self.leaflet.setChecked(isinstance(writer, LeafletWriter))

    def loadPreviewFile(self, file):
        """
        Loads a web based preview from a local file path
        """
        self.previewUrl = QUrl.fromLocalFile(file)
        if self.preview:
            self.preview.settings().clearMemoryCaches()
            self.preview.setUrl(self.previewUrl)

    def getParameters(self):
        parameters = defaultdict(dict)
        for group, settings in self.items.iteritems():
            for param, item in settings.iteritems():
                parameters[group][param] = item.value()
                if param == "Layer search":
                    parameters["Appearance"]["Search layer"] = (
                        self.layer_search_combo.itemData(
                            self.layer_search_combo.currentIndex()))
        basemaps = [i.text() for i in self.basemaps.selectedItems()]
        parameters["Appearance"]["Base layer"] = basemaps
        return parameters

    def saveParameters(self):
        """
        Saves current dialog state to project
        """
        WRITER_REGISTRY.saveWriterToProject(self.createWriter())
        EXPORTER_REGISTRY.writeToProject(self.exporter)

    def getLayersAndGroups(self):
        layers = []
        groups = {}
        popup = []
        visible = []
        json = []
        cluster = []
        for i in xrange(self.layers_item.childCount()):
            item = self.layers_item.child(i)
            if isinstance(item, TreeLayerItem):
                if item.checkState(0) == Qt.Checked:
                    layers.append(item.layer)
                    popup.append(item.popup)
                    visible.append(item.visible)
                    json.append(item.json)
                    cluster.append(item.cluster)
            else:
                group = item.name
                groupLayers = []
                if item.checkState(0) != Qt.Checked:
                    continue
                for layer in item.layers:
                    groupLayers.append(layer)
                    layers.append(layer)
                    popup.append(utils.NO_POPUP)
                    if item.visible:
                        visible.append(True)
                    else:
                        visible.append(False)
                    if hasattr(item, "json") and item.json:
                        json.append(True)
                    else:
                        json.append(False)
                    if hasattr(item, "cluster") and item.cluster:
                        cluster.append(True)
                    else:
                        cluster.append(False)
                groups[group] = groupLayers[::-1]

        return (layers[::-1],
                groups,
                popup[::-1],
                visible[::-1],
                json[::-1],
                cluster[::-1])

    def closeEvent(self, event):
        self.saveParameters()
        (layers, groups, popup, visible,
         json, cluster) = self.getLayersAndGroups()
        for layer, pop, vis in zip(layers, popup, visible):
            attrDict = {}
            for attr in pop:
                attrDict['attr'] = pop[attr]
                layer.setCustomProperty("qgis2web/popup/" + attr, pop[attr])
                layer.setCustomProperty("qgis2web/Visible", vis)

        QSettings().setValue(
            "qgis2web/MainDialogGeometry", self.saveGeometry())

        QSettings().setValue("qgis2web/previewOnStartup",
                             self.previewOnStartup.checkState())
        QSettings().setValue("qgis2web/closeFeedbackOnSuccess",
                             self.closeFeedbackOnSuccess.checkState())
        QSettings().setValue("qgis2web/previewFeatureLimit",
                             self.previewFeatureLimit.text())
        event.accept()
Example #35
0
    def _page_loaded(self, success):
        if self.develop and self.display:
            if self.inspector is None:
                self.inspector = QWebInspector()

            self.inspector.setPage(self.page)
            self.inspector.show()

        selenium_scripts = [
            'atoms.js',
            'htmlutils.js',
            # 'selenium-logging.js',
            #
            # 'find_matching_child.js',
            # 'selenium-api.js',
            # 'selenium-api-override.js',
            #
            # 'selenium-browserbot.js',
            # 'selenium-browserdetect.js',
            # 'selenium-commandhandlers.js',
            # 'xmlextras.js',
        ]

        for script in selenium_scripts:
            self.evaluate_js_file(os.path.dirname(__file__) + '/../selenium-scripts/' + script)

#         self.evaluate(
#             """
#             selenium=Selenium.createForWindow(window);
#             GCrawlerFactory = new CommandHandlerFactory();
#             GCrawlerFactory.registerAll(selenium);
#
#             function do_selenium_command(command,target,value)
#             {
#
#                 var command=new SeleniumCommand(command,target,value, false);
#                 var handler=GCrawlerFactory.getCommandHandler(command.command);
#                 if (handler)
#                 {
#                     command.target = selenium.preprocessParameter(command.target);
#                     command.value = selenium.preprocessParameter(command.value);
#
#                 try
#                 {
#                     handler.execute(selenium, command);
#                 }catch(e)
#                 {
#                     if (e.isSeleniumError)
#                         e.message;
#                 }
#
#                 }else
#                 {
#                     'Do not hava command '+command.command;
#                 }
#             }
#
# """)

        self.loaded = True
        # self.cache.clear()
        logger.debug("Page load finished")
Example #36
0
    def saveTranslations(self, translations):
        pass

    @pyqtSlot(int, result=str)
    def open_files(self, mode):
        a = QFileDialog()
        if mode == 1:
            v = a.getOpenFileNames(caption="Импорт файлов rpm...", filter="RPM Files (*.rpm);;Any files (*.*)")
            return json.dumps(str(v))
        elif mode == 2:
            return a.getExistingDirectory(options=QFileDialog.ShowDirsOnly)
        elif mode == 3:
            return a.getOpenFileName()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    view = Browser()
    view.page().mainFrame().addToJavaScriptWindowObject("Bridge", view)
    view.setWindowTitle("Handsome Localizer v1.0")
    view.load(QUrl("html/main.html"))
    view.setVisible(True)
    view.setMinimumWidth(1024)
    view.setMinimumHeight(480)
    view.page().settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
    inspector = QWebInspector()
    inspector.setPage(view.page())
    inspector.setVisible(True)
    app.exec_()
class WBrowserWeb(QWidget, Logger.ClassLogger):
    """
    Browser web widget
    """
    TagsHtml = pyqtSignal(dict, dict, dict, dict, dict, dict)

    def __init__(self, parent):
        """
        Constructor
        """
        QWidget.__init__(self)

        self.createActions()
        self.createWidgets()
        self.createToolbar()
        self.createConnections()
        self.center()

    def createToolbar(self):
        """
        Create toolbar
        """
        self.dockToolbarWebBrowser.setObjectName("Toolbar for web browser")
        self.dockToolbarWebBrowser.addAction(self.loadWebPageAction)
        self.dockToolbarWebBrowser.addAction(
            self.webView.pageAction(QWebPage.Back))
        self.dockToolbarWebBrowser.addAction(
            self.webView.pageAction(QWebPage.Forward))
        self.dockToolbarWebBrowser.addAction(
            self.webView.pageAction(QWebPage.Reload))
        self.dockToolbarWebBrowser.addAction(
            self.webView.pageAction(QWebPage.Stop))
        self.dockToolbarWebBrowser.setIconSize(QSize(16, 16))
        self.dockToolbarWebBrowser.addSeparator()

    def createWidgets(self):
        """
        Create all qt widgets
        """
        self.setWindowTitle(self.tr("Extensive Testing Client - Web Browser"))
        self.setWindowIcon(QIcon(":/main.png"))

        self.dockToolbarWebBrowser = QToolBar(self)
        self.dockToolbarWebBrowser.setToolButtonStyle(
            Qt.ToolButtonTextBesideIcon)

        browserLayoutGroup = QVBoxLayout()
        browserLayoutGroup.addWidget(self.dockToolbarWebBrowser)

        toolbarBrowserLayoutGroup = QHBoxLayout()

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

        self.webCounter = QLabel("(0%)")

        toolbarBrowserLayoutGroup.addWidget(QLabel("Load URL:"))
        toolbarBrowserLayoutGroup.addWidget(self.webCounter)
        toolbarBrowserLayoutGroup.addWidget(self.locationEdit)

        self.webTitle = QLabel("Title:")

        self.webView = QWebView()

        if QtHelper.str2bool(
                Settings.instance().readValue(key='Server/proxy-web-active')):

            proxy = QNetworkProxy()
            proxy.setType(3)
            # http
            proxy.setHostName(
                Settings.instance().readValue(key='Server/addr-proxy-http'))
            proxy.setPort(
                int(Settings.instance().readValue(
                    key='Server/port-proxy-http')))
            self.webView.page().networkAccessManager().setProxy(proxy)

        if QT_VERSION_STR.startswith("4."):
            self.webInspector = QWebInspector()
            self.webView.settings().setAttribute(
                QWebSettings.DeveloperExtrasEnabled, True)
            self.webInspector.setPage(self.webView.page())

        self.webView.setHtml(
            '<html><head></head><body>No content loaded</body></html>')
        self.webView.settings().setAttribute(QWebSettings.PluginsEnabled, True)
        self.webView.settings().setAttribute(
            QWebSettings.JavascriptCanOpenWindows, True)

        browserLayoutGroup.addLayout(toolbarBrowserLayoutGroup)
        browserLayoutGroup.addWidget(self.webTitle)

        self.webTab = QTabWidget()
        self.webTab.addTab(self.webView, "Web Page")
        if QT_VERSION_STR.startswith("4."):
            self.webTab.addTab(self.webInspector, "Source Inspector")

        browserLayoutGroup.addWidget(self.webTab)

        self.setLayout(browserLayoutGroup)

    def createConnections(self):
        """
        Create toolbar
        """
        self.locationEdit.returnPressed.connect(self.onChangeWebLocation)
        self.webView.loadProgress.connect(self.onWebProgress)
        self.webView.loadFinished.connect(self.onFinishLoading)

    def createActions(self):
        """
        Create qt actions
        """
        self.loadWebPageAction = QtHelper.createAction(
            self,
            "&Go to...",
            self.onChangeWebLocation,
            icon=QIcon(":/act-half-refresh.png"),
            tip='Load Webpage')

    def stop(self):
        """
        Stop the web view
        """
        self.webView.stop()

    def onChangeWebLocation(self):
        """
        On change web location
        """
        self.webCounter.setText("(1%)")
        url = QUrl.fromUserInput(self.locationEdit.text())
        self.webView.load(url)
        self.webView.setFocus()

    def onWebProgress(self, p):
        """
        On web progress
        """
        self.webCounter.setText("(%s%%)" % p)

    def onFinishLoading(self):
        """
        On finish loading
        """
        self.webTitle.setText("Title: %s" % self.webView.title())

        # need complete refonte with qt5
        if QT_VERSION_STR.startswith("5."):
            return

        frame = self.webView.page().mainFrame()
        document = frame.documentElement()

        elements = []
        self.examineChildElements(document, elements)

        tagList = {}
        idList = {}
        classList = {}
        nameList = {}
        linkList = {}
        cssList = {}

        for el in elements:
            # by tagname
            if 'tagname' in el:
                if el['tagname'] not in tagList: tagList[el['tagname']] = ''

            # by id
            if 'id' in el:
                if el['id'] not in idList: idList[el['id']] = ''

            # by name
            if 'name' in el:
                if el['name'] not in nameList: nameList[el['name']] = ''

            # by class
            if 'class' in el:
                if el['class'] not in classList:
                    classList[el['class'].replace(" ", ".")] = ''

            # by link text
            if 'text' in el:
                if 'tagname' in el:
                    if sys.version_info > (3, ):
                        if el['tagname'].lower() == 'a':
                            if el['text'] not in linkList:
                                linkList[el['text']] = ''
                    else:
                        if str(el['tagname']).lower() == 'a':
                            if el['text'] not in linkList:
                                linkList[el['text']] = ''

            # by css selector
            if 'tagname' in el:
                if sys.version_info > (3, ):
                    cssSelector = "%s" % el['tagname'].lower()
                else:
                    cssSelector = "%s" % str(el['tagname']).lower()
                if 'id' in el:
                    cssSelector += "#%s" % el['id']
                if 'class' in el:
                    cssSelector += ".%s" % el['class'].replace(" ", ".")
                cssList[cssSelector] = ''

        self.TagsHtml.emit(tagList, idList, classList, nameList, linkList,
                           cssList)

    def examineChildElements(self, parentElement, listResult):
        """
        Examine child elements
        """
        # Traverse the document.
        element = parentElement.firstChild()
        while not element.isNull():
            el = {}
            if element.attribute("id"): el['id'] = element.attribute("id")
            if element.attribute("name"):
                el['name'] = element.attribute("name")
            if element.attribute("class"):
                el['class'] = element.attribute("class")
            if element.tagName(): el['tagname'] = element.tagName()
            if element.toPlainText(): el['text'] = element.toPlainText()

            listResult.append(el)
            self.examineChildElements(element, listResult)
            element = element.nextSibling()

    def center(self):
        """
        Center the dialog
        """
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
Example #38
0
class SynopticWidget(QtGui.QWidget):
    """
    A Qt widget displaying a SVG synoptic in a webview.

    This widget does not have a "backend", so it's intended
    to be subclassed to add control system specific behavior.
    See TaurusSynopticWidget for a TANGO implementation.
    """

    subscribe = QtCore.pyqtSignal(str)

    def __init__(self, url=None, parent=None, *args, **kwargs):
        super(SynopticWidget, self).__init__(parent)
        self.subscribe.connect(self._handle_subscriptions)
        self._url = url
        self._setup_ui(url)
        self._modelNames = None

    def _setup_ui(self, url=None, section=None):
        self.hbox = hbox = QtGui.QHBoxLayout(self)
        self.hbox.setContentsMargins(0, 0, 0, 0)
        self.hbox.layout().setContentsMargins(0, 0, 0, 0)
        self.setLayout(self.hbox)
        if url:
            self.set_url(url, section)

    def set_url(self, url, section=None):
        # TODO: probably breaks things if the url is already set
        self._url = url
        self.splitter = QtGui.QSplitter(self)
        self.splitter.setOrientation(QtCore.Qt.Vertical)
        self.hbox.addWidget(self.splitter)
        view = self._create_view(url, section)
        self._setup_inspector(view)
        self.splitter.addWidget(view)
        print "set_url", url

    def setConfig(self, configFile):
        abspath = os.path.dirname(os.path.abspath(configFile))
        #build a javascript defining the models
        text = "var modelNames ={"
        with open(configFile, 'r') as read_file:
            data = json.load(read_file)
            for key in data.keys():
                text += key + " : \"" + data[key] + "\","
        text += "};"
        print(text)
        self._modelNames = text

    def _create_view(self, html=None, section=None):
        "Create the webview that will display the synoptic itself"
        view = QWebView(self)

        # This is supposedly an optimisation. Disable if there are
        # graphical artifacts or something.
        view.settings().TiledBackingStoreEnabled = True
        view.setRenderHint(QtGui.QPainter.TextAntialiasing, False)

        page = LoggingWebPage()
        view.setPage(page)
        view.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)

        # setup the JS interface
        frame = view.page().mainFrame()
        self.js = JSInterface(frame)
        self.js.subscription.connect(self.subscribe)

        # mouse interaction signals
        self.clicked = self.js.leftclicked
        self.rightClicked = self.js.rightclicked
        self.hovered = self.js.hovered
        self.clicked.connect(self._on_click)
        self.rightClicked.connect(self._on_rightclick)
        self.hovered.connect(self._on_hover)

        # Inject JSInterface into the JS global namespace as "Backend"
        def addBackend():
            frame.addToJavaScriptWindowObject('QtBackend', self.js)

        view.connect(frame, QtCore.SIGNAL("javaScriptWindowObjectCleared()"),
                     addBackend)

        # load the page
        # need to set the "base URL" for the webview to find the
        # resources (js, css).
        base_url = QtCore.QUrl().fromLocalFile(
            os.path.abspath(os.path.dirname(__file__)) + "/web/")

        # some ugly magic to get the path to the SVG file right. It
        # needs to be absolute because local paths go to the base URL.
        abspath = os.path.dirname(os.path.abspath(html))
        print("absolute path " + abspath + '/' + html)

        with open(html) as f:
            text = f.read().replace("${path}", abspath)  # TODO: use template
            if self._modelNames is not None:
                if "/*configplaceholder*/" in text:
                    print("placeholder found")
                    texta, textb = text.split("/*configplaceholder*/", 1)
                    text = texta + self._modelNames + textb
            view.setHtml(text, base_url)

        return view

    def _setup_inspector(self, view):
        """Create a WebInspector widget connected to the WebView. This allows inspecting
        the DOM, debugging javascript, logging, etc. Can be toggled using F12."""

        self._inspector = None
        page = view.page()

        def toggle_inspector():
            if self._inspector:
                self._inspector.setVisible(not self._inspector.isVisible())
            else:
                # create the inspector "on demand"
                page.settings().setAttribute(
                    QWebSettings.DeveloperExtrasEnabled, True)
                self._inspector = QWebInspector(self)
                self._inspector.setPage(page)
                self.splitter.addWidget(self._inspector)

        shortcut = QtGui.QShortcut(self)
        shortcut.setKey(QtCore.Qt.Key_F12)
        shortcut.activated.connect(toggle_inspector)

    def _handle_subscriptions(self, models):
        # we get the subscribed models as a comma separated list from Qt,
        # let's deliver something neater.
        if models:
            self.handle_subscriptions(str(models).split("\n"))
        else:
            self.handle_subscriptions([])

    def handle_subscriptions(self, models):
        # This noop needs to be overridden in order for subscriptions
        # to actually do anything!
        # "models" is a list of models that are currently visible
        # in the synoptic.
        pass

    def _on_click(self, kind, name):
        # this is a workaround for a strange behavior; under some circumstances
        # we get QStrings here, and sometimes unicode. Investigate!
        self.on_click(str(kind), str(name))

    def on_click(self, kind, name):
        """Default behavior on click. Override to change!"""
        if kind == "section":
            self.zoom_to(kind, name)
        elif kind == "model":
            self.select(kind, [name])

    def _on_rightclick(self, kind, name):
        # see _on_click()
        self.on_rightclick(str(kind), str(name))

    def on_rightclick(self, kind, name):
        "Placeholder; override me!"
        pass

    def _on_hover(self, section, models):
        # we get a comma separated string of concatenated models here.
        splitmodels = str(models).split("\n") if models else []
        self.on_hover(section, splitmodels)

    def on_hover(self, section, models):
        "Show a basic 'tooltip' when the mouse pointer is over an item."
        # Override this to add more interesting behavior
        if section:
            self.js.evaluate("synoptic.showTooltip();")
            self.js.evaluate("synoptic.setTooltipHTML('%s')" % section)
        elif models:
            self.js.evaluate("synoptic.showTooltip();")
            self.js.evaluate("synoptic.setTooltipHTML('%s')" % models[0])
        else:
            self.js.evaluate("synoptic.hideTooltip();")

    # # # 'Public' API # # #

    def zoom_to(self, kind, name):
        "Move the view so that the given object is visible"
        self.js.evaluate("synoptic.zoomTo(%r, %r)" % (str(kind), str(name)))

    def select(self, kind, names, replace=True):
        """Set a list of items as 'selected'. By default unselects all
        previously selected things first.
        """
        print "select", kind, names
        if replace:
            self.js.evaluate("synoptic.unselectAll()")
        if names:
            for name in names:
                self.js.evaluate("synoptic.select(%r, %r)" %
                                 (str(kind), [str(name)]))

    def unselect_all(self):
        self.js.evaluate("synoptic.unselectAll();")
Example #39
0
class Web_Page( QWebPage ):

    # =======================================================================
    def __init__(self, parent, parentMain, UID):

        # -------------------------------------------------------------------
        QWebPage.__init__(self, parent);

        # -------------------------------------------------------------------
        self.PARENT                                 = parentMain;
        self.UID                                    = UID;
        self.PARENT_TAB                             = parent;
        self.DEBUG                                  = False;
        self.LOG_TAG                                = str(self.__class__.__name__).upper();

        # -------------------------------------------------------------------
        self.L_BTN_CLICK                            = False;
        self.M_BTN_CLICK                            = False;
        self.R_BTN_CLICK                            = False;

        # -------------------------------------------------------------------
        self.PROGRESS_BAR                           = None;

        self.PROGRESS_BAR_PR                        = float( self.PARENT.WIDTH / 100);
        self.PROGRESS_BAR_W                         = 0;

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

        # SEARCH_INPUT
        self.SEARCH_INPUT                           =  QLineEdit("", self.PARENT);
        self.SEARCH_INPUT.setGeometry(0, 615, 400, 30);
        self.SEARCH_INPUT.setStyleSheet("QLineEdit{ background-color: rgba(0,0,0, 180); font-size: 12px; font-family: monospace; color: #fff; padding-left: 10px; border-style: none;}");
        self.connect( self.SEARCH_INPUT, SIGNAL('textChanged(const QString)') , self.FIND_ON_PAGE );
        self.connect( self.SEARCH_INPUT, SIGNAL('returnPressed()') , self.FIND_ON_PAGE );
        #self.SEARCH_INPUT.setReadOnly( True );
        self.SEARCH_INPUT_IS_OPEN                   = False;
        self.SEARCH_INPUT.hide();

        # -------------------------------------------------------------------
        self.AGENTS                                 = [

            # Chrome 41.0.2228.0
            "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
            # Chrome 41.0.2227.1
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36",
            # Chrome 41.0.2227.0
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
            # Chrome 41.0.2226.0
            "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36",
            # Chrome 41.0.2225.0
            "Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
            "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2225.0 Safari/537.36",
            # Chrome 41.0.2224.3
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2224.3 Safari/537.36",
            # Chrome 40.0.2214.93
            "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36",
            # Chrome 37.0.2062.124
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.124 Safari/537.36",
            # Chrome 37.0.2049.0
            "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
            "Mozilla/5.0 (Windows NT 4.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36",
            # Chrome 36.0.1985.67
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36",
            # Chrome 36.0.1985.125
            "Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36",
            # Chrome 36.0.1944.0
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1944.0 Safari/537.36",
            # Chrome 35.0.3319.102
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36",
            # Chrome 35.0.2309.372
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2309.372 Safari/537.36",
            # Chrome 35.0.2117.157
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.2117.157 Safari/537.36",
            # Chrome 35.0.1916.47
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36",
            # Chrome 34.0.1866.237
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1866.237 Safari/537.36",
            # Chrome 34.0.1847.137
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/4E423F",
            # Chrome 34.0.1847.116
            "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36",
            "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10",
            

        ];


        # -------------------------------------------------------------------
        self.USER_AGENT                             = self.AGENTS[0];

        self.HEADERS                                = {
            "User-Agent"        : "[USER-AGENT]",
            "Accept"            : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",

            #"Accept-Language"   : "en-US,en;q=0.5",
            #"Referer"           : "https://btc-e.com/",
            #"Connection"        : "keep-alive",
            #"Cache-Control"     : "max-age=0",
            #"Cookie"            : ""

        }

        # -------------------------------------------------------------------
        #self.setContentEditable( True );
        self.setLinkDelegationPolicy( QWebPage.DelegateAllLinks );
        self.setForwardUnsupportedContent( True );
        self.setNetworkAccessManager( self.PARENT.NET_MANAGER );

        self.linkClicked.connect( self.ON_LINK_CLICKED );
        self.linkHovered.connect( self.ON_LINK_HOVERED );
        self.loadProgress.connect( self.ON_PAGE_LOAD_PROGRESS );

        self.downloadRequested.connect( self.PARENT.DOWNLOAD_MANAGER.REQUEST );
        self.unsupportedContent.connect( self.PARENT.DOWNLOAD_MANAGER.REQUEST );

        # -------------------------------------------------------------------
        self.PRINT_ACTION = QAction( self );
        self.PRINT_ACTION.setShortcuts( QKeySequence.Print );
        self.PRINT_ACTION.triggered.connect( self.PRINT );
        self.PARENT.addAction( self.PRINT_ACTION );

        # -------------------------------------------------------------------
        # SETTINGS
       
        self.SETTINGS                               = self.settings();
        self.SETTINGS.setDefaultTextEncoding("utf-8"); # <= [TO-CONFIG.FILE] + ALL FROM BELOW

        #self.SETTINGS.clearIconDatabase();
        #self.SETTINGS.clearMemoryCaches();

        self.SETTINGS.setAttribute( QWebSettings.AutoLoadImages, True );
        self.SETTINGS.setAttribute( QWebSettings.DnsPrefetchEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.JavascriptEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.JavaEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.PluginsEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.PrivateBrowsingEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.JavascriptCanOpenWindows, True ); #
        self.SETTINGS.setAttribute( QWebSettings.JavascriptCanCloseWindows, False ); #
        self.SETTINGS.setAttribute( QWebSettings.JavascriptCanAccessClipboard, True ); #
        self.SETTINGS.setAttribute( QWebSettings.DeveloperExtrasEnabled, True ); #
        self.SETTINGS.setAttribute( QWebSettings.SpatialNavigationEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.LinksIncludedInFocusChain, True );
        self.SETTINGS.setAttribute( QWebSettings.ZoomTextOnly, False );
        self.SETTINGS.setAttribute( QWebSettings.PrintElementBackgrounds, False );
        self.SETTINGS.setAttribute( QWebSettings.OfflineStorageDatabaseEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.OfflineWebApplicationCacheEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.LocalStorageEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.LocalStorageDatabaseEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.LocalContentCanAccessRemoteUrls, True );
        self.SETTINGS.setAttribute( QWebSettings.LocalContentCanAccessFileUrls, True );
        self.SETTINGS.setAttribute( QWebSettings.XSSAuditingEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.AcceleratedCompositingEnabled, True );
        self.SETTINGS.setAttribute( QWebSettings.TiledBackingStoreEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.FrameFlatteningEnabled, False );
        self.SETTINGS.setAttribute( QWebSettings.SiteSpecificQuirksEnabled, True );

        # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

        self.SETTINGS.enablePersistentStorage( self.PARENT.STORAGE_ROOT );
        self.SETTINGS.setLocalStoragePath( self.PARENT.STORAGE_ROOT+"local_storage/" );
        self.SETTINGS.setIconDatabasePath ( self.PARENT.STORAGE_ROOT+"icons_path/" )
        self.SETTINGS.setMaximumPagesInCache ( 10 );

        # FIXME: Create settings config file [TO-CONFIG.FILE]

        self.SETTINGS.setOfflineWebApplicationCachePath( self.PARENT.STORAGE_ROOT+"/cache/" );
        self.SETTINGS.setOfflineWebApplicationCacheQuota ( 25 * 1024 *1024 );

        self.SETTINGS.setOfflineStoragePath( self.PARENT.STORAGE_ROOT );
        self.SETTINGS.setOfflineStorageDefaultQuota ( 25 * 1024 *1024 );
        #self.SETTINGS.setObjectCacheCapacities (int cacheMinDeadCapacity, int cacheMaxDead, int totalCapacity)

        # -------------------------------------------------------------------
        self.INSPECTOR    = QWebInspector( None );

        """
        __init__ (self, QWidget parent = None)
        closeEvent (self, QCloseEvent event)
        bool event (self, QEvent)
        hideEvent (self, QHideEvent event)
        QWebPage page (self)
        resizeEvent (self, QResizeEvent event)
        setPage (self, QWebPage page)
        showEvent (self, QShowEvent event)
        QSize sizeHint (self)
        """

        # -------------------------------------------------------------------
        self.INIT();
        # -------------------------------------------------------------------

    # =======================================================================
    def INIT( self ):

        # -------------------------------------------------------------------
        self.HEADERS["User-Agent"] = self.USER_AGENT;

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

    # =======================================================================
    def POST_INIT( self ):

        # -------------------------------------------------------------------
        self.PROGRESS_BAR = QFrame( self.PARENT.WEB_VIEWS[ self.UID ]["WEB_VIEW"] );
        self.PROGRESS_BAR.setStyleSheet( "QFrame{ background-color: #F00; }" );
        self.PROGRESS_BAR.setGeometry( 0, 0, 0, 5 );
        # -------------------------------------------------------------------

    # =======================================================================
    def EXEC_JS( self, _JS ):

        # -------------------------------------------------------------------
        #frame = self.PARENT.WEB_VIEW.page().mainFrame();
        #frame = self.mainFrame();
        #frame.evaluateJavaScript( _JS );
        
        self.mainFrame().evaluateJavaScript( _JS.encode("utf-8") );
        
        # -------------------------------------------------------------------

    # =======================================================================
    def GET_EXTENTIONS( self ):

        # -------------------------------------------------------------------
        #supportsExtension();
        pass;
        # -------------------------------------------------------------------

    # =======================================================================
    def GET_META_DATA( self ):

        # -------------------------------------------------------------------
        print( "GET_META_DATA:" );

        frame = self.mainFrame();

        meta_data =frame.metaData(); #dict-of-QString-list-of-QString metaData

        for meta in meta_data:
            print(meta);

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

    # =======================================================================
    def GET_PAGE_HTML( self ):

        # -------------------------------------------------------------------
        frame = self.mainFrame();
        return unicode(frame.toHtml()).encode('utf-8');

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

    # =======================================================================
    def GET_PAGE_TITLE( self ):

        # -------------------------------------------------------------------
        return str(self.mainFrame().title());

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

    # =======================================================================
    def CMD( self, _CMD ):

        # -------------------------------------------------------------------
        #__exec:page:exec:js:function_name

        # -------------------------------------------------------------------
        try:
    
            # -----------------------------------------------
            if _CMD[0] == "exec":
                if _CMD[1] == "js":

                    self.EXEC_JS( "".join(_CMD[2:]) );
                    self.LOCAL_INFO_LOG( str(_CMD) );
                    return True;

            # -----------------------------------------------
            elif _CMD[0] == "set":
                if _CMD[1] == "user-agent":

                    self.USER_AGENT = "".join(_CMD[2:]).replace('\"', '\\"').replace("\'", "\\'");
                    self.EXEC_JS( "alert('set:user-agent:"+self.USER_AGENT+"');" );
                    self.LOCAL_INFO_LOG( str(_CMD) );
                    return True;

            # -----------------------------------------------
            elif _CMD[0] == "get":
                if _CMD[1] == "user-agent":

                    self.EXEC_JS( "alert('get:user-agent:"+self.USER_AGENT+"');" );
                    self.LOCAL_INFO_LOG( str(_CMD) );
                    return True;

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

            self.LOCAL_ERROR_LOG( "UNKNOWN: "+str(_CMD)+" CMD" );                    
            return False;

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

        except Exception as _err:
            self.LOCAL_ERROR_LOG( str(_CMD)+": "+str(_err) );
            return False;
    
        # -------------------------------------------------------------------

    # =======================================================================
    def AAA_user_BBB_AgentForUrl( self, _url ):

        # -------------------------------------------------------------------
        # Chrome Win/NT 32 Doc-Browser');

        #print("-------------------------------------------------------------")
        #_ByteArray = QUrl.toPercentEncoding( _url.toString(), "{}", " ");
       
        #encoded_url = str( _url.encodedQuery() )
        #print( encoded_url );


        """
        print( "authority(): "+str( _url.authority() ) );
        print( "encodedHost(): "+str( _url.encodedHost() ) );
        print( "encodedPath(): "+str( _url.encodedPath() ) );
        print( "encodedQuery(): "+str( _url.encodedQuery() ) );
        
        print( "encodedUserName(): "+str( _url.encodedUserName() ) );
        print( "host(): "+str( _url.host() ) );
        print( "isLocalFile(): "+str( _url.isLocalFile() ) );
        print( "path(): "+str( _url.path() ) );
        print( "port(): "+str( _url.port() ) );
        print( "userInfo(): "+str( _url.userInfo() ) );
        print( "userName(): "+str( _url.userName() ) );
        print( "topLevelDomain(): "+str( _url.topLevelDomain() ) );
        print( "toString(): "+str( _url.toString() ) );
        """


        #print("-------------------------------------------------------------")
        return self.USER_AGENT;
        # -------------------------------------------------------------------

    # =======================================================================
    def REPAINT_REQUESTED ( self, _QRect ): #repaintRequested (const QRect&)

        # -------------------------------------------------------------------
        print("NOT-IMPLEMENTED: repaintRequested (const QRect&):");
        # -------------------------------------------------------------------
    
    # =======================================================================
    def SHOW_INSPECTOR( self ):

        # -------------------------------------------------------------------
        self.INSPECTOR.setPage( self );


        self.INSPECTOR.setGeometry( 0,0, 800, 450 );
        self.INSPECTOR.show( );
        #self.INSPECTOR.showMaximized( );

        toolbar_items = [
            ".elements", ".resources", ".network", ".scripts", 
            ".timeline", ".profiles", ".audits", ".console"
        ];

        self.mainFrame().evaluateJavaScript("""
            document.addEventListener('DOMContentLoaded',function(){
                setTimeout(function(){
                    document.querySelector('.toolbar-item.network').click()
                }, 2000);
            });
        """);

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

    # =======================================================================
    def ON_LINK_HOVERED(self, _url_A, _url_B, _url_C ): # (const QString&,const QString&,const QString&)

        # -------------------------------------------------------------------
        #print( "ON_LINK_HOVERED: "+self.UID+": ["+str(_url_A)+"]" );
        
        self.PARENT.STATUS_BAR.setText( unicode(str(_url_A)) );
        # -------------------------------------------------------------------

    # =======================================================================
    def ON_LINK_CLICKED(self, _url):

        # -------------------------------------------------------------------
        _url = unicode( str(_url.toString()).replace("file://", "") );

        # -------------------------------------------------------------------
        #print("ON_LINK_CLICKED: "+self.UID );

        if self.M_BTN_CLICK:
            self.PARENT.CREATE_TAB( _url );
            self.PARENT.URL_BAR.SET_TEXT( _url );

        else:
            self.PARENT.URL_BAR.SET_TEXT( _url );
            self.PARENT.GO_TO_URL();


        self.PARENT.HISTORY_HANDLER.hide();
        # -------------------------------------------------------------------
        #toAscii();
        #toUtf8();
        #toLatin1();
        #toLocal8Bit();
        self.L_BTN_CLICK = False;
        self.M_BTN_CLICK = False;
        self.R_BTN_CLICK = False;
        # -------------------------------------------------------------------

    # =======================================================================
    def ON_PAGE_LOAD_PROGRESS(self, _int_pr):

        # -------------------------------------------------------------------
        if _int_pr >= 100:

            if self.PARENT.CURRENT_TAB_BAR_UID == self.UID:
                self.PARENT.LOADING_BAR.setText( "Loading: Done." );
            self.PROGRESS_BAR_W = 0;


        else:

            if self.PARENT.CURRENT_TAB_BAR_UID == self.UID:
                self.PARENT.LOADING_BAR.setText( "Loading: ["+str(_int_pr)+"]" );

            self.PROGRESS_BAR_W = self.PROGRESS_BAR_PR * _int_pr;

        self.PROGRESS_BAR.setGeometry( 0, 0, self.PROGRESS_BAR_W, 5 );
        # -------------------------------------------------------------------

    # =======================================================================
    def SEARCH_INPUT_CTRL( self, _action ):

        # -------------------------------------------------------------------
        if _action == "show":
            self.SEARCH_INPUT_IS_OPEN = True;
            self.SEARCH_INPUT.setFocus();
            self.SEARCH_INPUT.show();

        else:
            self.SEARCH_INPUT_IS_OPEN = False;
            self.SEARCH_INPUT.clearFocus();
            self.SEARCH_INPUT.hide();
        # -------------------------------------------------------------------

    # =======================================================================
    def FIND_ON_PAGE(self):

        # -------------------------------------------------------------------
        #print("FIND_ON_PAGE: "+self.UID );

        try:

            self.SEARCH_INPUT.setFocus();
            self.SEARCH_INPUT_CTRL("show");

            _value = unicode( str(self.SEARCH_INPUT.text()).strip() );

            #findText (self, QString subString, FindFlags options = 0)
            self.findText (_value, QWebPage.FindWrapsAroundDocument);

            # QWebPage.HighlightAllOccurrences

        except Exception as _err:
            self.LOCAL_ERROR_LOG( str(_err) );

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

    # =======================================================================
    def PRINT( self ):

        # -------------------------------------------------------------------
        try: 

            pdf_name = self.GET_PAGE_TITLE()+"_"+str(self.PARENT.GET_TIME(True))+"_";
            pdf_name = pdf_name.replace( " ", "-" ).replace( ":", "-" )+".pdf";

            self.PRINTER = QPrinter( QPrinter.ScreenResolution );
            self.PRINTER.setFontEmbeddingEnabled( False );
            self.PRINTER.setFullPage( True );
            #self.PRINTER.setPrinterName ("name of printer");
            #self.PRINTER.setPrintProgram ( "print program");

            self.PRINTER.setOutputFileName ( self.PARENT.DOWNLOAD_DIR+pdf_name );

            # ------ >
            #self.PRINTER.setOutputFormat( QPrinter.NativeFormat ); # <= IMAGE
            self.PRINTER.setOutputFormat( QPrinter.PdfFormat ); # <= TEXT
            #self.PRINTER.setOutputFormat( QPrinter.PostScriptFormat ); # ???

            #QPrinter will print output using a method defined by the platform it is running on. 
            # This mode is the default when printing directly to a printer.
            #QPrinter.NativeFormat [0]   
            
            #QPrinter will generate its output as a searchable PDF file. This mode is the default when printing to a file.
            #QPrinter.PdfFormat [1]   

            #QPrinter will generate its output as in the PostScript format. (This feature was introduced in Qt 4.2.)
            #QPrinter.PostScriptFormat [2]

            self.mainFrame().print_( self.PRINTER );

            self.LOCAL_INFO_LOG( "PDF: Saved ["+str(self.PARENT.DOWNLOAD_DIR+pdf_name)+"]" );


        except Exception as _err:
            self.LOCAL_ERROR_LOG( str(_err) );

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

    # =======================================================================
    def SEND_ESC( self ):

        # -------------------------------------------------------------------
        #print("SEND_ESC: START");
        js = '''
                
            try{

                var e = document.createEvent('KeyboardEvent');
                e.initKeyboardEvent("keyup", true, true, window, 0,0,0,0,0, 27,0 );
                document.dispatchEvent(e);

                var e = document.createEvent('KeyboardEvent');
                e.initKeyboardEvent("keydown", true, true, window, 0,0,0,0,0, 27,0 );
                document.dispatchEvent(e);

                var e = document.createEvent('KeyboardEvent');
                e.initKeyboardEvent("keypress", true, true, window, 0,0,0,0,0, 27,0 );
                document.dispatchEvent(e);



            }catch(e){
                alert(e);
            }

        '''


        # -------------------------------------------------------------------
        self.mainFrame().evaluateJavaScript( js );
        #print("SEND_ESC: DONE");
        # -------------------------------------------------------------------

    # =======================================================================
    def event( self, _evt ):

        # -------------------------------------------------------------------
        #self.L_BTN_CLICK = False;
        #self.M_BTN_CLICK = False;
        #self.R_BTN_CLICK = False;

        # -------------------------------------------------------------------
        # http://pyqt.sourceforge.net/Docs/PyQt4/qevent.html#Type-enum
        #print( _evt.type() );
        # -------------------------------------------------------------------
        #if _evt.type() == QEvent.FocusOut:      # (QFocusEvent) == 9 == focus OUT BY CLICK
        #elif _evt.type() == QEvent.FocusIn:     # (QFocusEvent) == 8 == focus IN BY CLICK

        # -------------------------------------------------------------------
        #if _evt.type() == QEvent.ContextMenu:   # (QContextMenuEvent) == 82

        # -------------------------------------------------------------------
        #QEvent.MouseButtonDblClick  4   Mouse press again (QMouseEvent).
        #QEvent.MouseButtonRelease   3   Mouse release (QMouseEvent).
        #QPoint _evt.globalPos(); | int _evt.global[X|Y](); | QPoint _evt.pos(); | QPointF _evt.posF(); | int _evt.[x|y]()
        #_evt.button() == ( Qt.LeftButton | Qt.RightButton | Qt.MidButton )
        if _evt.type() == QEvent.MouseButtonPress: # 2   Mouse press (QMouseEvent).

            #print( "WEB_PAGE["+str(self.UID)+"].event:" );
            if _evt.button() == Qt.LeftButton:
                #print("Qt.LeftButton: "+str(Qt.LeftButton))
                self.L_BTN_CLICK = True;

            elif _evt.button() == Qt.MidButton:
                #print("Qt.MidButton: "+str(Qt.MidButton))
                self.M_BTN_CLICK = True;
            
            elif _evt.button() == Qt.RightButton:
                #print("Qt.RightButton: "+str(Qt.RightButton))
                self.R_BTN_CLICK = True;

        # -------------------------------------------------------------------
        """
        #QEvent.KeyPress 6   Key press (QKeyEvent).
        #QEvent.KeyRelease   7   Key release (QKeyEvent).
        if _evt.type() == QEvent.KeyRelease:
            print("KeyRelease: ["+str(_evt.text())+", "+str(_evt.nativeScanCode())+", "+str(_evt.key())+"]");

        int count (self)
        bool isAutoRepeat (self)
        int key (self)
        bool matches (self, QKeySequence.StandardKey key)
        Qt.KeyboardModifiers modifiers (self)
        int nativeModifiers (self)
        int nativeScanCode (self)
        int nativeVirtualKey (self)
        QString text (self)
        """

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

        """
        if _evt.type() == QEvent.Enter:         # 10

            self.setStyleSheet( self.STL["hovered"] );
            self.HAS_FOCUS = True;

        elif _evt.type() == QEvent.Leave:       # 11 

            self.setStyleSheet( self.STL["default"] );
            self.HAS_FOCUS = False;
        """

        # -------------------------------------------------------------------
        return QWebPage.event(self, _evt);
        # -------------------------------------------------------------------

    # =======================================================================
    def LOCAL_INFO_LOG( self, _msg, METHOD=None ):

        # -------------------------------------------------------------------
        if METHOD is None:
            self.PARENT.LOCAL_INFO_LOG( "['"+self.LOG_TAG+"']: ["+_msg+"]" );
        else:
            self.PARENT.LOCAL_INFO_LOG( "['"+self.LOG_TAG+"."+METHOD+"']: ["+_msg+"]" );
        # -------------------------------------------------------------------

    # =======================================================================
    def LOCAL_ERROR_LOG( self, _msg, METHOD=None ):

        # -------------------------------------------------------------------
        if self.DEBUG or self.PARENT.DEBUG_GLOBAL: self.PARENT.DEBUGGER.DEBUG();
        # -------------------------------------------------------------------
        if METHOD is None:
            self.PARENT.LOCAL_ERROR_LOG( "['"+self.LOG_TAG+"']: ["+_msg+"]" );
        else:
            self.PARENT.LOCAL_ERROR_LOG( "['"+self.LOG_TAG+"."+METHOD+"']: ["+_msg+"]" );
        # -------------------------------------------------------------------

    # =======================================================================
    def LOCAL_WARNING_LOG( self, _msg, METHOD=None ):

        # -------------------------------------------------------------------
        if METHOD is None:
            self.PARENT.LOCAL_WARNING_LOG( "['"+self.LOG_TAG+"']: ["+_msg+"]" );
        else:
            self.PARENT.LOCAL_WARNING_LOG( "['"+self.LOG_TAG+"."+METHOD+"']: ["+_msg+"]" );