コード例 #1
0
class DyStockTradeStrategyMarketMonitorWidget(QWidget):
    """
        股票策略实时监控窗口,动态创建
    """
    signal = QtCore.pyqtSignal(type(DyEvent()))

    def __init__(self, eventEngine, strategyCls, strategyState):
        super().__init__()

        self._eventEngine = eventEngine
        self._strategyCls = strategyCls

        self._cloneDataWidgets = []

        self._registerEvent()

        self._initUi(strategyState)

    def _initUi(self, strategyState):
        self._dataWidget = DyStockTradeStrategyMarketMonitorDataWidget(
            self._strategyCls, self)
        self._indWidget = DyStockTradeStrategyMarketMonitorIndWidget(
            self._eventEngine, self._strategyCls, strategyState)

        self._dataLabel = QLabel('数据')
        self._indLabel = QLabel('指示')

        grid = QGridLayout()
        grid.setSpacing(0)

        grid.addWidget(self._dataLabel, 0, 0)
        grid.addWidget(self._dataWidget, 1, 0)
        grid.addWidget(self._indLabel, 2, 0)
        grid.addWidget(self._indWidget, 3, 0)

        grid.setRowStretch(0, 1)
        grid.setRowStretch(1, 30)
        grid.setRowStretch(2, 1)
        grid.setRowStretch(3, 30)

        self.setLayout(grid)

        # set menu for labels
        self._dataLabel.setContextMenuPolicy(Qt.CustomContextMenu)
        self._dataLabel.customContextMenuRequested.connect(
            self._showDataLabelContextMenu)

        self._indLabel.setContextMenuPolicy(Qt.CustomContextMenu)
        self._indLabel.customContextMenuRequested.connect(
            self._showIndLabelContextMenu)

        self._dataLabelMenu = QMenu(self)

        action = QAction('叠加', self)
        action.triggered.connect(self._overlapAct)
        self._dataLabelMenu.addAction(action)

        action = QAction('克隆', self)
        action.triggered.connect(self._cloneDataWidgetAct)
        self._dataLabelMenu.addAction(action)

        self._indLabelMenu = QMenu(self)

        action = QAction('叠加', self)
        action.triggered.connect(self._overlapAct)
        self._indLabelMenu.addAction(action)

    def _stockMarketMonitorUiHandler(self, event):
        if 'data' in event.data:
            data = event.data['data']['data']
            new = event.data['data']['new']

            strategyCls = event.data['class']
            if strategyCls.maxUiDataRowNbr is not None:
                data = data[:strategyCls.maxUiDataRowNbr]

            self._dataWidget.update(data, new)
            for w in self._cloneDataWidgets:
                w.update(data, new)

        if 'ind' in event.data:
            self._indWidget.update(event.data['ind'])

    def _signalEmitWrapper(self, event):
        """ !!!Note: The value of signal.emit will always be changed each time you getting.
        """
        self.signal.emit(event)

    def _registerEvent(self):
        self.signal.connect(self._stockMarketMonitorUiHandler)
        self._eventEngine.register(
            DyEventType.stockMarketMonitorUi + self._strategyCls.name,
            self._signalEmitWrapper)

    def _unregisterEvent(self):
        self.signal.disconnect(self._stockMarketMonitorUiHandler)
        self._eventEngine.unregister(
            DyEventType.stockMarketMonitorUi + self._strategyCls.name,
            self._signalEmitWrapper)

    def closeEvent(self, event):
        self._dataWidget.close()
        self._indWidget.close()

        self._unregisterEvent()

        return super().closeEvent(event)

    def _showDataLabelContextMenu(self, position):
        self._dataLabelMenu.popup(QCursor.pos())

    def _showIndLabelContextMenu(self, position):
        self._indLabelMenu.popup(QCursor.pos())

    def _overlapAct(self):
        grid = self.layout()

        # remove
        self._dataLabel.setText('')
        self._indLabel.setText('')

        grid.removeWidget(self._dataLabel)
        grid.removeWidget(self._dataWidget)
        grid.removeWidget(self._indLabel)
        grid.removeWidget(self._indWidget)

        # add
        self._tabWidget = QTabWidget()

        self._tabWidget.addTab(self._dataWidget, '数据')
        self._tabWidget.addTab(self._indWidget, '指示')

        grid.addWidget(self._tabWidget, 0, 0)

        grid.setRowStretch(0, 1)
        grid.setRowStretch(1, 0)
        grid.setRowStretch(2, 0)
        grid.setRowStretch(3, 0)

        # 设置Tab右键菜单事件
        tabBar = self._tabWidget.tabBar()
        tabBar.setContextMenuPolicy(Qt.CustomContextMenu)
        tabBar.customContextMenuRequested.connect(self._showTabContextMenu)

        # 创建TabBar菜单
        self._tabBarMenu = QMenu(self)

        action = QAction('平铺', self)
        action.triggered.connect(self._flatAct)
        self._tabBarMenu.addAction(action)

    def _showTabContextMenu(self, position):
        self._tabBarMenu.popup(QCursor.pos())

    def _flatAct(self):
        grid = self.layout()

        # remove
        self._tabWidget.removeTab(0)
        self._tabWidget.removeTab(0)

        grid.removeWidget(self._tabWidget)

        self._tabWidget.hide()

        # add
        self._dataLabel.setText('数据')
        self._indLabel.setText('指示')

        grid.addWidget(self._dataLabel, 0, 0)
        grid.addWidget(self._dataWidget, 1, 0)
        grid.addWidget(self._indLabel, 2, 0)
        grid.addWidget(self._indWidget, 3, 0)

        self._dataWidget.show()
        self._indWidget.show()

        grid.setRowStretch(0, 1)
        grid.setRowStretch(1, 30)
        grid.setRowStretch(2, 1)
        grid.setRowStretch(3, 30)

    def removeCloneDataWidget(self, cloneWidget):
        try:
            self._cloneDataWidgets.remove(cloneWidget)
        except:
            pass

    def _cloneDataWidgetAct(self):
        dataWidget = self._dataWidget.clone()
        self._cloneDataWidgets.append(dataWidget)

        dataWidget.setWindowTitle('策略[{}]: 数据'.format(
            self._strategyCls.chName))
        dataWidget.showMaximized()
コード例 #2
0
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.settings = QSettings("Vial", "Vial")
        themes.set_theme(self.get_theme())

        self.current_device = None
        self.devices = []
        # create empty VIA definitions. Easier than setting it to none and handling a bunch of exceptions
        self.via_stack_json = {"definitions": {}}
        self.sideload_json = None
        self.sideload_vid = self.sideload_pid = -1

        self.combobox_devices = QComboBox()
        self.combobox_devices.currentIndexChanged.connect(
            self.on_device_selected)

        self.btn_refresh_devices = QToolButton()
        self.btn_refresh_devices.setToolButtonStyle(Qt.ToolButtonTextOnly)
        self.btn_refresh_devices.setText(tr("MainWindow", "Refresh"))
        self.btn_refresh_devices.clicked.connect(self.on_click_refresh)

        layout_combobox = QHBoxLayout()
        layout_combobox.addWidget(self.combobox_devices)
        layout_combobox.addWidget(self.btn_refresh_devices)

        self.layout_editor = LayoutEditor()
        self.keymap_editor = KeymapEditor(self.layout_editor)
        self.firmware_flasher = FirmwareFlasher(self)
        self.macro_recorder = MacroRecorder()
        self.matrix_tester = MatrixTest(self.layout_editor)

        self.editors = [(self.keymap_editor, "Keymap"),
                        (self.layout_editor, "Layout"),
                        (self.macro_recorder, "Macros"),
                        (self.matrix_tester, "Matrix tester"),
                        (self.firmware_flasher, "Firmware updater")]
        Unlocker.global_layout_editor = self.layout_editor

        self.tabs = QTabWidget()
        self.refresh_tabs()

        self.lbl_no_devices = QLabel(
            tr(
                "MainWindow",
                'No devices detected. Connect a Vial-compatible device and press '
                '"Refresh"\n'
                'or select "File" → "Download VIA definitions" in order to enable'
                ' support for VIA keyboards.'))
        self.lbl_no_devices.setAlignment(Qt.AlignCenter)

        layout = QVBoxLayout()
        layout.addLayout(layout_combobox)
        layout.addWidget(self.tabs)
        layout.addWidget(self.lbl_no_devices)
        layout.setAlignment(self.lbl_no_devices, Qt.AlignHCenter)
        w = QWidget()
        w.setLayout(layout)
        self.setCentralWidget(w)

        self.init_menu()

        # cache for via definition files
        self.cache_path = QStandardPaths.writableLocation(
            QStandardPaths.CacheLocation)
        if not os.path.exists(self.cache_path):
            os.makedirs(self.cache_path)
        # check if the via defitions already exist
        if os.path.isfile(os.path.join(self.cache_path, "via_keyboards.json")):
            with open(os.path.join(self.cache_path,
                                   "via_keyboards.json")) as vf:
                self.via_stack_json = json.load(vf)
                vf.close()

        # make sure initial state is valid
        self.on_click_refresh()

    def init_menu(self):
        layout_load_act = QAction(tr("MenuFile", "Load saved layout..."), self)
        layout_load_act.setShortcut("Ctrl+O")
        layout_load_act.triggered.connect(self.on_layout_load)

        layout_save_act = QAction(tr("MenuFile", "Save current layout..."),
                                  self)
        layout_save_act.setShortcut("Ctrl+S")
        layout_save_act.triggered.connect(self.on_layout_save)

        sideload_json_act = QAction(tr("MenuFile", "Sideload VIA JSON..."),
                                    self)
        sideload_json_act.triggered.connect(self.on_sideload_json)

        download_via_stack_act = QAction(
            tr("MenuFile", "Download VIA definitions"), self)
        download_via_stack_act.triggered.connect(self.load_via_stack_json)

        load_dummy_act = QAction(tr("MenuFile", "Load dummy JSON..."), self)
        load_dummy_act.triggered.connect(self.on_load_dummy)

        exit_act = QAction(tr("MenuFile", "Exit"), self)
        exit_act.setShortcut("Ctrl+Q")
        exit_act.triggered.connect(qApp.exit)

        file_menu = self.menuBar().addMenu(tr("Menu", "File"))
        file_menu.addAction(layout_load_act)
        file_menu.addAction(layout_save_act)
        file_menu.addSeparator()
        file_menu.addAction(sideload_json_act)
        file_menu.addAction(download_via_stack_act)
        file_menu.addAction(load_dummy_act)
        file_menu.addSeparator()
        file_menu.addAction(exit_act)

        keyboard_unlock_act = QAction(tr("MenuSecurity", "Unlock"), self)
        keyboard_unlock_act.triggered.connect(self.unlock_keyboard)

        keyboard_lock_act = QAction(tr("MenuSecurity", "Lock"), self)
        keyboard_lock_act.triggered.connect(self.lock_keyboard)

        keyboard_reset_act = QAction(
            tr("MenuSecurity", "Reboot to bootloader"), self)
        keyboard_reset_act.triggered.connect(self.reboot_to_bootloader)

        keyboard_layout_menu = self.menuBar().addMenu(
            tr("Menu", "Keyboard layout"))
        keymap_group = QActionGroup(self)
        selected_keymap = self.settings.value("keymap")
        for idx, keymap in enumerate(KEYMAPS):
            act = QAction(tr("KeyboardLayout", keymap[0]), self)
            act.triggered.connect(
                lambda checked, x=idx: self.change_keyboard_layout(x))
            act.setCheckable(True)
            if selected_keymap == keymap[0]:
                self.change_keyboard_layout(idx)
                act.setChecked(True)
            keymap_group.addAction(act)
            keyboard_layout_menu.addAction(act)
        # check "QWERTY" if nothing else is selected
        if keymap_group.checkedAction() is None:
            keymap_group.actions()[0].setChecked(True)

        self.security_menu = self.menuBar().addMenu(tr("Menu", "Security"))
        self.security_menu.addAction(keyboard_unlock_act)
        self.security_menu.addAction(keyboard_lock_act)
        self.security_menu.addSeparator()
        self.security_menu.addAction(keyboard_reset_act)

        self.theme_menu = self.menuBar().addMenu(tr("Menu", "Theme"))
        theme_group = QActionGroup(self)
        selected_theme = self.get_theme()
        for name, _ in [("System", None)] + themes.themes:
            act = QAction(tr("MenuTheme", name), self)
            act.triggered.connect(lambda x, name=name: self.set_theme(name))
            act.setCheckable(True)
            act.setChecked(selected_theme == name)
            theme_group.addAction(act)
            self.theme_menu.addAction(act)
        # check "System" if nothing else is selected
        if theme_group.checkedAction() is None:
            theme_group.actions()[0].setChecked(True)

    def on_layout_load(self):
        dialog = QFileDialog()
        dialog.setDefaultSuffix("vil")
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setNameFilters(["Vial layout (*.vil)"])
        if dialog.exec_() == QDialog.Accepted:
            with open(dialog.selectedFiles()[0], "rb") as inf:
                data = inf.read()
            self.keymap_editor.restore_layout(data)
            self.rebuild()

    def on_layout_save(self):
        dialog = QFileDialog()
        dialog.setDefaultSuffix("vil")
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        dialog.setNameFilters(["Vial layout (*.vil)"])
        if dialog.exec_() == QDialog.Accepted:
            with open(dialog.selectedFiles()[0], "wb") as outf:
                outf.write(self.keymap_editor.save_layout())

    def on_click_refresh(self):
        self.combobox_devices.clear()
        self.devices = find_vial_devices(self.via_stack_json,
                                         self.sideload_vid, self.sideload_pid)

        for dev in self.devices:
            self.combobox_devices.addItem(dev.title())

        if self.devices:
            self.lbl_no_devices.hide()
            self.tabs.show()
        else:
            self.lbl_no_devices.show()
            self.tabs.hide()

    def on_device_selected(self):
        if self.current_device is not None:
            self.current_device.close()
        self.current_device = None
        idx = self.combobox_devices.currentIndex()
        if idx >= 0:
            self.current_device = self.devices[idx]

        if self.current_device is not None:
            if self.current_device.sideload:
                self.current_device.open(self.sideload_json)
            elif self.current_device.via_stack:
                self.current_device.open(self.via_stack_json["definitions"][
                    self.current_device.via_id])
            else:
                self.current_device.open(None)

            if isinstance(self.current_device, VialKeyboard) \
                    and self.current_device.keyboard.keyboard_id in EXAMPLE_KEYBOARDS:
                QMessageBox.warning(
                    self, "", "An example keyboard UID was detected.\n"
                    "Please change your keyboard UID to be unique before you ship!"
                )

        self.rebuild()

        self.refresh_tabs()

    def rebuild(self):
        # don't show "Security" menu for bootloader mode, as the bootloader is inherently insecure
        self.security_menu.menuAction().setVisible(
            isinstance(self.current_device, VialKeyboard))

        # if unlock process was interrupted, we must finish it first
        if isinstance(
                self.current_device, VialKeyboard
        ) and self.current_device.keyboard.get_unlock_in_progress():
            Unlocker.unlock(self.current_device.keyboard)
            self.current_device.keyboard.reload()

        for e in [
                self.layout_editor, self.keymap_editor, self.firmware_flasher,
                self.macro_recorder, self.matrix_tester
        ]:
            e.rebuild(self.current_device)

    def refresh_tabs(self):
        self.tabs.clear()
        for container, lbl in self.editors:
            if not container.valid():
                continue

            w = QWidget()
            w.setLayout(container)
            self.tabs.addTab(w, tr("MainWindow", lbl))

    def load_via_stack_json(self):
        data = urlopen(
            "https://github.com/vial-kb/via-keymap-precompiled/raw/main/via_keyboard_stack.json"
        )
        self.via_stack_json = json.load(data)
        # write to cache
        with open(os.path.join(self.cache_path, "via_keyboards.json"),
                  "w") as cf:
            cf.write(json.dumps(self.via_stack_json, indent=2))
            cf.close()

    def on_sideload_json(self):
        dialog = QFileDialog()
        dialog.setDefaultSuffix("json")
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setNameFilters(["VIA layout JSON (*.json)"])
        if dialog.exec_() == QDialog.Accepted:
            with open(dialog.selectedFiles()[0], "rb") as inf:
                data = inf.read()
            self.sideload_json = json.loads(data)
            self.sideload_vid = int(self.sideload_json["vendorId"], 16)
            self.sideload_pid = int(self.sideload_json["productId"], 16)
            self.on_click_refresh()

    def on_load_dummy(self):
        dialog = QFileDialog()
        dialog.setDefaultSuffix("json")
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setNameFilters(["VIA layout JSON (*.json)"])
        if dialog.exec_() == QDialog.Accepted:
            with open(dialog.selectedFiles()[0], "rb") as inf:
                data = inf.read()
            self.sideload_json = json.loads(data)
            self.sideload_vid = self.sideload_pid = 0
            self.on_click_refresh()

    def lock_ui(self):
        self.tabs.setEnabled(False)
        self.combobox_devices.setEnabled(False)
        self.btn_refresh_devices.setEnabled(False)

    def unlock_ui(self):
        self.tabs.setEnabled(True)
        self.combobox_devices.setEnabled(True)
        self.btn_refresh_devices.setEnabled(True)

    def unlock_keyboard(self):
        if isinstance(self.current_device, VialKeyboard):
            Unlocker.unlock(self.current_device.keyboard)

    def lock_keyboard(self):
        if isinstance(self.current_device, VialKeyboard):
            self.current_device.keyboard.lock()

    def reboot_to_bootloader(self):
        if isinstance(self.current_device, VialKeyboard):
            Unlocker.unlock(self.current_device.keyboard)
            self.current_device.keyboard.reset()

    def change_keyboard_layout(self, index):
        self.settings.setValue("keymap", KEYMAPS[index][0])
        self.keymap_editor.set_keymap_override(KEYMAPS[index][1])

    def get_theme(self):
        return self.settings.value("theme", "Dark")

    def set_theme(self, theme):
        themes.set_theme(theme)
        self.settings.setValue("theme", theme)
        msg = QMessageBox()
        msg.setText(
            tr(
                "MainWindow",
                "In order to fully apply the theme you should restart the application."
            ))
        msg.exec_()
コード例 #3
0
class TableWidget(QSplitter):

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

        # vbox = QVBoxLayout(self)
        # vbox.setContentsMargins(0, 0, 0, 0)

        self._tabs = QTabWidget()
        self._tabs.setAutoFillBackground(True)
        p = self._tabs.palette()
        p.setColor(p.Window, QColor("white"))
        self._tabs.setPalette(p)
        self._other_tab = QTabWidget()
        self._other_tab.setAutoFillBackground(True)
        self._other_tab.setPalette(p)
        self.addWidget(self._tabs)
        self.addWidget(self._other_tab)
        self.setSizes([1, 1])
        self._other_tab.hide()

        self.relations = {}

        # Stack
        self.stacked = QStackedWidget()
        self._tabs.addTab(self.stacked, "Workspace")
        self.stacked_result = QStackedWidget()
        self._tabs.addTab(self.stacked_result, self.tr("Resultados"))

        btn_split = QToolButton()
        btn_split.setToolTip(self.tr("Click para dividir la pantalla"))
        btn_split.setAutoRaise(True)
        btn_split.setIcon(QIcon(":img/split"))
        self._tabs.setCornerWidget(btn_split)
        btn_split.clicked.connect(self._split)
        btn_split = QToolButton()
        btn_split.setToolTip(self.tr("Click para juntar las pantallas"))
        btn_split.setAutoRaise(True)
        btn_split.setIcon(QIcon(":img/split"))
        btn_split.clicked.connect(self._unsplit)
        self._other_tab.setCornerWidget(btn_split)
        # self.setContextMenuPolicy(Qt.CustomContextMenu)
        # self.customContextMenuRequested.connect(self._show_menu)

        lateral_widget = Pireal.get_service("lateral_widget")
        lateral_widget.resultClicked.connect(self._on_result_list_clicked)
        lateral_widget.resultSelectionChanged.connect(
            lambda index: self.stacked_result.setCurrentIndex(index))
        # lateral_widget.newRowsRequested.connect(self._insert_rows)

    def insert_rows(self, tuplas):
        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            for tupla in tuplas:
                model.insertRow(model.rowCount(), tupla)
        current_view.adjust_columns()

    def _on_result_list_clicked(self, index):
        self.stacked_result.setCurrentIndex(index)
        if not self._other_tab.isVisible():
            self._tabs.setCurrentIndex(1)

    def _unsplit(self):
        self._other_tab.hide()
        result_widget = self._other_tab.widget(0)
        self._tabs.addTab(result_widget, self.tr("Resultados"))
        self._tabs.cornerWidget().show()

    def _split(self):
        result_widget = self._tabs.widget(1)
        self._other_tab.addTab(result_widget, self.tr("Resultados"))
        self._other_tab.show()
        self.setSizes([1, 1])
        self._tabs.cornerWidget().hide()
        self.setOrientation(Qt.Horizontal)

    def _show_menu(self, position):
        menu = QMenu(self)

        if self.count() > 0:
            add_tuple_action = menu.addAction(self.tr("Agregar Tupla"))
            add_col_action = menu.addAction(self.tr("Add Column"))

            add_tuple_action.triggered.connect(self.add_tuple)
            add_col_action.triggered.connect(self.add_column)
            menu.addSeparator()

        add_relation_action = menu.addAction(self.tr("Create new Relation"))
        add_relation_action.triggered.connect(self.__new_relation)

        menu.exec_(self.mapToGlobal(position))

    def __new_relation(self):
        central_service = Pireal.get_service("central")
        central_service.create_new_relation()

    def count(self):
        return self.stacked.count()

    def remove_table(self, index):
        widget = self.stacked.widget(index)
        self.stacked.removeWidget(widget)
        del widget

    def current_table(self):
        return self.stacked.currentWidget()

    def remove_relation(self, name):
        del self.relations[name]

    def add_relation(self, name, rela):
        if self.relations.get(name, None) is None:
            self.relations[name] = rela
            return True
        return False

    def add_table(self, rela, name, table):
        """ Add new table from New Relation Dialog """

        self.add_relation(name, rela)
        self.stacked.addWidget(table)

    def add_tuple(self):
        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            model.insertRow(model.rowCount())

    def add_column(self):
        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            model.insertColumn(model.columnCount())

    def delete_tuple(self):
        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            selection = current_view.selectionModel()
            if selection.hasSelection():
                selection = selection.selection()
                rows = set([index.row() for index in selection.indexes()])
                rows = sorted(list(rows))
                previous = -1
                i = len(rows) - 1
                while i >= 0:
                    current = rows[i]
                    if current != previous:
                        model.removeRow(current)
                    i -= 1

    def delete_column(self):
        """ Elimina la/las columnas seleccionadas """

        current_view = self.current_table()
        if current_view is not None:
            model = current_view.model()
            selection = current_view.selectionModel()
            if selection.hasSelection():
                selection = selection.selection()
                columns = set(
                    [index.column() for index in selection.indexes()])
                columns = sorted(list(columns))
                previous = -1
                i = len(columns) - 1
                while i >= 0:
                    current = columns[i]
                    if current != previous:
                        model.removeColumn(current)
                    i -= 1

    def create_table(self, rela, editable=True):
        """ Se crea la vista y el modelo """

        _view = view.View()
        _model = model.Model(rela)
        if not editable:
            _model.editable = False
        _view.setModel(_model)
        _view.setItemDelegate(delegate.Delegate())
        _view.setHorizontalHeader(view.Header())
        return _view
コード例 #4
0
class PlotWindow(QWidget):
    def __init__(self, tab):
        super(PlotWindow, self).__init__()
        self.tab = tab
        self.allAxes = {}
        self.curveList = []
        self.extraLines = []
        self.layout = QHBoxLayout()
        self.graph_layout = QVBoxLayout()
        self.gbox_layout = QVBoxLayout()

        self.tabGBActor = QTabWidget()

        self.dateplot = DatePlot(self)
        self.customize = Customize(self)
        self.button_arrow = self.ButtonArrow()
        self.button_del_graph = self.ButtonDelete()

        self.gbox_layout.addWidget(self.dateplot)
        self.gbox_layout.addWidget(self.customize)
        self.gbox_layout.addWidget(self.tabGBActor)
        self.gbox_layout.addWidget(self.button_del_graph)

        self.layout.addLayout(self.graph_layout)
        self.layout.addWidget(self.button_arrow)
        self.layout.addLayout(self.gbox_layout)

        for widget in [self.dateplot, self.customize, self.tabGBActor]:
            widget.setMaximumWidth(400)

        self.setLayout(self.layout)

    @property
    def mainwindow(self):
        return self.tab.mainwindow

    @property
    def config(self):
        return self.dateplot.config

    @property
    def axes2curves(self):
        d = {ax: [] for ax in [None] + list(self.allAxes.values())}

        for curve in self.curveList:
            d[curve.getAxes()].append(curve)

        return d

    @property
    def line2Curve(self):
        return {curve.line: curve for curve in self.curveList}

    @property
    def axes2id(self):
        d = {ax: id for id, ax in self.allAxes.items()}
        d[None] = None
        return d

    def createGraph(self, custom):
        try:
            self.graph.close()
            self.graph_layout.removeWidget(self.graph)
            self.graph.deleteLater()
        except AttributeError:
            pass

        self.graph = Graph(self, custom)
        self.graph_layout.insertWidget(0, self.graph)

    def getAxes(self, newType, i=-1):

        for i, ax in self.allAxes.items():
            try:
                curve = self.axes2curves[ax][0]
                if curve.type == newType:
                    return ax
            except IndexError:
                return ax

            if i == 3:
                raise ValueError('No Axe available')
        return i + 1

    def setAxes(self, allAxes):
        for idAxes, oldAxes in list(self.allAxes.items()):
            self.unsetLines(oldAxes, allAxes)
            self.allAxes.pop(idAxes, None)

        self.allAxes = allAxes

    def unsetLines(self, axes, newAxes):
        while axes.lines:
            line = axes.lines[0]
            axes.lines.remove(line)
            try:
                curve = self.line2Curve[line]
                curve.line = False
                if curve.getAxes() not in newAxes.values():
                    curve.setAxes(None)
            except KeyError:
                pass
            del line

    def addCurve(self, curveConf):

        new_curve = Curve(self, curveConf)
        axes = self.getAxes(new_curve.type)

        if isinstance(axes, int):
            idAxes = axes
            self.customize.allAxes[idAxes].checkbox.setChecked(2)
            axes = self.allAxes[idAxes]

        new_curve.setAxes(axes)
        self.appendCurve(new_curve)
        self.graph.plotCurves(new_curve)

        return new_curve

    def appendCurve(self, new_curve):

        self.curveList.append(new_curve)
        self.customize.appendRow(new_curve)

    def switchCurve(self, axeId, curve):
        ax = self.allAxes[axeId] if axeId is not None else None
        self.graph.switchCurve(ax, curve)

    def removeCurve(self, curve):
        self.curveList.remove(curve)
        self.graph.removeCurve(curve)

        try:
            checkbox = curve.checkbox
            checkbox.setCheckable(True)
            checkbox.setChecked(0)
        except RuntimeError:
            pass  # Checkbox could have been already deleted

    def constructGroupbox(self, config):

        while self.tabGBActor.count():
            widget = self.tabGBActor.widget(0)
            self.clearLayout(widget.layout())
            self.tabGBActor.removeTab(0)
            widget.close()
            widget.deleteLater()

        sortedModule = self.sortCfg(config)

        for actorname in sorted(sortedModule):
            config = sortedModule[actorname]
            if config:
                t = TabActor(self, config)
                self.tabGBActor.addTab(t, actorname)

    def showhideConfig(self, button_arrow):

        if not self.tabGBActor.isHidden():
            self.tabGBActor.hide()
            self.dateplot.hide()
            self.customize.hide()
            self.button_del_graph.hide()
            button_arrow.setIcon(self.mainwindow.icon_arrow_left)
        else:
            self.tabGBActor.show()
            self.button_del_graph.show()
            self.dateplot.show()
            self.customize.show()
            button_arrow.setIcon(self.mainwindow.icon_arrow_right)

    def ButtonDelete(self):
        button = QPushButton('Remove Graph')
        button.clicked.connect(partial(self.removeGraph, self.layout))
        return button

    def ButtonArrow(self):

        button_arrow = QPushButton()
        button_arrow.setIcon(self.mainwindow.icon_arrow_right)
        button_arrow.clicked.connect(partial(self.showhideConfig, button_arrow))
        button_arrow.setStyleSheet('border: 0px')

        return button_arrow

    def removeGraph(self, layout):
        self.clearLayout(layout)
        self.tab.removeGraph(self)

    def clearLayout(self, layout):

        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()
                else:
                    self.clearLayout(item.layout())

    def table2label(self, tablename, mergeAIT=False):
        for key, label in self.mainwindow.cuArms.items():
            if key in tablename:
                return label
        if mergeAIT:
            return 'AIT'
        else:
            return tablename.split('__')[0].upper()

    def sortCfg(self, config):
        sortedDict = {}
        for dev in config:
            label = self.table2label(tablename=dev.tablename, mergeAIT=False)
            try:
                sortedDict[label].append(dev)
            except KeyError:
                sortedDict[label] = [dev]
        return sortedDict
コード例 #5
0
class App(QMainWindow):
    resized = pyqtSignal()
    def __init__(self, width=1080, height=720):
        super().__init__()
        self.connectionStatus = False
        self.width = width
        self.height = height
        self.initUI()
        # self.initSignalsSlots()
        self.qsObj = None
        self.deviceName = ""
        self.serialPort = None
        self.currentTabMode = -1
        self.sched = None

    def initUI(self):
        self.title = 'AutonomousFlight Configurator v1.0'
        self.left = 0
        self.top = 0
        # self.width = 1080
        # self.height = 720
        self.toolbarheight = 65
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.centerWindow()
        self.bundle_dir = os.path.dirname(os.path.abspath(__file__))
        self.initWidgets()
        self.setFocus()

    def centerWindow(self):
        frameGeo = self.frameGeometry()
        screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
        centerPoint = QApplication.desktop().screenGeometry(screen).center()
        frameGeo.moveCenter(centerPoint)
        self.move(frameGeo.topLeft())

    def initWidgets(self):
        # HeaderBar
        self.initHeaderWidget = InitHeaderWidget(self)
        self.initHeaderWidget.setGeometry(0, 0, self.width, 100)
        self.initHeaderWidget.show()
        self.initHeaderWidget.connectionStatusChangedSignal.connect(self.processInitConnection)
        # Init CoverPage
        self.coverPageWidget = CoverPageWidget(self)
        self.coverPageWidget.setGeometry(0, 100, self.width, self.height-100)
        self.coverPageWidget.show()

        # Show
        self.show()

    def initWorkingWidget(self):
        # Init StatusHeaderBar
        self.statusHeaderWidget = StatusHeaderWidget(self, self.qsObj)
        self.statusHeaderWidget.setGeometry(0, 0, self.width, 100)
        self.statusHeaderWidget.connectionStatusChangedSignal.connect(self.processStatusConnection)
        # self.statusHeaderWidget.hide()
        # Init InfoTabs
        self.infoTabsWidget = QTabWidget(self)
        self.infoTabsWidget.setGeometry(0, 100, self.width, self.height-130)
        # Vertical: 2
        self.infoTabsWidget.setTabPosition(2)

        self.tabNameList = ["CLI", "Overview", "Calibration", "Configure",
                            "ParameterSetting", "Mode", "Sensor", "Motor",
                            "Topology", "Blackbox", "SerialTerminal"]

        self.tabObjectDict = {"CLI":CLIWidget(self),
                              "Overview":OverviewInfoWidget(self, self.qsObj),
                              "Calibration":CalibrationWidget(self, self.qsObj),
                              "Configure":ConfigureWidget(self, self.qsObj),
                              "ParameterSetting":ParameterSettingWidget(self, self.qsObj),
                              "Mode":FlightModeWidget(self, self.qsObj),
                              "Sensor":SensorWidget(self, self.qsObj),
                              "Motor":MotorInfoWidget(self, self.qsObj),
                              "Topology":TopologyWidget(self, self.qsObj),
                              "Blackbox":BlackboxWidget(self),
                              "SerialTerminal":SerialTerminalWidget(self)}

        for key,value in self.tabObjectDict.items():
            self.infoTabsWidget.addTab(value, key)
        # self.infoTabsWidget.hide()
        self.infoTabsWidget.currentChanged.connect(self.setTabMode)
        # Init StatusBar
        self.statusBar = QStatusBar()
        # "Packet error:","I2C error:","Cycle Time:",
        # "CPU Load:","MSP Version:", "MSP Load:",
        # "MSP Roundtrip:","HW roundtrip:","Drop ratio:"
        self.statusBarTopicList = ["Cycle Time:", "I2C error:", "CPU Load:", "MSP Version:"]
        self.packetInfoLabel = QLabel(" | ".join(self.statusBarTopicList))
        self.statusBar.addWidget(self.packetInfoLabel)
        self.setStatusBar(self.statusBar)
        # self.statusBar.hide()

    def initSignalsSlots(self):
        pass

    def processInitConnection(self):
        result = False
        try:
            # Start serial port
            self.startSerialPort()
            self.qsObj = QuadStates()
            self.mspHandle = MSPv1(self.serialPort, self.qsObj)
            result = self.mspHandle.preCheck()
            # Respond to reboot command from MSPv1
            self.mspHandle.rebootSignal.connect(self.reboot)
        except:
            print("Fail to open serial port.")
        if result:
            self.connectionStatus = True
            self.debug()
            self.initWorkingWidget()

            # Send command to MSP class
            self.statusHeaderWidget.statusDataRequestSignal.connect(self.mspHandle.processHeaderDataRequest)
            self.tabObjectDict["CLI"].cliSignal.connect(self.mspHandle.cliCommandSwitch)
            self.tabObjectDict["Overview"].overviewInfoSignal.connect(self.mspHandle.overviewInfoResponse)
            self.tabObjectDict["Mode"].flightmodeSaveSignal.connect(self.mspHandle.processModeRangesSave)
            self.tabObjectDict["Configure"].configureSaveSignal.connect(self.mspHandle.processConfigureSave)
            self.tabObjectDict["ParameterSetting"].parameterSaveSignal.connect(self.mspHandle.processParameterSettingSave)
            self.tabObjectDict["Calibration"].accCalibrateSignal.connect(self.mspHandle.processAccCalibrationRequest)
            self.tabObjectDict["Calibration"].magCalibrateSignal.connect(self.mspHandle.processMagCalibrationRequest)
            self.tabObjectDict["Calibration"].calibrationSaveSignal.connect(self.mspHandle.processCalibrationSave)
            self.tabObjectDict["Sensor"].sensorDataRequestSignal.connect(self.mspHandle.processSensorDataRequest)
            self.tabObjectDict["Motor"].motorDataRequestSignal.connect(self.mspHandle.processMotorDataRequest)
            self.tabObjectDict["Mode"].modeRCDataRequestSignal.connect(self.mspHandle.processModeRCDataRequest)
            self.tabObjectDict["Topology"].topologySaveSignal.connect(self.mspHandle.processTopologySave)
            self.tabObjectDict["SerialTerminal"].serTerSignal.connect(self.mspHandle.processSerialTerminalRequest)

            # MSP data changed will raise this signal to update labels in UI page
            self.mspHandle.headerDataUpdateSignal.connect(self.headerPageUpdate)
            self.mspHandle.cliFeedbackSignal.connect(self.tabObjectDict["CLI"].processFeedback)
            self.mspHandle.calibrationFeedbackSignal.connect(self.tabObjectDict["Calibration"].processFeedback)
            self.mspHandle.overviewDataUpdateSignal.connect(self.overviewPageUpdate)
            self.mspHandle.sensorDataUpdateSignal.connect(self.sensorPageUpdate)
            self.mspHandle.motorDataUpdateSignal.connect(self.motorPageUpdate)
            self.mspHandle.modeRCDataUpdateSignal.connect(self.flightmodePageRCUpdate)
            self.mspHandle.serTerFeedbackSignal.connect(self.tabObjectDict["SerialTerminal"].processFeedback)

            # Change UI
            self.initHeaderWidget.hide()
            self.coverPageWidget.hide()
            self.statusHeaderWidget.show()
            self.infoTabsWidget.show()
            self.infoTabsWidget.setCurrentIndex(0)
            self.setTabMode(0)
            self.statusBar.show()

            # Start StatusHeader Timer
            self.statusHeaderWidget.start()

    def processStatusConnection(self):
        self.connectionStatus = False
        #
        # self.checkSchedulerShutdown()
        self.setTabMode(0)
        self.statusHeaderWidget.stop()
        # End serial port
        self.closeSerialPort()
        self.qsObj = None
        # Change UI
        self.statusHeaderWidget.hide()
        self.infoTabsWidget.hide()
        self.statusBar.hide()
        self.initHeaderWidget.show()
        self.coverPageWidget.show()

    def keyPressEvent(self, event):
        if self.currentTabMode == 0:
            self.tabObjectDict["CLI"].keyPressed(event)

    def debug(self):
        print("---Debug---")
        # print(self.qsObj.msp_activeboxes)
        # print(self.qsObj.msp_boxids)
        # print(len(self.qsObj.msp_boxids))
        # print(self.qsObj.msp_boxnames)
        # print(len(self.qsObj.msp_boxnames))
        # print(self.qsObj.msp_mode_ranges)
        # print(len(self.qsObj.msp_mode_ranges))
        print("---Debug---")
        pass

    # Process reboot
    def reboot(self):
        # Step 1: Close current connection
        self.processStatusConnection()
        # Step 2: Wait for 0.3 seconds
        self.waitTimer = QTimer()
        self.waitTimer.setInterval(300)
        self.waitTimer.setSingleShot(True)

        # Step 3: Reconnect
        self.waitTimer.timeout.connect(self.processInitConnection)
        self.waitTimer.start(300)

    # Page index
    # Change corresponding index if the tabObjectDict is changed.
    def setTabMode(self, index):
        if self.currentTabMode != index:
            if index == self.tabNameList.index("CLI"):
                # Stop header widget update
                self.statusHeaderWidget.stop()
            elif self.currentTabMode == self.tabNameList.index("CLI"):
                # Resume header widget update
                self.statusHeaderWidget.start()
            if index == self.tabNameList.index("Overview"):
                # Overview Page
                self.tabObjectDict["Overview"].start()
            elif self.currentTabMode == self.tabNameList.index("Overview"):
                self.tabObjectDict["Overview"].stop()
            if index == self.tabNameList.index("Calibration"):
                # Calibration
                self.calibrationPageUpdate()
            # Mode
            if index == self.tabNameList.index("Mode"):
                self.flightmodePageUpdate()
                self.tabObjectDict["Mode"].start()
            elif self.currentTabMode == self.tabNameList.index("Mode"):
                self.tabObjectDict["Mode"].stop()
            # Configure
            if index == self.tabNameList.index("Configure"):
                # Configure
                self.configurePageUpdate()
            if index == self.tabNameList.index("ParameterSetting"):
                # Parameter Setting
                self.parameterSettingPageUpdate()
            if index == self.tabNameList.index("Sensor"):
                # Sensor
                self.tabObjectDict["Sensor"].start()
            elif self.currentTabMode == self.tabNameList.index("Sensor"):
                self.tabObjectDict["Sensor"].stop()
            if index == self.tabNameList.index("Motor"):
                # Motor
                self.tabObjectDict["Motor"].start()
            elif self.currentTabMode == self.tabNameList.index("Motor"):
                self.tabObjectDict["Motor"].stop()
            # Topology
            if index == self.tabNameList.index("Topology"):
                # Topology
                self.topologyPageUpdate()
            if index == self.tabNameList.index("Blackbox"):
                # Blackbox
                pass
            if index == self.tabNameList.index("SerialTerminal"):
                # Serial Terminal
                # Stop header widget update
                self.statusHeaderWidget.stop()
                self.tabObjectDict["SerialTerminal"].start()
            elif self.currentTabMode == self.tabNameList.index("SerialTerminal"):
                self.tabObjectDict["SerialTerminal"].stop()
                # Resume header widget update
                self.statusHeaderWidget.start()

            self.currentTabMode = index

    def startSerialPort(self):
        self.deviceName = self.initHeaderWidget.connectionMethodComboBox.currentText()
        self.serialPort = SerialCommunication(self.deviceName)

    def closeSerialPort(self):
        self.serialPort.stopDevice()
        self.serialPort = None

    def headerPageUpdate(self, ind):
        if ind == 0:
            self.statusHeaderWidget.updateMMSV()
        elif ind == 1:
            self.statusHeaderWidget.updateSensorStatus()

    def overviewPageUpdate(self, ind):
        if ind == 0:
            self.tabObjectDict["Overview"].updateAttitudeLabels()
        elif ind == 1:
            self.tabObjectDict["Overview"].updateArmingFlagLabels()
        elif ind == 2:
            self.tabObjectDict["Overview"].updateBatteryLabels()
        elif ind == 3:
            self.tabObjectDict["Overview"].updateCommunicationLabels()
        elif ind == 4:
            self.tabObjectDict["Overview"].updateGPSLabels()
        # # Update header sensor lights.
        # self.statusHeaderWidget.update(self.qsObj.msp_sensor_status)
        # Update status bar
        self.statusBarUpdate()

    def statusBarUpdate(self):
        self.statusBarTopicList = ["Cycle Time:", "I2C Error:", "CPU Load:", "MSP Version:"]
        self.statusBarValueDict = {}
        for field in self.statusBarTopicList:
            data = None
            if field == "Cycle Time:":
                data = self.qsObj.msp_status_ex['cycleTime']
            elif field == "I2C Error:":
                data = self.qsObj.msp_status_ex['i2cError']
            elif field == "CPU Load:":
                data = self.qsObj.msp_status_ex['averageSystemLoadPercent']
            elif field == "MSP Version:":
                data = "1"
            else:
                pass
            self.statusBarValueDict[field] = str(data)
        labelString = "| "
        for key,value in self.statusBarValueDict.items():
            labelString = labelString + key + value + " | "
        self.packetInfoLabel.setText(labelString)


    def sensorPageUpdate(self, ind):
        if ind == 0:
            self.tabObjectDict["Sensor"].updateACCPlot()
            self.tabObjectDict["Sensor"].updateGYROPlot()
            self.tabObjectDict["Sensor"].updateMAGPlot()
        elif ind == 1:
            self.tabObjectDict["Sensor"].updateBAROPlot()
        elif ind == 2:
            self.tabObjectDict["Sensor"].updateRangeFinderPlot()

    def motorPageUpdate(self, ind):
        if ind == 0:
            self.tabObjectDict["Motor"].updateMotorValues()

    def flightmodePageRCUpdate(self, ind):
        if ind == 0:
            self.tabObjectDict["Mode"].updateCurrentValueLabels()

    def flightmodePageUpdate(self):
        self.tabObjectDict["Mode"].setRanges()

    def parameterSettingPageUpdate(self):
        self.mspHandle.processParameterSettingCheck()
        self.tabObjectDict['ParameterSetting'].setValues()

    def configurePageUpdate(self):
        self.mspHandle.processConfigureCheck()
        self.tabObjectDict['Configure'].setValues()

    def calibrationPageUpdate(self):
        self.mspHandle.processCalibrationCheck()
        self.tabObjectDict['Calibration'].setValues()

    def topologyPageUpdate(self):
        self.mspHandle.processTopologyCheck()
        self.tabObjectDict['Topology'].setValues()
コード例 #6
0
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.setWindowTitle("TFM - Inversión Bolsa")

        self.file = ""
        self.area = QPlainTextEdit()
        self.lineaFichero = QLineEdit()
        self.validacion = ""

        layout = QGridLayout()
        self.createlayoutMain(layout)

        self.window = QWidget()
        self.window.setLayout(layout)
        self.window.show()
        self.window.setFixedSize(self.window.size())

    def createlayoutMain(self, layout):

        #Icono
        label = QLabel("Ayuda Broker")
        label.setFont(QFont("Helvetica", 30))
        layout.addWidget(label, 0, 5)

        #Dialogo Carga Fichero
        lineaFichero = QLineEdit()
        lineaFichero.setReadOnly(True)
        self.lineaFichero = lineaFichero

        botonFile = QPushButton("Cargar Fichero")
        botonFile.clicked.connect(self.filedialog)

        layout.addWidget(lineaFichero, 1, 0, 1, 12)
        layout.addWidget(botonFile, 1, 12)

        #Boton ejecutar algoritmo
        botonMain = QPushButton("Ejecutar Algoritmo")
        botonMain.clicked.connect(self.ejecuta_algoritmo)
        layout.addWidget(botonMain, 2, 0)

        #Cuadro de logs oculto por defecto
        logarea = QPlainTextEdit()
        logarea.setReadOnly(True)
        logarea.setVisible(False)
        self.area = logarea
        layout.addWidget(logarea, 3, 0, 3, 18)

        #Tabs
        self.tabs = QTabWidget()
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        self.tab3 = QWidget()

        self.tabs.addTab(self.tab1, "Gráfica Red Neuronal Entrenada")
        self.tabs.addTab(self.tab2, "Datos útiles")
        self.tabs.addTab(self.tab3, "Predecir otro valor")

        #Tab Gráfica
        self.tab1.layout = QVBoxLayout()
        self.labelGraph = QLabel(self)
        self.tab1.layout.addWidget(self.labelGraph)
        self.tab1.setLayout(self.tab1.layout)

        #Tab Datos Útiles
        self.tab2.layout = QGridLayout()
        self.tab2.setLayout(self.tab2.layout)

        self.font = QFont("Helvetica", 15)
        self.font.setBold(True)

        self.lTendenciaActual = QLabel("Tendencia Actual:")
        self.lTendenciaActual.setFont(self.font)
        self.tab2.layout.addWidget(self.lTendenciaActual, 1, 1)

        self.lAscendente = QLabel("Ascendente:")
        self.lAscendente.setFont(self.font)

        self.lDescendente = QLabel("Descendente:")
        self.lDescendente.setFont(self.font)

        self.lMayorNumDiasSubiendo = QLabel("Mayor nº de días subiendo:")
        self.lMayorNumDiasSubiendo.setFont(self.font)
        self.tab2.layout.addWidget(self.lMayorNumDiasSubiendo, 5, 1)

        self.lMayorNumDiasBajando = QLabel("Mayor nº de días bajando:")
        self.lMayorNumDiasBajando.setFont(self.font)
        self.tab2.layout.addWidget(self.lMayorNumDiasBajando, 7, 1)

        self.lPrecioMinimo = QLabel("Precio Mínimo:")
        self.lPrecioMinimo.setFont(self.font)
        self.tab2.layout.addWidget(self.lPrecioMinimo, 9, 1)

        self.lPrecioMaximo = QLabel("Precio Máximo:")
        self.lPrecioMaximo.setFont(self.font)
        self.tab2.layout.addWidget(self.lPrecioMaximo, 11, 1)

        fontvalor = QFont("Helvetica", 15)

        self.lTendenciaActual = QLabel("")
        self.lTendenciaActual.setFont(fontvalor)
        self.tab2.layout.addWidget(self.lTendenciaActual, 1, 2)

        self.lAscendenteDescendente = QLabel("")
        self.lAscendenteDescendente.setFont(fontvalor)
        self.tab2.layout.addWidget(self.lAscendenteDescendente, 3, 2)

        self.lMayorNumDiasBajando = QLabel("")
        self.lMayorNumDiasBajando.setFont(fontvalor)
        self.tab2.layout.addWidget(self.lMayorNumDiasBajando, 5, 2)

        self.lMayorNumDiasSubiendo = QLabel("")
        self.lMayorNumDiasSubiendo.setFont(fontvalor)
        self.tab2.layout.addWidget(self.lMayorNumDiasSubiendo, 7, 2)

        self.lPrecioMinimo = QLabel("")
        self.lPrecioMinimo.setFont(fontvalor)
        self.tab2.layout.addWidget(self.lPrecioMinimo, 9, 2)

        self.lPrecioMaximo = QLabel("")
        self.lPrecioMaximo.setFont(fontvalor)
        self.tab2.layout.addWidget(self.lPrecioMaximo, 11, 2)

        self.lprediccion = QLabel("")
        self.tab2.layout.addWidget(self.lprediccion, 13, 1, 1, 2)

        self.tab2.layout.setRowStretch(0, 1)
        self.tab2.layout.setRowStretch(2, 1)
        self.tab2.layout.setRowStretch(4, 1)
        self.tab2.layout.setRowStretch(6, 1)
        self.tab2.layout.setRowStretch(8, 1)
        self.tab2.layout.setRowStretch(10, 1)
        self.tab2.layout.setRowStretch(12, 1)

        self.tab2.layout.setColumnStretch(0, 1)
        self.tab2.layout.setColumnStretch(3, 1)

        #Tab otro valor
        self.tab3.layout = QGridLayout()
        self.tab3.setLayout(self.tab3.layout)

        self.precio1 = QLineEdit()
        self.precio2 = QLineEdit()
        self.precio3 = QLineEdit()
        self.precio4 = QLineEdit()
        self.precio5 = QLineEdit()
        self.precio6 = QLineEdit()
        self.precio7 = QLineEdit()
        self.precio8 = QLineEdit()

        self.lprecio1 = QLabel("Día 1: ")
        fontN = self.lprecio1.font()
        fontN.setBold(True)
        self.lprecio1.setFont(fontN)
        self.tab3.layout.addWidget(self.lprecio1, 3, 1)

        self.lprecio2 = QLabel("Día 2: ")
        self.lprecio2.setFont(fontN)
        self.tab3.layout.addWidget(self.lprecio2, 3, 3)

        self.lprecio3 = QLabel("Día 3: ")
        self.lprecio3.setFont(fontN)
        self.tab3.layout.addWidget(self.lprecio3, 4, 1)

        self.lprecio4 = QLabel("Día 4: ")
        self.lprecio4.setFont(fontN)
        self.tab3.layout.addWidget(self.lprecio4, 4, 3)

        self.lprecio5 = QLabel("Día 5: ")
        self.lprecio5.setFont(fontN)
        self.tab3.layout.addWidget(self.lprecio5, 5, 1)

        self.lprecio6 = QLabel("Día 6: ")
        self.lprecio6.setFont(fontN)
        self.tab3.layout.addWidget(self.lprecio6, 5, 3)

        self.lprecio7 = QLabel("Día 7: ")
        self.lprecio7.setFont(fontN)
        self.tab3.layout.addWidget(self.lprecio7, 6, 1)

        self.lprecio8 = QLabel("Día 8: ")
        self.lprecio8.setFont(fontN)
        self.tab3.layout.addWidget(self.lprecio8, 6, 3)

        self.tab3.layout.setRowStretch(0, 1)
        self.tab3.layout.setRowStretch(1, 1)
        self.tab3.layout.setRowStretch(7, 1)
        self.tab3.layout.setRowStretch(9, 1)
        self.tab3.layout.setRowStretch(11, 1)
        self.tab3.layout.setColumnStretch(0, 1)
        self.tab3.layout.setColumnStretch(5, 1)

        self.ltituloTab3 = QLabel(
            "Para predecir otro precio, es necesario indicar los precios de los 8 días anteriores"
        )
        self.tab3.layout.addWidget(self.ltituloTab3, 1, 1, 1, 4)

        self.tab3.layout.addWidget(self.precio1, 3, 2)
        self.tab3.layout.addWidget(self.precio2, 3, 4)

        self.tab3.layout.addWidget(self.precio3, 4, 2)
        self.tab3.layout.addWidget(self.precio4, 4, 4)

        self.tab3.layout.addWidget(self.precio5, 5, 2)
        self.tab3.layout.addWidget(self.precio6, 5, 4)

        self.tab3.layout.addWidget(self.precio7, 6, 2)
        self.tab3.layout.addWidget(self.precio8, 6, 4)

        self.botonNuevoValor = QPushButton("Predecir Precio")
        self.botonNuevoValor.clicked.connect(self.predecirNuevoValor)
        self.tab3.layout.addWidget(self.botonNuevoValor, 8, 3)

        self.lnuevoPrecioTab3 = QLabel("")
        self.tab3.layout.addWidget(self.lnuevoPrecioTab3, 10, 1, 1, 4)

        layout.addWidget(self.tabs, 6, 0, 2, 18)
        self.tabs.setVisible(False)

    def predecirNuevoValor(self):
        if not ((self.precio1.text().strip() == "") or
                (self.precio2.text().strip() == "") or
                (self.precio3.text().strip() == "") or
                (self.precio4.text().strip() == "") or
                (self.precio5.text().strip() == "") or
                (self.precio6.text().strip() == "") or
                (self.precio7.text().strip() == "") or
                (self.precio8.text().strip() == "")):
            prediccion = np.asarray([
                self.precio1.text().strip(),
                self.precio2.text().strip(),
                self.precio3.text().strip(),
                self.precio4.text().strip(),
                self.precio5.text().strip(),
                self.precio6.text().strip(),
                self.precio7.text().strip(),
                self.precio8.text().strip()
            ])
            entradaPrediccion = []
            entradaPrediccion.append(prediccion)
            try:
                res = self.modelo.predict([entradaPrediccion])
                self.lnuevoPrecioTab3.setText("El próximo precio es: " +
                                              str(res[0][0]))
            except Exception as p:
                self.area.insertPlainText(
                    "Algo fue mal durante la ejecución del algoritmo, revisa los datos de entrada...\n"
                )
                self.area.repaint()
                print(str(p))
        else:
            self.area.insertPlainText(
                "Todos los campos deben estar rellenos...\n")
            self.area.repaint()

    def filedialog(self):
        # Cargar Archivo
        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Single File', QtCore.QDir.rootPath(), '*.csv')
        if fileName:
            self.file = fileName
            self.lineaFichero.setText(self.file)
            self.lineaFichero.repaint()

    def initAlgoritmo(self):
        self.area.setPlainText("")
        self.area.repaint()
        self.tabs.hide()
        plt.cla()

        if os.path.exists("grafico.jpg"):
            os.remove("grafico.jpg")

    def ejecuta_algoritmo(self):

        self.area.show()

        #Limpiamos las areas de logs, gráfica y datos
        self.initAlgoritmo()

        if Utils.rutaFicheroValido(self):

            try:
                # Leemos el CSV completo que contiene los datos
                self.datos_csv = pd.read_csv(self.file,
                                             delimiter=",",
                                             index_col=0,
                                             parse_dates=["date"])

                if Utils.validaExcel(self, self.datos_csv):
                    self.area.insertPlainText(
                        "El Formato del excel es correcto...\n")
                    self.area.repaint()
                    # Creamos la Red Neuronal

                    # Tomamos todos los datos y los dividimos en un 80% para entrenat y 20% para validar
                    # year2017 = datos_csv.close['2017-01-01':'2017-12-31']
                    year = self.datos_csv.precio

                    # count2017 = len(datos_csv.close['2017-01-01':'2017-12-31'])
                    count = len(self.datos_csv.precio)

                    numEntradas = 8
                    numDatosEntrenamiento = round(count * 0.8)
                    numDatosValidacion = round(count * 0.2)

                    self.area.insertPlainText(
                        "El número total de datos son: " + str(count) + "\n")
                    self.area.insertPlainText(
                        "Los datos de entrenamiento son: " +
                        str(numDatosEntrenamiento) + "\n")
                    self.area.insertPlainText("Los datos de validacion son: " +
                                              str(numDatosValidacion) + "\n")
                    self.area.repaint()

                    dfEntrenamiento = year[:numDatosEntrenamiento]
                    dfValidacion = year[numDatosEntrenamiento:]

                    print(
                        " Entrenamiento: Elementos sobrantes del array será: "
                        + str(numDatosEntrenamiento % numEntradas) +
                        " y se usaran " +
                        str(round(numDatosEntrenamiento / numEntradas)))
                    print(" Validacion: Elementos sobrantes del array será: " +
                          str(numDatosValidacion % numEntradas) +
                          " y se usaran " +
                          str(round(numDatosValidacion / numEntradas)))
                    listaEntrenamiento = Utils.listaTransformada(
                        numEntradas, numDatosEntrenamiento, dfEntrenamiento)
                    listaValidacion = Utils.listaTransformada(
                        numEntradas, numDatosValidacion, dfValidacion)

                    print(str(listaEntrenamiento[0][:2]))
                    print(str(listaEntrenamiento[1][:2]))

                    try:
                        self.modelo = Utils.modeloRedNeuronal(numEntradas)
                        self.historic = self.modelo.fit(
                            listaEntrenamiento[0],
                            listaEntrenamiento[1],
                            epochs=40,
                            validation_data=(listaValidacion[0],
                                             listaValidacion[1]),
                            batch_size=numEntradas)
                        self.area.insertPlainText(
                            "FIN: La red neuronal ha sido entrenada\n")
                        self.area.repaint()

                        # Generamos la gráfica y rellenamos la tab 1
                        results = self.modelo.predict(listaValidacion[0])
                        if len(results) > 100:
                            plt.scatter(range(len(listaValidacion[1][:100])),
                                        (listaValidacion[1])[:100],
                                        c='g')
                            plt.scatter(range(len(results[:100])),
                                        results[:100],
                                        c='r')
                        else:
                            plt.scatter(range(len(listaValidacion[1])),
                                        listaValidacion[1],
                                        c='g')
                            plt.scatter(range(len(results)), results, c='r')

                        plt.xlabel("Punto Evaluado")
                        plt.ylabel("Precio")
                        plt.title('Red Neuronal entrenada vs realidad')

                        score = self.modelo.evaluate(listaEntrenamiento[0],
                                                     listaEntrenamiento[1],
                                                     batch_size=128)
                        print(str(self.modelo.metrics_names))
                        print("La efectividad ha sido del: " + str(score))

                        red_patch = mpatches.Patch(color='red',
                                                   label='Precios predichos')
                        green_patch = mpatches.Patch(color='green',
                                                     label='Precios reales')
                        plt.legend(handles=[red_patch, green_patch])
                        plt.savefig('grafico.jpg')
                        pixmap = QPixmap('grafico.jpg')
                        self.labelGraph.setPixmap(pixmap)
                        self.tabs.setVisible(True)

                        # Generamos los datos útiles y rellenamos la tab 2
                        Utils.dataExcel(self, self.datos_csv)

                        fontvalor = QFont("Helvetica", 15)

                        self.lTendenciaActual.setText(str(
                            self.tendenciaActual))
                        self.lMayorNumDiasBajando.setText(
                            str(self.mayorTendenciaDescentente))
                        self.lMayorNumDiasSubiendo.setText(
                            str(self.mayorTendenciaAscendente))
                        self.lPrecioMinimo.setText(str(self.precioMinimo))
                        self.lPrecioMaximo.setText(str(self.precioMaximo))

                        if self.tendenciaActual == "Ascendente":

                            self.tab2.layout.addWidget(self.lAscendente, 3, 1)
                            self.lAscendenteDescendente.setText(
                                str(self.tendenciaAscendente))

                        else:

                            self.tab2.layout.addWidget(self.lDescendente, 3, 1)
                            self.lAscendenteDescendente.setText(
                                str(self.tendenciaDescentente))

                        prediccionArray = np.asarray(
                            self.datos_csv.tail(8).precio.values.tolist())
                        entradaPrediccion = []
                        entradaPrediccion.append(prediccionArray)

                        res = self.modelo.predict([entradaPrediccion])
                        self.lprediccion.setText(
                            "La red Neuronal predice que el próximo precio será: "
                            + str(res[0][0]))
                    except Exception as e:
                        self.area.insertPlainText(
                            "Hubo algun error durante la ejecución del algritmo\n"
                        )
                        self.area.repaint()
                        print(str(e))
                else:
                    self.area.insertPlainText(self.validacion)
                    self.area.repaint()

            except Exception as b:
                self.area.insertPlainText(
                    "Algo fue mal durante la lectura del CSV, revisa que sea correcto\n"
                )
                self.area.repaint()
                print(str(b))

        else:
            self.area.insertPlainText(self.validacion)
            self.area.repaint()
コード例 #7
0
class ManifestWidget(TritonWidget):
    def __init__(self, base, drive):
        TritonWidget.__init__(self, base)
        self.drive = drive

        self.setWindowTitle('NextcloudRestore')
        self.setBackgroundColor(self, Qt.white)

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

        self.menuBar = QMenuBar()
        fileMenu = self.menuBar.addMenu('File')

        self.label = QLabel('Searching for manifests...')
        self.label.setAlignment(Qt.AlignCenter)
        self.label.setFont(QFont('Sans Serif', 20))

        self.tabs = QTabWidget()
        self.tabs.setMinimumSize(300, 300)
        self.tabs.setMaximumSize(300, 300)
        self.tabs.hide()

        self.layout.setAlignment(Qt.AlignCenter)
        self.layout.addWidget(self.menuBar)
        self.layout.addWidget(self.label)
        self.layout.addWidget(self.tabs)
        self.setLayout(self.layout)
        self.resizeAndCenter()
        self.show()

        self.retriever = ManifestRetriever(self.drive)
        self.retriever.signal.connect(self.gotManifests)
        self.retriever.start()

        self.downloader = None

    def gotManifests(self, manifests):
        self.label.setText('Choose the manifest to recover:')

        for folder in sorted(manifests.keys()):
            files = manifests[folder]
            tab = ManifestTab(self, folder, files)

            self.tabs.addTab(tab, folder)

        self.tabs.show()
        self.resizeAndCenter()

    def downloadManifest(self, name, manifest):
        destination = self.base.tmp.getFile(name)

        if os.path.exists(destination):
            self.downloadedManifest(name, manifest, destination)
            return

        self.label.setText('Downloading manifest...')
        self.tabs.setEnabled(False)

        self.downloader = ManifestDownloader(name, manifest, destination)
        self.downloader.signal.connect(self.downloadedManifest)
        self.downloader.start()

    def downloadedManifest(self, name, manifest, destination):
        self.label.setText('Manifest downloaded.')
        self.tabs.setEnabled(True)
コード例 #8
0
	def hide ( self ):
		QTabWidget.hide ( self )
コード例 #9
0
ファイル: main_window.py プロジェクト: jkutianski/vial-gui
class MainWindow(QMainWindow):
    def __init__(self, appctx):
        super().__init__()
        self.appctx = appctx

        self.settings = QSettings("Vial", "Vial")
        if self.settings.value("size", None) and self.settings.value(
                "pos", None):
            self.resize(self.settings.value("size"))
            self.move(self.settings.value("pos"))
        else:
            self.resize(WINDOW_WIDTH, WINDOW_HEIGHT)
        themes.set_theme(self.get_theme())

        self.combobox_devices = QComboBox()
        self.combobox_devices.currentIndexChanged.connect(
            self.on_device_selected)

        self.btn_refresh_devices = QToolButton()
        self.btn_refresh_devices.setToolButtonStyle(Qt.ToolButtonTextOnly)
        self.btn_refresh_devices.setText(tr("MainWindow", "Refresh"))
        self.btn_refresh_devices.clicked.connect(self.on_click_refresh)

        layout_combobox = QHBoxLayout()
        layout_combobox.addWidget(self.combobox_devices)
        layout_combobox.addWidget(self.btn_refresh_devices)

        self.layout_editor = LayoutEditor()
        self.keymap_editor = KeymapEditor(self.layout_editor)
        self.firmware_flasher = FirmwareFlasher(self)
        self.macro_recorder = MacroRecorder()
        self.tap_dance = TapDance()
        self.combos = Combos()
        QmkSettings.initialize(appctx)
        self.qmk_settings = QmkSettings()
        self.matrix_tester = MatrixTest(self.layout_editor)
        self.rgb_configurator = RGBConfigurator()

        self.editors = [(self.keymap_editor, "Keymap"),
                        (self.layout_editor, "Layout"),
                        (self.macro_recorder, "Macros"),
                        (self.rgb_configurator, "Lighting"),
                        (self.tap_dance, "Tap Dance"), (self.combos, "Combos"),
                        (self.qmk_settings, "QMK Settings"),
                        (self.matrix_tester, "Matrix tester"),
                        (self.firmware_flasher, "Firmware updater")]

        Unlocker.global_layout_editor = self.layout_editor

        self.current_tab = None
        self.tabs = QTabWidget()
        self.tabs.currentChanged.connect(self.on_tab_changed)
        self.refresh_tabs()

        no_devices = 'No devices detected. Connect a Vial-compatible device and press "Refresh"<br>' \
                     'or select "File" → "Download VIA definitions" in order to enable support for VIA keyboards.'
        if sys.platform.startswith("linux"):
            no_devices += '<br><br>On Linux you need to set up a custom udev rule for keyboards to be detected. ' \
                          'Follow the instructions linked below:<br>' \
                          '<a href="https://get.vial.today/manual/linux-udev.html">https://get.vial.today/manual/linux-udev.html</a>'
        self.lbl_no_devices = QLabel(tr("MainWindow", no_devices))
        self.lbl_no_devices.setTextFormat(Qt.RichText)
        self.lbl_no_devices.setAlignment(Qt.AlignCenter)

        layout = QVBoxLayout()
        layout.addLayout(layout_combobox)
        layout.addWidget(self.tabs)
        layout.addWidget(self.lbl_no_devices)
        layout.setAlignment(self.lbl_no_devices, Qt.AlignHCenter)
        self.tray_keycodes = TabbedKeycodes()
        self.tray_keycodes.make_tray()
        layout.addWidget(self.tray_keycodes)
        self.tray_keycodes.hide()
        w = QWidget()
        w.setLayout(layout)
        self.setCentralWidget(w)

        self.init_menu()

        self.autorefresh = Autorefresh()
        self.autorefresh.devices_updated.connect(self.on_devices_updated)

        # cache for via definition files
        self.cache_path = QStandardPaths.writableLocation(
            QStandardPaths.CacheLocation)
        if not os.path.exists(self.cache_path):
            os.makedirs(self.cache_path)

        # check if the via defitions already exist
        if os.path.isfile(os.path.join(self.cache_path, "via_keyboards.json")):
            with open(os.path.join(self.cache_path,
                                   "via_keyboards.json")) as vf:
                data = vf.read()
            try:
                self.autorefresh.load_via_stack(data)
            except JSONDecodeError as e:
                # the saved file is invalid - just ignore this
                logging.warning(
                    "Failed to parse stored via_keyboards.json: {}".format(e))

        # make sure initial state is valid
        self.on_click_refresh()

    def init_menu(self):
        layout_load_act = QAction(tr("MenuFile", "Load saved layout..."), self)
        layout_load_act.setShortcut("Ctrl+O")
        layout_load_act.triggered.connect(self.on_layout_load)

        layout_save_act = QAction(tr("MenuFile", "Save current layout..."),
                                  self)
        layout_save_act.setShortcut("Ctrl+S")
        layout_save_act.triggered.connect(self.on_layout_save)

        sideload_json_act = QAction(tr("MenuFile", "Sideload VIA JSON..."),
                                    self)
        sideload_json_act.triggered.connect(self.on_sideload_json)

        download_via_stack_act = QAction(
            tr("MenuFile", "Download VIA definitions"), self)
        download_via_stack_act.triggered.connect(self.load_via_stack_json)

        load_dummy_act = QAction(tr("MenuFile", "Load dummy JSON..."), self)
        load_dummy_act.triggered.connect(self.on_load_dummy)

        exit_act = QAction(tr("MenuFile", "Exit"), self)
        exit_act.setShortcut("Ctrl+Q")
        exit_act.triggered.connect(qApp.exit)

        file_menu = self.menuBar().addMenu(tr("Menu", "File"))
        file_menu.addAction(layout_load_act)
        file_menu.addAction(layout_save_act)
        file_menu.addSeparator()
        file_menu.addAction(sideload_json_act)
        file_menu.addAction(download_via_stack_act)
        file_menu.addAction(load_dummy_act)
        file_menu.addSeparator()
        file_menu.addAction(exit_act)

        keyboard_unlock_act = QAction(tr("MenuSecurity", "Unlock"), self)
        keyboard_unlock_act.triggered.connect(self.unlock_keyboard)

        keyboard_lock_act = QAction(tr("MenuSecurity", "Lock"), self)
        keyboard_lock_act.triggered.connect(self.lock_keyboard)

        keyboard_reset_act = QAction(
            tr("MenuSecurity", "Reboot to bootloader"), self)
        keyboard_reset_act.triggered.connect(self.reboot_to_bootloader)

        keyboard_layout_menu = self.menuBar().addMenu(
            tr("Menu", "Keyboard layout"))
        keymap_group = QActionGroup(self)
        selected_keymap = self.settings.value("keymap")
        for idx, keymap in enumerate(KEYMAPS):
            act = QAction(tr("KeyboardLayout", keymap[0]), self)
            act.triggered.connect(
                lambda checked, x=idx: self.change_keyboard_layout(x))
            act.setCheckable(True)
            if selected_keymap == keymap[0]:
                self.change_keyboard_layout(idx)
                act.setChecked(True)
            keymap_group.addAction(act)
            keyboard_layout_menu.addAction(act)
        # check "QWERTY" if nothing else is selected
        if keymap_group.checkedAction() is None:
            keymap_group.actions()[0].setChecked(True)

        self.security_menu = self.menuBar().addMenu(tr("Menu", "Security"))
        self.security_menu.addAction(keyboard_unlock_act)
        self.security_menu.addAction(keyboard_lock_act)
        self.security_menu.addSeparator()
        self.security_menu.addAction(keyboard_reset_act)

        self.theme_menu = self.menuBar().addMenu(tr("Menu", "Theme"))
        theme_group = QActionGroup(self)
        selected_theme = self.get_theme()
        for name, _ in [("System", None)] + themes.themes:
            act = QAction(tr("MenuTheme", name), self)
            act.triggered.connect(lambda x, name=name: self.set_theme(name))
            act.setCheckable(True)
            act.setChecked(selected_theme == name)
            theme_group.addAction(act)
            self.theme_menu.addAction(act)
        # check "System" if nothing else is selected
        if theme_group.checkedAction() is None:
            theme_group.actions()[0].setChecked(True)

        about_vial_act = QAction(tr("MenuAbout", "About Vial..."), self)
        about_vial_act.triggered.connect(self.about_vial)
        self.about_menu = self.menuBar().addMenu(tr("Menu", "About"))
        self.about_menu.addAction(about_vial_act)

    def on_layout_load(self):
        dialog = QFileDialog()
        dialog.setDefaultSuffix("vil")
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setNameFilters(["Vial layout (*.vil)"])
        if dialog.exec_() == QDialog.Accepted:
            with open(dialog.selectedFiles()[0], "rb") as inf:
                data = inf.read()
            self.keymap_editor.restore_layout(data)
            self.rebuild()

    def on_layout_save(self):
        dialog = QFileDialog()
        dialog.setDefaultSuffix("vil")
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        dialog.setNameFilters(["Vial layout (*.vil)"])
        if dialog.exec_() == QDialog.Accepted:
            with open(dialog.selectedFiles()[0], "wb") as outf:
                outf.write(self.keymap_editor.save_layout())

    def on_click_refresh(self):
        # we don't do check_protocol here either because if the matrix test tab is active,
        # that ends up corrupting usb hid packets
        self.autorefresh.update(check_protocol=False)

    def on_devices_updated(self, devices, hard_refresh):
        self.combobox_devices.blockSignals(True)

        self.combobox_devices.clear()
        for dev in devices:
            self.combobox_devices.addItem(dev.title())
            if self.autorefresh.current_device and dev.desc[
                    "path"] == self.autorefresh.current_device.desc["path"]:
                self.combobox_devices.setCurrentIndex(
                    self.combobox_devices.count() - 1)

        self.combobox_devices.blockSignals(False)

        if devices:
            self.lbl_no_devices.hide()
            self.tabs.show()
        else:
            self.lbl_no_devices.show()
            self.tabs.hide()

        if hard_refresh:
            self.on_device_selected()

    def on_device_selected(self):
        try:
            self.autorefresh.select_device(
                self.combobox_devices.currentIndex())
        except ProtocolError:
            QMessageBox.warning(
                self, "", "Unsupported protocol version!\n"
                "Please download latest Vial from https://get.vial.today/")

        if isinstance(self.autorefresh.current_device, VialKeyboard) \
                and self.autorefresh.current_device.keyboard.keyboard_id in EXAMPLE_KEYBOARDS:
            QMessageBox.warning(
                self, "", "An example keyboard UID was detected.\n"
                "Please change your keyboard UID to be unique before you ship!"
            )

        self.rebuild()
        self.refresh_tabs()

    def rebuild(self):
        # don't show "Security" menu for bootloader mode, as the bootloader is inherently insecure
        self.security_menu.menuAction().setVisible(
            isinstance(self.autorefresh.current_device, VialKeyboard))

        # if unlock process was interrupted, we must finish it first
        if isinstance(
                self.autorefresh.current_device, VialKeyboard
        ) and self.autorefresh.current_device.keyboard.get_unlock_in_progress(
        ):
            Unlocker.unlock(self.autorefresh.current_device.keyboard)
            self.autorefresh.current_device.keyboard.reload()

        for e in [
                self.layout_editor, self.keymap_editor, self.firmware_flasher,
                self.macro_recorder, self.tap_dance, self.combos,
                self.qmk_settings, self.matrix_tester, self.rgb_configurator
        ]:
            e.rebuild(self.autorefresh.current_device)

    def refresh_tabs(self):
        self.tabs.clear()
        for container, lbl in self.editors:
            if not container.valid():
                continue

            c = EditorContainer(container)
            self.tabs.addTab(c, tr("MainWindow", lbl))

    def load_via_stack_json(self):
        with urlopen(
                "https://github.com/vial-kb/via-keymap-precompiled/raw/main/via_keyboard_stack.json"
        ) as resp:
            data = resp.read()
        self.autorefresh.load_via_stack(data)
        # write to cache
        with open(os.path.join(self.cache_path, "via_keyboards.json"),
                  "wb") as cf:
            cf.write(data)

    def on_sideload_json(self):
        dialog = QFileDialog()
        dialog.setDefaultSuffix("json")
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setNameFilters(["VIA layout JSON (*.json)"])
        if dialog.exec_() == QDialog.Accepted:
            with open(dialog.selectedFiles()[0], "rb") as inf:
                data = inf.read()
            self.autorefresh.sideload_via_json(data)

    def on_load_dummy(self):
        dialog = QFileDialog()
        dialog.setDefaultSuffix("json")
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setNameFilters(["VIA layout JSON (*.json)"])
        if dialog.exec_() == QDialog.Accepted:
            with open(dialog.selectedFiles()[0], "rb") as inf:
                data = inf.read()
            self.autorefresh.load_dummy(data)

    def lock_ui(self):
        self.autorefresh._lock()
        self.tabs.setEnabled(False)
        self.combobox_devices.setEnabled(False)
        self.btn_refresh_devices.setEnabled(False)

    def unlock_ui(self):
        self.autorefresh._unlock()
        self.tabs.setEnabled(True)
        self.combobox_devices.setEnabled(True)
        self.btn_refresh_devices.setEnabled(True)

    def unlock_keyboard(self):
        if isinstance(self.autorefresh.current_device, VialKeyboard):
            Unlocker.unlock(self.autorefresh.current_device.keyboard)

    def lock_keyboard(self):
        if isinstance(self.autorefresh.current_device, VialKeyboard):
            self.autorefresh.current_device.keyboard.lock()

    def reboot_to_bootloader(self):
        if isinstance(self.autorefresh.current_device, VialKeyboard):
            Unlocker.unlock(self.autorefresh.current_device.keyboard)
            self.autorefresh.current_device.keyboard.reset()

    def change_keyboard_layout(self, index):
        self.settings.setValue("keymap", KEYMAPS[index][0])
        KeycodeDisplay.set_keymap_override(KEYMAPS[index][1])

    def get_theme(self):
        return self.settings.value("theme", "Dark")

    def set_theme(self, theme):
        themes.set_theme(theme)
        self.settings.setValue("theme", theme)
        msg = QMessageBox()
        msg.setText(
            tr(
                "MainWindow",
                "In order to fully apply the theme you should restart the application."
            ))
        msg.exec_()

    def on_tab_changed(self, index):
        TabbedKeycodes.close_tray()
        old_tab = self.current_tab
        new_tab = None
        if index >= 0:
            new_tab = self.tabs.widget(index)

        if old_tab is not None:
            old_tab.editor.deactivate()
        if new_tab is not None:
            new_tab.editor.activate()

        self.current_tab = new_tab

    def about_vial(self):
        QMessageBox.about(
            self, "About Vial", 'Vial {}<br><br>'
            'Licensed under the terms of the<br>GNU General Public License (version 2 or later)<br><br>'
            '<a href="https://get.vial.today/">https://get.vial.today/</a>'.
            format(self.appctx.build_settings["version"]))

    def closeEvent(self, e):
        self.settings.setValue("size", self.size())
        self.settings.setValue("pos", self.pos())

        e.accept()
コード例 #10
0
class DyStockTradeStrategyMarketMonitorWidget(QWidget):
    """
        股票策略实时监控窗口,动态创建
    """
    signal = QtCore.pyqtSignal(type(DyEvent()))

    def __init__(self, eventEngine, strategyCls, strategyState):
        super().__init__()

        self._eventEngine = eventEngine
        self._strategyCls = strategyCls

        self._registerEvent()

        self._initUi(strategyState)

    def _initUi(self, strategyState):
        self._dataWidget = DyStockTradeStrategyMarketMonitorDataWidget(self._strategyCls)
        self._indWidget = DyStockTradeStrategyMarketMonitorIndWidget(self._eventEngine, self._strategyCls, strategyState)

        self._dataLabel = QLabel('数据')
        self._indLabel = QLabel('指示')

        grid = QGridLayout()
        grid.setSpacing(0)

        grid.addWidget(self._dataLabel, 0, 0)
        grid.addWidget(self._dataWidget, 1, 0)
        grid.addWidget(self._indLabel, 2, 0)
        grid.addWidget(self._indWidget, 3, 0)
        
        grid.setRowStretch(0, 1)
        grid.setRowStretch(1, 30)
        grid.setRowStretch(2, 1)
        grid.setRowStretch(3, 30)

        self.setLayout(grid)

        # set menu for labels
        self._dataLabel.setContextMenuPolicy(Qt.CustomContextMenu)
        self._dataLabel.customContextMenuRequested.connect(self._showLabelContextMenu)

        self._indLabel.setContextMenuPolicy(Qt.CustomContextMenu)
        self._indLabel.customContextMenuRequested.connect(self._showLabelContextMenu)

        self._labelMenu = QMenu(self) 
        
        action = QAction('叠加', self)
        action.triggered.connect(self._overlapAct)
        self._labelMenu.addAction(action)

    def _stockMarketMonitorUiHandler(self, event):
        if 'data' in event.data:
            data = event.data['data']['data']
            new = event.data['data']['new']

            strategyCls = event.data['class']
            if strategyCls.maxUiDataRowNbr is not None:
                data = data[:strategyCls.maxUiDataRowNbr]

            self._dataWidget.update(data, new)

        if 'ind' in event.data:
            self._indWidget.update(event.data['ind'])

    def _signalEmitWrapper(self, event):
        """ !!!Note: The value of signal.emit will always be changed each time you getting.
        """
        self.signal.emit(event)

    def _registerEvent(self):
        self.signal.connect(self._stockMarketMonitorUiHandler)
        self._eventEngine.register(DyEventType.stockMarketMonitorUi + self._strategyCls.name, self._signalEmitWrapper)

    def _unregisterEvent(self):
        self.signal.disconnect(self._stockMarketMonitorUiHandler)
        self._eventEngine.unregister(DyEventType.stockMarketMonitorUi + self._strategyCls.name, self._signalEmitWrapper)

    def closeEvent(self, event):
        self._dataWidget.close()
        self._indWidget.close()

        self._unregisterEvent()

        return super().closeEvent(event)

    def _showLabelContextMenu(self, position):
        self._labelMenu.popup(QCursor.pos())

    def _overlapAct(self):
        grid = self.layout()

        # remove
        self._dataLabel.setText('')
        self._indLabel.setText('')

        grid.removeWidget(self._dataLabel)
        grid.removeWidget(self._dataWidget)
        grid.removeWidget(self._indLabel)
        grid.removeWidget(self._indWidget)

        # add
        self._tabWidget = QTabWidget()

        self._tabWidget.addTab(self._dataWidget, '数据')
        self._tabWidget.addTab(self._indWidget, '指示')

        grid.addWidget(self._tabWidget, 0, 0)

        grid.setRowStretch(0, 1)
        grid.setRowStretch(1, 0)
        grid.setRowStretch(2, 0)
        grid.setRowStretch(3, 0)

        # 设置Tab右键菜单事件
        tabBar = self._tabWidget.tabBar()
        tabBar.setContextMenuPolicy(Qt.CustomContextMenu)
        tabBar.customContextMenuRequested.connect(self._showTabContextMenu)

        # 创建TabBar菜单
        self._tabBarMenu = QMenu(self)

        action = QAction('平铺', self)
        action.triggered.connect(self._flatAct)
        self._tabBarMenu.addAction(action)

    def _showTabContextMenu(self, position):
        self._tabBarMenu.popup(QCursor.pos())

    def _flatAct(self):
        grid = self.layout()

        # remove
        self._tabWidget.removeTab(0)
        self._tabWidget.removeTab(0)

        grid.removeWidget(self._tabWidget)

        self._tabWidget.hide()
        
        # add
        self._dataLabel.setText('数据')
        self._indLabel.setText('指示')

        grid.addWidget(self._dataLabel, 0, 0)
        grid.addWidget(self._dataWidget, 1, 0)
        grid.addWidget(self._indLabel, 2, 0)
        grid.addWidget(self._indWidget, 3, 0)

        self._dataWidget.show()
        self._indWidget.show()
        
        grid.setRowStretch(0, 1)
        grid.setRowStretch(1, 30)
        grid.setRowStretch(2, 1)
        grid.setRowStretch(3, 30)
コード例 #11
0
class Window(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setFixedSize(QSize(WIND_HEIGHT, WIND_WIDTH))
        self.setWindowTitle('HeadHunter')
        self.setWindowIcon(QIcon('sources/hh.png'))
        self.color = '#cfebfd'
        self.second_color = '#87cefa'
        self.third_color = '#0000cc'
        self.start_sal = MIN_SALARY

        self.data = work_with_data.get_prepocess_data(False)
        self.categorical_columns = ['Area', 'Employment', 'Experience']
        self.binary_columns = list(LANGUAGES) + list(SIZE_COMPANY.keys())
        self.model = model.get_forest_model(self.data,
                                            self.categorical_columns,
                                            self.binary_columns)

        # 1 Widget
        self.tabs_lang = QTabWidget(self)
        self.tabs_lang1 = QWidget()
        self.tabs_lang2 = QWidget()
        self.tabs_lang.resize(WIND_HEIGHT, WIND_WIDTH - BUTTON_MENU_WIDTH - 5)
        self.tabs_lang.move(0, BUTTON_MENU_WIDTH + 5)
        self.tabs_lang.addTab(self.tabs_lang1,
                              'Статистика по средней зарплате')
        self.tabs_lang.addTab(self.tabs_lang2,
                              'Статистика по количеству вакансий')

        # 2 Widget
        self.tabs_city = QTabWidget(self)
        self.tabs_city1 = QWidget()
        self.tabs_city2 = QWidget()
        self.tabs_city.resize(WIND_HEIGHT, WIND_WIDTH - BUTTON_MENU_WIDTH - 5)
        self.tabs_city.move(0, BUTTON_MENU_WIDTH + 5)
        self.tabs_city.addTab(self.tabs_city1,
                              'Статистика по средней зарплате')
        self.tabs_city.addTab(self.tabs_city2,
                              'Статистика по количеству вакансий')

        # 3 Widget
        self.tabs_map = QTabWidget(self)
        self.tab_map1 = QWidget()
        self.tabs_map.resize(WIND_HEIGHT, WIND_WIDTH - BUTTON_MENU_WIDTH - 25)
        self.tabs_map.move(0, BUTTON_MENU_WIDTH + 25)
        self.tabs_map.addTab(self.tab_map1, '')

        # 4 Widget
        self.tabs_model = QTabWidget(self)
        self.tab_model1 = QWidget()
        self.tabs_model.resize(WIND_HEIGHT,
                               WIND_WIDTH - BUTTON_MENU_WIDTH - 25)
        self.tabs_model.move(0, BUTTON_MENU_WIDTH + 25)
        self.tabs_model.addTab(self.tab_model1, '')

        # 1,2 plot
        self.plot_lang1 = MatPlot(WIND_HEIGHT * 0.25, 0, self.tabs_lang1,
                                  self.second_color)
        self.plot_lang2 = MatPlot(WIND_HEIGHT * 0.25, 0, self.tabs_lang2,
                                  self.second_color)

        # 3,4 plot
        self.plot_city1 = MatPlot(WIND_HEIGHT * 0.25, 0, self.tabs_city1,
                                  self.second_color)
        self.plot_city2 = MatPlot(WIND_HEIGHT * 0.25, 0, self.tabs_city2,
                                  self.second_color)

        # map
        self.plot_map1 = MatPlot(0, 0, self.tab_map1, self.color,
                                 self.third_color)

        # button
        self.button_lang = QPushButton('Статистика\nпо языкам', self)
        self.button_lang.clicked.connect(lambda: self.show_tab(self.tabs_lang))
        self.button_lang.resize(BUTTON_MENU_HEIGHT, BUTTON_MENU_WIDTH)
        self.button_lang.move(BUTTON_MENU_HEIGHT * 0, 0)

        self.button_city = QPushButton('Статистика\nпо городам', self)
        self.button_city.clicked.connect(lambda: self.show_tab(self.tabs_city))
        self.button_city.resize(BUTTON_MENU_HEIGHT, BUTTON_MENU_WIDTH)
        self.button_city.move(BUTTON_MENU_HEIGHT * 1, 0)

        self.button_map = QPushButton('Востребованность\nв городах', self)
        self.button_map.clicked.connect(lambda: self.show_tab(self.tabs_map))
        self.button_map.resize(BUTTON_MENU_HEIGHT, BUTTON_MENU_WIDTH)
        self.button_map.move(BUTTON_MENU_HEIGHT * 2, 0)

        self.button_model = QPushButton('Заработная\nплата', self)
        self.button_model.clicked.connect(
            lambda: self.show_tab(self.tabs_model))
        self.button_model.resize(BUTTON_MENU_HEIGHT, BUTTON_MENU_WIDTH)
        self.button_model.move(BUTTON_MENU_HEIGHT * 3, 0)

        self.button_update = QPushButton('Обновить', self)
        self.button_update.clicked.connect(self.update_data)
        self.button_update.resize(BUTTON_MENU_HEIGHT / 3,
                                  BUTTON_MENU_WIDTH / 3)
        self.button_update.move(
            BUTTON_MENU_HEIGHT * 3 + 2 * BUTTON_MENU_HEIGHT / 3,
            BUTTON_MENU_WIDTH + 2)

        # 1-2 filter
        self.all_filters = {}
        self.filters_city1 = QFrame(self.tabs_city1)
        self.filters_city1.resize(FRAME_WIDTH, FRAME_HEIGHT - 50)
        self.filters_city1.move(10, 10)
        self.all_filters['City1'] = (self.create_filters(self.filters_city1,
                                                         'City1',
                                                         lang=True,
                                                         sal=False))

        self.filters_city2 = QFrame(self.tabs_city2)
        self.filters_city2.resize(FRAME_WIDTH, FRAME_HEIGHT)
        self.filters_city2.move(10, 10)
        self.all_filters['City2'] = (self.create_filters(self.filters_city2,
                                                         'City2',
                                                         lang=True))

        # 3-4 filter
        self.filters_lang1 = QFrame(self.tabs_lang1)
        self.filters_lang1.resize(FRAME_WIDTH, FRAME_HEIGHT - 50)
        self.filters_lang1.move(10, 10)
        self.all_filters['Lang1'] = (self.create_filters(self.filters_lang1,
                                                         'Lang1',
                                                         area=True,
                                                         sal=False))

        self.filters_lang2 = QFrame(self.tabs_lang2)
        self.filters_lang2.resize(FRAME_WIDTH, FRAME_HEIGHT)
        self.filters_lang2.move(10, 10)
        self.all_filters['Lang2'] = (self.create_filters(self.filters_lang2,
                                                         'Lang2',
                                                         area=True))

        # model
        self.filter_model = {}
        self.create_filters_model(self.tab_model1)
        self.button_forecast = QPushButton('Расчет', self.tab_model1)
        self.button_forecast.clicked.connect(self.create_forecast)
        self.button_forecast.resize(BUTTON_MENU_HEIGHT, BUTTON_MENU_WIDTH)
        self.button_forecast.move(WIND_HEIGHT / 2 - BUTTON_MENU_HEIGHT / 2,
                                  300)
        self.button_forecast.setEnabled(False)

        self.label_forecast = QLabel(self.tab_model1)
        self.label_forecast.setAlignment(Qt.AlignCenter)
        self.label_forecast.resize(WIND_HEIGHT, BUTTON_MENU_WIDTH)
        self.label_forecast.move(0, 400)

        self.plot_all()
        self.show_tab(self.tabs_lang)
        self.set_style()

    def show_tab(self, item_view):
        self.tabs_lang.hide()
        self.tabs_map.hide()
        self.tabs_city.hide()
        self.tabs_model.hide()

        item_view.show()

    def create_filters(self, parent, code, lang=False, area=False, sal=True):
        if sal:
            label_sal = QLabel(parent)
            label_sal.setText('Зарплата от')
            label_sal.resize(100, 15)
            label_sal.move(5, 125)

            label_sal_val = QLabel(parent)
            label_sal_val.move(FRAME_WIDTH - 50, 125)
            label_sal_val.resize(45, 15)
            label_sal_val.setAlignment(Qt.AlignRight)
            label_sal_val.setText(str(self.start_sal))

            sld_sal = QSlider(Qt.Horizontal, parent)
            sld_sal.setMinimum(int(self.start_sal / 5000))
            sld_sal.setMaximum(40)
            sld_sal.setPageStep(1)
            sld_sal.move(5, 145)
            sld_sal.resize(FRAME_WIDTH - 10, 20)
            sld_sal.valueChanged[int].connect(
                lambda val, tab=code: self.sld_action(val, tab))
        else:
            label_sal_val = None
            sld_sal = None

        if lang:
            combo_lang = QComboBox(parent)
            combo_lang.setMaxVisibleItems(20)
            combo_lang.addItem("Все языки")
            combo_lang.resize(FRAME_WIDTH - 10, 20)
            combo_lang.move(5, 10)
            combo_lang.addItems(LANGUAGES)
            combo_lang.activated.connect(
                lambda val, tab=code: self.refresh_plot(tab))
        else:
            combo_lang = None

        if area:
            combo_area = QComboBox(parent)
            combo_area.setMaxVisibleItems(20)
            combo_area.addItem("Все города")
            combo_area.resize(FRAME_WIDTH - 10, 20)
            combo_area.move(5, 10)
            combo_area.addItems(
                [work_with_data.decode_param(val) for val in AREA])
            combo_area.activated.connect(
                lambda val, tab=code: self.refresh_plot(tab))
        else:
            combo_area = None

        combo_sizecomp = QComboBox(parent)
        combo_sizecomp.setMaxVisibleItems(5)
        combo_sizecomp.addItem("Все компании")
        combo_sizecomp.resize(FRAME_WIDTH - 10, 20)
        combo_sizecomp.move(5, 40)
        combo_sizecomp.addItems([
            work_with_data.decode_param(size_comp)
            for size_comp in SIZE_COMPANY
        ])
        combo_sizecomp.activated.connect(
            lambda val, tab=code: self.refresh_plot(tab))

        combo_exp = QComboBox(parent)
        combo_exp.setMaxVisibleItems(10)
        combo_exp.addItem("Любой опыт")
        combo_exp.resize(FRAME_WIDTH - 10, 20)
        combo_exp.move(5, 70)
        combo_exp.addItems([
            work_with_data.decode_param(experience)
            for experience in EXPERIENCE
        ])
        combo_exp.activated.connect(
            lambda val, tab=code: self.refresh_plot(tab))

        combo_empl = QComboBox(parent)
        combo_empl.setMaxVisibleItems(10)
        combo_empl.addItem("Любой график")
        combo_empl.resize(FRAME_WIDTH - 10, 20)
        combo_empl.move(5, 100)
        combo_empl.addItems([
            work_with_data.decode_param(employment)
            for employment in EMPLOYMENT
        ])
        combo_empl.activated.connect(
            lambda val, tab=code: self.refresh_plot(tab))

        items = {
            'Lang': combo_lang,
            'Area': combo_area,
            'MinSal': sld_sal,
            'SizeComp': combo_sizecomp,
            'Employment': combo_empl,
            'Experience': combo_exp,
            'lbl_min': label_sal_val
        }
        return items

    def create_filters_model(self, parent):
        checks = {}
        for i, lang in enumerate(LANGUAGES):
            check = QCheckBox(parent)
            check.setText(lang)
            check.stateChanged.connect(self.check_action)
            check.move(250 * (i % 4) + 80, 25 * (i // 4) + 25)
            checks[lang] = check

        combo_area = QComboBox(parent)
        combo_area.setMaxVisibleItems(20)
        combo_area.resize(WIND_HEIGHT / 2 - 80 - 20, 20)
        combo_area.move(80, 200)
        combo_area.addItems([work_with_data.decode_param(val) for val in AREA])

        combo_empl = QComboBox(parent)
        combo_empl.setMaxVisibleItems(10)
        combo_empl.resize(WIND_HEIGHT / 2 - 80 - 20, 20)
        combo_empl.move(WIND_HEIGHT / 2, 200)
        combo_empl.addItems([
            work_with_data.decode_param(employment)
            for employment in EMPLOYMENT
        ])

        combo_exp = QComboBox(parent)
        combo_exp.setMaxVisibleItems(10)
        combo_exp.resize(WIND_HEIGHT / 2 - 80 - 20, 20)
        combo_exp.move(80, 240)
        combo_exp.addItems([
            work_with_data.decode_param(experience)
            for experience in EXPERIENCE
        ])

        combo_sizecomp = QComboBox(parent)
        combo_sizecomp.setMaxVisibleItems(5)
        combo_sizecomp.resize(WIND_HEIGHT / 2 - 80 - 20, 20)
        combo_sizecomp.move(WIND_HEIGHT / 2, 240)
        combo_sizecomp.addItems([
            work_with_data.decode_param(size_comp)
            for size_comp in SIZE_COMPANY
        ])

        self.filter_model = {
            'Lang': checks,
            'Area': combo_area,
            'Employment': combo_empl,
            'Experience': combo_exp,
            'SizeComp': combo_sizecomp
        }

    def set_style(self):
        main_style = 'background: #ffffff;'
        style_combobox = """
            QComboBox{{
                font-weight: 600;
                background: {};
                border: none;
            }}
            QComboBox QAbstractItemView {{
                selection-color: #000000;
                selection-background-color: {};
            }}
            QComboBox::drop-down{{
                border: 1px;
            }}
            QComboBox::hover{{
                background: {};
            }}
        """.format(self.color, self.color, self.second_color)
        style_slider = """
                    QSlider::groove:horizontal {{  
                        height: 3px;
                        background: #B0AEB1;
                    }}
                    QSlider::handle:horizontal {{
                        background: {};
                        border: 1px solid {};
                        width: 10px;
                        margin: -10px 0; 
                    }}
                    QSlider::sub-page:qlineargradient {{
                        background: {};
                    }}
        """.format(self.color, self.color, self.third_color)
        style_filters = '''
            background-color: #ffffff
        '''
        style_button = '''
            QPushButton {{
                background-color: {};
                font: bold 12px;
                border: 1px solid #ffffff;
            }}
            QPushButton:hover {{
                background-color: {};
                color: #ffffff;
            }}
        '''.format(self.color, self.third_color)
        style_tabs = '''
            QTabBar::tab {height: 0px; width: 0px;};
        '''
        style_checkbox = """
            QCheckBox::indicator:checked {
                image: url(sources//hh_enabled.png);
            }
            QCheckBox::indicator:unchecked {
                image: url(sources//hh_notenabled.png);
            }
        """

        for key in self.all_filters:
            for name_item in ('Area', 'Lang', 'SizeComp', 'Experience',
                              'Employment'):
                if self.all_filters[key][name_item] is not None:
                    self.all_filters[key][name_item].setStyleSheet(
                        style_combobox)

            # for name_item in ('SizeComp', 'Experience', 'Employment'):
            #    self.all_filters[key][name_item].setStyleSheet(style_combobox)

            if self.all_filters[key]['MinSal'] is not None:
                self.all_filters[key]['MinSal'].setStyleSheet(style_slider)

        for key in self.filter_model:
            if key in ('Area', 'SizeComp', 'Experience', 'Employment'):
                self.filter_model[key].setStyleSheet(style_combobox)
            if key in ('Lang', ):
                for check in self.filter_model[key].values():
                    check.setStyleSheet(style_checkbox)

        self.setStyleSheet(main_style)
        self.filters_city1.setStyleSheet(style_filters)
        self.filters_city2.setStyleSheet(style_filters)
        self.filters_lang1.setStyleSheet(style_filters)
        self.filters_lang2.setStyleSheet(style_filters)

        self.button_lang.setStyleSheet(style_button)
        self.button_city.setStyleSheet(style_button)
        self.button_map.setStyleSheet(style_button)
        self.button_model.setStyleSheet(style_button)
        self.button_update.setStyleSheet(style_button)

        self.tabs_map.setStyleSheet(style_tabs)
        self.tabs_model.setStyleSheet(style_tabs)
        self.button_forecast.setStyleSheet(style_button)
        self.label_forecast.setStyleSheet("""
            QLabel {{
                font: bold 24px;
                border: 1px solid #ffffff;
                color: {};
            }}
        """.format(self.second_color))

        # self.label_forecast.setFont(QFont("Times", 8, QFont.Bold))

    def plot_all(self):
        for nametab in ('Lang1', 'Lang2', 'City1', 'City2'):
            self.refresh_plot(nametab)
        self.draw_plot_map1()

    def sld_action(self, value, nametab):
        self.all_filters[nametab]['lbl_min'].setText(str(value * 5000))
        self.refresh_plot(nametab)

    def check_action(self):
        active_checks = []
        for lang, checkbox in self.filter_model['Lang'].items():
            if checkbox.isChecked():
                active_checks.append(lang)
        if len(active_checks) >= MAX_LANG_MODEL:
            for checkbox in self.filter_model['Lang'].values():
                if not checkbox.isChecked():
                    checkbox.setEnabled(False)
        else:
            for checkbox in self.filter_model['Lang'].values():
                checkbox.setEnabled(True)

        self.button_forecast.setEnabled(bool(len(active_checks)))

    def refresh_plot(self, tabname):
        df_t = self.data

        sal = self.all_filters[tabname]['MinSal']
        if sal is not None:
            min_sal = sal.value() * 5000
            df_t = self.data[self.data['Salary'] > min_sal]

        area = self.all_filters[tabname]['Area']
        if area is not None and area.currentIndex():
            area = work_with_data.encode_param(area.currentText())
            df_t = df_t[df_t['Area'] == area]

        lang = self.all_filters[tabname]['Lang']
        if lang is not None and lang.currentIndex():
            lang = lang.currentText()
            df_t = df_t[df_t[lang] == 1]

        if self.all_filters[tabname]['SizeComp'].currentIndex():
            size_comp = work_with_data.encode_param(
                self.all_filters[tabname]['SizeComp'].currentText())
            df_t = df_t[df_t[size_comp] == 1]

        if self.all_filters[tabname]['Experience'].currentIndex():
            exp = work_with_data.encode_param(
                self.all_filters[tabname]['Experience'].currentText())
            df_t = df_t[df_t['Experience'] == exp]

        if self.all_filters[tabname]['Employment'].currentIndex():
            empl = work_with_data.encode_param(
                self.all_filters[tabname]['Employment'].currentText())
            df_t = df_t[df_t['Employment'] == empl]

        if tabname == 'Lang1':
            self.draw_plot_lang1(df_t)
        elif tabname == 'Lang2':
            self.draw_plot_lang2(df_t)
        elif tabname == 'City1':
            self.draw_plot_city1(df_t)
        elif tabname == 'City2':
            self.draw_plot_city2(df_t)

    def draw_plot_lang1(self, data=None):
        if data is None:
            data = self.data

        mass_sal = [(lang, data[data[lang] == 1]['Salary'].mean())
                    for lang in LANGUAGES]
        mass_sal = [val for val in mass_sal if str(val[1]) != 'nan']
        mass_sal.sort(key=lambda x: -x[1])
        temp = list(zip(*mass_sal))

        if not temp:
            temp = [[], []]

        self.plot_lang1.plot_bar(*temp, 'Средняя зарплата по языкам')

    def draw_plot_lang2(self, data=None):
        if data is None:
            data = self.data

        count_vac = [(lang, data[data[lang] == 1].shape[0])
                     for lang in LANGUAGES]
        count_vac.sort(key=lambda x: -x[1])
        count_vac = filter(lambda x: x[1] > 0, count_vac)

        temp = list(zip(*count_vac))

        if not temp:
            temp = [[], []]

        self.plot_lang2.plot_bar(*temp, 'Количество вакансий по языкам')

    def draw_plot_city1(self, data=None):
        if data is None:
            data = self.data

        mass_sal = [(area, data[data['Area'] == area]['Salary'].mean())
                    for area in AREA.keys()]
        mass_sal = [val for val in mass_sal if str(val[1]) != 'nan']
        mass_sal.sort(key=lambda x: -x[1])

        temp = list(zip(*mass_sal))

        if not temp:
            temp = [[], []]
        else:
            temp[0] = [work_with_data.decode_param(city) for city in temp[0]]

        self.plot_city1.plot_bar(*temp, 'Средняя зарплата по городам')

    def draw_plot_city2(self, data=None):
        if data is None:
            data = self.data

        count_vac = [(area, data[data['Area'] == area].shape[0])
                     for area in AREA.keys()]
        count_vac.sort(key=lambda x: -x[1])
        count_vac = filter(lambda x: x[1] > 0, count_vac)

        temp = list(zip(*count_vac))

        if not temp:
            temp = [[], []]
        else:
            temp[0] = [work_with_data.decode_param(city) for city in temp[0]]

        self.plot_city2.plot_bar(*temp, 'Количество вакансий по городам')

    def draw_plot_map1(self, data=None):
        if data is None:
            data = self.data

        mass_sal = [(area, data[data['Area'] == area].shape[0])
                    for area in AREA.keys()]
        mass_sal = filter(lambda x: x[1] > 0, mass_sal)

        temp = list(zip(*mass_sal))

        min_vac = min(temp[1])
        temp[1] = [vac / min_vac for vac in temp[1]]
        self.plot_map1.plot_map(*temp, 'Количество вакансий по городам')

    def create_forecast(self):
        vacancy = []
        for key in self.categorical_columns:
            vacancy.append(
                work_with_data.encode_param(
                    self.filter_model[key].currentText()))

        for checkbox in self.filter_model['Lang'].values():
            vacancy.append(int(checkbox.isChecked()))

        for size_comp in SIZE_COMPANY:
            vacancy.append(
                int(
                    work_with_data.encode_param(self.filter_model['SizeComp'].
                                                currentText()) == size_comp))

        df = pd.DataFrame([vacancy],
                          columns=self.categorical_columns +
                          self.binary_columns)
        self.label_forecast.setText('Возможная зарплата: {:.0f} руб'.format(
            self.model.get_predict(df)[0]))

    def update_data(self):
        answer = QMessageBox.question(self, 'Обновление данных',
                                      'Вы хотите обновить данные?',
                                      QMessageBox.Ok | QMessageBox.Cancel,
                                      QMessageBox.Cancel)
        if answer == QMessageBox.Ok:
            self.data = work_with_data.get_prepocess_data(True)
            self.model = model.get_forest_model(self.data,
                                                self.categorical_columns,
                                                self.binary_columns)
            self.plot_all()