コード例 #1
0
ファイル: IndexWidget.py プロジェクト: zhangbailong945/lbcs
class IndexWidget(QWidget):
    def __init__(self, *args, **kwargs):
        super(IndexWidget, self).__init__(*args, **kwargs)
        self.setAttribute(Qt.WA_StyledBackground, True)
        self.initUI()

    def initUI(self):
        self.webView = QWebEngineView(self)
        self.webView.setContextMenuPolicy(Qt.NoContextMenu)
        self.webView.load(QUrl("http://www.zhangbailong.com"))
コード例 #2
0
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.browser = QWebEngineView()
        self.browser.setHtml("<h1>Test</h1>")
        self.browser.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
        self.setCentralWidget(self.browser)

        self.show()

    def html(self, value):
        self.browser.setHtml(value)
コード例 #3
0
class TabWelcomeSplash(TabRootClass):
    def __init__(self, parent=None):
        super(TabWelcomeSplash, self).__init__(parent)


    def initUI(self):
        # self.setWindowOpacity(1)
        # self.setWindowFlags(Qt.FramelessWindowHint)
        # self.setAttribute(Qt.WA_TranslucentBackground)
        # self.showFullScreen()
        rect = QApplication.desktop().screenGeometry()
        self.resize(rect.width(), rect.height())
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)

        self.webview = QWebEngineView()

        vbox = QVBoxLayout()
        vbox.addWidget(self.webview)

        main = QGridLayout()
        main.setSpacing(0)
        main.addLayout(vbox, 0, 0)

        self.setLayout(main)

        #dirname, filename = os.path.split(os.path.abspath(__file__))
        # dir = os.getcwd(); #

        realPath = os.path.realpath(__file__)
        realDir = os.path.dirname(realPath);
        realHtml = realDir + "/splash_html_page/splash.html"
        realUrl = "file:///"+ realHtml;

        #self.webview.load(QUrl("file:////Users/jerryw/MyCode/QUANTAXIS/QUANTAXIS_Monitor_GUI/MainTabWindows/splash_html_page/splash.html"))
        self.webview.load(QUrl(realUrl))

        self.webview.setContextMenuPolicy(Qt.NoContextMenu)
        self.webview.show()
コード例 #4
0
class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        self.initUI()

    def closeEvent(self, event):

        msg_box = QMessageBox()
        msg_box.setIcon(QMessageBox.Warning)
        msg_box.setWindowTitle("Alert")
        msg_box.setText("Are you sure you want to exit the program?")
        msg_box.setWindowIcon(QIcon("resources/icons/trello.ico"))
        msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)

        retval = msg_box.exec_()

        if retval == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def initUI(self):

        self.web = QWebEngineView()
        self.web.setWindowTitle("Trello")
        self.web.setWindowIcon(QIcon("resources/icons/trello.ico"))
        self.web.load(QUrl("https://trello.com/"))
        self.web.showMaximized()
        self.web.setContextMenuPolicy(Qt.NoContextMenu)
        self.web.show()
        self.web.loadFinished.connect(self.webpageLoaded)

        self.web.closeEvent = self.closeEvent

    def webpageLoaded(self):
        QApplication.restoreOverrideCursor()
コード例 #5
0
class BrowserView(QMainWindow):
    instances = {}

    create_window_trigger = QtCore.pyqtSignal(object)
    set_title_trigger = QtCore.pyqtSignal(str)
    load_url_trigger = QtCore.pyqtSignal(str)
    html_trigger = QtCore.pyqtSignal(str)
    dialog_trigger = QtCore.pyqtSignal(int, str, bool, str, str)
    destroy_trigger = QtCore.pyqtSignal()
    fullscreen_trigger = QtCore.pyqtSignal()
    current_url_trigger = QtCore.pyqtSignal()
    evaluate_js_trigger = QtCore.pyqtSignal(str, str)

    class JSBridge(QtCore.QObject):
        api = None
        parent_uid = None

        try:
            qtype = QtCore.QJsonValue  # QT5
        except AttributeError:
            qtype = str  # QT4

        def __init__(self):
            super(BrowserView.JSBridge, self).__init__()

        @QtCore.pyqtSlot(str, qtype, result=str)
        def call(self, func_name, param):
            func_name = BrowserView._convert_string(func_name)
            param = BrowserView._convert_string(param)

            return _js_bridge_call(self.parent_uid, self.api, func_name, param)

    def __init__(self, uid, title, url, width, height, resizable, fullscreen,
                 min_size, confirm_quit, background_color, debug, js_api,
                 webview_ready):
        super(BrowserView, self).__init__()
        BrowserView.instances[uid] = self
        self.uid = uid

        self.js_bridge = BrowserView.JSBridge()
        self.js_bridge.api = js_api
        self.js_bridge.parent_uid = self.uid

        self.is_fullscreen = False
        self.confirm_quit = confirm_quit

        self._file_name_semaphore = Semaphore(0)
        self._current_url_semaphore = Semaphore(0)

        self.load_event = Event()

        self._js_results = {}
        self._current_url = None
        self._file_name = None

        self.resize(width, height)
        self.title = title
        self.setWindowTitle(title)

        # Set window background color
        self.background_color = QColor()
        self.background_color.setNamedColor(background_color)
        palette = self.palette()
        palette.setColor(self.backgroundRole(), self.background_color)
        self.setPalette(palette)

        if not resizable:
            self.setFixedSize(width, height)

        self.setMinimumSize(min_size[0], min_size[1])

        self.view = QWebView(self)

        if url is not None:
            self.view.setUrl(QtCore.QUrl(url))
        else:
            self.load_event.set()

        self.setCentralWidget(self.view)

        self.create_window_trigger.connect(BrowserView.on_create_window)
        self.load_url_trigger.connect(self.on_load_url)
        self.html_trigger.connect(self.on_load_html)
        self.dialog_trigger.connect(self.on_file_dialog)
        self.destroy_trigger.connect(self.on_destroy_window)
        self.fullscreen_trigger.connect(self.on_fullscreen)
        self.current_url_trigger.connect(self.on_current_url)
        self.evaluate_js_trigger.connect(self.on_evaluate_js)
        self.set_title_trigger.connect(self.on_set_title)

        if _qt_version >= [5, 5]:
            self.channel = QWebChannel(self.view.page())
            self.view.page().setWebChannel(self.channel)

        self.view.page().loadFinished.connect(self.on_load_finished)

        if fullscreen:
            self.toggle_fullscreen()

        self.view.setContextMenuPolicy(
            QtCore.Qt.NoContextMenu)  # disable right click context menu

        self.move(QApplication.desktop().availableGeometry().center() -
                  self.rect().center())
        self.activateWindow()
        self.raise_()
        webview_ready.set()

    def on_set_title(self, title):
        self.setWindowTitle(title)

    def on_file_dialog(self, dialog_type, directory, allow_multiple,
                       save_filename, file_filter):
        if dialog_type == FOLDER_DIALOG:
            self._file_name = QFileDialog.getExistingDirectory(
                self,
                localization['linux.openFolder'],
                options=QFileDialog.ShowDirsOnly)
        elif dialog_type == OPEN_DIALOG:
            if allow_multiple:
                self._file_name = QFileDialog.getOpenFileNames(
                    self, localization['linux.openFiles'], directory,
                    file_filter)
            else:
                self._file_name = QFileDialog.getOpenFileName(
                    self, localization['linux.openFile'], directory,
                    file_filter)
        elif dialog_type == SAVE_DIALOG:
            if directory:
                save_filename = os.path.join(str(directory),
                                             str(save_filename))

            self._file_name = QFileDialog.getSaveFileName(
                self, localization['global.saveFile'], save_filename)

        self._file_name_semaphore.release()

    def on_current_url(self):
        url = BrowserView._convert_string(self.view.url().toString())
        self._current_url = None if url == '' else url
        self._current_url_semaphore.release()

    def on_load_url(self, url):
        self.view.setUrl(QtCore.QUrl(url))

    def on_load_html(self, content):
        self.view.setHtml(content, QtCore.QUrl(''))

    def closeEvent(self, event):
        if self.confirm_quit:
            reply = QMessageBox.question(
                self, self.title, localization['global.quitConfirmation'],
                QMessageBox.Yes, QMessageBox.No)

            if reply == QMessageBox.No:
                event.ignore()
                return

        event.accept()
        del BrowserView.instances[self.uid]

    def on_destroy_window(self):
        self.close()

    def on_fullscreen(self):
        if self.is_fullscreen:
            self.showNormal()
        else:
            self.showFullScreen()

        self.is_fullscreen = not self.is_fullscreen

    def on_evaluate_js(self, script, uuid):
        def return_result(result):
            result = BrowserView._convert_string(result)
            uuid_ = BrowserView._convert_string(uuid)

            js_result = self._js_results[uuid_]
            js_result[
                'result'] = None if result is None or result == 'null' else result if result == '' else json.loads(
                    result)
            js_result['semaphore'].release()

        escaped_script = 'JSON.stringify(eval("{0}"))'.format(
            _escape_string(script))

        try:  # PyQt4
            result = self.view.page().mainFrame().evaluateJavaScript(
                escaped_script)
            return_result(result)
        except AttributeError:  # PyQt5
            self.view.page().runJavaScript(escaped_script, return_result)

    def on_load_finished(self):
        if self.js_bridge.api:
            self._set_js_api()
        else:
            self.load_event.set()

    def set_title(self, title):
        self.set_title_trigger.emit(title)

    def get_current_url(self):
        self.load_event.wait()
        self.current_url_trigger.emit()
        self._current_url_semaphore.acquire()

        return self._current_url

    def load_url(self, url):
        self.load_event.clear()
        self.load_url_trigger.emit(url)

    def load_html(self, content):
        self.load_event.clear()
        self.html_trigger.emit(content)

    def create_file_dialog(self, dialog_type, directory, allow_multiple,
                           save_filename, file_filter):
        self.dialog_trigger.emit(dialog_type, directory, allow_multiple,
                                 save_filename, file_filter)
        self._file_name_semaphore.acquire()

        if _qt_version >= [5, 0]:  # QT5
            if dialog_type == FOLDER_DIALOG:
                file_names = (self._file_name, )
            elif dialog_type == SAVE_DIALOG or not allow_multiple:
                file_names = (self._file_name[0], )
            else:
                file_names = tuple(self._file_name[0])

        else:  # QT4
            if dialog_type == FOLDER_DIALOG:
                file_names = (BrowserView._convert_string(self._file_name), )
            elif dialog_type == SAVE_DIALOG or not allow_multiple:
                file_names = (BrowserView._convert_string(
                    self._file_name[0]), )
            else:
                file_names = tuple(
                    [BrowserView._convert_string(s) for s in self._file_name])

        # Check if we got an empty tuple, or a tuple with empty string
        if len(file_names) == 0 or len(file_names[0]) == 0:
            return None
        else:
            return file_names

    def destroy_(self):
        self.destroy_trigger.emit()

    def toggle_fullscreen(self):
        self.fullscreen_trigger.emit()

    def evaluate_js(self, script):
        self.load_event.wait()

        result_semaphore = Semaphore(0)
        unique_id = uuid1().hex
        self._js_results[unique_id] = {
            'semaphore': result_semaphore,
            'result': ''
        }

        self.evaluate_js_trigger.emit(script, unique_id)
        result_semaphore.acquire()

        result = deepcopy(self._js_results[unique_id]['result'])
        del self._js_results[unique_id]

        return result

    def _set_js_api(self):
        def _register_window_object():
            frame.addToJavaScriptWindowObject('external', self.js_bridge)

        script = _parse_api_js(self.js_bridge.api)

        if _qt_version >= [5, 5]:
            qwebchannel_js = QtCore.QFile('://qtwebchannel/qwebchannel.js')
            if qwebchannel_js.open(QtCore.QFile.ReadOnly):
                source = bytes(qwebchannel_js.readAll()).decode('utf-8')
                self.view.page().runJavaScript(source)
                self.channel.registerObject('external', self.js_bridge)
                qwebchannel_js.close()
        elif _qt_version >= [5, 0]:
            frame = self.view.page().mainFrame()
            _register_window_object()
        else:
            frame = self.view.page().mainFrame()
            _register_window_object()

        try:  # PyQt4
            self.view.page().mainFrame().evaluateJavaScript(script)
        except AttributeError:  # PyQt5
            self.view.page().runJavaScript(script)

        self.load_event.set()

    @staticmethod
    def _convert_string(result):
        try:
            if result is None or result.isNull():
                return None

            result = result.toString()  # QJsonValue conversion
        except AttributeError:
            pass

        return _convert_string(result)

    @staticmethod
    # Receive func from subthread and execute it on the main thread
    def on_create_window(func):
        func()
コード例 #6
0
ファイル: qt.py プロジェクト: patrick-chen/testlib
class BrowserView(QMainWindow):
    instance = None
    load_url_trigger = pyqtSignal(str)
    html_trigger = pyqtSignal(str, str)
    dialog_trigger = pyqtSignal(int, str, bool, str)
    destroy_trigger = pyqtSignal()
    fullscreen_trigger = pyqtSignal()
    current_url_trigger = pyqtSignal()

    def __init__(self, title, url, width, height, icon, resizable, fullscreen,
                 min_size):
        super(BrowserView, self).__init__()
        BrowserView.instance = self
        self.is_fullscreen = False

        self._file_name_semaphor = threading.Semaphore(0)
        self._current_url_semaphore = threading.Semaphore()

        self.resize(width, height)
        self.setWindowTitle(title)

        if not resizable:
            self.setFixedSize(width, height)

        self.setMinimumSize(min_size[0], min_size[1])

        #self.view = QWebView(self)
        self.view = QWebView(self)
        self.view.setContextMenuPolicy(
            Qt.NoContextMenu)  # disable right click context menu
        if icon is not None:
            self.setWindowIcon(QIcon(icon))
        if url is not None:
            self.view.setUrl(QUrl(url))

        self.setCentralWidget(self.view)
        self.load_url_trigger.connect(self._handle_load_url)
        self.html_trigger.connect(self._handle_load_html)
        #self.dialog_trigger.connect(self._handle_file_dialog)
        self.destroy_trigger.connect(self._handle_destroy_window)
        self.fullscreen_trigger.connect(self._handle_fullscreen)
        #self.current_url_trigger.connect(self._handle_current_url)

        if fullscreen:
            self.toggle_fullscreen()

        self.move(QApplication.desktop().availableGeometry().center() -
                  self.rect().center())
        self.activateWindow()
        self.raise_()
        #webview_ready.set()

    def _handle_get_current_url(self):
        self._current_url = self.view.url().toString()
        self._current_url_semaphore.release()

    def _handle_load_url(self, url):
        self.view.setUrl(QUrl(url))

    def _handle_load_html(self, content, base_uri):
        self.view.setHtml(content, QUrl(base_uri))

    def _handle_destroy_window(self):
        self.close()

    def _handle_fullscreen(self):
        if self.is_fullscreen:
            self.showNormal()
        else:
            self.showFullScreen()

        self.is_fullscreen = not self.is_fullscreen

    def get_current_url(self):
        self.current_url_trigger.emit()
        self._current_url_semaphore.acquire()

        return self._current_url

    def load_url(self, url):
        self.load_url_trigger.emit(url)

    def load_html(self, content, base_uri):
        self.html_trigger.emit(content, base_uri)

    def create_file_dialog(self, dialog_type, directory, allow_multiple,
                           save_filename):
        self.dialog_trigger.emit(dialog_type, directory, allow_multiple,
                                 save_filename)
        self._file_name_semaphor.acquire()

        if dialog_type == FOLDER_DIALOG or not allow_multiple:
            return str(self._file_name)
        elif allow_multiple:
            file_names = map(str, self._file_name)

            if len(file_names) == 1:
                return file_names[0]
            else:
                return file_names
        else:
            return None
コード例 #7
0
ファイル: web_container.py プロジェクト: pombredanne/whither
class QtWebContainer(WebContainer):
    def __init__(self,
                 bridge_objs: BridgeObjects = None,
                 *args,
                 **kwargs) -> None:
        super().__init__(name='_web_container',
                         bridge_objs=bridge_objs,
                         *args,
                         **kwargs)

        if self._config.debug_mode:
            os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = '12345'

        self.profile = QWebEngineProfile.defaultProfile()
        self.interceptor = QtUrlRequestInterceptor()

        self.view = QWebEngineView(parent=self._main_window.widget)
        self.page = self.view.page()

        self.channel = QWebChannel(self.page)
        self.bridge_initialized = False

        self._initialize_page(self.page)

        if self._config.debug_mode:
            self.devtools = DevTools()

        if not self._config.context_menu.enabled:
            self.view.setContextMenuPolicy(Qt.PreventContextMenu)

        if not self._config.allow_remote_urls:
            self.profile.setRequestInterceptor(self.interceptor)

        if self._config.entry_point.autoload:
            self.initialize_bridge_objects()
            self.load()

        self.view.show()
        self._main_window.widget.setCentralWidget(self.view)

    @staticmethod
    def _create_webengine_script(path: Url, name: str) -> QWebEngineScript:
        script = QWebEngineScript()
        script_file = QFile(path)

        if script_file.open(QFile.ReadOnly):
            script_string = str(script_file.readAll(), 'utf-8')

            script.setInjectionPoint(QWebEngineScript.DocumentCreation)
            script.setName(name)
            script.setWorldId(QWebEngineScript.MainWorld)
            script.setSourceCode(script_string)

        return script

    def _get_channel_api_script(self) -> QWebEngineScript:
        return self._create_webengine_script(':/qtwebchannel/qwebchannel.js',
                                             'QWebChannel API')

    def _init_bridge_channel(self) -> None:
        self.page.setWebChannel(self.channel)
        self.page.scripts().insert(self._get_channel_api_script())

        self.bridge_initialized = True

    def _initialize_page(self, page: QWebEnginePage) -> None:
        page_settings = self.page.settings().globalSettings()

        if self._config.allow_remote_urls:
            ENABLED_SETTINGS.append('LocalContentCanAccessRemoteUrls')
        else:
            DISABLED_SETTINGS.append('LocalContentCanAccessRemoteUrls')

        for setting in DISABLED_SETTINGS:
            try:
                page_settings.setAttribute(
                    getattr(QWebEngineSettings, setting), False)
            except AttributeError:
                pass

        for setting in ENABLED_SETTINGS:
            try:
                page_settings.setAttribute(
                    getattr(QWebEngineSettings, setting), True)
            except AttributeError:
                pass

        page.setView(self.view)

    def initialize_bridge_objects(self) -> None:
        if not self.bridge_initialized:
            self._init_bridge_channel()

        registered_objects = self.channel.registeredObjects()

        for obj in self.bridge_objects:
            if obj not in registered_objects:
                self.channel.registerObject(obj._name, obj)

    def load(self, url: str = '') -> None:
        url = url if url else self._config.entry_point.url

        if 'http' not in url and not os.path.exists(url):
            self.page.setHtml(DEFAULT_ENTRY_POINT)
            return

        if not url.startswith('file'):
            url = 'file://{0}'.format(url)

        self.page.load(QUrl(url))

    def load_script(self, path: Url, name: str):
        script = self._create_webengine_script(path, name)
        return self.page.scripts().insert(script)
コード例 #8
0
ファイル: browser.py プロジェクト: rda0/web-greeter
class Browser(Application):
    # pylint: disable=too-many-instance-attributes
    """The main browser"""
    url_scheme: QWebEngineUrlScheme
    bridge_initialized: bool
    dev_view: QWebEngineView
    dev_page: WebPage
    qdock: QDockWidget

    def __init__(self):
        super().__init__()
        self.init()
        # self.load()

    def init(self):
        """Initialize browser"""
        logger.debug("Initializing Browser Window")

        if web_greeter_config["config"]["greeter"]["debug_mode"]:
            os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = '12345'

        url_scheme = "web-greeter"
        self.url_scheme = QWebEngineUrlScheme(url_scheme.encode())
        self.url_scheme.setDefaultPort(QWebEngineUrlScheme.PortUnspecified)
        self.url_scheme.setFlags(QWebEngineUrlScheme.SecureScheme
                                 or QWebEngineUrlScheme.LocalScheme
                                 or QWebEngineUrlScheme.LocalAccessAllowed)
        QWebEngineUrlScheme.registerScheme(self.url_scheme)

        self.profile = QWebEngineProfile.defaultProfile()
        self.interceptor = QtUrlRequestInterceptor(url_scheme)
        self.url_scheme_handler = QtUrlSchemeHandler()

        self.view = QWebEngineView(parent=self.window)
        self.page = WebPage()
        self.view.setPage(self.page)
        self.page.setObjectName("WebG Page")
        self.view.setObjectName("WebG View")

        self.channel = QWebChannel(self.page)
        self.bridge_initialized = False

        self.profile.installUrlSchemeHandler(url_scheme.encode(),
                                             self.url_scheme_handler)

        self._initialize_page()

        if web_greeter_config["config"]["greeter"]["debug_mode"]:
            self._initialize_devtools()
        else:
            self.view.setContextMenuPolicy(Qt.PreventContextMenu)

        self._init_actions()
        if web_greeter_config["app"]["frame"]:
            self._init_menu_bar()
        else:
            self.window.setWindowFlags(self.window.windowFlags()
                                       | Qt.FramelessWindowHint)

        if web_greeter_config["config"]["greeter"]["secure_mode"]:
            if hasattr(QWebEngineProfile, "setUrlRequestInterceptor"):
                self.profile.setUrlRequestInterceptor(self.interceptor)
            else:  # Older Qt5 versions
                self.profile.setRequestInterceptor(self.interceptor)

        self.page.setBackgroundColor(QColor(0, 0, 0))
        self.window.setStyleSheet("""QMainWindow, QWebEngineView {
	                                background: #000000;
                                 }""")

        self.window.setCentralWidget(self.view)

        logger.debug("Browser Window created")

    def load(self):
        """Load theme and initialize bridge"""
        self.load_theme()

        self.bridge_objects = (self.greeter, self.greeter_config,
                               self.theme_utils)
        self.initialize_bridge_objects()
        self.load_script(':/_greeter/js/bundle.js', 'Web Greeter Bundle')

    def _initialize_devtools(self):
        self.dev_view = QWebEngineView(parent=self.window)
        self.dev_page = WebPage()
        self.dev_view.setPage(self.dev_page)
        self.page.setDevToolsPage(self.dev_page)
        self.dev_view.setObjectName("Devtools view")
        self.dev_page.setObjectName("Devtools page")

        self.dev_page.windowCloseRequested.connect(
            lambda: self.toggle_devtools_value(False))

        inspect_element_action = self.page.action(self.page.InspectElement)
        inspect_element_action.triggered.connect(
            lambda: self.toggle_devtools_value(True))

        self.qdock = QDockWidget()
        self.qdock.setWidget(self.dev_view)
        self.qdock.setFeatures(QDockWidget.DockWidgetMovable
                               or QDockWidget.DockWidgetClosable)

        self.window.addDockWidget(Qt.RightDockWidgetArea, self.qdock)
        self.qdock.hide()
        logger.debug("DevTools initialized")

    def toggle_devtools(self):
        """Toggle devtools"""
        if not web_greeter_config["config"]["greeter"]["debug_mode"]:
            return
        self.toggle_devtools_value(not self.qdock.isVisible())

    def toggle_devtools_value(self, value: bool):
        """Toggle devtools by value"""
        if not web_greeter_config["config"]["greeter"]["debug_mode"]:
            return

        if value:
            self.qdock.show()
            self.dev_view.setFocus()
        else:
            self.qdock.hide()
            self.view.setFocus()

    def _init_actions(self):
        """Init browser actions"""
        self.exit_action = QAction(QIcon("exit.png"), "&Quit", self.window)
        self.exit_action.setShortcut("Ctrl+Q")
        self.exit_action.setStatusTip("Exit application")
        self.exit_action.triggered.connect(qApp.quit)

        self.toggle_dev_action = QAction("Toggle Developer Tools", self.window)
        self.toggle_dev_action.setShortcut("Ctrl+Shift+I")
        self.toggle_dev_action.triggered.connect(self.toggle_devtools)

        self.fullscreen_action = QAction("Toggle Fullscreen", self.window)
        self.fullscreen_action.setShortcut("F11")
        self.fullscreen_action.triggered.connect(
            lambda: self.toggle_fullscreen(not self.window.isFullScreen()))

        self.inc_zoom_action = QAction("Zoom In", self.window)
        self.inc_zoom_action.setShortcut("Ctrl++")
        self.inc_zoom_action.triggered.connect(self._inc_zoom)
        self.dec_zoom_action = QAction("Zoom Out", self.window)
        self.dec_zoom_action.setShortcut("Ctrl+-")
        self.dec_zoom_action.triggered.connect(self._dec_zoom)
        self.reset_zoom_action = QAction("Actual Size", self.window)
        self.reset_zoom_action.setShortcut("Ctrl+0")
        self.reset_zoom_action.triggered.connect(self._reset_zoom)

        self.window.addAction(self.exit_action)
        self.window.addAction(self.toggle_dev_action)
        self.window.addAction(self.fullscreen_action)
        self.window.addAction(self.inc_zoom_action)
        self.window.addAction(self.dec_zoom_action)
        self.window.addAction(self.reset_zoom_action)

    def _inc_zoom(self):
        if self.view.hasFocus():
            self.page.increaseZoom()
        else:
            self.dev_page.increaseZoom()

    def _dec_zoom(self):
        if self.view.hasFocus():
            self.page.decreaseZoom()
        else:
            self.dev_page.decreaseZoom()

    def _reset_zoom(self):
        if self.view.hasFocus():
            self.page.setZoomFactor(1)
        else:
            self.dev_page.setZoomFactor(1)

    def _init_menu_bar(self):
        minimize_action = QAction("Minimize", self.window)
        minimize_action.setShortcut("Ctrl+M")
        minimize_action.triggered.connect(self.window.showMinimized)
        close_action = QAction("Close", self.window)
        close_action.setShortcut("Ctrl+W")
        close_action.triggered.connect(self.window.close)

        self.page.action(
            self.page.ReloadAndBypassCache).setText("Force Reload")

        self.page.fullScreenRequested.connect(self.accept_fullscreen)

        self.menu_bar = QMenuBar()

        file_menu = self.menu_bar.addMenu("&File")
        file_menu.addAction(self.exit_action)

        edit_menu = self.menu_bar.addMenu("&Edit")
        edit_menu.addAction(self.page.action(self.page.Undo))
        edit_menu.addAction(self.page.action(self.page.Redo))
        edit_menu.addSeparator()
        edit_menu.addAction(self.page.action(self.page.Cut))
        edit_menu.addAction(self.page.action(self.page.Copy))
        edit_menu.addAction(self.page.action(self.page.Paste))
        edit_menu.addSeparator()
        edit_menu.addAction(self.page.action(self.page.SelectAll))

        view_menu = self.menu_bar.addMenu("&View")
        view_menu.addAction(self.page.action(self.page.Reload))
        view_menu.addAction(self.page.action(self.page.ReloadAndBypassCache))
        view_menu.addAction(self.toggle_dev_action)
        view_menu.addSeparator()
        view_menu.addAction(self.reset_zoom_action)
        view_menu.addAction(self.inc_zoom_action)
        view_menu.addAction(self.dec_zoom_action)
        view_menu.addSeparator()
        view_menu.addAction(self.fullscreen_action)

        window_menu = self.menu_bar.addMenu("&Window")
        window_menu.addAction(minimize_action)
        window_menu.addAction(close_action)

        # help_menu = menu_bar.addMenu("&Help")

        self.window.setMenuBar(self.menu_bar)

    def accept_fullscreen(self, request):
        """Accepts fullscreen requests"""
        if web_greeter_config["config"]["greeter"]["debug_mode"]:
            request.reject()
            return
        if request.toggleOn():
            self.toggle_fullscreen(True)
        else:
            self.toggle_fullscreen(False)
        request.accept()

    def toggle_fullscreen(self, value: bool):
        """Toggle fullscreen"""
        if not web_greeter_config["config"]["greeter"]["debug_mode"]:
            return
        if value:
            state = self.states["FULLSCREEN"]
            self.window.setWindowFlags(self.window.windowFlags()
                                       or Qt.FramelessWindowHint)
            self.menu_bar.setParent(None)
            self.window.setMenuBar(None)
        else:
            state = self.states["NORMAL"]
            self.window.setWindowFlags(self.window.windowFlags()
                                       or not Qt.FramelessWindowHint)
            self.window.setMenuBar(self.menu_bar)
        try:
            self.window.windowHandle().setWindowState(state)
        except (AttributeError, TypeError):
            self.window.setWindowState(state)

    def _initialize_page(self):
        page_settings = self.page.settings().globalSettings()

        if not web_greeter_config["config"]["greeter"]["secure_mode"]:
            ENABLED_SETTINGS.append('LocalContentCanAccessRemoteUrls')
        else:
            DISABLED_SETTINGS.append('LocalContentCanAccessRemoteUrls')

        for setting in DISABLED_SETTINGS:
            try:
                page_settings.setAttribute(
                    getattr(QWebEngineSettings, setting), False)
            except AttributeError:
                pass

        for setting in ENABLED_SETTINGS:
            try:
                page_settings.setAttribute(
                    getattr(QWebEngineSettings, setting), True)
            except AttributeError:
                pass

        self.page.setView(self.view)

    def load_theme(self):
        """Load theme"""
        theme = web_greeter_config["config"]["greeter"]["theme"]
        dir_t = "/usr/share/web-greeter/themes/"
        path_to_theme = os.path.join(dir_t, theme, "index.html")
        def_theme = "gruvbox"

        if theme.startswith("/"):
            path_to_theme = theme
        elif theme.__contains__(".") or theme.__contains__("/"):
            path_to_theme = os.path.join(os.getcwd(), theme)
            path_to_theme = os.path.realpath(path_to_theme)

        if not path_to_theme.endswith(".html"):
            path_to_theme = os.path.join(path_to_theme, "index.html")

        if not os.path.exists(path_to_theme):
            print("Path does not exists", path_to_theme)
            path_to_theme = os.path.join(dir_t, def_theme, "index.html")

        web_greeter_config["config"]["greeter"]["theme"] = path_to_theme

        url = QUrl(f"web-greeter://app/{path_to_theme}")
        self.page.load(url)

        logger.debug("Theme loaded")

    @staticmethod
    def _create_webengine_script(path: Url, name: str) -> QWebEngineScript:
        script = QWebEngineScript()
        script_file = QFile(path)

        # print(script_file, path)

        if script_file.open(QFile.ReadOnly):
            script_string = str(script_file.readAll(), 'utf-8')

            script.setInjectionPoint(QWebEngineScript.DocumentCreation)
            script.setName(name)
            script.setWorldId(QWebEngineScript.MainWorld)
            script.setSourceCode(script_string)
            # print(script_string)

        return script

    def _get_channel_api_script(self) -> QWebEngineScript:
        return self._create_webengine_script(':/qtwebchannel/qwebchannel.js',
                                             'QWebChannel API')

    def _init_bridge_channel(self) -> None:
        self.page.setWebChannel(self.channel)
        self.bridge_initialized = True

    def initialize_bridge_objects(self) -> None:
        """Initialize bridge objects :D"""
        if not self.bridge_initialized:
            self._init_bridge_channel()
        registered_objects = self.channel.registeredObjects()

        for obj in self.bridge_objects:
            if obj not in registered_objects:
                # pylint: disable=protected-access
                self.channel.registerObject(obj._name, obj)
                # print("Registered", obj._name)

    def load_script(self, path: Url, name: str):
        """Loads a script in page"""
        qt_api = self._get_channel_api_script()
        qt_api_source = qt_api.sourceCode()
        script = self._create_webengine_script(path, name)
        script.setSourceCode(qt_api_source + "\n" + script.sourceCode())
        self.page.scripts().insert(script)
コード例 #9
0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1189, 574)
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(46, 52, 54))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush)
        brush = QtGui.QBrush(QtGui.QColor(69, 78, 81))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Light, brush)
        brush = QtGui.QBrush(QtGui.QColor(57, 65, 67))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Midlight, brush)
        brush = QtGui.QBrush(QtGui.QColor(23, 26, 27))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Dark, brush)
        brush = QtGui.QBrush(QtGui.QColor(30, 34, 36))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Mid, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.BrightText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(46, 52, 54))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Shadow, brush)
        brush = QtGui.QBrush(QtGui.QColor(23, 26, 27))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.AlternateBase,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 220))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ToolTipBase,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ToolTipText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(46, 52, 54))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush)
        brush = QtGui.QBrush(QtGui.QColor(69, 78, 81))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Light, brush)
        brush = QtGui.QBrush(QtGui.QColor(57, 65, 67))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Midlight,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(23, 26, 27))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Dark, brush)
        brush = QtGui.QBrush(QtGui.QColor(30, 34, 36))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Mid, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.BrightText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(46, 52, 54))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Shadow, brush)
        brush = QtGui.QBrush(QtGui.QColor(23, 26, 27))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.AlternateBase,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 220))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ToolTipBase,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ToolTipText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(23, 26, 27))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(46, 52, 54))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush)
        brush = QtGui.QBrush(QtGui.QColor(69, 78, 81))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Light, brush)
        brush = QtGui.QBrush(QtGui.QColor(57, 65, 67))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Midlight,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(23, 26, 27))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Dark, brush)
        brush = QtGui.QBrush(QtGui.QColor(30, 34, 36))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Mid, brush)
        brush = QtGui.QBrush(QtGui.QColor(23, 26, 27))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.BrightText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(23, 26, 27))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(46, 52, 54))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(46, 52, 54))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Shadow, brush)
        brush = QtGui.QBrush(QtGui.QColor(46, 52, 54))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.AlternateBase,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 220))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipBase,
                         brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ToolTipText,
                         brush)
        MainWindow.setPalette(palette)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/resources/app.png"),
                       QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        MainWindow.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setSizeConstraint(
            QtWidgets.QLayout.SetDefaultConstraint)
        self.verticalLayout.setObjectName("verticalLayout")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setSizeConstraint(
            QtWidgets.QLayout.SetDefaultConstraint)
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.fileNameLabel = QtWidgets.QLabel(self.centralwidget)
        self.fileNameLabel.setObjectName("fileNameLabel")
        self.horizontalLayout_3.addWidget(self.fileNameLabel)
        self.fileNameTextBox = QtWidgets.QLineEdit(self.centralwidget)
        self.fileNameTextBox.setReadOnly(True)
        self.fileNameTextBox.setObjectName("fileNameTextBox")
        self.horizontalLayout_3.addWidget(self.fileNameTextBox)
        self.openFileBtn = QtWidgets.QToolButton(self.centralwidget)
        icon1 = QtGui.QIcon()
        icon1.addPixmap(QtGui.QPixmap(":/resources/open.png"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.openFileBtn.setIcon(icon1)
        self.openFileBtn.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
        self.openFileBtn.setObjectName("openFileBtn")
        self.horizontalLayout_3.addWidget(self.openFileBtn)
        self.verticalLayout.addLayout(self.horizontalLayout_3)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.previousBtn = QtWidgets.QPushButton(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.previousBtn.sizePolicy().hasHeightForWidth())
        self.previousBtn.setSizePolicy(sizePolicy)
        self.previousBtn.setObjectName("previousBtn")
        self.horizontalLayout_2.addWidget(self.previousBtn)
        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setObjectName("comboBox")
        self.horizontalLayout_2.addWidget(self.comboBox)
        self.nextBtn = QtWidgets.QPushButton(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.nextBtn.sizePolicy().hasHeightForWidth())
        self.nextBtn.setSizePolicy(sizePolicy)
        self.nextBtn.setObjectName("nextBtn")
        self.horizontalLayout_2.addWidget(self.nextBtn)
        self.testCaseBtn = QtWidgets.QPushButton(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.testCaseBtn.sizePolicy().hasHeightForWidth())
        self.testCaseBtn.setSizePolicy(sizePolicy)
        icon2 = QtGui.QIcon()
        icon2.addPixmap(QtGui.QPixmap(":/resources/download.png"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.testCaseBtn.setIcon(icon2)
        self.testCaseBtn.setIconSize(QtCore.QSize(28, 28))
        self.testCaseBtn.setFlat(True)
        self.testCaseBtn.setObjectName("testCaseBtn")
        self.horizontalLayout_2.addWidget(self.testCaseBtn)
        self.problemDownloadBtn = QtWidgets.QPushButton(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.problemDownloadBtn.sizePolicy().hasHeightForWidth())
        self.problemDownloadBtn.setSizePolicy(sizePolicy)
        self.problemDownloadBtn.setIcon(icon2)
        self.problemDownloadBtn.setIconSize(QtCore.QSize(28, 28))
        self.problemDownloadBtn.setFlat(True)
        self.problemDownloadBtn.setObjectName("problemDownloadBtn")
        self.horizontalLayout_2.addWidget(self.problemDownloadBtn)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.statementWebView = QWebView(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.statementWebView.sizePolicy().hasHeightForWidth())
        self.statementWebView.setSizePolicy(sizePolicy)
        self.statementWebView.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
        self.statementWebView.setUrl(QtCore.QUrl("about:blank"))
        self.statementWebView.setObjectName("statementWebView")
        self.horizontalLayout.addWidget(self.statementWebView)
        self.solutionWebView = QWebView(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.solutionWebView.sizePolicy().hasHeightForWidth())
        self.solutionWebView.setSizePolicy(sizePolicy)
        self.solutionWebView.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
        self.solutionWebView.setUrl(QtCore.QUrl("about:blank"))
        self.solutionWebView.setObjectName("solutionWebView")
        self.horizontalLayout.addWidget(self.solutionWebView)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 1189, 22))
        self.menubar.setObjectName("menubar")
        self.menuOpen = QtWidgets.QMenu(self.menubar)
        self.menuOpen.setObjectName("menuOpen")
        MainWindow.setMenuBar(self.menubar)
        self.statusBar = QtWidgets.QStatusBar(MainWindow)
        self.statusBar.setObjectName("statusBar")
        MainWindow.setStatusBar(self.statusBar)
        self.actionOpen = QtWidgets.QAction(MainWindow)
        self.actionOpen.setIcon(icon1)
        self.actionOpen.setObjectName("actionOpen")
        self.actionReset = QtWidgets.QAction(MainWindow)
        self.actionReset.setObjectName("actionReset")
        self.actionExit = QtWidgets.QAction(MainWindow)
        icon3 = QtGui.QIcon()
        icon3.addPixmap(QtGui.QPixmap(":/resources/exit.png"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.actionExit.setIcon(icon3)
        self.actionExit.setObjectName("actionExit")
        self.menuOpen.addAction(self.actionOpen)
        self.menuOpen.addAction(self.actionReset)
        self.menuOpen.addSeparator()
        self.menuOpen.addAction(self.actionExit)
        self.menubar.addAction(self.menuOpen.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(
            _translate("MainWindow", "Hackerrank Submission Data Reader"))
        self.fileNameLabel.setText(_translate("MainWindow", "File Name"))
        self.openFileBtn.setText(_translate("MainWindow", "Open"))
        self.previousBtn.setText(_translate("MainWindow", "<"))
        self.nextBtn.setText(_translate("MainWindow", ">"))
        self.testCaseBtn.setText(
            _translate("MainWindow", "Download Test Cases"))
        self.problemDownloadBtn.setText(
            _translate("MainWindow", "Download Problem Sattement"))
        self.menuOpen.setTitle(_translate("MainWindow", "File"))
        self.actionOpen.setText(_translate("MainWindow", "Open"))
        self.actionOpen.setShortcut(_translate("MainWindow", "Ctrl+O"))
        self.actionReset.setText(_translate("MainWindow", "Reset"))
        self.actionReset.setShortcut(_translate("MainWindow", "Ctrl+R"))
        self.actionExit.setText(_translate("MainWindow", "Exit"))
コード例 #10
0
ファイル: PreviewerHTML.py プロジェクト: zhoumaomao11/Pymakr
class PreviewerHTML(QWidget):
    """
    Class implementing a previewer widget for HTML, Markdown and ReST files.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (QWidget)
        """
        super(PreviewerHTML, self).__init__(parent)

        self.__layout = QVBoxLayout(self)

        self.titleLabel = QLabel(self)
        self.titleLabel.setWordWrap(True)
        self.titleLabel.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__layout.addWidget(self.titleLabel)

        try:
            from PyQt5.QtWebKitWidgets import QWebPage, QWebView
            self.previewView = QWebView(self)
            self.previewView.page().setLinkDelegationPolicy(
                QWebPage.DelegateAllLinks)
            self.__usesWebKit = True
        except ImportError:
            from PyQt5.QtWebEngineWidgets import QWebEngineView
            self.previewView = QWebEngineView(self)
            self.__usesWebKit = False

        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.previewView.sizePolicy().hasHeightForWidth())
        self.previewView.setSizePolicy(sizePolicy)
        self.previewView.setContextMenuPolicy(Qt.NoContextMenu)
        self.previewView.setUrl(QUrl("about:blank"))
        self.__layout.addWidget(self.previewView)

        self.jsCheckBox = QCheckBox(self.tr("Enable JavaScript"), self)
        self.jsCheckBox.setToolTip(
            self.tr("Select to enable JavaScript for HTML previews"))
        self.__layout.addWidget(self.jsCheckBox)

        self.ssiCheckBox = QCheckBox(self.tr("Enable Server Side Includes"),
                                     self)
        self.ssiCheckBox.setToolTip(
            self.tr("Select to enable support for Server Side Includes"))
        self.__layout.addWidget(self.ssiCheckBox)

        self.jsCheckBox.clicked[bool].connect(self.on_jsCheckBox_clicked)
        self.ssiCheckBox.clicked[bool].connect(self.on_ssiCheckBox_clicked)
        self.previewView.titleChanged.connect(self.on_previewView_titleChanged)
        if self.__usesWebKit:
            self.previewView.linkClicked.connect(
                self.on_previewView_linkClicked)

        self.jsCheckBox.setChecked(Preferences.getUI("ShowFilePreviewJS"))
        self.ssiCheckBox.setChecked(Preferences.getUI("ShowFilePreviewSSI"))

        self.__scrollBarPositions = {}
        self.__vScrollBarAtEnd = {}
        self.__hScrollBarAtEnd = {}

        self.__processingThread = PreviewProcessingThread()
        self.__processingThread.htmlReady.connect(self.__setHtml)

        self.__previewedPath = None
        self.__previewedEditor = None

    def shutdown(self):
        """
        Public method to perform shutdown actions.
        """
        self.__processingThread.wait()

    @pyqtSlot(bool)
    def on_jsCheckBox_clicked(self, checked):
        """
        Private slot to enable/disable JavaScript.
        
        @param checked state of the checkbox (boolean)
        """
        Preferences.setUI("ShowFilePreviewJS", checked)
        self.__setJavaScriptEnabled(checked)

    def __setJavaScriptEnabled(self, enable):
        """
        Private method to enable/disable JavaScript.
        
        @param enable flag indicating the enable state (boolean)
        """
        self.jsCheckBox.setChecked(enable)

        settings = self.previewView.settings()
        settings.setAttribute(settings.JavascriptEnabled, enable)

        self.processEditor()

    @pyqtSlot(bool)
    def on_ssiCheckBox_clicked(self, checked):
        """
        Private slot to enable/disable SSI.
        
        @param checked state of the checkbox (boolean)
        """
        Preferences.setUI("ShowFilePreviewSSI", checked)
        self.processEditor()

    def processEditor(self, editor=None):
        """
        Public slot to process an editor's text.
        
        @param editor editor to be processed (Editor)
        """
        if editor is None:
            editor = self.__previewedEditor
        else:
            self.__previewedEditor = editor

        if editor is not None:
            fn = editor.getFileName()

            if fn:
                extension = os.path.normcase(os.path.splitext(fn)[1][1:])
            else:
                extension = ""
            if extension in \
                Preferences.getEditor("PreviewHtmlFileNameExtensions") or \
               editor.getLanguage() == "HTML":
                language = "HTML"
            elif extension in \
                    Preferences.getEditor("PreviewMarkdownFileNameExtensions"):
                language = "Markdown"
            elif extension in \
                    Preferences.getEditor("PreviewRestFileNameExtensions"):
                language = "ReST"
            else:
                self.__setHtml(
                    fn,
                    self.tr(
                        "<p>No preview available for this type of file.</p>"))
                return

            if fn:
                project = e5App().getObject("Project")
                if project.isProjectFile(fn):
                    rootPath = project.getProjectPath()
                else:
                    rootPath = os.path.dirname(os.path.abspath(fn))
            else:
                rootPath = ""

            self.__processingThread.process(
                fn, language, editor.text(), self.ssiCheckBox.isChecked(),
                rootPath, Preferences.getEditor("PreviewRestUseSphinx"))

    def __setHtml(self, filePath, html):
        """
        Private method to set the HTML to the view and restore the scroll bars
        positions.
        
        @param filePath file path of the previewed editor (string)
        @param html processed HTML text ready to be shown (string)
        """
        self.__previewedPath = Utilities.normcasepath(
            Utilities.fromNativeSeparators(filePath))
        self.__saveScrollBarPositions()
        if self.__usesWebKit:
            self.previewView.page().mainFrame().contentsSizeChanged.connect(
                self.__restoreScrollBarPositions)
        else:
            self.previewView.page().loadFinished.connect(
                self.__restoreScrollBarPositions)
        self.previewView.setHtml(html, baseUrl=QUrl.fromLocalFile(filePath))
        if self.__previewedEditor:
            self.__previewedEditor.setFocus()

    @pyqtSlot(str)
    def on_previewView_titleChanged(self, title):
        """
        Private slot to handle a change of the title.
        
        @param title new title (string)
        """
        if title:
            self.titleLabel.setText(self.tr("Preview - {0}").format(title))
        else:
            self.titleLabel.setText(self.tr("Preview"))

    def __saveScrollBarPositions(self):
        """
        Private method to save scroll bar positions for a previewed editor.
        """
        if self.__usesWebKit:
            frame = self.previewView.page().mainFrame()
            if frame.contentsSize() == QSize(0, 0):
                return  # no valid data, nothing to save

            pos = frame.scrollPosition()
            self.__scrollBarPositions[self.__previewedPath] = pos
            self.__hScrollBarAtEnd[self.__previewedPath] = \
                frame.scrollBarMaximum(Qt.Horizontal) == pos.x()
            self.__vScrollBarAtEnd[self.__previewedPath] = \
                frame.scrollBarMaximum(Qt.Vertical) == pos.y()
        else:
            from PyQt5.QtCore import QPoint
            pos = self.__execJavaScript("(function() {"
                                        "var res = {"
                                        "    x: 0,"
                                        "    y: 0,"
                                        "};"
                                        "res.x = window.scrollX;"
                                        "res.y = window.scrollY;"
                                        "return res;"
                                        "})()")
            pos = QPoint(pos["x"], pos["y"])
            self.__scrollBarPositions[self.__previewedPath] = pos
            self.__hScrollBarAtEnd[self.__previewedPath] = False
            self.__vScrollBarAtEnd[self.__previewedPath] = False

    def __restoreScrollBarPositions(self):
        """
        Private method to restore scroll bar positions for a previewed editor.
        """
        if self.__usesWebKit:
            try:
                self.previewView.page().mainFrame().contentsSizeChanged.\
                    disconnect(self.__restoreScrollBarPositions)
            except TypeError:
                # not connected, simply ignore it
                pass

            if self.__previewedPath not in self.__scrollBarPositions:
                return

            frame = self.previewView.page().mainFrame()
            frame.setScrollPosition(
                self.__scrollBarPositions[self.__previewedPath])

            if self.__hScrollBarAtEnd[self.__previewedPath]:
                frame.setScrollBarValue(Qt.Horizontal,
                                        frame.scrollBarMaximum(Qt.Horizontal))

            if self.__vScrollBarAtEnd[self.__previewedPath]:
                frame.setScrollBarValue(Qt.Vertical,
                                        frame.scrollBarMaximum(Qt.Vertical))
        else:
            if self.__previewedPath not in self.__scrollBarPositions:
                return

            pos = self.__scrollBarPositions[self.__previewedPath]
            self.previewView.page().runJavaScript(
                "window.scrollTo({0}, {1});".format(pos.x(), pos.y()))

    @pyqtSlot(QUrl)
    def on_previewView_linkClicked(self, url):
        """
        Private slot handling the clicking of a link.
        
        @param url url of the clicked link (QUrl)
        """
        e5App().getObject("UserInterface").launchHelpViewer(url.toString())

    def __execJavaScript(self, script):
        """
        Private function to execute a JavaScript function Synchroneously.
        
        @param script JavaScript script source to be executed
        @type str
        @return result of the script
        @rtype depending upon script result
        """
        from PyQt5.QtCore import QEventLoop
        loop = QEventLoop()
        resultDict = {"res": None}

        def resultCallback(res, resDict=resultDict):
            if loop and loop.isRunning():
                resDict["res"] = res
                loop.quit()

        self.previewView.page().runJavaScript(script, resultCallback)

        loop.exec_()
        return resultDict["res"]
コード例 #11
0
class MainWindow(QtWidgets.QMainWindow):
    """Main application window."""

    def __init__(self, model_editor):
        """Initialize the class."""
        super(MainWindow, self).__init__()

        self.setMinimumSize(960, 660)

        self._hsplitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal, self)
        self._model_editor = model_editor
        self.setCentralWidget(self._hsplitter)

        # tabs
        self._tab = QtWidgets.QTabWidget(self._hsplitter)
        self._tab.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        self._tab.setMinimumSize(600, 200)
        self._tab.sizeHint = lambda: QtCore.QSize(700, 250)

        self.info = QWebEngineView(self._tab)
        self.info.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
        self.info_page = panels.InfoPanelPage()
        self.info.setPage(self.info_page)

        """info panel"""
        self.err = panels.ErrorWidget(self._tab)
        """error message panel"""
        self._tab.addTab(self.info, "Structure Info")
        self._tab.addTab(self.err, "Messages")

        # debug panel
        if cfg.config.DEBUG_MODE:
            self.debug_tab = panels.DebugPanelWidget(self._tab)
            self._tab.addTab(self.debug_tab, "Debug")

        # splitters
        self._vsplitter = QtWidgets.QSplitter(QtCore.Qt.Vertical, self._hsplitter)
        self.editor = panels.YamlEditorWidget(self._vsplitter)
        """main editor component"""
        self.tree = panels.TreeWidget(self._vsplitter)
        """tree data display widget"""
        self._vsplitter.addWidget(self.editor)
        self._vsplitter.addWidget(self._tab)
        self._hsplitter.insertWidget(0, self.tree)

        # Menu bar
        self._menu = self.menuBar()
        self._file_menu = MainFileMenu(self, self._model_editor)
        self.update_recent_files(0)
        self._edit_menu = MainEditMenu(self, self.editor)
        self._settings_menu = MainSettingsMenu(self, self._model_editor)
        self._menu.addMenu(self._file_menu)
        self._menu.addMenu(self._edit_menu)
        self._menu.addMenu(self._settings_menu)

        # status bar
        self._column = QtWidgets.QLabel(self)
        self._column.setFrameStyle(QtWidgets.QFrame.StyledPanel)

        self._reload_icon = QtWidgets.QLabel(self)
        self._reload_icon.setPixmap(icon.get_pixmap("refresh", 16))
        self._reload_icon.setVisible(False)
        self._reload_icon_timer = QtCore.QTimer(self)
        self._reload_icon_timer.timeout.connect(lambda: self._reload_icon.setVisible(False))

        cfg.config.observers.append(self)

        self._status = self.statusBar()
        self._status.addPermanentWidget(self._reload_icon)
        self._status.addPermanentWidget(self._column)
        self.setStatusBar(self._status)
        self._status.showMessage("Ready", 5000)

        # signals
        self.err.itemSelected.connect(self._item_selected)
        self.tree.itemSelected.connect(self._item_selected)
        self.editor.nodeChanged.connect(self._reload_node)
        self.editor.cursorChanged.connect(self._cursor_changed)
        self.editor.structureChanged.connect(self._structure_changed)
        self.editor.errorMarginClicked.connect(self._error_margin_clicked)
        self.editor.elementChanged.connect(lambda new, old: self._update_info(new))
        self.editor.nodeSelected.connect(self._on_node_selected)

        # initialize components
        self._update_info(None)
        self.config_changed()

        # set focus
        self.editor.setFocus()

    def keyPressEvent(self, event):
        if event.matches(QKeySequence.Copy) and self.info.selectedText() != "":
            QtWidgets.QApplication.clipboard().setText(self.info.selectedText())
        else:
            super().keyReleaseEvent(event)

    def reload(self):
        """reload panels after structure changes"""
        self._reload_icon.setVisible(True)
        self._reload_icon.update()
        self.editor.setUpdatesEnabled(False)
        cfg.update()
        self.editor.setUpdatesEnabled(True)
        self.editor.reload()
        self.tree.reload()
        self.err.reload()
        line, index = self.editor.getCursorPosition()
        self._reload_node(line+1, index+1)
        self._reload_icon_timer.start(700)

    def show_status_message(self, message, duration=5000):
        """Show a message in status bar for the given duration (in ms)."""
        self._status.showMessage(message, duration)

    def update_recent_files(self, from_row=1):
        """Update recently opened files."""
        self._file_menu.update_recent_files(from_row)

    def _item_selected(self, start_line, start_column, end_line, end_column):
        """Handle when an item is selected from tree or error tab.

        :param int start_line: line where the selection starts
        :param int start_column: column where the selection starts
        :param int end_line: line where the selection ends
        :param int end_column: column where the selection ends
        """
        self.editor.setFocus()

        # remove empty line and whitespaces at the end of selection
        if end_line > start_line and end_line > 1:
            last_line_text = self.editor.text(end_line-1)
            if end_column > len(last_line_text):
                end_column = len(last_line_text) + 1
            last_line_text_selected = last_line_text[:end_column-1]
            if LineAnalyzer.is_empty(last_line_text_selected):
                end_line -= 1
                end_line_text = self.editor.text(end_line-1)
                end_column = len(end_line_text)

        # select in reversed order - move cursor to the beginning of selection
        self.editor.mark_selected(end_line, end_column, start_line, start_column)

    def _reload_node(self, line, index):
        """reload info after changing node selection"""
        node = cfg.get_data_node(Position(line, index))
        self.editor.set_new_node(node)
        cursor_type = self.editor.cursor_type_position
        self._update_info(cursor_type)
        if cfg.config.DEBUG_MODE:
            self.debug_tab.show_data_node(node)

    def _cursor_changed(self, line, column):
        """Editor node change signal"""
        self._column.setText("Line: {:5d}  Pos: {:3d}".format(line, column))

    def _structure_changed(self, line, column):
        """Editor structure change signal"""
        if cfg.update_yaml_file(self.editor.text()):
            self.reload()
        else:
            self._reload_node(line, column)

    def _error_margin_clicked(self, line):
        """Click error icon in margin"""
        self._tab.setCurrentIndex(self._tab.indexOf(self.err))
        self.err.select_error(line)

    def _update_info(self, cursor_type):
        """Update the info panel."""
        if self.editor.pred_parent is not None:
            self.info_page.update_from_node(self.editor.pred_parent,
                                       CursorType.parent.value)
            return
        if self.editor.curr_node is not None:
            self.info_page.update_from_node(self.editor.curr_node, cursor_type)
            return

        # show root input type info by default
        self.info_page.update_from_data({'record_id': cfg.root_input_type['id']}, True)
        return

    def _on_node_selected(self, line, column):
        """Handles nodeSelected event from editor."""
        node = cfg.get_data_node(Position(line, column))
        self.tree.select_data_node(node)

    def closeEvent(self, event):
        """Performs actions before app is closed."""
        # prompt user to save changes (if any)
        if not self._model_editor.save_old_file():
            return event.ignore()

        super(MainWindow, self).closeEvent(event)

    def config_changed(self):
        """Handle changes of config."""
        self.editor.set_line_endings(cfg.config.line_endings)
コード例 #12
0
class Visualization(QMainWindow):

    themes = ['light', 'dark']
    themesTip = ['切换为深色主题', '切换为浅色主题']

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

        self.leftTopView = None
        self.leftTopEcharts = False

        self.BottomView = None
        self.BottomEcharts = False
        self.initDataSet()
        self.initUi()
        self.loadUrl()

    def initUi(self):

        self.statusBar().showMessage('加载中...')

        self.setGeometry(100, 60, 600, 400)
        self.setWindowTitle('股票看板')
        self.setWindowIcon(QIcon('logo.jpg'))

        self.themeSetAct = QAction('更换图表主题(&T)', self)
        self.themeSetAct.setShortcut('Ctrl+T')
        # 默认浅色主题
        self.themeIndex = 0
        self.themeSetAct.setStatusTip(Visualization.themesTip[self.themeIndex])
        self.themeSetAct.triggered.connect(self.changeTheme)

        menubar = self.menuBar()
        setMenu = menubar.addMenu('设置(&S)')
        setMenu.addAction(self.themeSetAct)

        self.widget = QWidget()
        self.setCentralWidget(self.widget)

        # 添加web view
        self.leftTopView = QWebEngineView()
        self.leftTopView.setContextMenuPolicy(Qt.NoContextMenu)

        self.BottomView = QWebEngineView()
        self.BottomView.setContextMenuPolicy(Qt.NoContextMenu)

        h1box = QHBoxLayout()
        h1box.addWidget(self.leftTopView)
        h1box.addWidget(RightTableView(self.data))
        h1box.setStretch(0, 1)
        h1box.setStretch(1, 1)

        h2box = QHBoxLayout()
        # v2box = QVBoxLayout()
        h2box.addWidget(self.BottomView)

        vbox = QVBoxLayout()
        vbox.addLayout(h1box)
        vbox.addLayout(h2box)
        vbox.setStretch(0, 1)
        vbox.setStretch(1, 1)

        self.widget.setLayout(vbox)

    def resizeEvent(self, *args, **kwargs):
        w, h = self.width(), self.height()

    def changeTheme(self):
        self.themeIndex = (self.themeIndex + 1) % 2
        self.themeSetAct.setStatusTip(Visualization.themesTip[self.themeIndex])

        if not self.BottomView:
            return
        options = self.getOptions(type='K')

        self.BottomView.page().runJavaScript('''
                myChart.dispose();
                var myChart = echarts.init(document.getElementById('container'), '{theme}', {{renderer: 'canvas'}});
                myChart.clear();
                window.onresize = function(){{
                    myChart.resize();
                }}
                var option = eval({options});
                myChart.setOption(option);
            '''.format(theme=Visualization.themes[self.themeIndex],
                       options=options))

        if not self.leftTopView:
            return
        options = self.getOptions(type='Pie')

        self.leftTopView.page().runJavaScript('''
                myChart.dispose();
                var myChart = echarts.init(document.getElementById('container'), '{theme}', {{renderer: 'canvas'}});
                myChart.clear();
                window.onresize = function(){{
                    myChart.resize();
                }}
                var option = eval({options});
                myChart.setOption(option);
            '''.format(theme=Visualization.themes[self.themeIndex],
                       options=options))

    def loadUrl(self):
        url = QUrl("file:///template.html")

        self.leftTopView.load(url)
        self.leftTopView.loadFinished.connect(self.setOptions)

        self.BottomView.load(url)
        self.BottomView.loadFinished.connect(self.setOptions)
        self.statusBar().showMessage('准备就绪')

    def setOptions(self):
        if not self.BottomView:
            return
        if not self.BottomEcharts:
            # 初始化echarts
            self.BottomView.page().runJavaScript('''
                    var myChart = echarts.init(document.getElementById('container'), 'light', {renderer: 'canvas'});
                    window.onresize = function(){{
                        myChart.resize();
                    }}
                ''')
            self.BottomEcharts = True

        options = self.getOptions(type='K')

        self.BottomView.page().runJavaScript('''
                var option = eval({});
                myChart.setOption(option);
            '''.format(options))

        if not self.leftTopView:
            return
        if not self.leftTopEcharts:
            # 初始化echarts
            self.leftTopView.page().runJavaScript('''
                    var myChart = echarts.init(document.getElementById('container'), 'light', {renderer: 'canvas'});
                    window.onresize = function(){{
                        myChart.resize();
                    }}
                ''')
            self.leftTopEcharts = True

        options = self.getOptions(type='Pie')

        self.leftTopView.page().runJavaScript('''
                var option = eval({});
                myChart.setOption(option);
            '''.format(options))

    def getOptions(self, type):
        if type == None or type == 'K':
            return self.createKlines()
        elif type == 'Pie':
            return self.create_pie(v=self.pie_data)

    def createKlines(self):
        overlap = Overlap()
        for quote in self.quote_data:
            line = Line(quote['title'])
            line.add('open', quote['date'], quote['open'], is_smooth=True)
            line.add('close', quote['date'], quote['close'], is_smooth=True)
            line.add('high', quote['date'], quote['high'], is_smooth=True)
            line.add('low', quote['date'], quote['low'], is_smooth=True)

            overlap.add(line)

        snippet = TRANSLATOR.translate(overlap.options)
        options = snippet.as_snippet()
        return options

    def create_pie(self, v):
        pie = Pie()
        pie.add("昨日行情", ['涨', '平', '跌'], v, is_label_show=True)
        snippet = TRANSLATOR.translate(pie.options)
        options = snippet.as_snippet()
        return options

    def initDataSet(self):
        client = pymongo.MongoClient(host="localhost", port=27017)
        db = client['stocks']
        table_basic = db['basic']
        table_quotes = db['quotes']

        last_weekday = get_last_WeekDay(datetime.now())
        last_weekday = int(last_weekday)

        self.pie_data = []
        self.pie_data.append(
            table_quotes.find({
                "change": {
                    "$gte": 0
                }
            }).count())
        self.pie_data.append(table_quotes.find({"change": 0}).count())
        self.pie_data.append(
            table_quotes.find({
                "change": {
                    "$lte": 0
                }
            }).count())

        self.data = get_data()

        self.quote_data = []
        stock_name = self.data[0][0][0]
        stock_code = self.data[0][0][1]
        title = f'{stock_name}_{stock_code}'

        date, open, close, high, low = get_selected_data(stock_code)

        self.quote_data.append({
            'title': title,
            'date': date,
            'open': open,
            'close': close,
            'high': high,
            'low': low
        })

        self.statusBar().showMessage('数据加载完成')
        print('数据加载完成')
コード例 #13
0
class Form(QDialog):

    TITLE_TEXT = "这是大标题"
    TITLE_SUBTEXT = "这是副标题"
    ATTR = ["属性1", "属性2", "属性3", "属性4", "属性5", "属性6"]

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

        self.view = None
        self.echarts = False
        self.initUi()
        self.load_url()
        self.isMap = False

    # 初始化UI界面
    def initUi(self):
        self.hl = QHBoxLayout(self)
        self.widget = QWidget()
        self.gl = QGridLayout(self.widget)
        self.isMap = False
       
        # ATTR1
        #第一个输入属性值的文本框
        self.QLineEdit1=QLineEdit()     # 新建属性输入文本框
        self.QLineEdit1.setPlaceholderText(self.ATTR[1-1]) # 默认值是“属性一”
        self.QLineEdit1.editingFinished.connect(self.reload_canvas)
        self.gl.addWidget(self.QLineEdit1,1 - 1,0,1,1)# 设置该输入框的排版位置
        self.spinbox1 = QSpinBox()      # 新建SpinBox
        self.spinbox1.setSingleStep(100)# 设置每次调节的单位
        self.spinbox1.setObjectName('spinbox')
        self.spinbox1.valueChanged.connect(self.set_options)
        self.spinbox1.setMaximum(1000)
        self.spinbox1.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox1, 1 - 1, 1, 1, 2)
        # ATTR2
        self.QLineEdit2=QLineEdit()     
        self.QLineEdit2.setPlaceholderText(self.ATTR[2-1]) 
        self.QLineEdit2.returnPressed.connect(self.reload_canvas)
        self.gl.addWidget(self.QLineEdit2,2 - 1,0,1,1)
        self.spinbox2 = QSpinBox()
        self.spinbox2.setSingleStep(100)
        self.spinbox2.setObjectName('spinbox')
        self.spinbox2.valueChanged.connect(self.set_options)
        self.spinbox2.setMaximum(1000)
        self.spinbox2.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox2, 2 - 1, 1, 1, 2)
        # ATTR3
        self.QLineEdit3=QLineEdit()     
        self.QLineEdit3.setPlaceholderText(self.ATTR[3-1]) 
        self.QLineEdit3.returnPressed.connect(self.reload_canvas)
        self.gl.addWidget(self.QLineEdit3,3 - 1,0,1,1)
        self.spinbox3 = QSpinBox()
        self.spinbox3.setSingleStep(100)
        self.spinbox3.setObjectName('spinbox')
        self.spinbox3.valueChanged.connect(self.set_options)
        self.spinbox3.setMaximum(1000)
        self.spinbox3.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox3, 3 - 1, 1, 1, 2)
        # ATTR4
        self.QLineEdit4=QLineEdit()     
        self.QLineEdit4.setPlaceholderText(self.ATTR[4-1]) 
        self.QLineEdit4.returnPressed.connect(self.reload_canvas)
        self.gl.addWidget(self.QLineEdit4,4 - 1,0,1,1)
        self.spinbox4 = QSpinBox()
        self.spinbox4.setSingleStep(100)
        self.spinbox4.setObjectName('spinbox')
        self.spinbox4.valueChanged.connect(self.set_options)
        self.spinbox4.setMaximum(1000)
        self.spinbox4.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox4, 4 - 1, 1, 1, 2)
        # ATTR5
        self.QLineEdit5=QLineEdit()     
        self.QLineEdit5.setPlaceholderText(self.ATTR[5-1]) 
        self.QLineEdit5.returnPressed.connect(self.reload_canvas)
        self.gl.addWidget(self.QLineEdit5,5 - 1,0,1,1)
        self.spinbox5 = QSpinBox()
        self.spinbox5.setSingleStep(100)
        self.spinbox5.setObjectName('spinbox')
        self.spinbox5.valueChanged.connect(self.set_options)
        self.spinbox5.setMaximum(1000)
        self.spinbox5.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox5, 5 - 1, 1, 1, 2)
        # ATTR6
        self.QLineEdit6=QLineEdit()     
        self.QLineEdit6.setPlaceholderText(self.ATTR[6-1]) 
        self.QLineEdit6.returnPressed.connect(self.reload_canvas)
        self.gl.addWidget(self.QLineEdit6,6 - 1,0,1,1)
        self.spinbox6 = QSpinBox()
        self.spinbox6.setSingleStep(100)
        self.spinbox6.setObjectName('spinbox')
        self.spinbox6.valueChanged.connect(self.set_options)
        self.spinbox6.setMaximum(1000)
        self.spinbox6.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox6, 6 - 1, 1, 1, 2)
        #属性文本框设置结束

        #左侧菜单设置
        self.hl.addWidget(self.widget)
        vs = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.gl.addItem(vs, 8, 0, 1, 2)
        
        #输入大标题与副标题
        #大标题
        label_title = QLabel( '大标题'+ ':')
        self.gl.addWidget(label_title, 6, 0, 1, 2) #addWidget里的四个数字什么意思
        self.QLineEdit_TITLE = QLineEdit()        #查询pyqt的文本输入框是什么控件
        self.QLineEdit_TITLE.setPlaceholderText(self.TITLE_TEXT)
        self.QLineEdit_TITLE.cursorMoveStyle='VisualMoveStyle'
        self.QLineEdit_TITLE.returnPressed.connect(self.reload_canvas)
        self.gl.addWidget(self.QLineEdit_TITLE, 6, 1, 1, 2)
        #小标题
        label_subtitle = QLabel( '小标题'+ ':')
        self.gl.addWidget(label_subtitle, 7, 0, 1, 2)
        self.QLineEdit_SUB = QLineEdit()        #查询pyqt的文本输入框是什么控件
        self.QLineEdit_SUB.setPlaceholderText(self.TITLE_TEXT)
        self.QLineEdit_SUB.cursorMoveStyle='VisualMoveStyle'
        self.QLineEdit_SUB.returnPressed.connect(self.reload_canvas)
        self.gl.addWidget(self.QLineEdit_SUB, 7, 1, 1, 2)
        #输入大标题与副标题

        #图例种类选择
        label_kind = QLabel( '图例'+ ':')
        self.gl.addWidget(label_kind, 9, 0, 1, 2)
        self.combobox_type = QComboBox()
        self.combobox_type.currentIndexChanged.connect(self.reload_canvas)
        self.combobox_type.addItems(['饼状图', '柱状图', '折线图', '折线柱状图','桑基图','雷达图','地理热点图'])
        self.gl.addWidget(self.combobox_type, 9, 1, 1, 2)
        
        #主题选择按钮
        label_theme = QLabel('主题' + ':')
        self.gl.addWidget(label_theme, 10, 0, 1, 2)
        self.combobox_theme = QComboBox()
        self.combobox_theme.addItems(['日间模式', '暗黑模式','复古香槟'])
        self.combobox_theme.currentTextChanged.connect(self.change_theme)
        self.gl.addWidget(self.combobox_theme, 10, 1, 1, 2)
        # 添加web view
        self.view = QWebEngineView()
        self.view.setContextMenuPolicy(Qt.NoContextMenu)
        self.hl.addWidget(self.view)

    def change_theme(self, theme):
        # self.isMap = False
        if not self.view:
            return
        options = self.get_options()
        if not options:
            return
        if self.combobox_theme.currentIndex()==0:
            theme='light'
        if self.combobox_theme.currentIndex()==1:
            theme='dark'
        if self.combobox_theme.currentIndex()==2:
            theme='vintage'

        self.view.page().runJavaScript(
            f'''
                myChart.dispose();
                var myChart = echarts.init(document.getElementById('container'), '{theme}', {{renderer: 'canvas'}});
                myChart.clear();
                var option = eval({options});
                myChart.setOption(option);
            '''
        )

    def load_url(self):
        #url = QUrl("file:///"+sys.path[0]+"/data/STEM_heatmap.html")
        url = QUrl("file:///"+sys.path[0]+"/template.html") # to make it adapted to any platform like MacOS,Windows,Linux
            #the formal version: url = QUrl("file:////Users/fangzeqiang/Desktop/PyQt_Echarts_GUI/template.html")
        self.view.load(url)
        self.view.loadFinished.connect(self.set_options)

    def reload_canvas(self):
        self.TITLE_TEXT=self.QLineEdit_TITLE.displayText()
        self.TITLE_SUBTEXT=self.QLineEdit_SUB.displayText()
        
        #重新渲染时,将左侧属性输入框中数据传入图表
        QLineEdit_Array=[self.QLineEdit1,self.QLineEdit2,self.QLineEdit3,self.QLineEdit4,self.QLineEdit5,self.QLineEdit6]
        for i in range(len(QLineEdit_Array)):
            self.ATTR[i]= QLineEdit_Array[i].displayText()  
            if self.ATTR[i]=='':
                self.ATTR[i]='属性'+str(i+1)
        if not self.view:
            return
            # 重载画布
        options = self.get_options()
        if not options:
            return
        self.view.page().runJavaScript(
            f'''
                myChart.clear();
                var option = eval({options});
                myChart.setOption(option);
            '''
        )

    def set_options(self):
        if not self.view:
            return
        if not self.echarts:
            # 初始化echarts
            self.view.page().runJavaScript(
                '''
                    var myChart = echarts.init(document.getElementById('container'),'light',{renderer: 'canvas'});
                '''
            )
            self.echarts = True

        options = self.get_options()
        if not options:
            return

        self.view.page().runJavaScript(
            f'''
                var option = eval({options});
                myChart.setOption(option);
            '''
        )

    def get_options(self):
        v1, v2, v3, v4, v5, v6 = self.spinbox1.value(), self.spinbox2.value(), self.spinbox3.value(), self.spinbox4.value(), \
                                 self.spinbox5.value(), self.spinbox6.value()
        v = [v1, v2, v3, v4, v5, v6]
        if self.combobox_type.currentIndex() == 0:
            # 饼图
            options = self.create_pie(v)
        elif self.combobox_type.currentIndex() == 1:
            # 柱状图
            options = self.create_bar(v)
        elif self.combobox_type.currentIndex() == 2:
            # 折线图
            options = self.create_line(v)
        elif self.combobox_type.currentIndex() == 3:
            # 折线、柱状图
            options = self.create_line_bar(v)
        elif self.combobox_type.currentIndex() == 4:
            # 桑基图
            options=self.create_sankey(v)
        elif self.combobox_type.currentIndex() == 5:
            # 雷达图
            options=self.create_radar(v)
        elif self.combobox_type.currentIndex() == 6:
            # 地理热点图
            # options=self.create_map(v)
            return
        else:
            return
        return options

    def create_pie(self, v):
        pie = Pie(self.TITLE_TEXT, self.TITLE_SUBTEXT)
        pie.add("属性", self.ATTR, v, is_label_show=True)
        snippet = TRANSLATOR.translate(pie.options)
        options = snippet.as_snippet()
        return options

    def create_bar(self, v):
        bar = Bar(self.TITLE_TEXT, self.TITLE_SUBTEXT)
        bar.add('Science', self.ATTR, v, is_more_utils=True)
        bar.add('Engineering', self.ATTR, v, is_more_utils=True)
        bar.add('Technology', self.ATTR, v, is_more_utils=True)
        bar.add('Mathematics', self.ATTR, v, is_more_utils=True)
        snippet = TRANSLATOR.translate(bar.options)
        options = snippet.as_snippet()
        return options

    def create_line(self, v):
        line = Line(self.TITLE_TEXT, self.TITLE_SUBTEXT)
        line.add("属性", self.ATTR, v, is_smooth=True, mark_line=["max", "average"])
        snippet = TRANSLATOR.translate(line.options)
        options = snippet.as_snippet()
        return options

    def create_line_bar(self, v):
        line = Line(self.TITLE_TEXT, self.TITLE_SUBTEXT)
        line.add("属性", self.ATTR, v, is_smooth=True, mark_line=["max", "average"])
        bar = Bar(self.TITLE_TEXT, self.TITLE_SUBTEXT)
        bar.add('属性', self.ATTR, v, is_more_utils=True)
        overlap = Overlap()
        overlap.add(line)
        overlap.add(bar)
        snippet = TRANSLATOR.translate(overlap.options)
        options = snippet.as_snippet()
        return options

    def create_sankey(self, v): #绘制桑基图
        sankey = Sankey(self.TITLE_TEXT, self.TITLE_SUBTEXT,width=1200, height=600)
        category1,category2,category3,category4,category5,category6=self.ATTR[0],self.ATTR[1],self.ATTR[2],self.ATTR[3],self.ATTR[4],self.ATTR[5]

        nodes = [
            {'name': 'Java软件开发'}, {'name': '前端技术'}, {'name': '移动端技术'},
            {'name': '自然语言处理'}, {'name': 'Python数据分析'}, {'name': '数据可视化'},
            {'name': '量化交易'},{'name': '算法工程'},{'name': '算法优化'},
            {'name': '机器学习开发'},{'name': '运维工程'},{'name': '云计算开发'},
            {'name': '软件UI设计'},{'name': '计算机视觉'},{'name': '产品经理'},{'name': '深度学习'}
        ]
        links = [
            {'source': 'Java软件开发', 'target': '前端技术', 'value': 5},
            {'source': '前端技术', 'target': '移动端技术', 'value': 12},
            {'source': 'Python数据分析', 'target': '自然语言处理', 'value': 10},
            {'source': 'Python数据分析', 'target': '数据可视化', 'value': 8},
            {'source': '自然语言处理', 'target': '算法工程', 'value': 15},
            {'source': '算法工程', 'target': '算法优化', 'value': 15},
            {'source': '自然语言处理', 'target': '算法优化', 'value': 30},
            {'source': '量化交易', 'target': '算法优化', 'value': 10},
            {'source': '自然语言处理', 'target': '移动端技术', 'value': 14},
            {'source': '机器学习开发', 'target': '自然语言处理', 'value': 14},
            {'source': '机器学习开发', 'target': '算法工程', 'value': 20},
            {'source': '软件UI设计', 'target': '移动端技术', 'value': 15},
            {'source': '深度学习', 'target': '计算机视觉', 'value': 12},
            {'source': '计算机视觉', 'target': '算法优化', 'value': 10},
            {'source': '运维工程', 'target': '云计算开发', 'value': 15},
            {'source': '前端技术', 'target': '云计算开发', 'value': 20},
            {'source': '云计算开发', 'target': '产品经理', 'value': 3},
            {'source': '移动端技术', 'target': '产品经理', 'value': 10},
            {'source': '算法优化', 'target': '产品经理', 'value': 7},
            {'source': '计算机视觉', 'target': '产品经理', 'value': 6},
            {'source': '数据可视化', 'target': '产品经理', 'value': 5},
        ]
        sankey.add(
            "技能树",
            nodes,
            links,
            line_opacity=0.2,
            line_curve=0.5,
            line_color="source",
            is_label_show=True,
            label_pos="right",
        )
        snippet = TRANSLATOR.translate(sankey.options)
        options = snippet.as_snippet()
        return options

    def create_radar(self, v): #绘制雷达图
        radar = Radar(self.TITLE_TEXT, self.TITLE_SUBTEXT)
        schema = [
            ("口头语言", 5), ("原创性", 5), ("问题敏感度", 5),
            ("逻辑思维", 5), ("数学能力", 5), ("人际沟通", 5)
        ]
        radar.config(schema)
        v1 = [v]
        v2 = [[2,3,5,4,2,1]]
        radar.add(
            "第一次推荐输入", 
            v1,
            is_splitline = True, 
            is_axisline_show = True,
            is_label_show=True,
            area_opacity = 0.2
        )
        radar.add(
            "第二次推荐输入", 
            v2, 
            label_color=["#4e79a7"], 
            is_area_show= False,
            legend_selectedmode='single',
            area_opacity = 0.5
        )
        snippet = TRANSLATOR.translate(radar.options)
        options = snippet.as_snippet()
        return options

    def create_map(self, v): #绘制地理地图!
        self.isMap = True
        '''
コード例 #14
0
ファイル: main.py プロジェクト: zhonghao8023/StockSpider
class Visualization(QMainWindow):

    themes = ['light', 'dark']
    themesTip = ['切换为深色主题', '切换为浅色主题']

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

        self.leftTopView = None
        self.leftTopEcharts = False

        self.BottomView = None
        self.BottomEcharts = False
        self.initDataSet()
        self.initUi()
        self.loadUrl()

    def initUi(self):

        self.statusBar().showMessage('加载中...')

        self.setGeometry(100, 60, 600, 400)
        self.setWindowTitle('关注微信公众号:月小水长')
        self.setWindowIcon(QIcon('logo.jpg'))

        self.themeSetAct = QAction('更换图表主题(&T)', self)
        self.themeSetAct.setShortcut('Ctrl+T')
        # 默认浅色主题
        self.themeIndex = 0
        self.themeSetAct.setStatusTip(Visualization.themesTip[self.themeIndex])
        self.themeSetAct.triggered.connect(self.changeTheme)

        menubar = self.menuBar()
        setMenu = menubar.addMenu('设置(&S)')
        setMenu.addAction(self.themeSetAct)

        self.widget = QWidget()
        self.setCentralWidget(self.widget)

        # 添加web view
        self.leftTopView = QWebEngineView()
        self.leftTopView.setContextMenuPolicy(Qt.NoContextMenu)

        self.BottomView = QWebEngineView()
        self.BottomView.setContextMenuPolicy(Qt.NoContextMenu)

        h1box = QHBoxLayout()
        h1box.addWidget(self.leftTopView)
        h1box.addWidget(RightTableView())
        h1box.setStretch(0, 1)
        h1box.setStretch(1, 1)

        h2box = QHBoxLayout()
        # v2box = QVBoxLayout()
        h2box.addWidget(self.BottomView)

        vbox = QVBoxLayout()
        vbox.addLayout(h1box)
        vbox.addLayout(h2box)
        vbox.setStretch(0, 1)
        vbox.setStretch(1, 1)

        self.widget.setLayout(vbox)

    def resizeEvent(self, *args, **kwargs):
        w, h = self.width(), self.height()

    def changeTheme(self):
        self.themeIndex = (self.themeIndex + 1) % 2
        self.themeSetAct.setStatusTip(Visualization.themesTip[self.themeIndex])

        if not self.BottomView:
            return
        options = self.getOptions(type='K')

        self.BottomView.page().runJavaScript('''
                myChart.dispose();
                var myChart = echarts.init(document.getElementById('container'), '{theme}', {{renderer: 'canvas'}});
                myChart.clear();
                window.onresize = function(){{
                    myChart.resize();
                }}
                var option = eval({options});
                myChart.setOption(option);
            '''.format(theme=Visualization.themes[self.themeIndex],
                       options=options))

        if not self.leftTopView:
            return
        options = self.getOptions(type='Pie')

        self.leftTopView.page().runJavaScript('''
                myChart.dispose();
                var myChart = echarts.init(document.getElementById('container'), '{theme}', {{renderer: 'canvas'}});
                myChart.clear();
                window.onresize = function(){{
                    myChart.resize();
                }}
                var option = eval({options});
                myChart.setOption(option);
            '''.format(theme=Visualization.themes[self.themeIndex],
                       options=options))

    def loadUrl(self):
        url = QUrl("file:///template.html")

        self.leftTopView.load(url)
        self.leftTopView.loadFinished.connect(self.setOptions)

        self.BottomView.load(url)
        self.BottomView.loadFinished.connect(self.setOptions)
        self.statusBar().showMessage('准备就绪')

    def setOptions(self):
        if not self.BottomView:
            return
        if not self.BottomEcharts:
            # 初始化echarts
            self.BottomView.page().runJavaScript('''
                    var myChart = echarts.init(document.getElementById('container'), 'light', {renderer: 'canvas'});
                    window.onresize = function(){{
                        myChart.resize();
                    }}
                ''')
            self.BottomEcharts = True

        options = self.getOptions(type='K')

        self.BottomView.page().runJavaScript('''
                var option = eval({});
                myChart.setOption(option);
            '''.format(options))

        if not self.leftTopView:
            return
        if not self.leftTopEcharts:
            # 初始化echarts
            self.leftTopView.page().runJavaScript('''
                    var myChart = echarts.init(document.getElementById('container'), 'light', {renderer: 'canvas'});
                    window.onresize = function(){{
                        myChart.resize();
                    }}
                ''')
            self.leftTopEcharts = True

        options = self.getOptions(type='Pie')

        self.leftTopView.page().runJavaScript('''
                var option = eval({});
                myChart.setOption(option);
            '''.format(options))

    def getOptions(self, type):
        if type == None or type == 'K':
            return self.createKlines()
        elif type == 'Pie':
            return self.create_pie(v=[3000, 600, 5000])

    def createKlines(self):
        overlap = Overlap()
        for quote in self.quote_data:
            line = Line(quote['title'])
            print(quote)
            line.add('open', quote['date'], quote['open'], is_smooth=True)
            line.add('close', quote['date'], quote['close'], is_smooth=True)
            line.add('high', quote['date'], quote['high'], is_smooth=True)
            line.add('low', quote['date'], quote['low'], is_smooth=True)

            overlap.add(line)

        snippet = TRANSLATOR.translate(overlap.options)
        options = snippet.as_snippet()
        return options

    def create_pie(self, v):
        pie = Pie()
        pie.add("昨日行情", ['涨', '平', '跌'], v, is_label_show=True)
        snippet = TRANSLATOR.translate(pie.options)
        options = snippet.as_snippet()
        return options

    def initDataSet(self):
        client = pymongo.MongoClient(host="localhost", port=27017)
        db = client['stock']
        table_basic = db['basic']

        self.stock_basis = myDict.AllowKeyRepeatDict()
        for basic in table_basic.find():
            self.stock_basis.add(key=basic['name'], value=basic['code'])

        self.quote_data = []

        stock_name = '中信证券'
        stock_code = self.stock_basis.query(key=stock_name)[0]
        title = stock_name + '_' + stock_code
        table_quote = db[title]
        queryDateRange = [20190301, 20191130]
        date = []
        open = []
        close = []
        high = []
        low = []
        # 为什么不能用 in 而要用 gte lte
        for quote in table_quote.find({
                'date': {
                    '$gte': queryDateRange[0],
                    '$lte': queryDateRange[1]
                }
        }).sort('date', pymongo.ASCENDING):
            date.append(str(quote['date']))
            open.append(float(quote['open']))
            close.append(float(quote['close']))
            high.append(float(quote['high']))
            low.append(float(quote['low']))

        self.quote_data.append({
            'title': title,
            'date': date,
            'open': open,
            'close': close,
            'high': high,
            'low': low
        })
        self.statusBar().showMessage('数据加载完成')
        print('数据加载完成')
コード例 #15
0
class PreviewerHTML(QWidget):
    """
    Class implementing a previewer widget for HTML, Markdown and ReST files.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (QWidget)
        """
        super(PreviewerHTML, self).__init__(parent)
        
        self.__layout = QVBoxLayout(self)
        
        self.titleLabel = QLabel(self)
        self.titleLabel.setWordWrap(True)
        self.titleLabel.setTextInteractionFlags(Qt.NoTextInteraction)
        self.__layout.addWidget(self.titleLabel)
        
        self.__previewAvailable = True
        
        try:
            from PyQt5.QtWebEngineWidgets import QWebEngineView
            self.previewView = QWebEngineView(self)
            self.previewView.page().linkHovered.connect(self.__showLink)
        except ImportError:
            self.__previewAvailable = False
            self.titleLabel.setText(self.tr(
                "<b>HTML Preview is not available!<br/>"
                "Install QtWebEngine.</b>"))
            self.titleLabel.setAlignment(Qt.AlignHCenter)
            self.__layout.addStretch()
            return
        
        sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.previewView.sizePolicy().hasHeightForWidth())
        self.previewView.setSizePolicy(sizePolicy)
        self.previewView.setContextMenuPolicy(Qt.NoContextMenu)
        self.previewView.setUrl(QUrl("about:blank"))
        self.__layout.addWidget(self.previewView)
        
        self.jsCheckBox = QCheckBox(self.tr("Enable JavaScript"), self)
        self.jsCheckBox.setToolTip(self.tr(
            "Select to enable JavaScript for HTML previews"))
        self.__layout.addWidget(self.jsCheckBox)
        
        self.ssiCheckBox = QCheckBox(self.tr("Enable Server Side Includes"),
                                     self)
        self.ssiCheckBox.setToolTip(self.tr(
            "Select to enable support for Server Side Includes"))
        self.__layout.addWidget(self.ssiCheckBox)
        
        self.jsCheckBox.clicked[bool].connect(self.on_jsCheckBox_clicked)
        self.ssiCheckBox.clicked[bool].connect(self.on_ssiCheckBox_clicked)
        self.previewView.titleChanged.connect(self.on_previewView_titleChanged)
        
        self.jsCheckBox.setChecked(
            Preferences.getUI("ShowFilePreviewJS"))
        self.ssiCheckBox.setChecked(
            Preferences.getUI("ShowFilePreviewSSI"))
        
        self.__scrollBarPositions = {}
        self.__vScrollBarAtEnd = {}
        self.__hScrollBarAtEnd = {}
        
        self.__processingThread = PreviewProcessingThread()
        self.__processingThread.htmlReady.connect(self.__setHtml)

        self.__previewedPath = None
        self.__previewedEditor = None
    
    def shutdown(self):
        """
        Public method to perform shutdown actions.
        """
        if self.__previewAvailable:
            self.__processingThread.wait()
    
    @pyqtSlot(bool)
    def on_jsCheckBox_clicked(self, checked):
        """
        Private slot to enable/disable JavaScript.
        
        @param checked state of the checkbox (boolean)
        """
        Preferences.setUI("ShowFilePreviewJS", checked)
        self.__setJavaScriptEnabled(checked)
    
    def __setJavaScriptEnabled(self, enable):
        """
        Private method to enable/disable JavaScript.
        
        @param enable flag indicating the enable state (boolean)
        """
        self.jsCheckBox.setChecked(enable)
        
        settings = self.previewView.settings()
        settings.setAttribute(settings.JavascriptEnabled, enable)
        
        self.processEditor()
    
    @pyqtSlot(bool)
    def on_ssiCheckBox_clicked(self, checked):
        """
        Private slot to enable/disable SSI.
        
        @param checked state of the checkbox (boolean)
        """
        Preferences.setUI("ShowFilePreviewSSI", checked)
        self.processEditor()
    
    @pyqtSlot(str)
    def __showLink(self, urlStr):
        """
        Private slot to show the hovered link in a tooltip.
        
        @param urlStr hovered URL
        @type str
        """
        QToolTip.showText(QCursor.pos(), urlStr, self.previewView)
    
    def processEditor(self, editor=None):
        """
        Public slot to process an editor's text.
        
        @param editor editor to be processed (Editor)
        """
        if not self.__previewAvailable:
            return
        
        if editor is None:
            editor = self.__previewedEditor
        else:
            self.__previewedEditor = editor
        
        if editor is not None:
            fn = editor.getFileName()
            
            if fn:
                extension = os.path.normcase(os.path.splitext(fn)[1][1:])
            else:
                extension = ""
            if (
                extension in Preferences.getEditor(
                    "PreviewHtmlFileNameExtensions") or
                editor.getLanguage() == "HTML"
            ):
                language = "HTML"
            elif (
                extension in Preferences.getEditor(
                    "PreviewMarkdownFileNameExtensions") or
                editor.getLanguage().lower() == "markdown"
            ):
                language = "Markdown"
            elif (
                extension in Preferences.getEditor(
                    "PreviewRestFileNameExtensions") or
                editor.getLanguage().lower() == "restructuredtext"
            ):
                language = "ReST"
            else:
                self.__setHtml(fn, self.tr(
                    "<p>No preview available for this type of file.</p>"))
                return
            
            if fn:
                project = e5App().getObject("Project")
                if project.isProjectFile(fn):
                    rootPath = project.getProjectPath()
                else:
                    rootPath = os.path.dirname(os.path.abspath(fn))
            else:
                rootPath = ""
            
            if bool(editor.text()):
                self.__processingThread.process(
                    fn, language, editor.text(),
                    self.ssiCheckBox.isChecked(), rootPath,
                    Preferences.getEditor("PreviewRestUseSphinx"),
                    Preferences.getEditor("PreviewMarkdownNLtoBR"),
                    Preferences.getEditor(
                        "PreviewMarkdownUsePyMdownExtensions"),
                    Preferences.getEditor("PreviewMarkdownHTMLFormat"),
                    Preferences.getEditor("PreviewRestDocutilsHTMLFormat"))

    def __setHtml(self, filePath, html, rootPath):
        """
        Private method to set the HTML to the view and restore the scroll bars
        positions.
        
        @param filePath file path of the previewed editor
        @type str
        @param html processed HTML text ready to be shown
        @type str
        @param rootPath path of the web site root
        @type str
        """
        self.__previewedPath = Utilities.normcasepath(
            Utilities.fromNativeSeparators(filePath))
        self.__saveScrollBarPositions()
        self.previewView.page().loadFinished.connect(
            self.__restoreScrollBarPositions)
        if not filePath:
            filePath = "/"
        if rootPath:
            baseUrl = QUrl.fromLocalFile(rootPath + "/index.html")
        else:
            baseUrl = QUrl.fromLocalFile(filePath)
        self.previewView.setHtml(html, baseUrl=baseUrl)
        if self.__previewedEditor:
            self.__previewedEditor.setFocus()
    
    @pyqtSlot(str)
    def on_previewView_titleChanged(self, title):
        """
        Private slot to handle a change of the title.
        
        @param title new title (string)
        """
        if title:
            self.titleLabel.setText(self.tr("Preview - {0}").format(title))
        else:
            self.titleLabel.setText(self.tr("Preview"))
    
    def __saveScrollBarPositions(self):
        """
        Private method to save scroll bar positions for a previewed editor.
        """
        from PyQt5.QtCore import QPoint
        try:
            pos = self.previewView.scrollPosition()
        except AttributeError:
            pos = self.__execJavaScript(
                "(function() {"
                "var res = {"
                "    x: 0,"
                "    y: 0,"
                "};"
                "res.x = window.scrollX;"
                "res.y = window.scrollY;"
                "return res;"
                "})()"
            )
            if pos is not None:
                pos = QPoint(pos["x"], pos["y"])
            else:
                pos = QPoint(0, 0)
        self.__scrollBarPositions[self.__previewedPath] = pos
        self.__hScrollBarAtEnd[self.__previewedPath] = False
        self.__vScrollBarAtEnd[self.__previewedPath] = False

    def __restoreScrollBarPositions(self):
        """
        Private method to restore scroll bar positions for a previewed editor.
        """
        if self.__previewedPath not in self.__scrollBarPositions:
            return
        
        pos = self.__scrollBarPositions[self.__previewedPath]
        self.previewView.page().runJavaScript(
            "window.scrollTo({0}, {1});".format(pos.x(), pos.y()))
    
    def __execJavaScript(self, script):
        """
        Private function to execute a JavaScript function Synchroneously.
        
        @param script JavaScript script source to be executed
        @type str
        @return result of the script
        @rtype depending upon script result
        """
        from PyQt5.QtCore import QEventLoop
        loop = QEventLoop()
        resultDict = {"res": None}
        
        def resultCallback(res, resDict=resultDict):
            if loop and loop.isRunning():
                resDict["res"] = res
                loop.quit()
        
        self.previewView.page().runJavaScript(
            script, resultCallback)
        
        loop.exec_()
        return resultDict["res"]
コード例 #16
0
class Form(QWidget):
    def __init__(self):
        super(Form, self).__init__()

        self.view = None
        self.echarts = False
        self.initUi()
        self.load_url()

    def initUi(self):
        self.hl = QHBoxLayout(self)
        self.widget = QWidget()
        self.gl = QGridLayout(self.widget)
        # ATTR1
        label1 = QLabel(ATTR[0] + ':')
        self.gl.addWidget(label1, 1 - 1, 0, 1, 1)
        self.spinbox1 = QSpinBox()
        self.spinbox1.setSingleStep(100)
        self.spinbox1.setObjectName('spinbox')
        self.spinbox1.valueChanged.connect(self.set_options)
        self.spinbox1.setMaximum(1000)
        self.spinbox1.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox1, 1 - 1, 1, 1, 1)
        # ATTR2
        label2 = QLabel(ATTR[1] + ':')
        self.gl.addWidget(label2, 2 - 1, 0, 1, 1)
        self.spinbox2 = QSpinBox()
        self.spinbox2.setSingleStep(100)
        self.spinbox2.setObjectName('spinbox')
        self.spinbox2.valueChanged.connect(self.set_options)
        self.spinbox2.setMaximum(1000)
        self.spinbox2.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox2, 2 - 1, 1, 1, 1)
        # ATTR3
        label3 = QLabel(ATTR[2] + ':')
        self.gl.addWidget(label3, 3 - 1, 0, 1, 1)
        self.spinbox3 = QSpinBox()
        self.spinbox3.setSingleStep(100)
        self.spinbox3.setObjectName('spinbox')
        self.spinbox3.valueChanged.connect(self.set_options)
        self.spinbox3.setMaximum(1000)
        self.spinbox3.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox3, 3 - 1, 1, 1, 1)
        # ATTR4
        label4 = QLabel(ATTR[3] + ':')
        self.gl.addWidget(label4, 4 - 1, 0, 1, 1)
        self.spinbox4 = QSpinBox()
        self.spinbox4.setSingleStep(100)
        self.spinbox4.setObjectName('spinbox')
        self.spinbox4.valueChanged.connect(self.set_options)
        self.spinbox4.setMaximum(1000)
        self.spinbox4.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox4, 4 - 1, 1, 1, 1)
        # ATTR5
        label5 = QLabel(ATTR[4] + ':')
        self.gl.addWidget(label5, 5 - 1, 0, 1, 1)
        self.spinbox5 = QSpinBox()
        self.spinbox5.setSingleStep(100)
        self.spinbox5.setObjectName('spinbox')
        self.spinbox5.valueChanged.connect(self.set_options)
        self.spinbox5.setMaximum(1000)
        self.spinbox5.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox5, 5 - 1, 1, 1, 1)
        # ATTR6
        label6 = QLabel(ATTR[5] + ':')
        self.gl.addWidget(label6, 6 - 1, 0, 1, 1)
        self.spinbox6 = QSpinBox()
        self.spinbox6.setSingleStep(100)
        self.spinbox6.setObjectName('spinbox')
        self.spinbox6.valueChanged.connect(self.set_options)
        self.spinbox6.setMaximum(1000)
        self.spinbox6.setValue(randint(0, 1000))
        self.gl.addWidget(self.spinbox6, 6 - 1, 1, 1, 1)

        self.hl.addWidget(self.widget)
        vs = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.gl.addItem(vs, 6, 0, 1, 2)
        self.combobox_type = QComboBox()
        self.combobox_type.currentIndexChanged.connect(self.reload_canvas)
        self.combobox_type.addItems(['饼图', '柱状图', '折线图', '折线、柱状图'])
        self.gl.addWidget(self.combobox_type, 7, 0, 1, 2)
        self.combobox_theme = QComboBox()
        self.combobox_theme.currentTextChanged.connect(self.change_theme)
        self.combobox_theme.addItems(['light', 'dark'])
        self.gl.addWidget(self.combobox_theme, 8, 0, 1, 2)
        # 添加web view
        self.view = QWebEngineView()
        self.view.setContextMenuPolicy(Qt.NoContextMenu)
        self.hl.addWidget(self.view)

    def change_theme(self, theme):
        if not self.view:
            return
        options = self.get_options()
        if not options:
            return
        self.view.page().runJavaScript(f'''
                myChart.dispose();
                var myChart = echarts.init(document.getElementById('container'), '{theme}', {{renderer: 'canvas'}});
                myChart.clear();
                var option = eval({options});
                myChart.setOption(option);
            ''')

    def load_url(self):
        url = QUrl("file:///template.html")
        self.view.load(url)
        self.view.loadFinished.connect(self.set_options)

    def reload_canvas(self):
        if not self.view:
            return
            # 重载画布
        options = self.get_options()
        if not options:
            return
        self.view.page().runJavaScript(f'''
                myChart.clear();
                var option = eval({options});
                myChart.setOption(option);
            ''')

    def set_options(self):
        if not self.view:
            return
        if not self.echarts:
            # 初始化echarts
            self.view.page().runJavaScript('''
                    var myChart = echarts.init(document.getElementById('container'), 'light', {renderer: 'canvas'});
                ''')
            self.echarts = True

        options = self.get_options()
        if not options:
            return

        self.view.page().runJavaScript(f'''
                var option = eval({options});
                myChart.setOption(option);
            ''')

    def get_options(self):
        v1, v2, v3, v4, v5, v6 = self.spinbox1.value(), self.spinbox2.value(), self.spinbox3.value(), self.spinbox4.value(), \
                                 self.spinbox5.value(), self.spinbox6.value()
        v = [v1, v2, v3, v4, v5, v6]
        if self.combobox_type.currentIndex() == 0:
            # 饼图
            options = self.create_pie(v)
        elif self.combobox_type.currentIndex() == 1:
            # 柱状图
            options = self.create_bar(v)
        elif self.combobox_type.currentIndex() == 2:
            # 折线图
            options = self.create_line(v)
        elif self.combobox_type.currentIndex() == 3:
            # 折线、柱状图
            options = self.create_line_bar(v)
        else:
            return
        return options

    def create_pie(self, v):
        pie = Pie(TITLE_TEXT, TITLE_SUBTEXT)
        pie.add("商家", ATTR, v, is_label_show=True)
        snippet = TRANSLATOR.translate(pie.options)
        options = snippet.as_snippet()
        return options

    def create_bar(self, v):
        bar = Bar(TITLE_TEXT, TITLE_SUBTEXT)
        bar.add('商家1', ATTR, v, is_more_utils=True)
        bar.add('商家2', ATTR, v, is_more_utils=True)
        snippet = TRANSLATOR.translate(bar.options)
        options = snippet.as_snippet()
        return options

    def create_line(self, v):
        line = Line(TITLE_TEXT, TITLE_SUBTEXT)
        line.add("商家", ATTR, v, is_smooth=True, mark_line=["max", "average"])
        snippet = TRANSLATOR.translate(line.options)
        options = snippet.as_snippet()
        return options

    def create_line_bar(self, v):
        line = Line(TITLE_TEXT, TITLE_SUBTEXT)
        line.add("商家", ATTR, v, is_smooth=True, mark_line=["max", "average"])
        bar = Bar(TITLE_TEXT, TITLE_SUBTEXT)
        bar.add('商家', ATTR, v, is_more_utils=True)
        bar.overlap(line)
        snippet = TRANSLATOR.translate(bar.options)
        options = snippet.as_snippet()
        return options
コード例 #17
0
ファイル: main.py プロジェクト: oneplum7/StockAnalysisSystem
class Visualization(QMainWindow):

    themes = ['light', 'dark']
    themesTip = ['切换为深色主题', '切换为浅色主题']

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

        self.BottomView = None
        self.BottomEcharts = False

        self.initUi()

        self.js_init = False

        self.load_html()

        self.leftTopEcharts = False

        self.stock_datas = []

        self.code = "300750"
        self.findData("300750")

        self.upKline()

    def initUi(self):

        self.statusBar().showMessage('加载中...')

        self.setGeometry(100, 60, 600, 400)
        self.setWindowTitle('王梅的股票查询分析系统')
        self.setWindowIcon(QIcon('logo.jpg'))

        self.themeSetAct = QAction('更换图表主题(&T)', self)
        self.themeSetAct.setShortcut('Ctrl+T')
        # 默认浅色主题
        self.themeIndex = 0
        self.themeSetAct.setStatusTip(Visualization.themesTip[self.themeIndex])
        #self.themeSetAct.triggered.connect(self.changeTheme)

        menubar = self.menuBar()
        setMenu = menubar.addMenu('设置(&S)')
        setMenu.addAction(self.themeSetAct)

        self.widget = QWidget()
        self.setCentralWidget(self.widget)

        # 添加web view
        self.leftTopView = QWebEngineView()
        self.leftTopView.setContextMenuPolicy(Qt.NoContextMenu)

        self.BottomView = QWebEngineView()
        self.BottomView.setContextMenuPolicy(Qt.NoContextMenu)

        self.StockLineEdit = QLineEdit(" ")
        search_Btn = QPushButton('搜索')
        search_Btn.clicked.connect(self.searchStock)

        # 搜索布局
        h0box = QHBoxLayout()
        h0box.addWidget(self.StockLineEdit)
        h0box.addWidget(search_Btn)
        h0box.setStretch(0, 4)
        h0box.setStretch(1, 1)

        # 左上布局
        lefttopbox = QVBoxLayout()
        lefttopbox.addLayout(h0box)
        lefttopbox.addWidget(self.leftTopView)
        lefttopbox.setStretch(0, 1)
        lefttopbox.setStretch(1, 1)

        # 右上布局
        h1box = QHBoxLayout()
        h1box.addLayout(lefttopbox)
        h1box.addWidget(RightTableView())
        #h1box.addWidget(self.leftTopView)
        h1box.setStretch(0, 1)
        h1box.setStretch(1, 1)

        # 底部布局
        h2box = QHBoxLayout()
        h2box.addWidget(self.BottomView)

        # 整个界面布局
        vbox = QVBoxLayout()
        vbox.addLayout(h1box)
        vbox.addLayout(h2box)
        vbox.setStretch(0, 1)
        vbox.setStretch(1, 1)

        self.widget.setLayout(vbox)

    def load_html(self):
        self.BottomView.setHtml(Js.html, QtCore.QUrl("index.html"))
        self.BottomView.loadFinished.connect(self.set_options)

    def set_options(self):
        ''' 设置 myChart.setOption 初始化以及各项配置 '''
        if not self.BottomView:  # 如果浏览器对象没有创建
            self.js_init = False  # 将js初始化设置为假
            return  # 并直接返回退出

        if not self.js_init:
            # 初始化echarts
            self.BottomView.page().runJavaScript(
                Js.Pos_Js)  # 执行js页面交互,页面CSS布局和美化
            self.BottomView.page().runJavaScript(Js.splitData)  # 载入K线处理函数
            self.BottomView.page().runJavaScript(Js.echart_init)  # echart 初始化
            self.BottomView.page().runJavaScript(Js.Formula_js)  # 指标
            self.BottomView.page().runJavaScript(f'''
                    var KNAME, data, macd;
                    var Zstart = 80;
                    var Zend = 100;
                    var MA1=0, MA2=0, MA3=0, MA4=0, MA5=0, MA6=0;
                    var color1 = "#0CF49B";
                    var color2 = "#FD1050";
                    myChart.clear();
                    var option = eval({Js.Kline_js});
                    myChart.setOption(option);
                ''')
            self.BottomView.page().runJavaScript(Js.websize)  # 页面自适应窗体
            self.js_init = True

    def upKline(self, data=None):
        ''' 刷新K线 '''
        if not self.BottomView:  # 如果浏览器对象没有创建
            return  # 并直接返回退出

        kdata = self.stock_datas
        #print(kdata)
        self.BottomView.page().runJavaScript(f'''
                KNAME= {self.code};
                data = splitData({kdata});
                macd = MACD(12, 26, 9, data.datas, 1);
                MA1 = MA(20, data.datas, 1);
                MA2 = MA(60, data.datas, 1);
                MA3 = MA(120, data.datas, 1);
                option = eval({Js.Kline_js});
            ''')
        self.BottomView.page().runJavaScript('''
                myChart.on('dataZoom',function(event){
                    if(event.batch){
                            Zstart=event.batch[0].start;
                            Zend=event.batch[0].end;
                    }else{
                            Zstart=event.start;
                            Zend=event.end;
                    };
                });

                myChart.setOption(option);

            ''')

        sTimer = Timer(10.0, self.upKline, (None, )).start()

    def searchStock(self):
        search_text = self.StockLineEdit.text().strip()  # 获取文本框内容并去掉空格

        # 药明康德
        mydb = mysql.connector.connect(host="localhost",
                                       user="******",
                                       password="******",
                                       database="mydatabase",
                                       charset='utf8')
        mycursor = mydb.cursor()
        sql = "select * from stock_base \
            where stock_code = '%s' or stock_name = '%s' or short_name = '%s'" % (
            search_text, search_text, search_text)

        try:
            # 执行sql语句
            mycursor.execute(sql)
            results = mycursor.fetchall()
            if results == None:
                print(results)
            for row in results:
                self.code = row[0]
            # 提交到数据库执行
            mydb.commit()
        except:
            # Rollback in case there is any error
            print("find error.")
            mydb.rollback()

        self.findData(self.code)

        mydb.close()

    def addData(self, code, name):
        tmp_stock = ""
        if int(code) > 600000:
            tmp_stock = "sh" + code
        else:
            tmp_stock = "sz" + code
        stodk_data_daily = ak.stock_zh_a_daily(symbol=tmp_stock, adjust="hfq")
        print(stodk_data_daily)
        mydb = mysql.connector.connect(host="localhost",
                                       user="******",
                                       password="******",
                                       database="mydatabase",
                                       charset='utf8')
        mycursor = mydb.cursor()
        for i in range(0, len(stodk_data_daily)):
            # SQL 插入语句
            data = []
            date = [t.strftime("%Y-%m-%d") for t in stodk_data_daily.index][i]
            open = stodk_data_daily.iat[i, 0]
            high = stodk_data_daily.iat[i, 1]
            low = stodk_data_daily.iat[i, 2]
            close = stodk_data_daily.iat[i, 3]
            volume = stodk_data_daily.iat[i, 4]
            data.append(date)
            data.append(open)
            data.append(high)
            data.append(low)
            data.append(close)
            data.append(volume)
            self.stock_datas.append(data)

            # sql = "select * from stock_detail \
            # where code = '%s' and data = '%s'" % (code,date)

            sql = "insert into stock_detail(code, name, date, open, high, low, close, volume) \
                    values('%s','%s','%s','%f','%f','%f','%f','%f')"                                                                     % \
                   (code, name, date, open, high,low,close,volume)
            try:
                # 执行sql语句
                mycursor.execute(sql)
                # 提交到数据库执行
                mydb.commit()
            except:
                # Rollback in case there is any error
                mydb.rollback()
        mydb.close()

    def findData(self, code):
        mydb = mysql.connector.connect(host="localhost",
                                       user="******",
                                       password="******",
                                       database="mydatabase",
                                       charset='utf8')
        mycursor = mydb.cursor()
        sql = "select * from stock_detail \
            where code = '%s'" % (code)
        try:
            # 执行SQL语句
            mycursor.execute(sql)
            # 获取所有记录列表
            results = mycursor.fetchall()
            if results == None:
                print(results)
            for row in results:
                data = []
                #t.strftime("%Y-%m-%d")
                date = row[3].strftime("%Y-%m-%d")
                open = row[4]
                high = row[5]
                low = row[6]
                close = row[7]
                volume = row[8]
                data.append(date)
                data.append(open)
                data.append(high)
                data.append(low)
                data.append(close)
                data.append(volume)
                self.stock_datas.append(data)
        except:
            print("find Error: unable to fetch data")

        if len(self.stock_datas) == 0:
            self.addData(code, "")

        mydb.close()
コード例 #18
0
ファイル: qt.py プロジェクト: www3838438/pywebview
class BrowserView(QMainWindow):
    instance = None
    running = False

    load_url_trigger = QtCore.pyqtSignal(str)
    html_trigger = QtCore.pyqtSignal(str, str)
    dialog_trigger = QtCore.pyqtSignal(int, str, bool, str, str)
    destroy_trigger = QtCore.pyqtSignal()
    fullscreen_trigger = QtCore.pyqtSignal()
    current_url_trigger = QtCore.pyqtSignal()
    evaluate_js_trigger = QtCore.pyqtSignal(str)

    def __init__(self, title, url, width, height, resizable, fullscreen,
                 min_size, confirm_quit, background_color, debug,
                 webview_ready):
        super(BrowserView, self).__init__()
        BrowserView.instance = self
        self.is_fullscreen = False
        self.confirm_quit = confirm_quit

        self._file_name_semaphor = threading.Semaphore(0)
        self._current_url_semaphore = threading.Semaphore()
        self._evaluate_js_semaphor = threading.Semaphore(0)

        self._evaluate_js_result = None
        self._current_url = None
        self._file_name = None

        self.resize(width, height)
        self.title = title
        self.setWindowTitle(title)

        # Set window background color
        self.background_color = QColor()
        self.background_color.setNamedColor(background_color)
        palette = self.palette()
        palette.setColor(self.backgroundRole(), self.background_color)
        self.setPalette(palette)

        if not resizable:
            self.setFixedSize(width, height)

        self.setMinimumSize(min_size[0], min_size[1])

        self.view = QWebView(self)
        self.view.setContextMenuPolicy(
            QtCore.Qt.NoContextMenu)  # disable right click context menu

        if url is not None:
            self.view.setUrl(QtCore.QUrl(url))

        self.setCentralWidget(self.view)

        self.load_url_trigger.connect(self.on_load_url)
        self.html_trigger.connect(self.on_load_html)
        self.dialog_trigger.connect(self.on_file_dialog)
        self.destroy_trigger.connect(self.on_destroy_window)
        self.fullscreen_trigger.connect(self.on_fullscreen)
        self.current_url_trigger.connect(self.on_current_url)
        self.evaluate_js_trigger.connect(self.on_evaluate_js)

        if fullscreen:
            self.toggle_fullscreen()

        self.move(QApplication.desktop().availableGeometry().center() -
                  self.rect().center())
        self.activateWindow()
        self.raise_()
        webview_ready.set()
        BrowserView.running = True

    def on_file_dialog(self, dialog_type, directory, allow_multiple,
                       save_filename, file_filter):
        if dialog_type == FOLDER_DIALOG:
            self._file_name = QFileDialog.getExistingDirectory(
                self,
                localization['linux.openFolder'],
                options=QFileDialog.ShowDirsOnly)
        elif dialog_type == OPEN_DIALOG:
            if allow_multiple:
                self._file_name = QFileDialog.getOpenFileNames(
                    self, localization['linux.openFiles'], directory,
                    file_filter)
            else:
                self._file_name = QFileDialog.getOpenFileName(
                    self, localization['linux.openFile'], directory,
                    file_filter)
        elif dialog_type == SAVE_DIALOG:
            if directory:
                save_filename = os.path.join(str(directory),
                                             str(save_filename))

            self._file_name = QFileDialog.getSaveFileName(
                self, localization['global.saveFile'], save_filename)

        self._file_name_semaphor.release()

    def on_current_url(self):
        self._current_url = self.view.url().toString()
        self._current_url_semaphore.release()

    def on_load_url(self, url):
        self.view.setUrl(QtCore.QUrl(url))

    def on_load_html(self, content, base_uri):
        self.view.setHtml(content, QtCore.QUrl(base_uri))

    def closeEvent(self, event):
        if self.confirm_quit:
            reply = QMessageBox.question(
                self, self.title, localization['global.quitConfirmation'],
                QMessageBox.Yes, QMessageBox.No)

            if reply == QMessageBox.NO:
                event.ignore()
                return

        event.accept()
        BrowserView.running = False

    def on_destroy_window(self):
        self.close()

    def on_fullscreen(self):
        if self.is_fullscreen:
            self.showNormal()
        else:
            self.showFullScreen()

        self.is_fullscreen = not self.is_fullscreen

    def on_evaluate_js(self, script):
        def return_result(result):
            self._evaluate_js_result = result
            self._evaluate_js_semaphor.release()

        try:  # PyQt4
            return_result(self.view.page().mainFrame().evaluateJavaScript(
                script).toPyObject())
        except AttributeError:  # PyQt5
            self.view.page().runJavaScript(script, return_result)

    def get_current_url(self):
        self.current_url_trigger.emit()
        self._current_url_semaphore.acquire()

        return self._current_url

    def load_url(self, url):
        self.load_url_trigger.emit(url)

    def load_html(self, content, base_uri):
        self.html_trigger.emit(content, base_uri)

    def create_file_dialog(self, dialog_type, directory, allow_multiple,
                           save_filename, file_filter):
        self.dialog_trigger.emit(dialog_type, directory, allow_multiple,
                                 save_filename, file_filter)
        self._file_name_semaphor.acquire()

        if _qt_version == 5:  # QT5
            if dialog_type == FOLDER_DIALOG:
                file_names = (self._file_name, )
            elif dialog_type == SAVE_DIALOG or not allow_multiple:
                file_names = (self._file_name[0], )
            else:
                file_names = tuple(self._file_name[0])

        else:  # QT4
            if dialog_type == FOLDER_DIALOG:
                file_names = (self._convert_string(self._file_name), )
            elif dialog_type == SAVE_DIALOG or not allow_multiple:
                file_names = (self._convert_string(self._file_name[0]), )
            else:
                file_names = tuple(
                    [self._convert_string(s) for s in self._file_name])

        # Check if we got an empty tuple, or a tuple with empty string
        if len(file_names) == 0 or len(file_names[0]) == 0:
            return None
        else:
            return file_names

    def destroy_(self):
        self.destroy_trigger.emit()

    def toggle_fullscreen(self):
        self.fullscreen_trigger.emit()

    def evaluate_js(self, script):
        self.evaluate_js_trigger.emit(script)
        self._evaluate_js_semaphor.acquire()

        return self._evaluate_js_result

    def _convert_string(self, qstring):
        if sys.version < '3':
            return unicode(qstring)
        else:
            return str(qstring)
コード例 #19
0
class FlowchartView(q.QWidget):
    selectRequested = qc.pyqtSignal(int)
    eventNameVisibilityChanged = qc.pyqtSignal(bool)
    eventParamVisibilityChanged = qc.pyqtSignal(bool)

    # View -> Core
    readySignal = qc.pyqtSignal()
    reloadedSignal = qc.pyqtSignal()
    eventSelected = qc.pyqtSignal(int)

    def __init__(self, parent, flow_data: FlowData) -> None:
        super().__init__(parent)
        self.flow_data: FlowData = flow_data
        self.is_current = True
        self.selected_event: typing.Optional[Event] = None
        self.showEventParams = False
        self.initWidgets()
        self.initLayout()
        self.connectWidgets()

    def initWidgets(self) -> None:
        self.web_object = FlowchartWebObject(self)
        self.flow_data.flowDataChanged.connect(self.onFlowDataChanged)
        self.flow_data.fileLoaded.connect(self.web_object.fileLoaded)
        self.selectRequested.connect(self.web_object.selectRequested)
        self.eventNameVisibilityChanged.connect(
            self.web_object.eventNameVisibilityChanged)
        self.eventParamVisibilityChanged.connect(
            self.onEventParamVisibilityChanged)
        self.eventParamVisibilityChanged.connect(
            self.web_object.eventParamVisibilityChanged)

        self.view = QWebEngineView()
        self.view.setContextMenuPolicy(qc.Qt.NoContextMenu)
        self.channel = QWebChannel()
        self.channel.registerObject('widget', self.web_object)
        self.view.page().setWebChannel(self.channel)
        self.view.page().setBackgroundColor(qg.QColor(0x38, 0x38, 0x38))
        self.view.setUrl(qc.QUrl.fromLocalFile(get_path('assets/index.html')))

        self.entry_point_view = q.QListView(self)
        self.ep_proxy_model = qc.QSortFilterProxyModel(self)
        self.ep_proxy_model.setSourceModel(self.flow_data.entry_point_model)
        self.ep_proxy_model.setFilterKeyColumn(-1)
        self.entry_point_view.setModel(self.ep_proxy_model)
        self.ep_search = SearchBar()
        self.ep_search.hide()

        self.container_model = ContainerModel(self)
        self.container_view = ContainerView(None, self.container_model,
                                            self.flow_data)
        self.container_stacked_widget = q.QStackedWidget()
        self.container_stacked_widget.addWidget(q.QWidget())
        self.container_stacked_widget.addWidget(self.container_view)

        self.update_timer = qc.QTimer(self)
        self.update_timer.timeout.connect(self.web_object.flowDataChanged)
        self.update_timer.setSingleShot(True)

    def initLayout(self) -> None:
        left_pane_splitter = q.QSplitter(qc.Qt.Vertical)
        ep_widget = q.QWidget()
        ep_layout = q.QVBoxLayout(ep_widget)
        ep_layout.setContentsMargins(0, 0, 0, 0)
        ep_layout.addWidget(self.entry_point_view, stretch=1)
        ep_layout.addWidget(self.ep_search)
        left_pane_splitter.addWidget(ep_widget)
        left_pane_splitter.addWidget(self.container_stacked_widget)
        left_pane_splitter.setSizes([
            int(left_pane_splitter.height() * 0.6),
            int(left_pane_splitter.height() * 0.4)
        ])

        splitter = q.QSplitter()
        splitter.addWidget(left_pane_splitter)
        splitter.addWidget(self.view)
        splitter.setSizes(
            [int(splitter.width() * 0.3),
             int(splitter.width() * 0.7)])
        layout = q.QHBoxLayout(self)
        layout.addWidget(splitter)
        layout.setContentsMargins(0, 0, 0, 0)

    def connectWidgets(self) -> None:
        self.ep_search.connectToFilterModel(self.ep_proxy_model)
        self.ep_search.addFindShortcut(self)

        self.flow_data.flowDataChanged.connect(
            lambda reason: self.entry_point_view.clearSelection())
        self.entry_point_view.selectionModel().selectionChanged.connect(
            self.onEntryPointSelected)

        connect_model_change_signals(self.container_model, self.flow_data,
                                     FlowDataChangeReason.EventParameters)
        self.eventSelected.connect(self.onEventSelectedInWebView)
        self.flow_data.flowDataChanged.connect(
            lambda reason: self.refreshParamModel())

        self.reloadedSignal.connect(self.onWebViewReloaded)

    def onEventParamVisibilityChanged(self, show: bool) -> None:
        self.showEventParams = show

    def setIsCurrentView(self, is_current: bool) -> None:
        self.is_current = is_current
        if is_current and self.update_timer.isActive():
            self.update_timer.stop()
            self.web_object.flowDataChanged.emit()

    def export(self) -> None:
        if not self.flow_data.flow:
            return
        path = q.QFileDialog.getSaveFileName(
            self, 'Select a location for the graph data',
            self.flow_data.flow.name + '.json', 'Data (*.json)')[0]
        if not path:
            return
        data = self.web_object.getData()
        try:
            with open(path, 'w') as f:
                json.dump(data, f, default=lambda x: str(x))
        except:
            q.QMessageBox.critical(self, 'Export graph data',
                                   'Failed to write to ' + path)

    def reload(self) -> None:
        self.view.reload()

    def onWebViewReloaded(self) -> None:
        if not self.selected_event or not self.flow_data.flow or not self.flow_data.flow.flowchart:
            return

        try:
            new_idx = self.flow_data.flow.flowchart.events.index(
                self.selected_event)
            self.selectRequested.emit(new_idx)
        except ValueError:
            self.container_model.set(None)
            self.container_stacked_widget.setCurrentIndex(0)

    def refreshParamModel(self) -> bool:
        if self.selected_event and hasattr(self.selected_event.data, 'params'):
            if not self.selected_event.data.params:  # type: ignore
                self.selected_event.data.params = Container()  # type: ignore
            self.container_model.set(
                self.selected_event.data.params)  # type: ignore
            self.container_stacked_widget.setCurrentIndex(1)
            return True
        return False

    def onEventSelectedInWebView(self, idx: int) -> None:
        if idx >= 0:
            event = self.flow_data.flow.flowchart.events[idx]
            self.selected_event = event
            if self.refreshParamModel():
                return
        else:
            self.selected_event = None

        self.container_model.set(None)
        self.container_stacked_widget.setCurrentIndex(0)

    def onFlowDataChanged(self, reason: FlowDataChangeReason) -> None:
        should_reload = bool(reason & (FlowDataChangeReason.Reset
                                       | FlowDataChangeReason.Actors
                                       | FlowDataChangeReason.Events))
        if self.showEventParams:
            should_reload = should_reload or bool(
                reason & FlowDataChangeReason.EventParameters)
        if not should_reload:
            return
        if self.is_current:
            self.web_object.flowDataChanged.emit()
        else:
            self.update_timer.start(15 * 1000)

    def onEntryPointSelected(self, selected, deselected) -> None:
        if len(selected.indexes()) != 1:
            return
        idx = selected.indexes()[0]
        self.selectRequested.emit(-1000 -
                                  self.ep_proxy_model.mapToSource(idx).row())

    def delayedSelect(self, event: Event) -> None:
        try:
            qc.QTimer.singleShot(
                1000, lambda: self.selectRequested.emit(
                    self.flow_data.flow.flowchart.events.index(event)))
        except ValueError:
            pass

    def webEditEvent(self, idx: int) -> None:
        if idx < 0:
            return
        show_event_editor(self, self.flow_data, idx)

    def webAddEntryPoint(self, event_idx: int) -> None:
        if event_idx < 0:
            return

        ep_name, ok = q.QInputDialog.getText(self, 'Add entry point',
                                             f'Name of the new entry point:',
                                             q.QLineEdit.Normal)
        if not ok or not ep_name:
            return

        ep = EntryPoint(ep_name)
        assert self.flow_data.flow and self.flow_data.flow.flowchart
        ep.main_event.v = self.flow_data.flow.flowchart.events[event_idx]
        self.flow_data.entry_point_model.append(ep)

    def webRemoveEntryPoint(self, ep_idx: int) -> None:
        try:
            self.flow_data.entry_point_model.removeRow(ep_idx)
        except IndexError as e:
            q.QMessageBox.critical(
                self, 'Bug',
                f'An error has occurred: {e}\n\nPlease report this issue and mention what you were doing when this message showed up.'
            )

    def addNewEvent(self) -> typing.Optional[Event]:
        return add_new_event(self, self.flow_data)

    def webAddEventAbove(self, parent_indices: typing.List[int],
                         event_idx: int) -> None:
        if event_idx < 0:
            return
        assert self.flow_data.flow and self.flow_data.flow.flowchart
        event = self.flow_data.flow.flowchart.events[event_idx]

        parent_events = [
            self.flow_data.flow.flowchart.events[i] for i in parent_indices
            if i >= 0
        ]
        list_widget = CheckableEventParentListWidget(None, event,
                                                     parent_events)
        if parent_events:
            dialog = q.QDialog(
                self, qc.Qt.WindowTitleHint | qc.Qt.WindowSystemMenuHint)
            dialog.setWindowTitle('Add new event above...')
            btn_box = q.QDialogButtonBox(q.QDialogButtonBox.Ok
                                         | q.QDialogButtonBox.Cancel)
            btn_box.accepted.connect(dialog.accept)
            btn_box.rejected.connect(dialog.reject)
            dialog_layout = q.QVBoxLayout(dialog)
            dialog_layout.addWidget(
                q.QLabel(
                    'Please select links that should be modified to point to the new event you are going to add.'
                ))
            dialog_layout.addWidget(list_widget)
            dialog_layout.addWidget(btn_box)
            ret = dialog.exec_()
            if not ret:
                return

        new_parent = self.addNewEvent()
        if not new_parent:
            return

        self._doAddEventAbove(list_widget.getSelectedEvents(), event,
                              new_parent)
        self.flow_data.flowDataChanged.emit(FlowDataChangeReason.Events)
        self.delayedSelect(new_parent)

    def _doAddEventAbove(self, parents: typing.List[typing.Tuple[
        Event, typing.List[typing.Any]]], event: Event,
                         new_parent: Event) -> None:
        # Update the parents to point to the new parent.
        for parent, branches in parents:
            if isinstance(parent.data, ActionEvent) or isinstance(
                    parent.data, JoinEvent) or isinstance(
                        parent.data, SubFlowEvent):
                # Easy case: just set the next pointer to the new parent.
                parent.data.nxt.v = new_parent

            # For switch and fork events, update all branches that currently point to the event.
            elif isinstance(parent.data, SwitchEvent):
                for case in branches:
                    if parent.data.cases[case].v == event:
                        parent.data.cases[case].v = new_parent
            elif isinstance(parent.data, ForkEvent):
                for i, fork in enumerate(branches):
                    if fork.v == event:
                        parent.data.forks[i].v = new_parent