class collapsibleGroupBox2(QWidget):
    def __init__(self, parent=None, title=None):
        QWidget.__init__(self, parent)
        self.frame = QFrame(self)
        self.button = QPushButton("Toggle", self)
        self.button.setCheckable(True)
        self.button.setChecked(True)
        self.switched = False
        self.vPolicy = None

        self.button.setStyleSheet(style.collapsibleGroupBoxButton())

        if title:
            self.setTitle(title)

    def resizeEvent(self, event):
        if not self.switched:
            self.switchLayout()
        return QWidget.resizeEvent(self, event)

    def switchLayout(self):
        self.frame.setLayout(self.layout())
        self.wLayout = QVBoxLayout(self)
        self.wLayout.setContentsMargins(0, 0, 0, 0)
        self.wLayout.setSpacing(0)
        self.wLayout.addWidget(self.button)
        self.wLayout.addWidget(self.frame)
        self.button.toggled.connect(self.setExpanded)
        self.frame.layout().setContentsMargins(0, 0, 0, 4)
        self.frame.layout().setSpacing(0)
        self.switched = True

        self.vPolicy = self.sizePolicy().verticalPolicy()
        self.parent().layout().setAlignment(Qt.AlignTop)

        self.setExpanded(self.button.isChecked())

    def setFlat(self, val):
        if val:
            self.frame.setFrameShape(QFrame.NoFrame)

    def setCheckable(self, val):
        pass

    def setTitle(self, title):
        self.button.setText(title)

    def setExpanded(self, val):
        self.frame.setVisible(val)
        if val:
            self.setSizePolicy(QSizePolicy.Preferred, self.vPolicy)
        else:
            self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)

    def saveState(self):
        return self.button.isChecked()

    def restoreState(self, val):
        self.button.setChecked(val)
class collapsibleGroupBox2(QWidget):
    def __init__(self, parent=None, title=None):
        QWidget.__init__(self, parent)
        self.frame = QFrame(self)
        self.button = QPushButton("Toggle", self)
        self.button.setCheckable(True)
        self.button.setChecked(True)
        self.switched = False
        self.vPolicy = None
        # self.button.setStyleSheet("background-color: lightBlue;")

        self.button.setStyleSheet(style.collapsibleGroupBoxButton())

        if title:
            self.setTitle(title)

    def resizeEvent(self, event):
        if not self.switched:
            self.switchLayout()
        return QWidget.resizeEvent(self, event)

    def switchLayout(self):
        self.frame.setLayout(self.layout())
        self.wLayout = QVBoxLayout(self)
        self.wLayout.setContentsMargins(0, 0, 0, 0)
        self.wLayout.setSpacing(0)
        self.wLayout.addWidget(self.button)
        self.wLayout.addWidget(self.frame)
        self.button.toggled.connect(self.setExpanded)
        self.frame.layout().setContentsMargins(0, 0, 0, 4)
        self.frame.layout().setSpacing(0)
        self.switched = True

        self.vPolicy = self.sizePolicy().verticalPolicy()
        self.parent().layout().setAlignment(Qt.AlignTop)

        self.setExpanded(self.button.isChecked())

    def setFlat(self, val):
        if val:
            self.frame.setFrameShape(QFrame.NoFrame)

    def setCheckable(self, val):
        pass

    def setTitle(self, title):
        self.button.setText(title)

    def setExpanded(self, val):
        self.frame.setVisible(val)
        if val:
            self.setSizePolicy(QSizePolicy.Preferred, self.vPolicy)
        else:
            self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)

    def saveState(self):
        return self.button.isChecked()

    def restoreState(self, val):
        self.button.setChecked(val)
Esempio n. 3
0
    def openWebUI(self):
        self.device_username = self.settings.value("device_username", "", str)
        self.device_password = self.settings.value("device_password", "", str)
        if self.device and self.device.p.get('IPAddress'):
            url = QUrl("http://{}:{}@{}".format( self.device_username, \
                        urllib.parse.quote(self.device_password),self.device.p['IPAddress']))

            try:
                webui = QWebEngineView()
                webui.load(url)

                frm_webui = QFrame()
                frm_webui.setWindowTitle("WebUI [{}]".format(
                    self.device.p['FriendlyName1']))
                frm_webui.setFrameShape(QFrame.StyledPanel)
                frm_webui.setLayout(VLayout(0))
                frm_webui.layout().addWidget(webui)
                frm_webui.destroyed.connect(self.updateMDI)

                self.mdi.addSubWindow(frm_webui)
                self.mdi.setViewMode(QMdiArea.TabbedView)
                frm_webui.setWindowState(Qt.WindowMaximized)

            except NameError:
                QDesktopServices.openUrl(url)
Esempio n. 4
0
 def add_select_button(self, frame: QFrame):
     # Create the select button
     c = QToolButton()
     c.setIconSize(QSize(32, 32))
     c.setText("Find")
     self.on_style_select_button(c)
     c.clicked.connect(self.on_show_selection_menu)
     frame.layout().insertWidget(0, c)
Esempio n. 5
0
	def _createTopBar(self):
		topbar = QFrame()
		topbar.setFixedHeight(50)
		topbar.setLayout(QHBoxLayout())
		topbar.setContentsMargins(10, 0, 0, 0)
		topbar.setSizePolicy(QSizePolicy(1, 0))
		topbar.setObjectName("topbar")

		self.titleText = QLabel("Produtos")
		topbar.layout().addWidget(self.titleText)
		return topbar
Esempio n. 6
0
    def __init__(self, item, item_list, viewer):
        super().__init__(item, viewer)
        self.setObjectName("LootWidget")
        self.item = item
        self.item_list = item_list
        self.viewer = viewer

        name_frame = QFrame()
        name_frame.setContentsMargins(0, 0, 0, 0)
        name_frame.setLayout(QHBoxLayout())
        self.name_label = NameLabel(item.name)
        self.name_label.setObjectName("LootWidget_name")
        name_frame.layout().addWidget(self.name_label)
        name_frame.layout().addStretch(1)

        self.reroll_button = RerollButton()
        self.reroll_button.clicked.connect(self.reroll_item)

        self.button_bar = QFrame()
        self.button_bar.setContentsMargins(0, 0, 0, 0)
        self.button_bar.setLayout(QHBoxLayout())

        self.button_bar.setHidden(True)
        self.type_dropdown = QComboBox()
        self.type_dropdown.addItem("Any")
        self.type_dropdown.addItem("Weapon")
        self.type_dropdown.addItem("Armor")
        self.type_dropdown.addItems(self.item_list.unique_attr("type"))
        if self.item.type in ["Staff", "Melee", "Ranged", "Rod"]:
            self.type_dropdown.setCurrentText("Weapon")
        elif self.item.type in ["Light Armor, Medium Armor, Heavy Armor"]:
            self.type_dropdown.setCurrentText("Armor")
        else:
            self.type_dropdown.setCurrentText(self.item.type)

        self.rarity_dropdown = QComboBox()
        self.rarity_dropdown.addItems(self.item_list.unique_attr("rarity"))
        self.rarity_dropdown.setCurrentText(self.item.rarity)

        self.button_bar.layout().addWidget(self.type_dropdown)
        self.button_bar.layout().addWidget(self.rarity_dropdown)
        self.button_bar.layout().addStretch(1)
        self.button_bar.layout().addWidget(self.reroll_button)

        self.setLayout(QVBoxLayout())
        QSpacerItem(50, 10)
        self.layout().setContentsMargins(20, 5, 10, 10)
        self.layout().addWidget(name_frame)
        self.layout().addWidget(self.button_bar)
        self.setFrameShape(QFrame.Box)
Esempio n. 7
0
    def __init__(self, body):
        super().__init__()
        self.body = body
        self.setLayout(QHBoxLayout())
        leftCol = QFrame()
        leftCol.setLayout(QVBoxLayout())
        leftCol.layout().setAlignment(Qt.AlignTop)
        leftCol.setStyleSheet("QFrame{background:#ddd;}")
        delBtn = QPushButton("X")
        delBtn.clicked.connect(self.deleteMe)
        leftCol.layout().addWidget(delBtn)
        self.layout().addWidget(leftCol)

        self.layout().addWidget(body)
Esempio n. 8
0
    def __init__(self, parent=None):
        super().__init__(parent)

        self.model = None
        self.transactionsTableView = QTableView()

        headerBox = QFrame()
        headerBox.setLayout(QHBoxLayout())
        headerBox.layout().setContentsMargins(0, 0, 0, 0)
        headerBox.layout().addWidget(QLabel("Transactions"))

        newTransactionButton = QPushButton(QIcon.fromTheme("list-add"), '',
                                           self)
        newTransactionButton.setFixedSize(20, 20)
        newTransactionButton.clicked.connect(self.addEntry)
        delTransactionButton = QPushButton(QIcon.fromTheme("list-remove"), '',
                                           self)
        delTransactionButton.setFixedSize(20, 20)
        delTransactionButton.clicked.connect(self.removeEntry)

        headerBox.layout().addWidget(newTransactionButton)
        headerBox.layout().addWidget(delTransactionButton)
        headerBox.layout().addStretch()

        boxLayout = QVBoxLayout(self)
        boxLayout.addWidget(headerBox)
        boxLayout.addWidget(self.transactionsTableView)
Esempio n. 9
0
    def __init__(self,
                 step: WorkflowStep,
                 index: int,
                 steps_view=None,
                 enable_button: bool = False):
        super().__init__()
        if step is None:
            raise ValueError("step")
        self.step = step
        self.name = step.name
        self.index = index
        self.form_rows: List[FormRow] = list()
        self.button = QPushButton(f"Run {step.name}")
        self.button.clicked.connect(
            lambda: steps_view.btn_run_clicked(self.index))
        self.steps_view = steps_view

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        if step.function.parameters is None:
            label_no_param = QLabel("No parameters needed")
            label_no_param.setAlignment(Qt.AlignCenter)
            label_no_param.setContentsMargins(0, 0, 6, 0)
            self.form_rows.append(FormRow("", label_no_param))
        else:
            for param_name, param_data in step.function.parameters.items():
                default_values = step.parameter_values[param_name]
                self._add_param_rows(param_name, param_data, default_values)

        buttons = QFrame()
        buttons.setStyleSheet("border: none;")
        buttons.setLayout(QHBoxLayout())

        buttons.layout().addWidget(self.button)

        if not enable_button:
            self.button.setDisabled(True)
        box_contents = QVBoxLayout()
        box_contents.addLayout(Form(self.form_rows, (11, 5, 5, 5)))
        box_contents.addWidget(buttons)

        step_name = f"<span>{step.step_number}.&nbsp;{step.name}</span>"
        box = CollapsibleBox(step_name, box_contents, self)

        layout.addWidget(box)
Esempio n. 10
0
class Example(QMainWindow):
    def __init__(self):
        super().__init__()
        self.count_of_buttons = 1
        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)
        self.setGeometry(700, 200, 500, 400)

        self.button_add = QPushButton('Add')
        self.button_add.clicked.connect(self.add_button)

        self.button_clear = QPushButton('Clear')  # +++
        self.button_clear.clicked.connect(self.clear_button)  # +++

        self.layout_buttons = QVBoxLayout()
        self.layout_buttons.addStretch()

        self.frame = QFrame()
        self.frame.setMinimumSize(200, 200)
        self.frame.setFrameStyle(QFrame.Box)
        self.frame.setLayout(self.layout_buttons)

        self.main_layout = QGridLayout(self.centralWidget)  # QGridLayout
        self.main_layout.addWidget(self.button_add, 0, 0)
        self.main_layout.addWidget(self.button_clear, 0, 1)  # +++
        self.main_layout.addWidget(self.frame, 1, 0, 1, 2)  # +++

    def add_button(self):
        # -       self.main_layout.addWidget(self.frame)
        self.button = QPushButton(f"Кнопка № {self.count_of_buttons}")
        self.button.clicked.connect(
            lambda ch, btn=self.button: self.pressed_btn(btn))
        self.count_of_buttons += 1
        self.layout_buttons.insertWidget(0, self.button)

    def pressed_btn(self, btn):
        print(f"кнопка нажата: {btn.text()}")

    # +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    def clear_button(self):
        widgets = self.frame.layout().count()
        if widgets > 1:
            for i in range(widgets - 1):
                widget = self.frame.layout().itemAt(0).widget()
                self.frame.layout().removeWidget(widget)
                widget.hide()
Esempio n. 11
0
class ImageDialog(QDialog):
    def __init__(self, image_path, parent=None):
        super(ImageDialog, self).__init__(parent)
        position = self.cursor().pos()
        position.setX(position.x())
        position.setY(position.y())
        self.move(position)
        #self.setWindowOpacity(0.8)
        self.setLayout(QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.widget = QFrame()
        self.widget.setStyleSheet('''
            QFrame{
            border-style: outset;
            border-width: 1px;
            border-radius: 5px;         
            }
        ''')

        self.widget.setLayout(QVBoxLayout())
        self.widget.layout().setContentsMargins(0, 0, 0, 0)
        self.setMouseTracking(True)
        self.setWindowFlags(QtCore.Qt.Popup | QtCore.Qt.WindowStaysOnTopHint
                            | QtCore.Qt.FramelessWindowHint
                            | QtCore.Qt.X11BypassWindowManagerHint)
        self.qgraphics_view = ImageDialogViewer()
        self.qgraphics_view.pixmap = QPixmap(image_path)
        self.widget.layout().addWidget(self.qgraphics_view)
        self.layout().addWidget(self.widget)

    def setMouseTracking(self, flag):
        def set_mouse_tracking(parent):
            for child in parent.findChildren(QtCore.QObject):
                try:
                    child.setMouseTracking(flag)
                except:
                    pass
                set_mouse_tracking(child)

        QWidget.setMouseTracking(self, flag)
        set_mouse_tracking(self)

    def mouseMoveEvent(self, event: QMouseEvent) -> None:
        # print('mouseMoveEvent: x=%d, y=%d' % (event.x(), event.y()))
        if not self.rect().contains(event.pos()):
            self.close()
Esempio n. 12
0
    def _init_search_field(self):
        search_field_frame = QFrame()
        search_field_layout = QHBoxLayout()
        search_field_layout.addWidget(VSep(self))

        self._search_field = SearchField(self)
        self._search_field.setIcon(qtawesome.icon("fa.search"))
        self._search_field.setPlaceholderText("Search codec")
        self._search_field.textChanged.connect(lambda text: {})
        search_field_layout.addWidget(self._search_field)

        self._search_field_button = QToolButton()
        self._search_field_button.setIcon(qtawesome.icon("fa.arrow-circle-right"))
        self._search_field_button.setContentsMargins(0, 0, 0, 0)
        search_field_layout.addWidget(self._search_field_button)

        search_field_frame.setLayout(search_field_layout)
        search_field_frame.setContentsMargins(5, 0, 5, 5) # left, top, right, bottom
        search_field_frame.layout().setContentsMargins(0, 0, 0, 0)
        return search_field_frame
Esempio n. 13
0
File: tdmgr.py Progetto: une18/tdm
    def openWebUI(self):
        if self.device and self.device.p.get('IPAddress'):
            url = QUrl("http://{}".format(self.device.p['IPAddress']))

            try:
                webui = QWebEngineView()
                webui.load(url)

                frm_webui = QFrame()
                frm_webui.setWindowTitle("WebUI [{}]".format(self.device.p['FriendlyName1']))
                frm_webui.setFrameShape(QFrame.StyledPanel)
                frm_webui.setLayout(VLayout(0))
                frm_webui.layout().addWidget(webui)
                frm_webui.destroyed.connect(self.updateMDI)

                self.mdi.addSubWindow(frm_webui)
                self.mdi.setViewMode(QMdiArea.TabbedView)
                frm_webui.setWindowState(Qt.WindowMaximized)

            except NameError:
                QDesktopServices.openUrl(QUrl("http://{}".format(self.device.p['IPAddress'])))
Esempio n. 14
0
class BookmarkWidget(QFrame):
    SPELL_TAB = 0
    DICE_TAB = 1

    def __init__(self, monster_table, monster_viewer, spell_table, spell_viewer):
        super().__init__()
        self.monster_table = monster_table
        self.spell_table = spell_table
        self.monster_viewer = monster_viewer
        self.spell_viewer = spell_viewer
        self.bookmark_frame = QFrame()
        self.bookmark_frame.setMaximumHeight(300)
        self.button_bar = QFrame()
        self.button_bar.setLayout(QHBoxLayout())
        bookmark_layout = QHBoxLayout()
        self.setLayout(QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum))

        self.spell_bookmark = LinkedSpellTable(self.spell_table, self.spell_viewer)
        self.monster_bookmark = LinkedMonsterTable(self.monster_table, self.monster_viewer)
        self.monster_tabWidget = QTabWidget()
        self.monster_tabWidget.addTab(self.monster_bookmark, "Monster")

        self.spell_tabWidget = QTabWidget()
        self.spell_tabWidget.addTab(self.spell_bookmark, "Spell")

        self.dice_bookmark = QFrame()
        dice_layout = QVBoxLayout()
        for i in range(5):
            dice_layout.addWidget(DiceBox().frame)
        dice_help_button = QPushButton("Help")
        dice_help_button.clicked.connect(self.dice_instructions)
        dice_layout.addWidget(dice_help_button)
        self.dice_bookmark.setLayout(dice_layout)
        self.spell_tabWidget.addTab(self.dice_bookmark, "Dice")

        bookmark_layout.addWidget(self.monster_tabWidget)
        bookmark_layout.addWidget(self.spell_tabWidget)
        self.bookmark_frame.setLayout(bookmark_layout)

        self.clear_bookmark_button = QPushButton("Clear Bookmark")
        self.toggle_bookmark_button = QPushButton("Toggle Bookmark")
        self.button_bar.layout().setContentsMargins(0, 0, 0, 0)
        self.button_bar.layout().addWidget(self.clear_bookmark_button)
        self.button_bar.layout().addWidget(self.toggle_bookmark_button)

        self.layout().addWidget(self.bookmark_frame)
        self.layout().addWidget(self.button_bar)

        self.bookmark_frame.setHidden(True)
        self.hidden = True

    def dice_instructions(self):
        sNexus.printSignal.emit("\nEither input diceroll in format xdy+z, AttackBonus|DamageRoll, or"
                                    " AttackBonus, DamageRoll\nExample: 1d20+6\n5|2d6+3\n5, 2d6+3\n")
    def toggle_hide(self):
        self.hidden = not self.hidden
        self.bookmark_frame.setHidden(self.hidden)
Esempio n. 15
0
 def __init__(self, item_list, viewer):
     self.challenge_rating_combo_box = QComboBox()
     self.challenge_rating_combo_box.addItems([
         self.challengeRatingLow, self.challengeRatingMidLow,
         self.challengeRatingMidHigh, self.challengeRatingHigh
     ])
     super().__init__()
     self.viewer = viewer
     rollButton = QPushButton("Roll")
     rollButton.clicked.connect(self.roll_loot)
     srd_label = QLabel("Only SRD")
     self.srd_checkbox = QCheckBox()
     bottom_bar = QFrame()
     bottom_bar.setLayout(QHBoxLayout())
     bottom_bar.layout().addStretch(1)
     bottom_bar.layout().addWidget(srd_label)
     bottom_bar.layout().addWidget(self.srd_checkbox)
     bottom_bar.layout().addWidget(self.challenge_rating_combo_box)
     bottom_bar.layout().addWidget(rollButton)
     self.layout().addWidget(bottom_bar)
     self.item_list = item_list
     sNexus.treasureHoardDeselectSignal.connect(self.deselectAll)
Esempio n. 16
0
class RainyHub(QMainWindow):
    def __init__(self):
        super().__init__()
        self._setup_ui()
        # self._setup_menu()
        self.bind_signals()
        self._display_ui()
        self.setStyleSheet(open(os.path.join("styles", "default.css")).read())
        self.db_path = os.path.join(os.getcwd(), "RainyDB")

    def _setup_ui(self):
        self.window_frame = QFrame()
        self.window_frame.setLayout(QHBoxLayout())
        # self.window_frame.layout().setContentsMargins(0, 0, 0, 0)
        self.dm_button = DMButton()
        self.bg_button = BGButton()
        self.window_frame.layout().addWidget(self.dm_button)
        self.window_frame.layout().addWidget(self.bg_button)
        self.setFixedSize(600, 300)
        self.setWindowTitle("RainyHub")

    def bind_signals(self):
        self.dm_button.clicked.connect(self.open_rainydm)
        self.bg_button.clicked.connect(self.open_rainybg)

    def _display_ui(self):
        self.setCentralWidget(self.window_frame)

    def open_rainydm(self):
        os.chdir("RainyDM")
        self.rainy_dm = DMTool(self.db_path)
        self.close()
        self.rainy_dm.show()

    def open_rainybg(self):
        os.chdir("RainyBG")
        self.rainy_bag = RainyBG(self.db_path)
        self.close()
        self.rainy_bag.show()
Esempio n. 17
0
    def value(self, value):
        ControlBase.label.fset(self, value)

        for item in range(self.form.count(), -1, -1):
            self.form.removeItem(item)

        for item in value:
            if isinstance(item, tuple):
                widget = QFrame(self.form)
                layout = QVBoxLayout()

                if conf.PYFORMS_USE_QT5:
                    layout.setContentsMargins(0, 0, 0, 0)
                else:
                    layout.setMargin(0)

                widget.setLayout(layout)

                for e in item[1]:
                    if isinstance(e, tuple):
                        hwidget = QFrame(self.form)
                        hlayout = QHBoxLayout()

                        if conf.PYFORMS_USE_QT5:
                            hlayout.setContentsMargins(0, 0, 0, 0)
                        else:
                            hlayout.setMargin(0)

                        hwidget.setLayout(hlayout)
                        for ee in e:
                            hlayout.addWidget(ee.form)
                        widget.layout().addWidget(hwidget)
                    else:
                        widget.layout().addWidget(e.form)
                self.form.addItem(widget, item[0])
            else:
                self.form.addItem(item.form, item.label)
Esempio n. 18
0
    def create_other_player_layout(self, name):
        # Creates a dice mat, a cup, a name label and the place to write what
        # bids the player made
        layout = QVBoxLayout()
        player_name = QLabel(name)

        scroll = QScrollArea()
        scroll.setMaximumHeight(90)
        scroll.setWidgetResizable(True)  # CRITICAL

        inner = QFrame(scroll)
        inner.setLayout(QVBoxLayout())

        scroll.setWidget(inner)  # CRITICAL

        for i in range(50):
            inner.layout().addWidget(QLabel(f"{i} threes"))

        layout.addWidget(player_name)
        layout.addWidget(scroll)

        frame = QFrame()
        frame.setLayout(layout)
        return frame
Esempio n. 19
0
class VerticallyCompressedWidget(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setLayout(QVBoxLayout())
        self._contentsFrame = QFrame(parent=self)
        spacer = QSpacerItem(0, 0, QSizePolicy.Expanding,
                             QSizePolicy.Expanding)
        self.layout().addWidget(self._contentsFrame)
        self.layout().addItem(spacer)
        self.layout = self._layout  # override methods
        self.setLayout = self._setLayout

    def _layout(self) -> QLayout:
        return self._contentsFrame.layout()

    def _setLayout(self, layout: QLayout):
        self._contentsFrame.setLayout(layout)
Esempio n. 20
0
    def __init__(self, parent: QWidget):
        super().__init__("Results", parent=parent)
        self.setStyleSheet(
            "QDockWidget > QWidget { border: 1px solid lightgray; }")
        self.setObjectName('ResultsTableDock')
        self._widget = QWidget()
        self._widget.setLayout(QGridLayout())
        self._table = ResultsTable()
        checkBoxFrame = QFrame(parent=self)
        checkBoxFrame.setLayout(QVBoxLayout())
        checkBoxFrame.layout().setContentsMargins(1, 1, 1, 1)
        checkBoxFrame.layout().setSpacing(1)
        self._checkBoxes = []
        for i, (name, (default, settingsName, compilerClass,
                       tooltip)) in enumerate(self._table.columns.items()):
            c = QCheckBox(name)
            c.setCheckState(2) if default else c.setCheckState(0)
            c.stateChanged.connect(
                lambda state, j=i: self._table.setColumnHidden(j, state == 0))
            checkBoxFrame.layout().addWidget(c)
            self._checkBoxes.append(c)
        self._roiNameEdit = QLineEdit('.*', self._widget)
        self._roiNameEdit.setToolTip(
            "ROIs matching this RegEx pattern will be compiled.")
        self._analysisNameEdit = QLineEdit('.*', self._widget)
        self._analysisNameEdit.setToolTip(
            "Analyses matching this RegEx pattern will be compiled.")
        self._compileButton = QPushButton("Compile")

        self._compMan = CompilationManager(self.window())
        self._compileButton.released.connect(self._compMan.run)
        self._compMan.compilationDone.connect(self._handleCompilationResults)

        scroll = QScrollArea()
        scroll.setWidget(checkBoxFrame)
        scroll.verticalScrollBar().setStyleSheet(
            "QScrollBar:horizontal { height: 10px; }")
        scroll.setMaximumWidth(checkBoxFrame.width() + 10)
        scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        scroll.horizontalScrollBar().setEnabled(False)
        sidebar = QWidget()
        l = QGridLayout()
        l.addWidget(scroll, 0, 0, 1, 2)
        l.addWidget(QLabel('Analysis:'), 1, 0, 1, 1)
        l.addWidget(self._analysisNameEdit, 1, 1, 1, 1)
        l.addWidget(QLabel("Roi:"), 2, 0, 1, 1)
        l.addWidget(self._roiNameEdit, 2, 1, 1, 1)
        l.addWidget(self._compileButton, 3, 0, 1, 2)
        sidebar.setLayout(l)
        sidebar.setMaximumWidth(scroll.width() + 10)
        self._widget.layout().addWidget(sidebar, 0, 0)
        self._widget.layout().addWidget(self._table, 0, 1)
        self.setWidget(self._widget)
Esempio n. 21
0
	def createTopBar(self):
		topbar = QFrame()
		topbar.setFixedHeight(50)
		topbar.setObjectName("topbar")
		topbar.setLayout(QHBoxLayout())
		topbar.layout().setAlignment(Qt.AlignLeft)

		"""buttonClose = loader.buttonIcon("close", 35, 35)
		buttonClose.setObjectName("buttonClose")
		buttonClose.setFixedSize(35, 35)
		buttonClose.setFlat(True)
		buttonClose.clicked.connect(self.close)		"""

		self._title = QLabel()
		topbar.layout().addWidget(self._title)
		topbar.layout().addStretch()
		#topbar.layout().addWidget(buttonClose)
		return topbar
class GridCard(QFrame, QObject):
    def __init__(self,
                 parent=None,
                 debug=False,
                 with_actions=True,
                 with_title=True):
        super(GridCard, self).__init__(parent)
        self._buttons = []

        self._content_layout = QVBoxLayout()
        self._content_layout.setContentsMargins(0, 0, 0, 0)
        self._content_layout.setSpacing(0)
        self.setLayout(self._content_layout)
        self.setFixedHeight(150)

        self._title_widget = QLabel()
        self._title_widget.setStyleSheet("QLabel { font-size : 14px;}")
        self._title_widget.setAlignment(QtCore.Qt.AlignHCenter
                                        | QtCore.Qt.AlignVCenter)
        self._title_widget.setScaledContents(True)

        self._sub_title_widget = QLabel()
        self._sub_title_widget.setStyleSheet("QLabel { font-size : 10px;}")
        self._sub_title_widget.setAlignment(QtCore.Qt.AlignHCenter
                                            | QtCore.Qt.AlignVCenter)
        self._sub_title_widget.setScaledContents(True)

        self._body_widget = None

        # layouts

        self._body_frame = QFrame()
        self._body_frame.setMinimumWidth(150)
        self._body_frame.setObjectName("image_container")
        self._body_frame.setLayout(QVBoxLayout())
        self._body_frame.layout().setContentsMargins(2, 2, 2, 2)
        self._body_frame.layout().setAlignment(QtCore.Qt.AlignHCenter)
        size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        size_policy.setVerticalStretch(4)
        self._body_frame.setSizePolicy(size_policy)

        self._title_frame = QFrame()
        self._title_frame.setLayout(QVBoxLayout())
        self._title_frame.layout().setContentsMargins(2, 2, 2, 2)
        self._title_frame.layout().addWidget(self._title_widget)
        self._title_frame.layout().addWidget(self._sub_title_widget)
        size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        size_policy.setVerticalStretch(1)
        self._title_frame.setSizePolicy(size_policy)

        self._actions_frame = QFrame()
        self._actions_frame.setLayout(QHBoxLayout())
        self._actions_frame.setFixedHeight(30)
        self._actions_frame.layout().setContentsMargins(0, 0, 0, 0)
        size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        size_policy.setVerticalStretch(2)
        self._actions_frame.setSizePolicy(size_policy)

        # self._body_frame.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Ex)
        # self._title_frame.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Minimum)
        # self._actions_frame.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Minimum)

        self._content_layout.addWidget(self._body_frame)
        if with_title:
            self._content_layout.addWidget(self._title_frame)
        if with_actions:
            self._content_layout.addWidget(self._actions_frame,
                                           alignment=QtCore.Qt.AlignCenter)

        if debug:
            self.setFrameStyle(QFrame.Box)
            self._body_frame.setFrameStyle(QFrame.Box)
            self._title_frame.setFrameStyle(QFrame.Box)
            self._actions_frame.setFrameStyle(QFrame.Box)

    def add_buttons(self, args: typing.Any):
        if isinstance(args, QPushButton):
            self._actions_frame.layout().addWidget(args)
        else:
            for btn in args:
                if isinstance(btn, QPushButton):
                    self._actions_frame.layout().addWidget(btn)

    @property
    def body(self) -> QWidget:
        return self._body_widget

    @body.setter
    def body(self, value):
        self._body_widget = value
        self._body_frame.layout().addWidget(value)

    @property
    def body_frame(self):
        return self._body_frame

    @property
    def label(self):
        return self._title_widget

    @label.setter
    def label(self, value):
        self._title_widget.setText(value)

    @property
    def label2(self):
        return self._sub_title_widget

    @label2.setter
    def label2(self, value):
        self._sub_title_widget.setText(value)

    @property
    def buttons(self):
        return self._buttons

    @buttons.setter
    def buttons(self, value):
        self._buttons = value
        for btn in self._buttons:
            self._actions_frame.layout().addWidget(btn)
Esempio n. 23
0
    class HeaderFrame(QFrame):
        """ Clickable frame with title. """

        class AbstractHeaderFrameItem(QFrame):

            def __init__(self, parent):
                super(__class__, self).__init__(parent)
                self.setContentsMargins(0, 0, 0, 0)
                self.setLayout(QHBoxLayout())
                self.layout().setContentsMargins(0, 0, 0, 0)
                self.layout().setSpacing(0)

            def clearLayout(self):
                while self.layout().count():
                    child = self.layout().takeAt(0)
                    if child.widget():
                        child.widget().deleteLater()

            def setCentralWidget(self, widget: QWidget):
                self.clearLayout()
                self.layout().addWidget(widget)

            def refresh(self):
                pass

        class VSepItem(AbstractHeaderFrameItem):

            def __init__(self, parent):
                super(__class__, self).__init__(parent)
                self.setCentralWidget(VSep(self))

        class HSpacerItem(AbstractHeaderFrameItem):

            def __init__(self, parent):
                super(__class__, self).__init__(parent)
                self.setCentralWidget(HSpacer(self))

        arrowClicked = pyqtSignal()
        upButtonClicked = pyqtSignal()
        downButtonClicked = pyqtSignal()
        configButtonClicked = pyqtSignal()
        closeButtonClicked = pyqtSignal()

        def __init__(self, parent: 'ui.widget.CollapsibleFrame'):
            super(__class__, self).__init__(parent)

            self._parent = parent
            self.setMinimumHeight(26)
            self.setMaximumHeight(26)
            self.indicateError(False)

            self._hlayout = QHBoxLayout()
            self._hlayout.setContentsMargins(0, 0, 0, 0)
            self._hlayout.setSpacing(0)

            self._arrow = None

            self._hlayout.addWidget(self._init_header_frame(parent.isCollapsed()))
            self.setLayout(self._hlayout)

        def _init_header_frame(self, collapsed: bool):
            self._frm_header = QFrame(self)
            self._frm_header.setMinimumHeight(24)
            self._frm_header.setMaximumHeight(24)
            frm_header_layout = QHBoxLayout(self)
            frm_header_layout.setContentsMargins(0, 0, 0, 0)
            frm_header_layout.addWidget(self._init_arrow(collapsed))
            background_color = self._frm_header.palette().color(self._frm_header.backgroundRole())
            self._frm_header.setStyleSheet("QFrame { border:0px; background:" + background_color.darker(96).name() + "; }")
            self._frm_header.setLayout(frm_header_layout)
            return self._frm_header

        def _init_arrow(self, collapsed):
            self._arrow = CollapsibleFrame.Arrow(self, collapsed=collapsed)
            self._arrow.setMinimumWidth(24)
            self._arrow.setMaximumWidth(24)
            self._arrow.setStyleSheet("border:0px")
            return self._arrow

        def addWidget(self, header_item: AbstractHeaderFrameItem):
            self._frm_header.layout().addWidget(header_item)

        def refresh(self):
            """ Refreshes the header model (e.g. line-count, character-count, etc.). """
            for i in range(self._frm_header.layout().count()):
                widget = self._frm_header.layout().itemAt(i).widget()
                if isinstance(widget, CollapsibleFrame.HeaderFrame.AbstractHeaderFrameItem):
                    widget.refresh()

        def indicateError(self, status: bool):
            """ Indicates an error by painting the title-border red. Otherweise black. """
            if status:
                self.setStyleSheet("QFrame { border:1px solid red; }")
            else:
                self.setStyleSheet("QFrame { border:1px solid rgb(41, 41, 41); }")

        def mouseReleaseEvent(self, event):
            if self.underMouse() and event.button() == QtCore.Qt.LeftButton:
                # The arrow (or something non-button like) was clicked
                self.arrowClicked.emit()
            return super(CollapsibleFrame.HeaderFrame, self).mousePressEvent(event)
Esempio n. 24
0
class GuiSessionViewer(QSplitter):
    def __init__(self, config, querylist, mainwin, owner, debug=True):
        QSplitter.__init__(self, mainwin)
        self.debug = debug
        self.conf = config
        self.sql = querylist
        self.window = mainwin
        self.owner = owner

        self.liststore = None

        self.MYSQL_INNODB = 2
        self.PGSQL = 3
        self.SQLITE = 4

        self.fig = None
        self.canvas = None
        self.ax = None
        self.graphBox = None

        # create new db connection to avoid conflicts with other threads
        self.db = Database.Database(self.conf, sql=self.sql)
        self.cursor = self.db.cursor

        settings = {}
        settings.update(self.conf.get_db_parameters())
        settings.update(self.conf.get_import_parameters())
        settings.update(self.conf.get_default_paths())

        # text used on screen stored here so that it can be configured
        self.filterText = {
            'handhead': _('Hand Breakdown for all levels listed above')
        }

        filters_display = {
            "Heroes": True,
            "Sites": True,
            "Games": True,
            "Currencies": True,
            "Limits": True,
            "LimitSep": True,
            "LimitType": True,
            "Type": False,
            "Seats": True,
            "SeatSep": False,
            "Dates": True,
            "Groups": False,
            "GroupsAll": False,
            "Button1": True,
            "Button2": False
        }

        self.filters = Filters.Filters(self.db, display=filters_display)
        self.filters.registerButton1Name("_Refresh")
        self.filters.registerButton1Callback(self.refreshStats)

        scroll = QScrollArea()
        scroll.setWidget(self.filters)

        # ToDo: store in config
        # ToDo: create popup to adjust column config
        # columns to display, keys match column name returned by sql, values in tuple are:
        #     is column displayed, column heading, xalignment, formatting
        self.columns = [(1.0, "SID"), (1.0, "Hands"), (0.5, "Start"),
                        (0.5, "End"), (1.0, "Rate"), (1.0, "Open"),
                        (1.0, "Close"), (1.0, "Low"), (1.0, "High"),
                        (1.0, "Range"), (1.0, "Profit")]

        self.detailFilters = []  # the data used to enhance the sql select

        self.stats_frame = QFrame()
        self.stats_frame.setLayout(QVBoxLayout())
        self.view = None
        heading = QLabel(self.filterText['handhead'])
        heading.setAlignment(Qt.AlignCenter)
        self.stats_frame.layout().addWidget(heading)

        self.main_vbox = QSplitter(Qt.Vertical)

        self.graphBox = QFrame()
        self.graphBox.setLayout(QVBoxLayout())

        self.addWidget(scroll)
        self.addWidget(self.main_vbox)
        self.setStretchFactor(0, 0)
        self.setStretchFactor(1, 1)
        self.main_vbox.addWidget(self.graphBox)
        self.main_vbox.addWidget(self.stats_frame)

    def refreshStats(self, checkState):
        if self.view:
            self.stats_frame.layout().removeWidget(self.view)
            self.view.setParent(None)
        self.fillStatsFrame(self.stats_frame)

    def fillStatsFrame(self, frame):
        sites = self.filters.getSites()
        heroes = self.filters.getHeroes()
        siteids = self.filters.getSiteIds()
        games = self.filters.getGames()
        currencies = self.filters.getCurrencies()
        limits = self.filters.getLimits()
        seats = self.filters.getSeats()
        sitenos = []
        playerids = []

        # Which sites are selected?
        for site in sites:
            sitenos.append(siteids[site])
            _hname = Charset.to_utf8(heroes[site])
            result = self.db.get_player_id(self.conf, site, _hname)
            if result is not None:
                playerids.append(result)

        if not sitenos:
            #Should probably pop up here.
            print _("No sites selected - defaulting to PokerStars")
            sitenos = [2]
        if not games:
            print _("No games found")
            return
        if not currencies:
            print _("No currencies found")
            return
        if not playerids:
            print _("No player ids found")
            return
        if not limits:
            print _("No limits found")
            return

        self.createStatsPane(frame, playerids, sitenos, games, currencies,
                             limits, seats)

    def createStatsPane(self, frame, playerids, sitenos, games, currencies,
                        limits, seats):
        starttime = time()

        (results, quotes) = self.generateDatasets(playerids, sitenos, games,
                                                  currencies, limits, seats)

        if DEBUG:
            for x in quotes:
                print "start %s\tend %s  \thigh %s\tlow %s" % (x[1], x[2],
                                                               x[3], x[4])

        self.generateGraph(quotes)

        self.addTable(frame, results)

        self.db.rollback()
        print _("Stats page displayed in %4.2f seconds") % (time() - starttime)

    def generateDatasets(self, playerids, sitenos, games, currencies, limits,
                         seats):
        if (DEBUG): print "DEBUG: Starting generateDatasets"
        THRESHOLD = 1800  # Min # of secs between consecutive hands before being considered a new session
        PADDING = 5  # Additional time in minutes to add to a session, session startup, shutdown etc

        # Get a list of timestamps and profits

        q = self.sql.query['sessionStats']
        start_date, end_date = self.filters.getDates()
        q = q.replace("<datestest>",
                      " BETWEEN '" + start_date + "' AND '" + end_date + "'")

        for m in self.filters.display.items():
            if m[0] == 'Games' and m[1]:
                if len(games) > 0:
                    gametest = str(tuple(games))
                    gametest = gametest.replace("L", "")
                    gametest = gametest.replace(",)", ")")
                    gametest = gametest.replace("u'", "'")
                    gametest = "AND gt.category in %s" % gametest
                else:
                    gametest = "AND gt.category IS NULL"
        q = q.replace("<game_test>", gametest)

        limittest = self.filters.get_limits_where_clause(limits)
        q = q.replace("<limit_test>", limittest)

        currencytest = str(tuple(currencies))
        currencytest = currencytest.replace(",)", ")")
        currencytest = currencytest.replace("u'", "'")
        currencytest = "AND gt.currency in %s" % currencytest
        q = q.replace("<currency_test>", currencytest)

        if seats:
            q = q.replace(
                '<seats_test>', 'AND h.seats BETWEEN ' + str(seats['from']) +
                ' AND ' + str(seats['to']))
        else:
            q = q.replace('<seats_test>', 'AND h.seats BETWEEN 0 AND 100')

        nametest = str(tuple(playerids))
        nametest = nametest.replace("L", "")
        nametest = nametest.replace(",)", ")")
        q = q.replace("<player_test>", nametest)
        q = q.replace("<ampersand_s>", "%s")

        if DEBUG:
            hands = [
                (u'10000', 10),
                (u'10000', 20),
                (u'10000', 30),
                (u'20000', -10),
                (u'20000', -20),
                (u'20000', -30),
                (u'30000', 40),
                (u'40000', 0),
                (u'50000', -40),
                (u'60000', 10),
                (u'60000', 30),
                (u'60000', -20),
                (u'70000', -20),
                (u'70000', 10),
                (u'70000', 30),
                (u'80000', -10),
                (u'80000', -30),
                (u'80000', 20),
                (u'90000', 20),
                (u'90000', -10),
                (u'90000', -30),
                (u'100000', 30),
                (u'100000', -50),
                (u'100000', 30),
                (u'110000', -20),
                (u'110000', 50),
                (u'110000', -20),
                (u'120000', -30),
                (u'120000', 50),
                (u'120000', -30),
                (u'130000', 20),
                (u'130000', -50),
                (u'130000', 20),
                (u'140000', 40),
                (u'140000', -40),
                (u'150000', -40),
                (u'150000', 40),
                (u'160000', -40),
                (u'160000', 80),
                (u'160000', -40),
            ]
        else:
            self.db.cursor.execute(q)
            hands = self.db.cursor.fetchall()

        #fixme - nasty hack to ensure that the hands.insert() works
        # for mysql data.  mysql returns tuples which can't be inserted
        # into so convert explicity to list.
        hands = list(hands)

        if (not hands):
            return ([], [])

        hands.insert(0, (hands[0][0], 0))

        # Take that list and create an array of the time between hands
        times = map(lambda x: long(x[0]), hands)
        profits = map(lambda x: float(x[1]), hands)
        #print "DEBUG: times   : %s" % times
        #print "DEBUG: profits: %s" % profits
        #print "DEBUG: len(times) %s" %(len(times))
        diffs = diff(
            times
        )  # This array is the difference in starttime between consecutive hands
        diffs2 = append(
            diffs, THRESHOLD + 1
        )  # Append an additional session to the end of the diffs, so the next line
        # includes an index into the last 'session'
        index = nonzero(
            diffs2 > THRESHOLD
        )  # This array represents the indexes into 'times' for start/end times of sessions
        # times[index[0][0]] is the end of the first session,
        #print "DEBUG: len(index[0]) %s" %(len(index[0]))
        if len(index[0]) > 0:
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            #print "DEBUG: index %s" %(index)
            pass
        else:
            index = [[0]]
            #print "DEBUG: index %s" %(index)
            #print "DEBUG: index[0][0] %s" %(index[0][0])
            pass

        first_idx = 1
        quotes = []
        results = []
        cum_sum = cumsum(profits) / 100
        sid = 1

        total_hands = 0
        total_time = 0
        global_open = None
        global_lwm = None
        global_hwm = None

        self.times = []
        # Take all results and format them into a list for feeding into gui model.
        #print "DEBUG: range(len(index[0]): %s" % range(len(index[0]))
        for i in range(len(index[0])):
            last_idx = index[0][i]
            hds = last_idx - first_idx + 1  # Number of hands in session
            if hds > 0:
                stime = strftime("%d/%m/%Y %H:%M", localtime(
                    times[first_idx]))  # Formatted start time
                etime = strftime("%d/%m/%Y %H:%M", localtime(
                    times[last_idx]))  # Formatted end time
                self.times.append((times[first_idx] - PADDING * 60,
                                   times[last_idx] + PADDING * 60))
                minutesplayed = (times[last_idx] - times[first_idx]) / 60
                minutesplayed = minutesplayed + PADDING
                if minutesplayed == 0:
                    minutesplayed = 1
                hph = hds * 60 / minutesplayed  # Hands per hour
                end_idx = last_idx + 1
                won = sum(profits[first_idx:end_idx]) / 100.0
                #print "DEBUG: profits[%s:%s]: %s" % (first_idx, end_idx, profits[first_idx:end_idx])
                hwm = max(cum_sum[first_idx -
                                  1:end_idx])  # include the opening balance,
                lwm = min(cum_sum[first_idx -
                                  1:end_idx])  # before we win/lose first hand
                open = (sum(profits[:first_idx])) / 100
                close = (sum(profits[:end_idx])) / 100
                #print "DEBUG: range: (%s, %s) - (min, max): (%s, %s) - (open,close): (%s, %s)" %(first_idx, end_idx, lwm, hwm, open, close)

                total_hands = total_hands + hds
                total_time = total_time + minutesplayed
                if (global_lwm == None or global_lwm > lwm):
                    global_lwm = lwm
                if (global_hwm == None or global_hwm < hwm):
                    global_hwm = hwm
                if (global_open == None):
                    global_open = open
                    global_stime = stime

                results.append([
                    sid, hds, stime, etime, hph,
                    "%.2f" % open,
                    "%.2f" % close,
                    "%.2f" % lwm,
                    "%.2f" % hwm,
                    "%.2f" % (hwm - lwm),
                    "%.2f" % won
                ])
                quotes.append((sid, open, close, hwm, lwm))
                #print "DEBUG: Hands in session %4s: %4s  Start: %s End: %s HPH: %s Profit: %s" %(sid, hds, stime, etime, hph, won)
                first_idx = end_idx
                sid = sid + 1
            else:
                print "hds <= 0"
        global_close = close
        global_etime = etime
        results.append([''] * 11)
        results.append([
            _("all"), total_hands, global_stime, global_etime,
            total_hands * 60 / total_time,
            "%.2f" % global_open,
            "%.2f" % global_close,
            "%.2f" % global_lwm,
            "%.2f" % global_hwm,
            "%.2f" % (global_hwm - global_lwm),
            "%.2f" % (global_close - global_open)
        ])

        return (results, quotes)

    def clearGraphData(self):

        try:
            try:
                if self.canvas:
                    self.graphBox.layout().removeWidget(self.canvas)
                    self.canvas.setParent(None)
            except:
                pass

            if self.fig is not None:
                self.fig.clear()
            self.fig = Figure(figsize=(5, 4), dpi=100)
            if self.canvas is not None:
                self.canvas.destroy()

            self.canvas = FigureCanvas(self.fig)
            self.canvas.setParent(self)
        except:
            err = traceback.extract_tb(sys.exc_info()[2])[-1]
            print _("Error:") + " " + err[2] + "(" + str(err[1]) + "): " + str(
                sys.exc_info()[1])
            raise

    def generateGraph(self, quotes):
        self.clearGraphData()

        self.ax = self.fig.add_subplot(111)

        self.ax.set_title(_("Session candlestick graph"))

        #Set axis labels and grid overlay properites
        self.ax.set_xlabel(_("Sessions"), fontsize=12)
        self.ax.set_ylabel("$", fontsize=12)
        self.ax.grid(color='g', linestyle=':', linewidth=0.2)

        candlestick_ochl(self.ax,
                         quotes,
                         width=0.50,
                         colordown='r',
                         colorup='g',
                         alpha=1.00)
        self.graphBox.layout().addWidget(self.canvas)
        self.canvas.draw()

    def addTable(self, frame, results):
        colxalign, colheading = range(2)

        self.liststore = QStandardItemModel(0, len(self.columns))
        self.liststore.setHorizontalHeaderLabels(
            [column[colheading] for column in self.columns])
        for row in results:
            listrow = [QStandardItem(str(r)) for r in row]
            for item in listrow:
                item.setEditable(False)
            self.liststore.appendRow(listrow)

        self.view = QTableView()
        self.view.setModel(self.liststore)
        self.view.verticalHeader().hide()
        self.view.setSelectionBehavior(QTableView.SelectRows)
        frame.layout().addWidget(self.view)
        self.view.doubleClicked.connect(self.row_activated)

    def row_activated(self, index):
        if index.row() < len(self.times):
            replayer = None
            for tabobject in self.owner.threads:
                if isinstance(tabobject, GuiHandViewer.GuiHandViewer):
                    replayer = tabobject
                    self.owner.tab_hand_viewer(None)
                    break
            if replayer is None:
                self.owner.tab_hand_viewer(None)
                for tabobject in self.owner.threads:
                    if isinstance(tabobject, GuiHandViewer.GuiHandViewer):
                        replayer = tabobject
                        break
            # added the timezone offset ('+00:00') to make the db query work. Otherwise the hands
            # at the edges of the date range are not included. A better solution may be possible.
            # Optionally the end date in the call below, which is a Long gets a '+1'.
            reformat = lambda t: strftime("%Y-%m-%d %H:%M:%S+00:00", gmtime(t))
            handids = replayer.get_hand_ids_from_date_range(
                reformat(self.times[index.row()][0]),
                reformat(self.times[index.row()][1]))
            replayer.reload_hands(handids)
Esempio n. 25
0
class TabToolbar(QToolBar):
    """[summary]

    Args:
        _TabToolbar ([type]): [description]

    Returns:
        [type]: [description]
    """

    Minimized = QtCore.pyqtSignal()
    Maximized = QtCore.pyqtSignal()
    SpecialTabClicked = QtCore.pyqtSignal()
    StyleChanged = QtCore.pyqtSignal()

    def __init__(self,
                 parent: QWidget = None,
                 group_maxheight: int = 75,
                 group_rowcount: int = 3):
        super(TabToolbar, self).__init__(parent)
        style.register_default_styles()
        self.group_rowcount = group_rowcount
        self.group_maxheight = group_maxheight
        self.has_specialtab = False
        self.current_index = 0
        self.ignore_styleevent = False
        self.is_shown = True
        self._is_minimized = False
        self.maxheight = QtWidgets.QWIDGETSIZE_MAX
        self._style = style.StyleParams()
        self.setObjectName("TabToolbar")

        # self.tempShowTimer = QtCore.QTimer()
        # self.tempShowTimer.setSingleShot(True)
        # self.tempShowTimer.setInterval(QApplication.doubleClickInterval())

        self.setProperty("TabToolbar", QtCore.QVariant(True))
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.layout().setSpacing(0)
        self.setContentsMargins(0, 0, 0, 0)
        self.setFloatable(False)
        self.setMovable(False)
        self.setAllowedAreas(QtCore.Qt.TopToolBarArea)
        self.tabBar = QTabWidget(self)

        self.tabBar.setProperty("TTWidget", QtCore.QVariant(True))
        self.tabBar.tabBar().setProperty("TTTab", QtCore.QVariant(True))
        self.tabBarHandle = self.addWidget(self.tabBar)
        self.tabBar.setUsesScrollButtons(True)

        self.cornerActions = QFrame(self)
        self.cornerActions.setFrameShape(QFrame.NoFrame)
        self.cornerActions.setLineWidth(0)
        self.cornerActions.setContentsMargins(0, 0, 0, 0)
        self.cornerActions.setSizePolicy(QSizePolicy.Preferred,
                                         QSizePolicy.Minimum)
        self.cornerLayout = QHBoxLayout(self.cornerActions)

        self.cornerLayout.setContentsMargins(0, 0, 0, 0)
        self.cornerLayout.setSpacing(0)
        self.cornerLayout.setDirection(QBoxLayout.LeftToRight)
        self.cornerActions.setLayout(self.cornerLayout)

        self.hideAction = QAction(self)
        self.hideAction.setCheckable(True)
        self.hideAction.setText("▲")
        self.hideButton = QToolButton(self.tabBar)
        self.hideButton.setProperty("TTHide", QtCore.QVariant(True))
        self.hideButton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
        self.hideButton.setDefaultAction(self.hideAction)
        self.hideButton.setAutoRaise(True)
        self.hideButton.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)

        self.hideAction.triggered.connect(self._hideaction)
        self.tabBar.tabBarDoubleClicked.connect(self.hideAction.trigger)
        self.tabBar.tabBarClicked.connect(self.current_tabchanged)
        self.tabBar.currentChanged.connect(self.focus_changed)
        self.cornerLayout.addWidget(self.hideButton)
        self.tabBar.setCornerWidget(self.cornerActions)
        self.set_style(style.get_defaultstyle())

    def _hideaction(self):
        # self.tempShowTimer.start()
        self._is_minimized = self.hideAction.isChecked()
        self.hideAction.setText("▼" if self._is_minimized else "▲")
        self.hide_at(self.tabBar.currentIndex())
        if self._is_minimized:
            self.Minimized.emit()
        else:
            self.Maximized.emit()

    def event(self, event: QtCore.QEvent):
        if event.type(
        ) == QtCore.QEvent.StyleChange and not self.ignore_styleevent:
            # TODO: Validatre if we need a timer
            stylename = (self._style.objectName()
                         if self._style else style.get_defaultstyle())
            self.set_style(stylename)
        return super(TabToolbar, self).event(event)

    def focus_changed(self, old: QWidget = None, now: QWidget = None):
        if now and now != self:
            if self.isMinimized() and self.is_shown:
                parent = now
                while parent:
                    parent = parent.parent()
                    if parent == self:
                        return
                self.hide_at(self.current_index)

    def rowcount(self):
        return self.group_rowcount

    def group_maxheight(self):
        return self.group_maxheight * style.get_scalefactor(self)

    def set_style(self, stylename: str):
        self.ignore_styleevent = True
        self._style = style.create_style(stylename)
        stylesheet = style.get_stylesheet(self._style)
        self.setStyleSheet(stylesheet)
        self.ignore_styleevent = False
        self.StyleChanged.emit()

    def get_style(self) -> str:
        if self._style:
            return self._style.objectName()
        return ""

    def add_corneraction(self, action: QAction):
        action_button = QToolButton(self.tabBar)
        action_button.setProperty("TTInternal", QtCore.QVariant(True))
        action_button.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly)
        action_button.setDefaultAction(action)
        action_button.setAutoRaise(True)
        action_button.setSizePolicy(QSizePolicy.Expanding,
                                    QSizePolicy.Expanding)
        self.cornerActions.layout().addWidget(action_button)

    def set_specialtabenabled(self, enabled: bool):
        self.has_specialtab = enabled
        self.tabBar.tabBar().setProperty("TTSpecial", QtCore.QVariant(enabled))
        if enabled and self.tabBar.count() > 0:
            self.tabBar.setCurrentIndex(1)

    def hide_action(self) -> QAction:
        return self.hideAction

    def tab_clicked(self, index: int):
        if self.tempShowTimer.isActive() or (index == 0
                                             and self.has_specialtab):
            return
        if self._is_minimized:
            if self.is_shown and index != self.current_index:
                return
            self._is_minimized = self.is_shown
            self.hide_at(index)
            self._is_minimized = True

    def current_tabchanged(self, index: int):
        QtCore.QSignalBlocker(self.tabBar)
        if index == 0 and self.has_specialtab:
            self.tabBar.setCurrentIndex(self.current_index)
            self.SpecialTabClicked.emit()
        else:
            self.current_index = index

    @property
    def current_tab(self) -> int:
        return self.current_index

    def set_currenttab(self, index: int):
        self.tabBar.setCurrentIndex(index)

    def hide_at(self, index: int):
        if self._is_minimized:
            minheight = self.tabBar.tabBar().height() + 2
            self.tabBar.setMaximumHeight(minheight)
            self.tabBar.setMinimumHeight(minheight)
            self.setMaximumHeight(minheight)
            self.setMinimumHeight(minheight)
            self.is_shown = False
        else:
            self.tabBar.setCurrentIndex(index)
            if not self.is_shown:
                self.tabBar.setMaximumHeight(self.maxheight)
                self.tabBar.setMinimumHeight(self.maxheight)
                self.setMaximumHeight(self.maxheight)
                self.setMinimumHeight(self.maxheight)
                self.tabBar.adjustSize()
            self.setFocus()
            self.is_shown = True

    def hide_tab(self, index: int):
        page = self.sender()
        QtCore.QSignalBlocker(page)
        for i in range(self.tabBar.count()):
            if self.tabBar.widget(i) == page:
                self.tabBar.removeTab(i)
                return
        self.current_index = self.tabBar.currentIndex()

    @QtCore.pyqtSlot(int)
    def _adjustverticalsize(self, vsize: int):
        self.maxheight = vsize + self.tabBar.tabBar().height() + 6
        self.setMaximumHeight(self.maxheight)
        self.setMinimumHeight(self.maxheight)

    def adjust_verticalsize(self, vsize: int):
        QtCore.QTimer.singleShot(0, lambda: self._adjustverticalsize(vsize)
                                 )  # type: ignore[attr-defined]
        # self._AdjustVerticleSize(vSize)

    def show_tab(self, index: int):
        tab_page = self.sender()
        QtCore.QSignalBlocker(tab_page)
        self.tabBar.insertTab(index, tab_page, tab_page.objectName())
        self.current_index = self.tabBar.currentIndex()

    def add_page(self, page_name: str) -> page.Page:
        tab_page = page.Page(self.tabBar.count(), page_name)
        QtCore.QSignalBlocker(tab_page)
        tab_page.Hiding.connect(self.hide_tab)
        tab_page.Showing.connect(self.show_tab)
        self.tabBar.addTab(tab_page, page_name)
        return tab_page
Esempio n. 26
0
class _UIElement(QObject):
    """
    Универсальный класс элемента интерфейса. Создан, потому что изначальные классы PyQt
    требуют значительной доработки и к тому же недостаточно интуитивны, легко запутаться
    в Qt-овском нагромождении из виджетов, лэйаутов, item объектов, прочей шелухи.
    Плюсы этого класса: позволяет отображать подпись над элементом,
                                  удобно включать/выключать функциональность,
                        сразу ставит виджет в центр (а не в край, чтоб потом его ещё ровнять)
                        убирает ненужные отступы между элементами
                        все последующие элементы наследуются от него
    """

    def __init__(self, widget: QWidget = None, layout: QLayout = None,
                 description: str = None, disable: bool = False, stroked: bool = False):
        """
        :param widget: класс Qt Widget, который будет отображаться как элемент интерфейса
        :param layout: класс слоя, который будет основанием, на котором будет лежать виджет
        :param description: описание или название, котороые при наличии будет отображаться над виджетом
        :param disable: опция отключения виджета при создании. По умолчанию False, т.е. виджет включён
        """
        super().__init__()

        self._inner_widget = widget
        self._layout = QVBoxLayout() if layout is None else layout
        self._layout.setContentsMargins(2, 2, 2, 2)
        if description is not None or layout is not None:
            self._out_widget = QFrame()
            if stroked:
                self._out_widget.setFrameStyle(QFrame.Plain)
            if description is not None:
                self._layout.addWidget(QLabel(description), alignment=Qt.AlignCenter)
            if widget is not None:
                self._layout.addWidget(widget)
            self._out_widget.setLayout(self._layout)
        elif widget is not None:
            self._out_widget = widget
            widget.setDisabled(disable)

    def toggle_element(self, state=None):
        if self._inner_widget is not None:
            self._inner_widget.setDisabled(self._inner_widget.isEnabled() if state is None else not state)

    def set_max_width(self, width):
        self._out_widget.setMaximumWidth(width)

    def set_max_height(self, height):
        self._out_widget.setMaximumHeight(height)

    def set_fixed_width(self, width):
        self._out_widget.setFixedWidth(width)

    def set_fixed_height(self, height):
        self._out_widget.setFixedHeight(height)

    def set_min_width(self, width):
        self._out_widget.setMinimumWidth(width)

    def set_min_height(self, height):
        self._out_widget.setMinimumHeight(height)

    def __layout__(self) -> QLayout:
        return self._out_widget.layout()

    def __widget__(self) -> QWidget:
        return self._out_widget
Esempio n. 27
0
class CorpusGeneralWidget(QWidget):
    def __init__(self, parent):
        super(CorpusGeneralWidget, self).__init__(parent)
        self.setLayout(QVBoxLayout())

        self.layout().addWidget(QLabel("Corpus Information", self))
        self.w_corpus = QFrame(self)
        self.w_corpus.setWindowTitle("Corpus Information")
        self.w_corpus.setLayout(QVBoxLayout())

        self.layout().addWidget(self.w_corpus)
        self.lt_actions = QHBoxLayout(self)
        self.layout().addWidget(QLabel("Template", self))
        self.layout().addItem(self.lt_actions)

        self.layout().addWidget(QLabel("Project Information", self))
        self.w_movie = CorpusMovieWidget(self)
        self.layout().addWidget(self.w_movie)

        self.w_name = QWidget(self)
        self.w_name.setLayout(QHBoxLayout())
        self.w_name.layout().addWidget(QLabel("Corpus Name"))
        self.textEdit_Name = QLineEdit(self.w_name)
        self.textEdit_Name.editingFinished.connect(self.on_name_changed)
        self.w_name.layout().addWidget(self.textEdit_Name)

        self.w_corpus.layout().addWidget(self.w_name)

        self.templateStack = QStackedWidget(self)
        self.templateStack.setSizePolicy(QSizePolicy.Expanding,
                                         QSizePolicy.Maximum)
        self.lt_actions.addWidget(self.templateStack)
        self.template_widget_manage = QWidget(self.templateStack)
        self.template_widget_edit = QWidget(self.templateStack)
        self.templateStack.addWidget(self.template_widget_manage)
        self.templateStack.addWidget(self.template_widget_edit)

        self.template_widget_manage.setLayout(QGridLayout())
        self.template_widget_edit.setLayout(QGridLayout())

        self.btn_EditTemplate = QPushButton("Edit Template", self)
        self.template_widget_manage.layout().addWidget(self.btn_EditTemplate,
                                                       0, 0)

        self.btn_ImportTemplate = QPushButton("Import Template", self)
        self.template_widget_manage.layout().addWidget(self.btn_ImportTemplate,
                                                       0, 1)

        self.btn_SaveTemplate = QPushButton("Save Template", self)
        self.template_widget_edit.layout().addWidget(self.btn_SaveTemplate, 0,
                                                     0)

        self.btn_CloseTemplate = QPushButton("Close Template", self)
        self.template_widget_edit.layout().addWidget(self.btn_CloseTemplate, 0,
                                                     1)

        self.layout().addItem(
            QSpacerItem(1, 1, QSizePolicy.Preferred, QSizePolicy.Expanding))
        self.corpus = None
        self.setEnabled(False)

    def on_corpus_loaded(self, corpus):
        self.corpus = corpus
        if self.corpus is not None:
            self.textEdit_Name.setText(self.corpus.name)
            self.setEnabled(True)
        else:
            self.setEnabled(False)

    def on_name_changed(self):
        if self.corpus is not None:
            if self.textEdit_Name.text() != "":
                self.corpus.name = self.textEdit_Name.text()
            self.corpus.save()

    def on_project_changed(self, project):
        self.w_movie.set_project(project)
Esempio n. 28
0
class VideoDialog(QDialog):
    def __init__(self, video_path, parent=None):
        super(VideoDialog, self).__init__(parent)
        #self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.resize(400, 400)
        position = self.cursor().pos()
        position.setX(position.x())
        position.setY(position.y())
        self.move(position)
        #self.setWindowOpacity(0.9)
        self.setLayout(QVBoxLayout())
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.widget = QFrame()
        self.widget.setStyleSheet('''
            QFrame{
            border-style: outset;
            border-width: 1px;
            /*border-radius: 10px;*/
            border-color: #B94129;
            }
        ''')
        #self.widget.setFrameStyle(QFrame.Box)
        self.widget.setLayout(QVBoxLayout())
        self.widget.layout().setContentsMargins(10, 10, 10, 10)

        self.video_player = VideoPlayer()
        self.video_player.source = video_path
        self.video_player.play()
        self.video_player.signals.video_position_changed_signal.connect(
            self.video_position_changed)
        duration = self.video_player.total_duration

        self.video_duration_slider = QSlider(orientation=QtCore.Qt.Horizontal)
        self.video_duration_slider.setRange(0, duration)
        self.video_duration_slider.setTickInterval(5)
        self.video_duration_slider.sliderMoved.connect(
            self.slider_changed_handler)
        #self.video_duration_slider.setTickPosition(QSlider.TicksBelow)

        self.setMouseTracking(True)
        self.setWindowFlags(QtCore.Qt.Popup | QtCore.Qt.WindowStaysOnTopHint
                            | QtCore.Qt.FramelessWindowHint
                            | QtCore.Qt.X11BypassWindowManagerHint)
        #self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.widget.layout().addWidget(self.video_player)
        self.widget.layout().addWidget(self.video_duration_slider)
        self.layout().addWidget(self.widget)

    def setMouseTracking(self, flag):
        def set_mouse_tracking(parent):
            for child in parent.findChildren(QtCore.QObject):
                try:
                    child.setMouseTracking(flag)
                except:
                    pass
                set_mouse_tracking(child)

        QWidget.setMouseTracking(self, flag)
        set_mouse_tracking(self)

    def slider_changed_handler(self, change):
        self.video_player.go_to(change)

    def video_position_changed(self, current, total):
        self.video_duration_slider.setValue(current)

    def mouseMoveEvent(self, event: QMouseEvent) -> None:
        # print('mouseMoveEvent: x=%d, y=%d' % (event.x(), event.y()))
        if not self.rect().contains(event.pos()):
            self.close()
    def __init__(self):
        super(memoryDump, self).__init__()

        if memoryDump.memoryDumpFrame == None:
            memoryDump.memoryDumpFrame = QFrame()

            Font = QtGui.QFont("Arial", 15, QtGui.QFont.Bold)
            Font.setBold(True)
            Title = QtWidgets.QLabel(self)
            Title.setText("EEPROM Memory Dump")
            Title.setAlignment(Qt.AlignCenter)
            Title.setFont(Font)
            Title.setAlignment(Qt.AlignCenter)
            Title.setGeometry(QRect(290, 40, 191, 31))

            self.refreshButton = QtWidgets.QPushButton("Refresh")
            self.refreshButton.clicked.connect(lambda: self.submitClicked)

            self.memoryAddressLabel = QLabel(self)
            self.memoryAddressLabel.setText('Memory Address:')
            self.line = QLineEdit(self)

            self.line.move(80, 20)
            self.line.resize(100, 32)
            self.memoryAddressLabel.move(20, 20)

            submitbutton = QPushButton('Submit', self)
            submitbutton.clicked.connect(self.submitClicked)
            submitbutton.resize(100, 32)
            submitbutton.move(80, 60)

            self.inputFrame = QFrame()
            self.inputFrame.layout = QHBoxLayout()
            self.inputFrame.layout.addWidget(self.memoryAddressLabel)
            self.inputFrame.layout.addWidget(self.line)
            self.inputFrame.layout.addWidget(submitbutton)
            self.inputFrame.layout.addWidget(self.refreshButton, 0,
                                             Qt.AlignRight)
            self.inputFrame.setLayout(self.inputFrame.layout)

            headerfont = QtGui.QFont()
            headerfont.setFamily("Arial Black")
            headerfont.setPointSize(11)

            memoryDump.tableWidget = QTableWidget()
            memoryDump.tableWidget.setRowCount(2)
            memoryDump.tableWidget.setColumnCount(3)
            memoryDump.map = {}

            memoryDump.tableWidget.setItem(0, 0,
                                           QTableWidgetItem("Address   "))
            memoryDump.tableWidget.setItem(0, 1,
                                           QTableWidgetItem("Hex Values"))
            memoryDump.tableWidget.setItem(0, 2,
                                           QTableWidgetItem("Text Values"))

            tableview = QtWidgets.QTableView()
            tableview.setAlternatingRowColors(True)
            tableview.horizontalHeader().setSectionResizeMode(
                QtWidgets.QHeaderView.Stretch)

            memoryDump.tableWidget.resizeColumnsToContents()

            simulatorFrame = QFrame()
            simulatorFrame.layout = QVBoxLayout()
            simulatorFrame.layout.addWidget(Title)
            simulatorFrame.layout.addWidget(self.inputFrame)
            simulatorFrame.layout.addWidget(memoryDump.tableWidget)
            simulatorFrame.setFrameShadow(simulatorFrame.Raised)
            simulatorFrame.setLayout(simulatorFrame.layout)

            memoryDump.memoryDumpFrame.setFrameShape(QFrame.StyledPanel)
            memoryDump.memoryDumpFrame.layout = QHBoxLayout()
            memoryDump.memoryDumpFrame.layout.addWidget(simulatorFrame)
            memoryDump.memoryDumpFrame.setLayout(
                memoryDump.memoryDumpFrame.layout)
Esempio n. 30
0
class XNova_MainWindow(QWidget):

    STATE_NOT_AUTHED = 0
    STATE_AUTHED = 1

    def __init__(self, parent=None):
        super(XNova_MainWindow, self).__init__(parent, Qt.Window)
        # state vars
        self.config_store_dir = './cache'
        self.cfg = configparser.ConfigParser()
        self.cfg.read('config/net.ini', encoding='utf-8')
        self.state = self.STATE_NOT_AUTHED
        self.login_email = ''
        self.cookies_dict = {}
        self._hidden_to_tray = False
        #
        # init UI
        self.setWindowIcon(QIcon(':/i/xnova_logo_64.png'))
        self.setWindowTitle('XNova Commander')
        # main layouts
        self._layout = QVBoxLayout()
        self._layout.setContentsMargins(0, 2, 0, 0)
        self._layout.setSpacing(3)
        self.setLayout(self._layout)
        self._horizontal_layout = QHBoxLayout()
        self._horizontal_layout.setContentsMargins(0, 0, 0, 0)
        self._horizontal_layout.setSpacing(6)
        # flights frame
        self._fr_flights = QFrame(self)
        self._fr_flights.setMinimumHeight(22)
        self._fr_flights.setFrameShape(QFrame.NoFrame)
        self._fr_flights.setFrameShadow(QFrame.Plain)
        # planets bar scrollarea
        self._sa_planets = QScrollArea(self)
        self._sa_planets.setMinimumWidth(125)
        self._sa_planets.setMaximumWidth(125)
        self._sa_planets.setFrameShape(QFrame.NoFrame)
        self._sa_planets.setFrameShadow(QFrame.Plain)
        self._sa_planets.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self._sa_planets.setWidgetResizable(True)
        self._panel_planets = QWidget(self._sa_planets)
        self._layout_pp = QVBoxLayout()
        self._panel_planets.setLayout(self._layout_pp)
        self._lbl_planets = QLabel(self.tr('Planets:'), self._panel_planets)
        self._lbl_planets.setMaximumHeight(32)
        self._layout_pp.addWidget(self._lbl_planets)
        self._layout_pp.addStretch()
        self._sa_planets.setWidget(self._panel_planets)
        #
        # tab widget
        self._tabwidget = XTabWidget(self)
        self._tabwidget.enableButtonAdd(False)
        self._tabwidget.tabCloseRequested.connect(self.on_tab_close_requested)
        self._tabwidget.addClicked.connect(self.on_tab_add_clicked)
        #
        # create status bar
        self._statusbar = XNCStatusBar(self)
        self.set_status_message(self.tr('Not connected: Log in!'))
        #
        # tab widget pages
        self.login_widget = None
        self.flights_widget = None
        self.overview_widget = None
        self.imperium_widget = None
        #
        # settings widget
        self.settings_widget = SettingsWidget(self)
        self.settings_widget.settings_changed.connect(self.on_settings_changed)
        self.settings_widget.hide()
        #
        # finalize layouts
        self._horizontal_layout.addWidget(self._sa_planets)
        self._horizontal_layout.addWidget(self._tabwidget)
        self._layout.addWidget(self._fr_flights)
        self._layout.addLayout(self._horizontal_layout)
        self._layout.addWidget(self._statusbar)
        #
        # system tray icon
        self.tray_icon = None
        show_tray_icon = False
        if 'tray' in self.cfg:
            if (self.cfg['tray']['icon_usage'] == 'show') or \
                    (self.cfg['tray']['icon_usage'] == 'show_min'):
                self.create_tray_icon()
        #
        # try to restore last window size
        ssz = self.load_cfg_val('main_size')
        if ssz is not None:
            self.resize(ssz[0], ssz[1])
        #
        # world initialization
        self.world = XNovaWorld_instance()
        self.world_timer = QTimer(self)
        self.world_timer.timeout.connect(self.on_world_timer)

    # overrides QWidget.closeEvent
    # cleanup just before the window close
    def closeEvent(self, close_event: QCloseEvent):
        logger.debug('closing')
        if self.tray_icon is not None:
            self.tray_icon.hide()
            self.tray_icon = None
        if self.world_timer.isActive():
            self.world_timer.stop()
        self.world.script_command = 'stop'  # also stop possible running scripts
        if self.world.isRunning():
            self.world.quit()
            logger.debug('waiting for world thread to stop (5 sec)...')
            wait_res = self.world.wait(5000)
            if not wait_res:
                logger.warn('wait failed, last chance, terminating!')
                self.world.terminate()
        # store window size
        ssz = (self.width(), self.height())
        self.store_cfg_val('main_size', ssz)
        # accept the event
        close_event.accept()

    def showEvent(self, evt: QShowEvent):
        super(XNova_MainWindow, self).showEvent(evt)
        self._hidden_to_tray = False

    def changeEvent(self, evt: QEvent):
        super(XNova_MainWindow, self).changeEvent(evt)
        if evt.type() == QEvent.WindowStateChange:
            if not isinstance(evt, QWindowStateChangeEvent):
                return
            # make sure we only do this for minimize events
            if (evt.oldState() != Qt.WindowMinimized) and self.isMinimized():
                # we were minimized! explicitly hide settings widget
                #     if it is open, otherwise it will be lost forever :(
                if self.settings_widget is not None:
                    if self.settings_widget.isVisible():
                        self.settings_widget.hide()
                # should we minimize to tray?
                if self.cfg['tray']['icon_usage'] == 'show_min':
                    if not self._hidden_to_tray:
                        self._hidden_to_tray = True
                        self.hide()

    def create_tray_icon(self):
        if QSystemTrayIcon.isSystemTrayAvailable():
            logger.debug('System tray icon is available, showing')
            self.tray_icon = QSystemTrayIcon(QIcon(':/i/xnova_logo_32.png'), self)
            self.tray_icon.setToolTip(self.tr('XNova Commander'))
            self.tray_icon.activated.connect(self.on_tray_icon_activated)
            self.tray_icon.show()
        else:
            self.tray_icon = None

    def hide_tray_icon(self):
        if self.tray_icon is not None:
            self.tray_icon.hide()
            self.tray_icon.deleteLater()
            self.tray_icon = None

    def set_tray_tooltip(self, tip: str):
        if self.tray_icon is not None:
            self.tray_icon.setToolTip(tip)

    def set_status_message(self, msg: str):
        self._statusbar.set_status(msg)

    def store_cfg_val(self, category: str, value):
        pickle_filename = '{0}/{1}.dat'.format(self.config_store_dir, category)
        try:
            cache_dir = pathlib.Path(self.config_store_dir)
            if not cache_dir.exists():
                cache_dir.mkdir()
            with open(pickle_filename, 'wb') as f:
                pickle.dump(value, f)
        except pickle.PickleError as pe:
            pass
        except IOError as ioe:
            pass

    def load_cfg_val(self, category: str, default_value=None):
        value = None
        pickle_filename = '{0}/{1}.dat'.format(self.config_store_dir, category)
        try:
            with open(pickle_filename, 'rb') as f:
                value = pickle.load(f)
                if value is None:
                    value = default_value
        except pickle.PickleError as pe:
            pass
        except IOError as ioe:
            pass
        return value

    @pyqtSlot()
    def on_settings_changed(self):
        self.cfg.read('config/net.ini', encoding='utf-8')
        # maybe show/hide tray icon now?
        show_tray_icon = False
        if 'tray' in self.cfg:
            icon_usage = self.cfg['tray']['icon_usage']
            if (icon_usage == 'show') or (icon_usage == 'show_min'):
                show_tray_icon = True
        # show if needs show and hidden, or hide if shown and needs to hide
        if show_tray_icon and (self.tray_icon is None):
            logger.debug('settings changed, showing tray icon')
            self.create_tray_icon()
        elif (not show_tray_icon) and (self.tray_icon is not None):
            logger.debug('settings changed, hiding tray icon')
            self.hide_tray_icon()
        # also notify world about changed config!
        self.world.reload_config()

    def add_tab(self, widget: QWidget, title: str, closeable: bool = True) -> int:
        tab_index = self._tabwidget.addTab(widget, title, closeable)
        return tab_index

    def remove_tab(self, index: int):
        self._tabwidget.removeTab(index)

    # called by main application object just after main window creation
    # to show login widget and begin login process
    def begin_login(self):
        # create flights widget
        self.flights_widget = FlightsWidget(self._fr_flights)
        self.flights_widget.load_ui()
        install_layout_for_widget(self._fr_flights, Qt.Vertical, margins=(1, 1, 1, 1), spacing=1)
        self._fr_flights.layout().addWidget(self.flights_widget)
        self.flights_widget.set_online_state(False)
        self.flights_widget.requestShowSettings.connect(self.on_show_settings)
        # create and show login widget as first tab
        self.login_widget = LoginWidget(self._tabwidget)
        self.login_widget.load_ui()
        self.login_widget.loginError.connect(self.on_login_error)
        self.login_widget.loginOk.connect(self.on_login_ok)
        self.login_widget.show()
        self.add_tab(self.login_widget, self.tr('Login'), closeable=False)
        # self.test_setup_planets_panel()
        # self.test_planet_tab()

    def setup_planets_panel(self, planets: list):
        layout = self._panel_planets.layout()
        layout.setSpacing(0)
        remove_trailing_spacer_from_layout(layout)
        # remove all previous planet widgets from planets panel
        if layout.count() > 0:
            for i in range(layout.count()-1, -1, -1):
                li = layout.itemAt(i)
                if li is not None:
                    wi = li.widget()
                    if wi is not None:
                        if isinstance(wi, PlanetSidebarWidget):
                            layout.removeWidget(wi)
                            wi.close()
                            wi.deleteLater()  # fix possible mem leak
                            del wi
        for pl in planets:
            pw = PlanetSidebarWidget(self._panel_planets)
            pw.setPlanet(pl)
            layout.addWidget(pw)
            pw.show()
            # connections from each planet bar widget
            pw.requestOpenGalaxy.connect(self.on_request_open_galaxy_tab)
            pw.requestOpenPlanet.connect(self.on_request_open_planet_tab)
        append_trailing_spacer_to_layout(layout)

    def update_planets_panel(self):
        """
        Calls QWidget.update() on every PlanetBarWidget
        embedded in ui.panel_planets, causing repaint
        """
        layout = self._panel_planets.layout()
        if layout.count() > 0:
            for i in range(layout.count()):
                li = layout.itemAt(i)
                if li is not None:
                    wi = li.widget()
                    if wi is not None:
                        if isinstance(wi, PlanetSidebarWidget):
                            wi.update()

    def add_tab_for_planet(self, planet: XNPlanet):
        # construct planet widget and setup signals/slots
        plw = PlanetWidget(self._tabwidget)
        plw.requestOpenGalaxy.connect(self.on_request_open_galaxy_tab)
        plw.setPlanet(planet)
        # construct tab title
        tab_title = '{0} {1}'.format(planet.name, planet.coords.coords_str())
        # add tab and make it current
        tab_index = self.add_tab(plw, tab_title, closeable=True)
        self._tabwidget.setCurrentIndex(tab_index)
        self._tabwidget.tabBar().setTabIcon(tab_index, QIcon(':/i/planet_32.png'))
        return tab_index

    def add_tab_for_galaxy(self, coords: XNCoords = None):
        gw = GalaxyWidget(self._tabwidget)
        tab_title = '{0}'.format(self.tr('Galaxy'))
        if coords is not None:
            tab_title = '{0} {1}'.format(self.tr('Galaxy'), coords.coords_str())
            gw.setCoords(coords.galaxy, coords.system)
        idx = self.add_tab(gw, tab_title, closeable=True)
        self._tabwidget.setCurrentIndex(idx)
        self._tabwidget.tabBar().setTabIcon(idx, QIcon(':/i/galaxy_32.png'))

    @pyqtSlot(int)
    def on_tab_close_requested(self, idx: int):
        # logger.debug('tab close requested: {0}'.format(idx))
        if idx <= 1:  # cannot close overview or imperium tabs
            return
        self.remove_tab(idx)

    @pyqtSlot()
    def on_tab_add_clicked(self):
        pos = QCursor.pos()
        planets = self.world.get_planets()
        # logger.debug('tab bar add clicked, cursor pos = ({0}, {1})'.format(pos.x(), pos.y()))
        menu = QMenu(self)
        # galaxy view
        galaxy_action = QAction(menu)
        galaxy_action.setText(self.tr('Add galaxy view'))
        galaxy_action.setData(QVariant('galaxy'))
        menu.addAction(galaxy_action)
        # planets
        menu.addSection(self.tr('-- Planet tabs: --'))
        for planet in planets:
            action = QAction(menu)
            action.setText('{0} {1}'.format(planet.name, planet.coords.coords_str()))
            action.setData(QVariant(planet.planet_id))
            menu.addAction(action)
        action_ret = menu.exec(pos)
        if action_ret is not None:
            # logger.debug('selected action data = {0}'.format(str(action_ret.data())))
            if action_ret == galaxy_action:
                logger.debug('action_ret == galaxy_action')
                self.add_tab_for_galaxy()
                return
            # else consider this is planet widget
            planet_id = int(action_ret.data())
            self.on_request_open_planet_tab(planet_id)

    @pyqtSlot(str)
    def on_login_error(self, errstr):
        logger.error('Login error: {0}'.format(errstr))
        self.state = self.STATE_NOT_AUTHED
        self.set_status_message(self.tr('Login error: {0}').format(errstr))
        QMessageBox.critical(self, self.tr('Login error:'), errstr)

    @pyqtSlot(str, dict)
    def on_login_ok(self, login_email, cookies_dict):
        # logger.debug('Login OK, login: {0}, cookies: {1}'.format(login_email, str(cookies_dict)))
        # save login data: email, cookies
        self.state = self.STATE_AUTHED
        self.set_status_message(self.tr('Login OK, loading world'))
        self.login_email = login_email
        self.cookies_dict = cookies_dict
        #
        # destroy login widget and remove its tab
        self.remove_tab(0)
        self.login_widget.close()
        self.login_widget.deleteLater()
        self.login_widget = None
        #
        # create overview widget and add it as first tab
        self.overview_widget = OverviewWidget(self._tabwidget)
        self.overview_widget.load_ui()
        self.add_tab(self.overview_widget, self.tr('Overview'), closeable=False)
        self.overview_widget.show()
        self.overview_widget.setEnabled(False)
        #
        # create 2nd tab - Imperium
        self.imperium_widget = ImperiumWidget(self._tabwidget)
        self.add_tab(self.imperium_widget, self.tr('Imperium'), closeable=False)
        self.imperium_widget.setEnabled(False)
        #
        # initialize XNova world updater
        self.world.initialize(cookies_dict)
        self.world.set_login_email(self.login_email)
        # connect signals from world
        self.world.world_load_progress.connect(self.on_world_load_progress)
        self.world.world_load_complete.connect(self.on_world_load_complete)
        self.world.net_request_started.connect(self.on_net_request_started)
        self.world.net_request_finished.connect(self.on_net_request_finished)
        self.world.flight_arrived.connect(self.on_flight_arrived)
        self.world.build_complete.connect(self.on_building_complete)
        self.world.loaded_overview.connect(self.on_loaded_overview)
        self.world.loaded_imperium.connect(self.on_loaded_imperium)
        self.world.loaded_planet.connect(self.on_loaded_planet)
        self.world.start()

    @pyqtSlot(str, int)
    def on_world_load_progress(self, comment: str, progress: int):
        self._statusbar.set_world_load_progress(comment, progress)

    @pyqtSlot()
    def on_world_load_complete(self):
        logger.debug('main: on_world_load_complete()')
        # enable adding new tabs
        self._tabwidget.enableButtonAdd(True)
        # update statusbar
        self._statusbar.set_world_load_progress('', -1)  # turn off progress display
        self.set_status_message(self.tr('World loaded.'))
        # update account info
        if self.overview_widget is not None:
            self.overview_widget.setEnabled(True)
            self.overview_widget.update_account_info()
            self.overview_widget.update_builds()
        # update flying fleets
        self.flights_widget.set_online_state(True)
        self.flights_widget.update_flights()
        # update planets
        planets = self.world.get_planets()
        self.setup_planets_panel(planets)
        if self.imperium_widget is not None:
            self.imperium_widget.setEnabled(True)
            self.imperium_widget.update_planets()
        # update statusbar
        self._statusbar.update_online_players_count()
        # update tray tooltip, add account name
        self.set_tray_tooltip(self.tr('XNova Commander') + ' - '
                              + self.world.get_account_info().login)
        # set timer to do every-second world recalculation
        self.world_timer.setInterval(1000)
        self.world_timer.setSingleShot(False)
        self.world_timer.start()

    @pyqtSlot()
    def on_loaded_overview(self):
        logger.debug('on_loaded_overview')
        # A lot of things are updated when overview is loaded
        #  * Account information and stats
        if self.overview_widget is not None:
            self.overview_widget.update_account_info()
        #  * flights will be updated every second anyway in on_world_timer(), so no need to call
        #    self.flights_widget.update_flights()
        #  * messages count also, is updated with flights
        #  * current planet may have changed
        self.update_planets_panel()
        #  * server time is updated also
        self._statusbar.update_online_players_count()

    @pyqtSlot()
    def on_loaded_imperium(self):
        logger.debug('on_loaded_imperium')
        # need to update imperium widget
        if self.imperium_widget is not None:
            self.imperium_widget.update_planets()
        # The important note here is that imperium update is the only place where
        # the planets list is read, so number of planets, their names, etc may change here
        # Also, imperium update OVERWRITES full planets array, so, all prev
        # references to planets in all GUI elements must be invalidated, because
        # they will point to unused, outdated planets
        planets = self.world.get_planets()
        # re-create planets sidebar
        self.setup_planets_panel(planets)
        # update all builds in overview widget
        if self.overview_widget:
            self.overview_widget.update_builds()
        # update all planet tabs with new planet references
        cnt = self._tabwidget.count()
        if cnt > 2:
            for index in range(2, cnt):
                tab_page = self._tabwidget.tabWidget(index)
                if tab_page is not None:
                    try:
                        tab_type = tab_page.get_tab_type()
                        if tab_type == 'planet':
                            tab_planet = tab_page.planet()
                            new_planet = self.world.get_planet(tab_planet.planet_id)
                            tab_page.setPlanet(new_planet)
                    except AttributeError:  # not all pages may have method get_tab_type()
                        pass

    @pyqtSlot(int)
    def on_loaded_planet(self, planet_id: int):
        logger.debug('Got signal on_loaded_planet({0}), updating overview '
                     'widget and planets panel'.format(planet_id))
        if self.overview_widget:
            self.overview_widget.update_builds()
        self.update_planets_panel()
        # update also planet tab, if any
        planet = self.world.get_planet(planet_id)
        if planet is not None:
            tab_idx = self.find_tab_for_planet(planet_id)
            if tab_idx != -1:
                tab_widget = self._tabwidget.tabWidget(tab_idx)
                if isinstance(tab_widget, PlanetWidget):
                    logger.debug('Updating planet tab #{}'.format(tab_idx))
                    tab_widget.setPlanet(planet)

    @pyqtSlot()
    def on_world_timer(self):
        if self.world:
            self.world.world_tick()
        self.update_planets_panel()
        if self.flights_widget:
            self.flights_widget.update_flights()
        if self.overview_widget:
            self.overview_widget.update_builds()
        if self.imperium_widget:
            self.imperium_widget.update_planet_resources()

    @pyqtSlot()
    def on_net_request_started(self):
        self._statusbar.set_loading_status(True)

    @pyqtSlot()
    def on_net_request_finished(self):
        self._statusbar.set_loading_status(False)

    @pyqtSlot(int)
    def on_tray_icon_activated(self, reason):
        # QSystemTrayIcon::Unknown	0	Unknown reason
        # QSystemTrayIcon::Context	1	The context menu for the system tray entry was requested
        # QSystemTrayIcon::DoubleClick	2	The system tray entry was double clicked
        # QSystemTrayIcon::Trigger	3	The system tray entry was clicked
        # QSystemTrayIcon::MiddleClick	4	The system tray entry was clicked with the middle mouse button
        if reason == QSystemTrayIcon.Trigger:
            # left-click
            self.setWindowState((self.windowState() & ~Qt.WindowMinimized) | Qt.WindowActive)
            self.show()
            return

    def show_tray_message(self, title, message, icon_type=None, timeout_ms=None):
        """
        Shows message from system tray icon, if system supports it.
        If no support, this is just a no-op
        :param title: message title
        :param message: message text
        :param icon_type: one of:
        QSystemTrayIcon.NoIcon      0   No icon is shown.
        QSystemTrayIcon.Information 1   An information icon is shown.
        QSystemTrayIcon.Warning     2   A standard warning icon is shown.
        QSystemTrayIcon.Critical    3   A critical warning icon is shown
        """
        if self.tray_icon is None:
            return
        if self.tray_icon.supportsMessages():
            if icon_type is None:
                icon_type = QSystemTrayIcon.Information
            if timeout_ms is None:
                timeout_ms = 10000
            self.tray_icon.showMessage(title, message, icon_type, timeout_ms)
        else:
            logger.info('This system does not support tray icon messages.')

    @pyqtSlot()
    def on_show_settings(self):
        if self.settings_widget is not None:
            self.settings_widget.show()
            self.settings_widget.showNormal()

    @pyqtSlot(XNFlight)
    def on_flight_arrived(self, fl: XNFlight):
        logger.debug('main: flight arrival: {0}'.format(fl))
        mis_str = flight_mission_for_humans(fl.mission)
        if fl.direction == 'return':
            mis_str += ' ' + self.tr('return')
        short_fleet_info = self.tr('{0} {1} => {2}, {3} ship(s)').format(
            mis_str, fl.src, fl.dst, len(fl.ships))
        self.show_tray_message(self.tr('XNova: Fleet arrived'), short_fleet_info)

    @pyqtSlot(XNPlanet, XNPlanetBuildingItem)
    def on_building_complete(self, planet: XNPlanet, bitem: XNPlanetBuildingItem):
        logger.debug('main: build complete: on planet {0}: {1}'.format(
            planet.name, str(bitem)))
        # update also planet tab, if any
        if isinstance(planet, XNPlanet):
            tab_idx = self.find_tab_for_planet(planet.planet_id)
            if tab_idx != -1:
                tab_widget = self._tabwidget.tabWidget(tab_idx)
                if isinstance(tab_widget, PlanetWidget):
                    logger.debug('Updating planet tab #{}'.format(tab_idx))
                    tab_widget.setPlanet(planet)
        # construct message to show in tray
        if bitem.is_shipyard_item:
            binfo_str = '{0} x {1}'.format(bitem.quantity, bitem.name)
        else:
            binfo_str = self.tr('{0} lv.{1}').format(bitem.name, bitem.level)
        msg = self.tr('{0} has built {1}').format(planet.name, binfo_str)
        self.show_tray_message(self.tr('XNova: Building complete'), msg)

    @pyqtSlot(XNCoords)
    def on_request_open_galaxy_tab(self, coords: XNCoords):
        tab_index = self.find_tab_for_galaxy(coords.galaxy, coords.system)
        if tab_index == -1:  # create new tab for these coords
            self.add_tab_for_galaxy(coords)
            return
        # else switch to that tab
        self._tabwidget.setCurrentIndex(tab_index)

    @pyqtSlot(int)
    def on_request_open_planet_tab(self, planet_id: int):
        tab_index = self.find_tab_for_planet(planet_id)
        if tab_index == -1: # create new tab for planet
            planet = self.world.get_planet(planet_id)
            if planet is not None:
                self.add_tab_for_planet(planet)
                return
        # else switch to that tab
        self._tabwidget.setCurrentIndex(tab_index)

    def find_tab_for_planet(self, planet_id: int) -> int:
        """
        Finds tab index where specified planet is already opened
        :param planet_id: planet id to search for
        :return: tab index, or -1 if not found
        """
        cnt = self._tabwidget.count()
        if cnt < 3:
            return -1  # only overview and imperium tabs are present
        for index in range(2, cnt):
            tab_page = self._tabwidget.tabWidget(index)
            if tab_page is not None:
                try:
                    tab_type = tab_page.get_tab_type()
                    if tab_type == 'planet':
                        tab_planet = tab_page.planet()
                        if tab_planet.planet_id == planet_id:
                            # we have found tab index where this planet is already opened
                            return index
                except AttributeError:  # not all pages may have method get_tab_type()
                    pass
        return -1

    def find_tab_for_galaxy(self, galaxy: int, system: int) -> int:
        """
        Finds tab index where specified galaxy view is already opened
        :param galaxy: galaxy target coordinate
        :param system: system target coordinate
        :return: tab index, or -1 if not found
        """
        cnt = self._tabwidget.count()
        if cnt < 3:
            return -1  # only overview and imperium tabs are present
        for index in range(2, cnt):
            tab_page = self._tabwidget.tabWidget(index)
            if tab_page is not None:
                try:
                    tab_type = tab_page.get_tab_type()
                    if tab_type == 'galaxy':
                        coords = tab_page.coords()
                        if (coords[0] == galaxy) and (coords[1] == system):
                            # we have found galaxy tab index where this place is already opened
                            return index
                except AttributeError:  # not all pages may have method get_tab_type()
                    pass
        return -1

    def test_setup_planets_panel(self):
        """
        Testing only - add 'fictive' planets to test planets panel without loading data
        :return: None
        """
        pl1 = XNPlanet('Arnon', XNCoords(1, 7, 6))
        pl1.pic_url = 'skins/default/planeten/small/s_normaltempplanet08.jpg'
        pl1.fields_busy = 90
        pl1.fields_total = 167
        pl1.is_current = True
        pl2 = XNPlanet('Safizon', XNCoords(1, 232, 7))
        pl2.pic_url = 'skins/default/planeten/small/s_dschjungelplanet05.jpg'
        pl2.fields_busy = 84
        pl2.fields_total = 207
        pl2.is_current = False
        test_planets = [pl1, pl2]
        self.setup_planets_panel(test_planets)

    def test_planet_tab(self):
        """
        Testing only - add 'fictive' planet tab to test UI without loading world
        :return:
        """
        # construct planet
        pl1 = XNPlanet('Arnon', coords=XNCoords(1, 7, 6), planet_id=12345)
        pl1.pic_url = 'skins/default/planeten/small/s_normaltempplanet08.jpg'
        pl1.fields_busy = 90
        pl1.fields_total = 167
        pl1.is_current = True
        pl1.res_current.met = 10000000
        pl1.res_current.cry = 50000
        pl1.res_current.deit = 250000000  # 250 mil
        pl1.res_per_hour.met = 60000
        pl1.res_per_hour.cry = 30000
        pl1.res_per_hour.deit = 15000
        pl1.res_max_silos.met = 6000000
        pl1.res_max_silos.cry = 3000000
        pl1.res_max_silos.deit = 1000000
        pl1.energy.energy_left = 10
        pl1.energy.energy_total = 1962
        pl1.energy.charge_percent = 92
        # planet building item
        bitem = XNPlanetBuildingItem()
        bitem.gid = 1
        bitem.name = 'Рудник металла'
        bitem.level = 29
        bitem.remove_link = ''
        bitem.build_link = '?set=buildings&cmd=insert&building={0}'.format(bitem.gid)
        bitem.seconds_total = 23746
        bitem.cost_met = 7670042
        bitem.cost_cry = 1917510
        bitem.is_building_item = True
        # second bitem
        bitem2 = XNPlanetBuildingItem()
        bitem2.gid = 2
        bitem2.name = 'Рудник кристалла'
        bitem2.level = 26
        bitem2.remove_link = ''
        bitem2.build_link = '?set=buildings&cmd=insert&building={0}'.format(bitem2.gid)
        bitem2.seconds_total = 13746
        bitem2.cost_met = 9735556
        bitem2.cost_cry = 4667778
        bitem2.is_building_item = True
        bitem2.is_downgrade = True
        bitem2.seconds_left = bitem2.seconds_total // 2
        bitem2.calc_end_time()
        # add bitems
        pl1.buildings_items = [bitem, bitem2]
        # add
        self.add_tab_for_planet(pl1)
Esempio n. 31
0
    def __init__(self, compare_frame_controller: CompareFrameController,
                 generator_tab_controller: GeneratorTabController,
                 project_manager: ProjectManager, parent):
        super().__init__(parent)

        self.project_manager = project_manager
        self.compare_frame_controller = compare_frame_controller
        self.generator_tab_controller = generator_tab_controller
        self.proto_analyzer = compare_frame_controller.proto_analyzer

        self.simulator_config = SimulatorConfiguration(self.project_manager)
        self.sim_expression_parser = SimulatorExpressionParser(self.simulator_config)
        SimulatorItem.simulator_config = self.simulator_config
        SimulatorItem.expression_parser = self.sim_expression_parser

        self.ui = Ui_SimulatorTab()
        self.ui.setupUi(self)
        util.set_splitter_stylesheet(self.ui.splitter)
        util.set_splitter_stylesheet(self.ui.splitterLeftRight)

        self.ui.splitter.setSizes([self.width() / 0.7, self.width() / 0.3])

        self.ui.treeProtocols.setHeaderHidden(True)
        self.tree_model = self.generator_tab_controller.tree_model
        self.ui.treeProtocols.setModel(self.tree_model)

        self.participant_table_model = ParticipantTableModel(project_manager.participants)
        self.ui.tableViewParticipants.setModel(self.participant_table_model)
        self.participant_table_model.update()

        self.simulator_message_field_model = SimulatorMessageFieldModel(self)
        self.ui.tblViewFieldValues.setModel(self.simulator_message_field_model)
        self.ui.tblViewFieldValues.setItemDelegateForColumn(1, ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS,
                                                                                parent=self.ui.tblViewFieldValues))
        self.ui.tblViewFieldValues.setItemDelegateForColumn(2, ComboBoxDelegate(SimulatorProtocolLabel.VALUE_TYPES,
                                                                                parent=self.ui.tblViewFieldValues))
        self.ui.tblViewFieldValues.setItemDelegateForColumn(3, ProtocolValueDelegate(controller=self,
                                                                                     parent=self.ui.tblViewFieldValues))
        self.project_manager.reload_field_types()
        self.update_field_name_column()

        self.simulator_message_table_model = SimulatorMessageTableModel(self.project_manager, self)
        self.ui.tblViewMessage.setModel(self.simulator_message_table_model)

        self.ui.ruleCondLineEdit.setValidator(RuleExpressionValidator(self.sim_expression_parser, is_formula=False))
        self.completer_model = QStringListModel([])
        self.ui.ruleCondLineEdit.setCompleter(QCompleter(self.completer_model, self.ui.ruleCondLineEdit))
        self.ui.ruleCondLineEdit.setToolTip(self.sim_expression_parser.rule_condition_help)

        self.simulator_scene = SimulatorScene(mode=0, simulator_config=self.simulator_config)
        self.simulator_scene.tree_root_item = compare_frame_controller.proto_tree_model.rootItem
        self.ui.gvSimulator.setScene(self.simulator_scene)
        self.ui.gvSimulator.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.ui.gvSimulator.proto_analyzer = compare_frame_controller.proto_analyzer

        self.__active_item = None

        self.ui.listViewSimulate.setModel(SimulatorParticipantListModel(self.simulator_config))
        self.ui.spinBoxNRepeat.setValue(self.project_manager.simulator_num_repeat)
        self.ui.spinBoxTimeout.setValue(self.project_manager.simulator_timeout_ms)
        self.ui.spinBoxRetries.setValue(self.project_manager.simulator_retries)
        self.ui.comboBoxError.setCurrentIndex(self.project_manager.simulator_error_handling_index)

        # place save/load button at corner of tab widget
        frame = QFrame(parent=self)
        frame.setLayout(QHBoxLayout())
        frame.setFrameStyle(frame.NoFrame)
        self.ui.btnSave = QToolButton(self.ui.tab)
        self.ui.btnSave.setIcon(QIcon.fromTheme("document-save"))
        frame.layout().addWidget(self.ui.btnSave)

        self.ui.btnLoad = QToolButton(self.ui.tab)
        self.ui.btnLoad.setIcon(QIcon.fromTheme("document-open"))
        frame.layout().addWidget(self.ui.btnLoad)
        frame.layout().setContentsMargins(0, 0, 0, 0)
        self.ui.tabWidget.setCornerWidget(frame)

        self.ui.splitterLeftRight.setSizes([0.2 * self.width(), 0.8 * self.width()])

        self.create_connects()
    def __init__(self, compare_frame_controller: CompareFrameController,
                 generator_tab_controller: GeneratorTabController,
                 project_manager: ProjectManager, parent):
        super().__init__(parent)

        self.project_manager = project_manager
        self.compare_frame_controller = compare_frame_controller
        self.generator_tab_controller = generator_tab_controller
        self.proto_analyzer = compare_frame_controller.proto_analyzer

        self.simulator_config = SimulatorConfiguration(self.project_manager)
        self.sim_expression_parser = SimulatorExpressionParser(
            self.simulator_config)
        SimulatorItem.simulator_config = self.simulator_config
        SimulatorItem.expression_parser = self.sim_expression_parser

        self.ui = Ui_SimulatorTab()
        self.ui.setupUi(self)
        util.set_splitter_stylesheet(self.ui.splitter)
        util.set_splitter_stylesheet(self.ui.splitterLeftRight)

        self.ui.splitter.setSizes([self.width() / 0.7, self.width() / 0.3])

        self.ui.treeProtocols.setHeaderHidden(True)
        self.tree_model = self.generator_tab_controller.tree_model
        self.ui.treeProtocols.setModel(self.tree_model)

        self.participant_table_model = ParticipantTableModel(
            project_manager.participants)
        self.ui.tableViewParticipants.setModel(self.participant_table_model)
        self.participant_table_model.update()

        self.simulator_message_field_model = SimulatorMessageFieldModel(self)
        self.ui.tblViewFieldValues.setModel(self.simulator_message_field_model)
        self.ui.tblViewFieldValues.setItemDelegateForColumn(
            1,
            ComboBoxDelegate(ProtocolLabel.DISPLAY_FORMATS,
                             parent=self.ui.tblViewFieldValues))
        self.ui.tblViewFieldValues.setItemDelegateForColumn(
            2,
            ComboBoxDelegate(SimulatorProtocolLabel.VALUE_TYPES,
                             parent=self.ui.tblViewFieldValues))
        self.ui.tblViewFieldValues.setItemDelegateForColumn(
            3,
            ProtocolValueDelegate(controller=self,
                                  parent=self.ui.tblViewFieldValues))
        self.project_manager.reload_field_types()
        self.update_field_name_column()

        self.simulator_message_table_model = SimulatorMessageTableModel(
            self.project_manager, self)
        self.ui.tblViewMessage.setModel(self.simulator_message_table_model)

        self.ui.ruleCondLineEdit.setValidator(
            RuleExpressionValidator(self.sim_expression_parser,
                                    is_formula=False))
        self.completer_model = QStringListModel([])
        self.ui.ruleCondLineEdit.setCompleter(
            QCompleter(self.completer_model, self.ui.ruleCondLineEdit))
        self.ui.ruleCondLineEdit.setToolTip(
            self.sim_expression_parser.rule_condition_help)

        self.simulator_scene = SimulatorScene(
            mode=0, simulator_config=self.simulator_config)
        self.simulator_scene.tree_root_item = compare_frame_controller.proto_tree_model.rootItem
        self.ui.gvSimulator.setScene(self.simulator_scene)
        self.ui.gvSimulator.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.ui.gvSimulator.proto_analyzer = compare_frame_controller.proto_analyzer

        self.__active_item = None

        self.ui.listViewSimulate.setModel(
            SimulatorParticipantListModel(self.simulator_config))
        self.ui.spinBoxNRepeat.setValue(
            self.project_manager.simulator_num_repeat)
        self.ui.spinBoxTimeout.setValue(
            self.project_manager.simulator_timeout_ms)
        self.ui.spinBoxRetries.setValue(self.project_manager.simulator_retries)
        self.ui.comboBoxError.setCurrentIndex(
            self.project_manager.simulator_error_handling_index)

        # place save/load button at corner of tab widget
        frame = QFrame(parent=self)
        frame.setLayout(QHBoxLayout())
        frame.setFrameStyle(frame.NoFrame)
        self.ui.btnSave = QToolButton(self.ui.tab)
        self.ui.btnSave.setIcon(QIcon.fromTheme("document-save"))
        frame.layout().addWidget(self.ui.btnSave)

        self.ui.btnLoad = QToolButton(self.ui.tab)
        self.ui.btnLoad.setIcon(QIcon.fromTheme("document-open"))
        frame.layout().addWidget(self.ui.btnLoad)
        frame.layout().setContentsMargins(0, 0, 0, 0)
        self.ui.tabWidget.setCornerWidget(frame)

        self.ui.splitterLeftRight.setSizes(
            [0.2 * self.width(), 0.8 * self.width()])

        self.create_connects()
Esempio n. 33
0
class QCollapsibleFrame(QWidget):
    def __init__(self, title, parent):
        super().__init__(parent)
        self.widget = None
        self.headerWidget = None
        self.contentsFrame = None
        self.mainLayout = QVBoxLayout()
        self.mainLayout.setSpacing(0)
        self.mainLayout.setContentsMargins(2, 2, 2, 2)
        self.setLayout(self.mainLayout)

        self.SetHeaderWidget(CCollapsibleFrameHeader(title, self))

    def getWidget(self):
        return self.widget

    def getDragHandler(self):
        return self.headerWidget.collapseButton

    def setWidget(self, widget):
        if not self.contentsFrame:
            self.contentsFrame = QFrame(self)
            frameLayout = QVBoxLayout()
            frameLayout.setSpacing(0)
            frameLayout.setContentsMargins(2, 2, 2, 2)
            self.contentsFrame.setLayout(frameLayout)
            self.layout().addWidget(self.contentsFrame)

        mainLayout = self.contentsFrame.layout()

        if self.widget:
            mainLayout.removeWidget(self.widget)
            self.widget.deleteLater()

        self.widget = widget
        if self.widget:
            mainLayout.addWidget(self.widget)
            self.contentsFrame.setHidden(self.headerWidget.bCollapsed)

    def setClosable(self, closable):
        self.headerWidget.setClosable(closable)

    def closable(self):
        return self.headerWidget.closable()

    def setTitle(self, title):
        self.headerWidget.setTitle(title)

    def collapsed(self):
        return self.headerWidget.bCollapsed

    def setCollapsed(self, bCollapsed):
        self.headerWidget.setCollapsed(bCollapsed)

    def setCollapsedStateChangeCallback(self, callback):
        self.headerWidget.onCollapsedStateChanged = callback

    def paintEvent(self, e):
        opt = QStyleOption()
        opt.initFrom(self)
        painter = QPainter(self)
        self.style().drawPrimitive(QStyle.PE_Widget, opt, painter, self)

    def setHearderWidget(self, header):
        self.headerWidget = header
        self.layout().addWidget(header)
        self.headerWidget.closeButton.clicked.connect(self.onCloseRequested)

    def onCloseRequested(self):
        self.closeRequested(self)

    def closeRequested(self, caller):
        pass