Пример #1
0
    def __init__(self, parent=None):
        super().__init__(parent)

        options = {
            #"pen_pos_down": ("Pen position down:", (0, 100), 40),
            #"pen_pos_up": ("Pen position up:", (0, 100), 60),
            "pen_rate_lower": ("Pen rate lower:", (1, 100), 50),
            "pen_rate_raise": ("Pen rate raise:", (1, 100), 75),
            "pen_delay_down": ("Pen delay down:", (-500, 500), 0),
            "pen_delay_up": ("Pen delay up:", (-500, 500), 0),
            "speed_pendown": ("Speed (pen down):", (1, 110), 25),
            "speed_penup": ("Speed (pen up):", (1, 110), 75),
            "accel": ("Acceleration:", (1, 100), 75),
        }

        settings = QSettings()
        layout = QFormLayout()

        for key, (label, (min_val, max_val), default) in options.items():
            spin_box = AxySettingsSpinBox(settings, key, default)
            spin_box.setRange(min_val, max_val)
            spin_box.setSingleStep(1)
            layout.addRow(label, spin_box)

        model = QComboBox()
        model.addItem("Axidraw V2 or V3", 1)
        model.addItem("Axidraw V3/A3 or SE/A3", 2)
        model.addItem("Axidraw V3 XLX", 3)
        model.addItem("Axidraw MiniKit", 4)
        model.currentIndexChanged.connect(
            lambda index: axy.set_option("model", model.itemData(index))
        )
        model.setCurrentIndex(settings.value("model", 0))
        model.currentIndexChanged.connect(lambda index: settings.setValue("model", index))
        layout.addRow("Model:", model)

        btn_box = QDialogButtonBox()
        btn_box.setStandardButtons(QDialogButtonBox.Ok)
        btn_box.accepted.connect(self.accept)
        btn_box.rejected.connect(self.reject)
        layout.addRow(btn_box)

        self.setLayout(layout)
Пример #2
0
class ConfigWindow(QDialog):
    # noinspection SpellCheckingInspection
    LOCALES = {
        'en': 'English',
        'nl': 'Nederlands'
    }

    def __init__(self, gui_window: mainWindow.MainWindow, device_manager: logic.DeviceManager):
        QDialog.__init__(self, gui_window)
        self.setModal(True)
        self.setWindowTitle(QCoreApplication.translate('configs', 'Configs', 'title'))
        self._device_manager = device_manager

        layout = QGridLayout()
        layout.addWidget(QLabel(QCoreApplication.translate('configs', 'Open on startup'), self), 0, 0)
        self._open_on_startup = QCheckBox(self)
        self._open_on_startup.setChecked(device_manager.open_on_start)
        self._open_on_startup.stateChanged.connect(self._open_on_startup_changed)
        layout.addWidget(self._open_on_startup, 0, 1)

        layout.addWidget(QLabel(QCoreApplication.translate('configs', 'Locale'), self), 1, 0)
        self._locale_select = QComboBox(self)
        self._locale_select.setToolTip(QCoreApplication.translate('configs', 'Restart required'))
        for locale_key, locale_value in ConfigWindow.LOCALES.items():
            self._locale_select.addItem(locale_value, userData=locale_key)
        self._locale_select.setCurrentIndex(self._locale_select.findData(device_manager.locale))
        self._locale_select.currentIndexChanged.connect(self._locale_changed)
        layout.addWidget(self._locale_select, 1, 1)

        self.setLayout(layout)

    def _open_on_startup_changed(self, state):
        self._device_manager.open_on_start = state == Qt.Checked

    def _locale_changed(self, index):
        self._device_manager.locale = self._locale_select.itemData(index)

    def closeEvent(self, event):
        event.ignore()
        self.hide()
class QGraphicsSceneOnQVariantTest(UsesQApplication):
    """Test storage ot QGraphicsScene into QVariants"""
    def setUp(self):
        super(QGraphicsSceneOnQVariantTest, self).setUp()
        self.s = MyDiagram()
        self.i = MyItem()
        self.combo = QComboBox()

    def tearDown(self):
        del self.s
        del self.i
        del self.combo
        super(QGraphicsSceneOnQVariantTest, self).tearDown()

    def testIt(self):
        self.s.addItem(self.i)
        self.assertEqual(len(self.s.items()), 1)

    def testSequence(self):
        # PYSIDE-641
        self.combo.addItem("test", userData=Sequence())
        self.assertTrue(isinstance(self.combo.itemData(0), Sequence))
Пример #4
0
 def on_player_changed(self, player: QComboBox, new_index: int):
     if new_index < 0:
         # Combo box was cleared.
         return
     settings = get_settings(self.start_state)
     if player is self.ui.player1:
         searches = self.ui.searches1
         searches_label = self.ui.searches_label1
         searches_lock = self.ui.searches_lock1
         setting_name = 'player_1'
         row = 1
     else:
         searches = self.ui.searches2
         searches_label = self.ui.searches_label2
         searches_lock = self.ui.searches_lock2
         setting_name = 'player_2'
         row = 2
     settings.setValue(setting_name, new_index)
     heuristic = player.itemData(new_index)
     searches.setVisible(heuristic is not None)
     searches_label.setVisible(heuristic is not None)
     searches_lock.setVisible(heuristic is not None)
     colspan = 4 if heuristic is None else 1
     self.ui.player_layout.addWidget(player, row, 1, 1, colspan)
Пример #5
0
class QBuyGroupForGroundObjectDialog(QDialog):
    def __init__(
        self,
        parent,
        ground_object: TheaterGroundObject,
        cp: ControlPoint,
        game: Game,
        current_group_value: int,
    ):
        super(QBuyGroupForGroundObjectDialog, self).__init__(parent)

        self.setMinimumWidth(350)
        self.ground_object = ground_object
        self.cp = cp
        self.game = game
        self.current_group_value = current_group_value

        self.setWindowTitle("Buy units @ " + self.ground_object.obj_name)
        self.setWindowIcon(EVENT_ICONS["capture"])

        self.buySamButton = QPushButton("Buy")
        self.buyArmorButton = QPushButton("Buy")
        self.buySamLayout = QGridLayout()
        self.buyArmorLayout = QGridLayout()
        self.amount = QSpinBox()
        self.buyArmorCombo = QComboBox()
        self.samCombo = QComboBox()
        self.buySamBox = QGroupBox("Buy SAM site :")
        self.buyArmorBox = QGroupBox("Buy defensive position :")

        faction = self.game.player_faction

        # Sams

        possible_sams = get_faction_possible_sams_generator(faction)
        for sam in possible_sams:
            # Pre Generate SAM to get the real price
            generator = sam(self.game, self.ground_object)
            generator.generate()
            self.samCombo.addItem(
                generator.name + " [$" + str(generator.price) + "M]", userData=generator
            )
        self.samCombo.currentIndexChanged.connect(self.samComboChanged)

        self.buySamLayout.addWidget(QLabel("Site Type :"), 0, 0, Qt.AlignLeft)
        self.buySamLayout.addWidget(self.samCombo, 0, 1, alignment=Qt.AlignRight)
        self.buySamLayout.addWidget(self.buySamButton, 1, 1, alignment=Qt.AlignRight)
        stretch = QVBoxLayout()
        stretch.addStretch()
        self.buySamLayout.addLayout(stretch, 2, 0)

        self.buySamButton.clicked.connect(self.buySam)

        # EWRs

        buy_ewr_box = QGroupBox("Buy EWR:")
        buy_ewr_layout = QGridLayout()
        buy_ewr_box.setLayout(buy_ewr_layout)

        buy_ewr_layout.addWidget(QLabel("Radar type:"), 0, 0, Qt.AlignLeft)

        self.ewr_selector = QComboBox()
        buy_ewr_layout.addWidget(self.ewr_selector, 0, 1, alignment=Qt.AlignRight)
        ewr_types = get_faction_possible_ewrs_generator(faction)
        for ewr_type in ewr_types:
            # Pre Generate to get the real price
            generator = ewr_type(self.game, self.ground_object)
            generator.generate()
            self.ewr_selector.addItem(
                generator.name() + " [$" + str(generator.price) + "M]",
                userData=generator,
            )
        self.ewr_selector.currentIndexChanged.connect(self.on_ewr_selection_changed)

        self.buy_ewr_button = QPushButton("Buy")
        self.buy_ewr_button.clicked.connect(self.buy_ewr)
        buy_ewr_layout.addWidget(self.buy_ewr_button, 1, 1, alignment=Qt.AlignRight)
        stretch = QVBoxLayout()
        stretch.addStretch()
        buy_ewr_layout.addLayout(stretch, 2, 0)

        # Armored units
        for unit in set(faction.ground_units):
            self.buyArmorCombo.addItem(f"{unit} [${unit.price}M]", userData=unit)
        self.buyArmorCombo.currentIndexChanged.connect(self.armorComboChanged)

        self.amount.setMinimum(2)
        self.amount.setMaximum(8)
        self.amount.setValue(2)
        self.amount.valueChanged.connect(self.amountComboChanged)

        self.buyArmorLayout.addWidget(QLabel("Unit type :"), 0, 0, Qt.AlignLeft)
        self.buyArmorLayout.addWidget(self.buyArmorCombo, 0, 1, alignment=Qt.AlignRight)
        self.buyArmorLayout.addWidget(
            QLabel("Group size :"), 1, 0, alignment=Qt.AlignLeft
        )
        self.buyArmorLayout.addWidget(self.amount, 1, 1, alignment=Qt.AlignRight)
        self.buyArmorLayout.addWidget(
            self.buyArmorButton, 2, 1, alignment=Qt.AlignRight
        )
        stretch2 = QVBoxLayout()
        stretch2.addStretch()
        self.buyArmorLayout.addLayout(stretch2, 3, 0)

        self.buyArmorButton.clicked.connect(self.buyArmor)

        # Do layout
        self.buySamBox.setLayout(self.buySamLayout)
        self.buyArmorBox.setLayout(self.buyArmorLayout)

        self.mainLayout = QHBoxLayout()

        if isinstance(self.ground_object, SamGroundObject):
            self.mainLayout.addWidget(self.buySamBox)
        elif isinstance(self.ground_object, VehicleGroupGroundObject):
            self.mainLayout.addWidget(self.buyArmorBox)
        elif isinstance(self.ground_object, EwrGroundObject):
            self.mainLayout.addWidget(buy_ewr_box)

        self.setLayout(self.mainLayout)

        try:
            self.samComboChanged(0)
            self.armorComboChanged(0)
            self.on_ewr_selection_changed(0)
        except:
            pass

    def samComboChanged(self, index):
        self.buySamButton.setText(
            "Buy [$"
            + str(self.samCombo.itemData(index).price)
            + "M] [-$"
            + str(self.current_group_value)
            + "M]"
        )

    def on_ewr_selection_changed(self, index):
        ewr = self.ewr_selector.itemData(index)
        self.buy_ewr_button.setText(
            f"Buy [${ewr.price}M][-${self.current_group_value}M]"
        )

    def armorComboChanged(self, index):
        unit_type = self.buyArmorCombo.itemData(self.buyArmorCombo.currentIndex())
        price = unit_type.price * self.amount.value()
        self.buyArmorButton.setText(f"Buy [${price}M][-${self.current_group_value}M]")

    def amountComboChanged(self):
        unit_type = self.buyArmorCombo.itemData(self.buyArmorCombo.currentIndex())
        price = unit_type.price * self.amount.value()
        self.buyArmorButton.setText(f"Buy [${price}M][-${self.current_group_value}M]")

    def buyArmor(self):
        logging.info("Buying Armor ")
        utype = self.buyArmorCombo.itemData(self.buyArmorCombo.currentIndex())
        price = utype.price * self.amount.value() - self.current_group_value
        if price > self.game.budget:
            self.error_money()
            self.close()
            return
        else:
            self.game.budget -= price

        # Generate Armor
        group = generate_armor_group_of_type_and_size(
            self.game, self.ground_object, utype, int(self.amount.value())
        )
        self.ground_object.groups = [group]

        # Replan redfor missions
        self.game.initialize_turn(for_red=True, for_blue=False)

        GameUpdateSignal.get_instance().updateGame(self.game)

    def buySam(self):
        sam_generator = self.samCombo.itemData(self.samCombo.currentIndex())
        price = sam_generator.price - self.current_group_value
        if price > self.game.budget:
            self.error_money()
            return
        else:
            self.game.budget -= price

        self.ground_object.groups = list(sam_generator.groups)

        # Replan redfor missions
        self.game.initialize_turn(for_red=True, for_blue=False)

        GameUpdateSignal.get_instance().updateGame(self.game)

    def buy_ewr(self):
        ewr_generator = self.ewr_selector.itemData(self.ewr_selector.currentIndex())
        price = ewr_generator.price - self.current_group_value
        if price > self.game.budget:
            self.error_money()
            return
        else:
            self.game.budget -= price

        self.ground_object.groups = [ewr_generator.vg]

        # Replan redfor missions
        self.game.initialize_turn(for_red=True, for_blue=False)

        GameUpdateSignal.get_instance().updateGame(self.game)

    def error_money(self):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText("Not enough money to buy these units !")
        msg.setWindowTitle("Not enough money")
        msg.setStandardButtons(QMessageBox.Ok)
        msg.setWindowFlags(Qt.WindowStaysOnTopHint)
        msg.exec_()
        self.close()
Пример #6
0
class QBriefingWindow(QDialog):

    def __init__(self, gameEvent: Event):
        super(QBriefingWindow, self).__init__()
        self.gameEvent = gameEvent
        self.setWindowTitle("Briefing : " + str(gameEvent))
        self.setMinimumSize(200,200)
        self.setWindowIcon(CONST.EVENT_ICONS[self.gameEvent.__class__])
        self.setModal(True)
        self.game = self.gameEvent.game

        if self.gameEvent.attacker_name == self.game.player_name:
            self.base = self.gameEvent.from_cp.base
            self.playerFromCp = self.gameEvent.from_cp
        else:
            self.base = self.gameEvent.to_cp.base
            self.playerFromCp = self.gameEvent.to_cp

        self.scramble_entries = {k: {} for k in self.gameEvent.tasks}
        self.initUi()

    def initUi(self):

        self.layout = QVBoxLayout()

        self.depart_box = QGroupBox("Departure")
        self.depart_layout = QHBoxLayout()
        self.depart_box.setLayout(self.depart_layout)
        self.depart_from_label = QLabel("Depart from : ")
        self.depart_from = QComboBox()

        for i, cp in enumerate([b for b in self.game.theater.controlpoints if b.captured]):
            self.depart_from.addItem(str(cp.name), cp)
            if cp.name == self.playerFromCp.name:
                self.depart_from.setCurrentIndex(i)

        self.depart_from.currentTextChanged.connect(self.on_departure_cp_changed)
        self.depart_layout.addWidget(self.depart_from_label)
        self.depart_layout.addWidget(self.depart_from)

        # Mission Description
        self.gridLayout = QGridLayout()
        self.initUnitRows()
        self.scramble_box = QGroupBox("Units")
        self.scramble_box.setLayout(self.gridLayout)

        self.action_layout = QHBoxLayout()
        self.commit_button = QPushButton("Commit")
        self.back_button = QPushButton("Cancel")
        self.commit_button.clicked.connect(self.start)
        self.back_button.clicked.connect(self.close)
        self.action_layout.addWidget(self.commit_button)
        self.action_layout.addWidget(self.back_button)

        self.support_box = self.initSupportBox()
        self.layout.addWidget(QLabel("<h2>{} on {}</h2>".format(self.gameEvent, self.gameEvent.to_cp.name)))
        self.layout.addWidget(self.depart_box)
        self.layout.addWidget(self.scramble_box)
        self.layout.addWidget(self.support_box)
        self.layout.addWidget(QLabel("<b>Ready?</b>"))
        self.layout.addLayout(self.action_layout)
        self.setLayout(self.layout)

    def initUnitRows(self):

        row = 0

        def header(text, row):
            self.gridLayout.addWidget(QLabel("<b>" + text + "</b>"), row, 0, 1, 2)

        def scramble_row(task_type, unit_type, unit_count, client_slots: bool, row: int):
            unit_name = QLabel("{} ({})".format(db.unit_type_name(unit_type), unit_count))
            self.gridLayout.addWidget(unit_name, row, 0)

            scramble_entry = QSpinBox()
            self.gridLayout.addWidget(scramble_entry, row, 1)

            if client_slots:
                client_entry = QSpinBox()
                self.gridLayout.addWidget(client_entry, row, 2)
            else:
                client_entry = None

            self.scramble_entries[task_type][unit_type] = scramble_entry, client_entry

        # Table headers
        self.gridLayout.addWidget(QLabel("Amount"), row, 1)
        self.gridLayout.addWidget(QLabel("Client slots"), row, 2)
        row += 1

        for flight_task in self.gameEvent.tasks:
            header("{}:".format(self.gameEvent.flight_name(flight_task)), row)
            row += 1

            if flight_task == PinpointStrike:
                if not self.base.armor:
                    self.gridLayout.addWidget(QLabel("No units"), row, 1)
                    row += 1
                for t, c in self.base.armor.items():
                    scramble_row(flight_task, t, c, False, row)
                    row += 1
            else:
                if not self.base.aircraft:
                    self.gridLayout.addWidget(QLabel("No units"), row, 1)
                    row += 1
                for t, c in self.base.aircraft.items():
                    scramble_row(flight_task, t, c, t.flyable, row)
                    row += 1

        return self.gridLayout

    def initSupportBox(self):

        self.support_box = QGroupBox("Support")
        self.support_layout = QGridLayout()
        self.support_box.setLayout(self.support_layout)

        self.awacs_label = QLabel("AWACS ({}m)".format(AWACS_BUDGET_COST))
        self.awacs_checkbox = QCheckBox()

        self.ca_slot_label = QLabel("Combined Arms Slots")
        self.ca_slot_entry = QSpinBox()
        self.ca_slot_entry.setValue(0)
        self.ca_slot_entry.setMinimum(0)
        self.ca_slot_entry.setMaximum(32)

        self.support_layout.addWidget(self.awacs_label, 0, 0)
        self.support_layout.addWidget(self.awacs_checkbox, 0, 1)
        self.support_layout.addWidget(self.ca_slot_label, 1, 0)
        self.support_layout.addWidget(self.ca_slot_entry, 1, 1)
        return self.support_box


    def initWaitingForResults(self):

        layout = QVBoxLayout()

        layout.addWidget(QLabel("<b>You are clear for takeoff</b>"))
        layout.addWidget(QLabel("In DCS open and play the mission : "))
        layout.addWidget(QLabel("<i>liberation_nextturn</i>"))
        layout.addWidget(QLabel("or"))
        layout.addWidget(QLabel("<i>liberation_nextturn_quick</i>"))

        layout.addWidget(QLabel("<b>Then save the debriefing to folder :</b>"))
        layout.addWidget(QLabel("Then save the debriefing to the folder:"))
        layout.addWidget(QLabel("<i>" + self.debriefing_directory_location() + "</i>"))
        layout.addWidget(QLabel("Waiting for results..."))

        # layout.addWidget(QLabel("In DCS open and play the mission : "))
        # layout.addWidget(QLabel("<b>You are clear for takeoff</b>"))

        self.setLayout(layout)

        pass

    def debriefing_directory_location(self) -> str:
        return os.path.join(base_path(), "liberation_debriefings")

    def start(self):

        if self.awacs_checkbox.isChecked() == 1:
            self.gameEvent.is_awacs_enabled = True
            self.game.awacs_expense_commit()
        else:
            self.gameEvent.is_awacs_enabled = False

        ca_slot_entry_value = self.ca_slot_entry.value()
        try:
            ca_slots = int(ca_slot_entry_value and ca_slot_entry_value or "0")
        except:
            ca_slots = 0
        self.gameEvent.ca_slots = ca_slots


        # Resolve Departure CP
        self.gameEvent.departure_cp = self.depart_from.itemData(self.depart_from.currentIndex())


        flights = {k: {} for k in self.gameEvent.tasks}  # type: db.TaskForceDict
        units_scramble_counts = {}  # type: typing.Dict[typing.Type[UnitType], int]
        tasks_scramble_counts = {}  # type: typing.Dict[typing.Type[Task], int]
        tasks_clients_counts = {}  # type: typing.Dict[typing.Type[Task], int]

        def dampen_count(unit_type, count: int) -> int:
            nonlocal units_scramble_counts
            total_count = self.base.total_units_of_type(unit_type)

            total_scrambled = units_scramble_counts.get(unit_type, 0)
            dampened_value = count if count + total_scrambled < total_count else total_count - total_scrambled
            units_scramble_counts[unit_type] = units_scramble_counts.get(unit_type, 0) + dampened_value

            return dampened_value

        for task_type, dict in self.scramble_entries.items():
            for unit_type, (count_entry, clients_entry) in dict.items():
                try:
                    count = int(count_entry.value())
                except:
                    count = 0

                try:
                    clients_count = int(clients_entry and clients_entry.value() or 0)
                except:
                    clients_count = 0

                dampened_count = dampen_count(unit_type, count)
                tasks_clients_counts[task_type] = tasks_clients_counts.get(task_type, 0) + clients_count
                tasks_scramble_counts[task_type] = tasks_scramble_counts.get(task_type, 0) + dampened_count

                flights[task_type][unit_type] = dampened_count, clients_count

        for task in self.gameEvent.ai_banned_tasks:
            if tasks_clients_counts.get(task, 0) == 0 and tasks_scramble_counts.get(task, 0) > 0:
                self.showErrorMessage("Need at least one player in flight {}".format(self.gameEvent.flight_name(task)))
                return

        for task in self.gameEvent.player_banned_tasks:
            if tasks_clients_counts.get(task, 0) != 0:
                self.showErrorMessage("Players are not allowed on flight {}".format(self.gameEvent.flight_name(task)))
                return

        if self.game.is_player_attack(self.gameEvent):
            if isinstance(self.gameEvent, FrontlineAttackEvent):
                if self.base.total_armor == 0:
                    self.showErrorMessage("No ground vehicles available to attack!")
                    return

            self.gameEvent.player_attacking(flights)
        else:
            if isinstance(self.gameEvent, FrontlineAttackEvent):
                if self.gameEvent.to_cp.base.total_armor == 0:
                    self.showErrorMessage("No ground vehicles available to defend!")
                    return

            self.gameEvent.player_defending(flights)

        self.game.initiate_event(self.gameEvent)

        waiting = QWaitingForMissionResultWindow(self.gameEvent, self.game)
        waiting.show()

        self.close()

    def showErrorMessage(self, text):
        about = QMessageBox()
        about.setWindowTitle("Error")
        about.setIcon(QMessageBox.Icon.Critical)
        about.setText(text)
        about.exec_()

    def on_departure_cp_changed(self):

        selectedBase = self.depart_from.itemData(self.depart_from.currentIndex())

        for i, cp in enumerate([b for b in self.game.theater.controlpoints if b.captured]):
            if cp.name == selectedBase.name:
                self.base = cp.base
                self.playerFromCp = cp
                break

        # Clear current selection
        self.scramble_entries = {k: {} for k in self.gameEvent.tasks}

        # Clear the grid layout
        for i in reversed(range(self.gridLayout.count())):
            self.gridLayout.itemAt(i).widget().setParent(None)

        # Rebuild the grid layout, so that it correspond to the newly selected CP
        self.initUnitRows()
Пример #7
0
class rawForm(baseForm):
    """
    Postprocessing of raw files.
    """
    dataChanged = QtCore.Signal(int)

    @classmethod
    def getNewWindow(cls,
                     targetImage=None,
                     axeSize=500,
                     layer=None,
                     parent=None):
        wdgt = rawForm(axeSize=axeSize,
                       targetImage=targetImage,
                       layer=layer,
                       parent=parent)
        wdgt.setWindowTitle(layer.name)
        return wdgt

    @staticmethod
    def slider2Temp(v):
        return 2000 + v * v

    @staticmethod
    def temp2Slider(T):
        return np.sqrt(T - 2000)

    @staticmethod
    def slider2Tint(v):
        return 0.1 + 0.0125 * v  # 0.2 + 0.0125 * v  # wanted range : 0.2...2.5
        # coeff = (self.tempCorrection / 4000 - 1) * 1.2 # experimental formula
        # eturn coeff + 0.01*v

    @staticmethod
    def tint2Slider(t):
        return (t - 0.1) / 0.0125
        # coeff = (self.tempCorrection / 4000 - 1) * 1.2 # experimental formula
        # return (t-coeff)/0.01
        # displayed value

    @staticmethod
    def sliderTint2User(v):
        return v - 75  # ((slider2Tint(v) - 1)*100)

    @staticmethod
    def slider2Exp(v):
        return 2**((v - 50) / 15.0)

    @staticmethod
    def exp2Slider(e):
        return round(15 * np.log2(e) + 50)

    @staticmethod
    def sliderExp2User(v):
        return (v - 50) / 15

    @staticmethod
    def slider2Cont(v):
        return v

    @staticmethod
    def cont2Slider(e):
        return e

    @staticmethod
    def slider2Br(v):
        return (np.power(3, v / 50) - 1) / 2

    @staticmethod
    def br2Slider(v):
        return 50 * log(2 * v + 1, 3)  # int(round(50.0 * e))

    @staticmethod
    def brSlider2User(v):
        return v - 50

    @staticmethod
    def slider2Sat(v):
        return v - 50

    @staticmethod
    def sat2Slider(e):
        return e + 50

    def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None):
        super().__init__(layer=layer, targetImage=targetImage, parent=parent)

        #######################################
        # Libraw correspondences:
        # rgb_xyz_matrix is libraw cam_xyz
        # camera_whitebalance is libraw cam_mul
        # daylight_whitebalance is libraw pre_mul
        # dng correspondences:
        # ASSHOTNEUTRAL tag value is (X,Y,Z) =  1 / rawpyObj.camera_whitebalance
        ##########################################
        rawpyObj = layer.parentImage.rawImage

        # constants and as shot values
        self.XYZ2CameraMatrix = rawpyObj.rgb_xyz_matrix[:3, :]
        self.XYZ2CameraInverseMatrix = np.linalg.inv(self.XYZ2CameraMatrix)
        # initial post processing multipliers (as shot)
        m1, m2, m3, m4 = rawpyObj.camera_whitebalance
        self.asShotMultipliers = (
            m1 / m2, 1.0, m3 / m2, m4 / m2
        )  # normalization is mandatory : for nef files white balance is around 256
        self.asShotTemp, self.asShotTint = multipliers2TemperatureAndTint(
            *1 / np.array(self.asShotMultipliers[:3]), self.XYZ2CameraMatrix)
        self.rawMultipliers = self.asShotMultipliers  # rawpyObj.camera_whitebalance # = 1/(dng ASSHOTNEUTRAL tag value)
        self.sampleMultipliers = False
        self.samples = []
        ########################################
        # XYZ-->Camera conversion matrix:
        # Last row is zero for RGB cameras (cf. rawpy and libraw docs).
        # type ndarray, shape (4,3)
        #########################################

        # attributes initialized in setDefaults, declared here for the sake of correctness
        self.tempCorrection, self.tintCorrection, self.expCorrection, self.highCorrection,\
                                                   self.contCorrection, self.satCorrection, self.brCorrection = [None] * 7
        # contrast spline vie (initialized by setContrastSpline)
        self.contrastForm = None
        # tone spline view (initialized by setToneSpline)
        self.toneForm = None
        # dock containers for contrast and tome forms
        self.dockC, self.dockT = None, None
        # options
        optionList0, optionNames0 = ['Auto Brightness', 'Preserve Highlights'
                                     ], ['Auto Expose', 'Preserve Highlights']
        optionList1, optionNames1 = ['Auto WB', 'Camera WB', 'User WB'
                                     ], ['Auto', 'Camera (As Shot)', 'User']
        optionList2, optionNames2 = [
            'cpLookTable', 'cpToneCurve', 'manualCurve'
        ], [
            'Use Camera Profile Look Table', 'Show Tone Curves',
            'Show Contrast Curve'
        ]
        self.listWidget1 = optionsWidget(
            options=optionList0,
            optionNames=optionNames0,
            exclusive=False,
            changed=lambda: self.dataChanged.emit(1))
        self.listWidget2 = optionsWidget(
            options=optionList1,
            optionNames=optionNames1,
            exclusive=True,
            changed=lambda: self.dataChanged.emit(1))
        self.listWidget3 = optionsWidget(
            options=optionList2,
            optionNames=optionNames2,
            exclusive=False,
            changed=lambda: self.dataChanged.emit(2))
        self.options = UDict(
            (self.listWidget1.options, self.listWidget2.options,
             self.listWidget3.options))
        # display the 'as shot' temperature
        item = self.listWidget2.item(1)
        item.setText(item.text() + ' : %d' % self.asShotTemp)

        # temperature slider
        self.sliderTemp = QbLUeSlider(Qt.Horizontal)
        self.sliderTemp.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultColorStylesheet)
        self.sliderTemp.setRange(0, 100)
        self.sliderTemp.setSingleStep(1)

        self.tempLabel = QLabel()
        self.tempLabel.setText("Temp")

        self.tempValue = QLabel()
        font = self.tempValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("10000")
        h = metrics.height()
        self.tempValue.setMinimumSize(w, h)
        self.tempValue.setMaximumSize(w, h)
        self.tempValue.setText(
            str("{:.0f}".format(self.slider2Temp(self.sliderTemp.value()))))

        self.sliderTemp.valueChanged.connect(
            self.tempUpdate)  # signal send new value as parameter
        self.sliderTemp.sliderReleased.connect(lambda: self.tempUpdate(
            self.sliderTemp.value()))  # signal pass no parameter

        # tint slider
        self.sliderTint = QbLUeSlider(Qt.Horizontal)
        self.sliderTint.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultIMGColorStylesheet)
        self.sliderTint.setRange(0, 150)

        self.sliderTint.setSingleStep(1)

        self.tintLabel = QLabel()
        self.tintLabel.setText("Tint")

        self.tintValue = QLabel()
        font = self.tempValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("100")
        h = metrics.height()
        self.tintValue.setMinimumSize(w, h)
        self.tintValue.setMaximumSize(w, h)
        self.tintValue.setText(
            str("{:.0f}".format(self.sliderTint2User(
                self.sliderTint.value()))))

        self.sliderTint.valueChanged.connect(self.tintUpdate)
        self.sliderTint.sliderReleased.connect(lambda: self.tintUpdate(
            self.sliderTint.value()))  # signal pass no parameter)

        ######################
        # From libraw and dcraw sources:
        # Exposure and brightness are curve transformations.
        # Exposure curve is y = alpha*x, with cubic root ending; it is applied before demosaicing.
        # Brightness is (similar to) y = x**alpha and part of gamma transformation from linear sRGB to RGB.
        # Exposure and brightness both dilate the histogram towards highlights.
        # Exposure dilatation is uniform (homothety), brightness dilataion is
        # maximum for the midtones and the highlghts are preserved.
        # As a consequence, normal workflow begins with the adjustment of exposure,
        # to fill the entire range of the histogram and to adjust the highlights. Next,
        # one adjusts the brightness to put the midtones at the level we want them to be.
        # Cf. https://www.cambridgeincolour.com/forums/thread653.htm
        #####################

        # profile combo
        self.dngDict = self.setCameraProfilesCombo()

        # cameraProfilesCombo index changed event handler

        def cameraProfileUpdate(value):
            self.dngDict = self.cameraProfilesCombo.itemData(value)
            if self.options['cpToneCurve']:
                toneCurve = dngProfileToneCurve(
                    self.dngDict.get('ProfileToneCurve', []))
                self.toneForm.baseCurve = [
                    QPointF(x * axeSize, -y * axeSize)
                    for x, y in zip(toneCurve.dataX, toneCurve.dataY)
                ]
                self.toneForm.update()
            # recompute as shot temp and tint using new profile
            self.asShotTemp, self.asShotTint = multipliers2TemperatureAndTint(
                *1 / np.array(self.asShotMultipliers[:3]),
                self.XYZ2CameraMatrix,
                dngDict=self.dngDict
            )  # TODO 6/12/19 added keyword dngDict validate
            # display updated as shot temp
            item = self.listWidget2.item(1)
            item.setText(item.text().split(":")[0] + ': %d' % self.asShotTemp)
            # invalidate cache
            self.layer.bufCache_HSV_CV32 = None
            self.dataChanged.emit(2)  # 2 = no postprocessing

        self.cameraProfilesCombo.currentIndexChanged.connect(
            cameraProfileUpdate)

        # denoising combo
        self.denoiseCombo = QComboBox()
        items = OrderedDict([('Off', 0), ('Medium', 1), ('Full', 2)])
        for key in items:
            self.denoiseCombo.addItem(key, items[key])

        # denoiseCombo index changed event handler
        def denoiseUpdate(value):
            self.denoiseValue = self.denoiseCombo.itemData(value)
            self.dataChanged.emit(1)

        self.denoiseCombo.currentIndexChanged.connect(denoiseUpdate)

        # overexposed area restoration
        self.overexpCombo = QComboBox()
        items = OrderedDict([('Clip', 0), ('Ignore', 1), ('Blend', 2),
                             ('Reconstruct', 3)])
        for key in items:
            self.overexpCombo.addItem(key, items[key])

        # overexpCombo index changed event handler
        def overexpUpdate(value):
            self.overexpValue = self.overexpCombo.itemData(value)
            self.dataChanged.emit(1)

        self.overexpCombo.currentIndexChanged.connect(overexpUpdate)

        # exp slider
        self.sliderExp = QbLUeSlider(Qt.Horizontal)
        self.sliderExp.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet)
        self.sliderExp.setRange(0, 100)

        self.sliderExp.setSingleStep(1)

        self.expLabel = QLabel()
        self.expLabel.setText("Exp.")

        self.expValue = QLabel()
        font = self.expValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("+1.0")
        h = metrics.height()
        self.expValue.setMinimumSize(w, h)
        self.expValue.setMaximumSize(w, h)
        self.expValue.setText(
            str("{:.1f}".format(self.slider2Exp(self.sliderExp.value()))))

        # exp done event handler
        def expUpdate(value):
            self.expValue.setText(
                str("{:+.1f}".format(
                    self.sliderExp2User(self.sliderExp.value()))))
            # move not yet terminated or value not modified
            if self.sliderExp.isSliderDown() or self.slider2Exp(
                    value) == self.expCorrection:
                return
            try:
                self.sliderExp.valueChanged.disconnect()
                self.sliderExp.sliderReleased.disconnect()
            except RuntimeError:
                pass
            # rawpy: expCorrection range is -2.0...3.0, boiling down to exp_shift range 2**(-2)=0.25...2**3=8.0
            self.expCorrection = self.slider2Exp(self.sliderExp.value())
            self.dataChanged.emit(1)
            self.sliderExp.valueChanged.connect(
                expUpdate)  # send new value as parameter
            self.sliderExp.sliderReleased.connect(lambda: expUpdate(
                self.sliderExp.value()))  # signal pass no parameter

        self.sliderExp.valueChanged.connect(
            expUpdate)  # send new value as parameter
        self.sliderExp.sliderReleased.connect(lambda: expUpdate(
            self.sliderExp.value()))  # signal pass no parameter

        # brightness slider
        brSlider = QbLUeSlider(Qt.Horizontal)
        brSlider.setRange(1, 101)

        self.sliderExp.setSingleStep(1)

        brSlider.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet)

        self.sliderBrightness = brSlider
        brLabel = QLabel()
        brLabel.setText("Bright.")

        self.brValue = QLabel()
        font = self.expValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("+99")
        h = metrics.height()
        self.brValue.setMinimumSize(w, h)
        self.brValue.setMaximumSize(w, h)
        self.brValue.setText(
            str("{:+d}".format(
                int(self.brSlider2User(self.sliderBrightness.value())))))

        # brightness done event handler
        def brUpdate(value):
            self.brValue.setText(
                str("{:+d}".format(
                    int(self.brSlider2User(self.sliderBrightness.value())))))
            # move not yet terminated or value not modified
            if self.sliderBrightness.isSliderDown() or self.slider2Br(
                    value) == self.brCorrection:
                return
            try:
                self.sliderBrightness.valueChanged.disconnect()
                self.sliderBrightness.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.brCorrection = self.slider2Br(self.sliderBrightness.value())
            self.dataChanged.emit(1)
            self.sliderBrightness.sliderReleased.connect(
                lambda: brUpdate(self.sliderBrightness.value()))
            self.sliderBrightness.valueChanged.connect(
                brUpdate)  # send new value as parameter

        self.sliderBrightness.valueChanged.connect(
            brUpdate)  # send new value as parameter
        self.sliderBrightness.sliderReleased.connect(
            lambda: brUpdate(self.sliderBrightness.value()))

        # contrast slider
        self.sliderCont = QbLUeSlider(Qt.Horizontal)
        self.sliderCont.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultBWStylesheet)
        self.sliderCont.setRange(0, 20)

        self.sliderCont.setSingleStep(1)

        self.contLabel = QLabel()
        self.contLabel.setText("Cont.")

        self.contValue = QLabel()
        font = self.contValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("100")
        h = metrics.height()
        self.contValue.setMinimumSize(w, h)
        self.contValue.setMaximumSize(w, h)
        self.contValue.setText(
            str("{:.0f}".format(self.slider2Cont(self.sliderCont.value()))))

        # cont done event handler
        def contUpdate(value):
            self.contValue.setText(
                str("{:.0f}".format(self.slider2Cont(
                    self.sliderCont.value()))))
            # move not yet terminated or value not modified
            if self.sliderCont.isSliderDown() or self.slider2Cont(
                    value) == self.tempCorrection:
                return
            try:
                self.sliderCont.valueChanged.disconnect()
                self.sliderCont.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.contCorrection = self.slider2Cont(self.sliderCont.value())
            self.contValue.setText(str("{:+d}".format(self.contCorrection)))
            # force to recalculate the spline
            self.layer.autoSpline = True
            self.dataChanged.emit(
                3)  # no postprocessing and no camera profile stuff
            self.sliderCont.valueChanged.connect(
                contUpdate)  # send new value as parameter
            self.sliderCont.sliderReleased.connect(lambda: contUpdate(
                self.sliderCont.value()))  # signal has no parameter

        self.sliderCont.valueChanged.connect(
            contUpdate)  # send new value as parameter
        self.sliderCont.sliderReleased.connect(lambda: contUpdate(
            self.sliderCont.value()))  # signal has no parameter

        # saturation slider
        self.sliderSat = QbLUeSlider(Qt.Horizontal)
        self.sliderSat.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultColorStylesheet)
        self.sliderSat.setRange(0, 100)

        self.sliderSat.setSingleStep(1)

        satLabel = QLabel()
        satLabel.setText("Sat.")

        self.satValue = QLabel()
        font = self.satValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("+10")
        h = metrics.height()
        self.satValue.setMinimumSize(w, h)
        self.satValue.setMaximumSize(w, h)
        self.satValue.setText(
            str("{:+d}".format(self.slider2Sat(self.sliderSat.value()))))
        """sat done event handler"""

        def satUpdate(value):
            self.satValue.setText(
                str("{:+d}".format(self.slider2Sat(self.sliderSat.value()))))
            # move not yet terminated or value not modified
            if self.sliderSat.isSliderDown() or self.slider2Sat(
                    value) == self.satCorrection:
                return
            try:
                self.sliderSat.valueChanged.disconnect()
                self.sliderSat.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.satCorrection = self.slider2Sat(self.sliderSat.value())
            self.dataChanged.emit(
                3)  # no post processing and no camera profile stuff
            self.sliderSat.valueChanged.connect(
                satUpdate)  # send new value as parameter
            self.sliderSat.sliderReleased.connect(lambda: satUpdate(
                self.sliderSat.value()))  # signal has no parameter

        self.sliderSat.valueChanged.connect(
            satUpdate)  # send new value as parameter
        self.sliderSat.sliderReleased.connect(lambda: satUpdate(
            self.sliderSat.value()))  # signal has no parameter

        # layout
        l = QVBoxLayout()
        l.addWidget(self.listWidget3)
        hl01 = QHBoxLayout()
        hl01.addWidget(QLabel('Camera Profile'))
        hl01.addWidget(self.cameraProfilesCombo)
        l.addLayout(hl01)
        hl0 = QHBoxLayout()
        hl0.addWidget(QLabel('Denoising'))
        hl0.addWidget(self.denoiseCombo)
        l.addLayout(hl0)
        hl00 = QHBoxLayout()
        hl00.addWidget(QLabel('Overexp. Restoration'))
        hl00.addWidget(self.overexpCombo)
        l.addLayout(hl00)
        hl1 = QHBoxLayout()
        hl1.addWidget(self.expLabel)
        hl1.addWidget(self.expValue)
        hl1.addWidget(self.sliderExp)
        l.addLayout(hl1)
        hl8 = QHBoxLayout()
        hl8.addWidget(brLabel)
        hl8.addWidget(self.brValue)
        hl8.addWidget(self.sliderBrightness)
        l.addLayout(hl8)
        l.addWidget(self.listWidget1)
        vl1 = QVBoxLayout()
        vl1.addWidget(self.listWidget2)
        gb1 = QGroupBox()
        gb1.setTitle('White Balance')
        hl2 = QHBoxLayout()
        hl2.addWidget(self.tempLabel)
        hl2.addWidget(self.tempValue)
        hl2.addWidget(self.sliderTemp)
        hl3 = QHBoxLayout()
        hl3.addWidget(self.tintLabel)
        hl3.addWidget(self.tintValue)
        hl3.addWidget(self.sliderTint)
        vl1.addLayout(hl2)
        vl1.addLayout(hl3)
        gb1.setLayout(vl1)
        l.addWidget(gb1)
        hl4 = QHBoxLayout()
        hl4.addWidget(self.contLabel)
        hl4.addWidget(self.contValue)
        hl4.addWidget(self.sliderCont)
        hl7 = QHBoxLayout()
        hl7.addWidget(satLabel)
        hl7.addWidget(self.satValue)
        hl7.addWidget(self.sliderSat)

        # separator
        sep = QFrame()
        sep.setFrameShape(QFrame.HLine)
        sep.setFrameShadow(QFrame.Sunken)
        l.addWidget(sep)
        l.addLayout(hl4)
        l.addLayout(hl7)
        l.addStretch(1)
        self.setLayout(l)
        self.adjustSize()
        self.setDefaults()
        self.setWhatsThis("""<b>Development of raw files</b><br>
                    <b>Default settings</b> are a good starting point.<br>
                    A <b>Tone Curve</b> is applied to the raw image prior to postprocessing.<br> 
                    The cuvre can be edited by checking the option
                    <b>Show Tone Curve</b>; this option works best with manual exposure.<br>
                    <b>Contrast</b> correction is based on an automatic algorithm 
                    well suited to multi-mode histograms.<br>
                    <b>Brightness, Contrast</b> and <b>Saturation</b> levels</b> are 
                    adjustable with the correponding sliders.<br>
                    The <b>Contrast Curve</b> can be edited manually by checking 
                    the option <b>Show Contrast Curve</b>.<br>
                    Uncheck <b>Auto Expose</b> to adjust the exposure manually.<br>
                    The <b>OverExp. Rest.</b> slider controls the mode of restoration of overexposed areas. 
                    Valid values are 0 to 3 (0=clip;1=unclip;2=blend;3=rebuild); (with Auto Exposed 
                    checked the mode is clip).<br>
                    """)  # end of setWhatsThis

    def close(self):
        """
        Overrides QWidget.close to
        close toneForm and contrastForm
        @return:
        @rtype: boolean
        """
        delete = self.testAttribute(Qt.WA_DeleteOnClose)
        for attr in ['toneForm', 'contrastForm']:
            form = getattr(self, attr, None)
            if delete and form is not None:
                dock = form.parent()
                dock.setAttribute(Qt.WA_DeleteOnClose)
                form.setAttribute(Qt.WA_DeleteOnClose)
                dock.close()
                form.close()
        return super().close()

    def showToneSpline(self):
        """
        On first call, init and show the Tone Curve form.
        Otherwise, show the form.
        Return True if called for the first time, False otherwise.
        @return:
        @rtype: boolean
        """
        axeSize = 200
        if self.toneForm is None:
            form = graphicsToneForm.getNewWindow(targetImage=self.targetImage,
                                                 axeSize=axeSize,
                                                 layer=self.layer,
                                                 parent=self,
                                                 curveType='cubic')
            form.setWindowFlags(Qt.WindowStaysOnTopHint)
            form.setAttribute(Qt.WA_DeleteOnClose, on=False)
            form.setFixedHeight(axeSize + 140)
            form.setWindowTitle('Cam Tone Curve')
            form.setButtonText('Reset Curve')
            # get base curve from profile
            toneCurve = dngProfileToneCurve(
                self.dngDict.get('ProfileToneCurve', []))
            form.baseCurve = [
                QPointF(x * axeSize, -y * axeSize)
                for x, y in zip(toneCurve.dataX, toneCurve.dataY)
            ]

            def f():
                layer = self.layer
                layer.bufCache_HSV_CV32 = None
                layer.applyToStack()
                layer.parentImage.onImageChanged()

            form.scene().quadricB.curveChanged.sig.connect(f)
            self.toneForm = form
            self.toneForm.optionName = 'cpToneCurve'
            dockT = self.addSubcontrol(
                self.parent())  # )stateAwareQDockWidget(self.parent())
            dockT.setWindowFlags(form.windowFlags())
            dockT.setWindowTitle(form.windowTitle())
            dockT.setStyleSheet(
                "QGraphicsView{margin: 10px; border-style: solid; border-width: 1px; border-radius: 1px;}"
            )
            window = self.parent().parent()
            window.addDockWidget(Qt.LeftDockWidgetArea, dockT)
            self.dockT = dockT
            dockT.setWidget(form)
            showFirst = True
            form.setWhatsThis("""<b>Camera Profile Tone Curve</b><br>
                            The profile curve, if any, is applied as a starting point for user adjustments,
                            after raw post-processing.
                            Its input and output are in <b>linear</b> gamma.
                            The curve is shown in red and cannot be changed.<br>
                            A user curve, shown in black, is editable and is applied right after the
                            former.<br>         
                            """)  # end of setWhatsThis
        else:
            form = self.toneForm
            showFirst = False
        form.scene().setSceneRect(-25, -axeSize - 25, axeSize + 50,
                                  axeSize + 50)
        self.dockT.showNormal()
        return showFirst

    def setContrastSpline(self, a, b, d, T):
        """
        Updates and displays the contrast spline Form.
        The form is created if needed.
        (Cf. also CoBrStaForm setContrastSpline).
        @param a: x_coordinates
        @type a:
        @param b: y-coordinates
        @type b:
        @param d: tangent slopes
        @type d:
        @param T: spline
        @type T: ndarray dtype=float
        """
        axeSize = 200
        if self.contrastForm is None:
            form = graphicsSplineForm.getNewWindow(targetImage=None,
                                                   axeSize=axeSize,
                                                   layer=self.layer,
                                                   parent=None)
            form.setFixedHeight(axeSize + 140)
            form.setWindowFlags(Qt.WindowStaysOnTopHint)
            form.setAttribute(Qt.WA_DeleteOnClose, on=False)
            form.setWindowTitle('Contrast Curve')

            def f():
                layer = self.layer
                layer.applyToStack()
                layer.parentImage.onImageChanged()

            form.scene().quadricB.curveChanged.sig.connect(f)
            self.contrastForm = form
            self.contrastForm.optionName = 'manualCurve'
            dockC = self.addSubcontrol(
                self.parent())  # stateAwareQDockWidget(self.parent())
            dockC.setWindowFlags(form.windowFlags())
            dockC.setWindowTitle(form.windowTitle())
            dockC.setStyleSheet(
                "QGraphicsView{margin: 10px; border-style: solid; border-width: 1px; border-radius: 1px;}"
            )
            window = self.parent().parent()
            window.addDockWidget(Qt.LeftDockWidgetArea, dockC)
            self.dockC = dockC
            dockC.setWidget(form)
        else:
            form = self.contrastForm
        # update the curve
        form.scene().setSceneRect(-25, -axeSize - 25, axeSize + 50,
                                  axeSize + 50)
        form.scene().quadricB.setCurve(a * axeSize, b * axeSize, d,
                                       T * axeSize)
        self.dockC.showNormal()

    # temp changed  event handler
    def tempUpdate(self, value):
        self.tempValue.setText(
            str("{:.0f}".format(self.slider2Temp(self.sliderTemp.value()))))
        # move not yet terminated or value not modified
        if self.sliderTemp.isSliderDown() or self.slider2Temp(
                value) == self.tempCorrection:
            return
        try:
            self.sliderTemp.valueChanged.disconnect()
            self.sliderTemp.sliderReleased.disconnect()
        except RuntimeError:
            pass
        self.tempCorrection = self.slider2Temp(self.sliderTemp.value())
        # get multipliers (temperatureAndTint2Multipliers returns the camera neutral)
        multipliers = [
            1 / m
            for m in temperatureAndTint2Multipliers(self.tempCorrection,
                                                    1.0,
                                                    self.XYZ2CameraMatrix,
                                                    dngDict=self.dngDict)
        ]  # TODO 6/12/19 added keyword dngDict validate
        multipliers[1] *= self.tintCorrection
        self.rawMultipliers = multipliers
        m = multipliers[1]
        self.rawMultipliers = [self.rawMultipliers[i] / m for i in range(4)]
        self.dataChanged.emit(1)
        self.sliderTemp.valueChanged.connect(
            self.tempUpdate)  # send new value as parameter
        self.sliderTemp.sliderReleased.connect(lambda: self.tempUpdate(
            self.sliderTemp.value()))  # signal has no parameter

    # tint change event handler
    def tintUpdate(self, value):
        self.tintValue.setText(
            str("{:.0f}".format(self.sliderTint2User(
                self.sliderTint.value()))))
        # move not yet terminated or value not modified
        if self.sliderTint.isSliderDown() or self.slider2Tint(
                value) == self.tintCorrection:
            return
        try:
            self.sliderTint.valueChanged.disconnect()
            self.sliderTint.sliderReleased.disconnect()
        except RuntimeError:
            pass
        self.tintCorrection = self.slider2Tint(self.sliderTint.value())
        # get multipliers (temperatureAndTint2Multipliers returns the camera neutral)
        multipliers = [
            1 / m
            for m in temperatureAndTint2Multipliers(self.tempCorrection,
                                                    1.0,
                                                    self.XYZ2CameraMatrix,
                                                    dngDict=self.dngDict)
        ]  # TODO 6/12/19 added keyword dngDict validate
        multipliers[1] *= self.tintCorrection
        self.rawMultipliers = multipliers
        m = multipliers[1]
        self.rawMultipliers = [self.rawMultipliers[i] / m for i in range(4)]
        self.dataChanged.emit(1)
        self.sliderTint.valueChanged.connect(self.tintUpdate)
        self.sliderTint.sliderReleased.connect(lambda: self.tintUpdate(
            self.sliderTint.value()))  # signal has no parameter)

    def setRawMultipliers(self, m0, m1, m2, sampling=True):
        mi = min(m0, m1, m2)
        m0, m1, m2 = m0 / mi, m1 / mi, m2 / mi
        self.rawMultipliers = [m0, m1, m2, m1]
        invMultipliers = [1 / self.rawMultipliers[i] for i in range(3)]
        try:
            self.sliderTemp.valueChanged.disconnect()
            self.sliderTint.valueChanged.disconnect()
        except RuntimeError:
            pass
        # get temp and tint
        temp, tint = multipliers2TemperatureAndTint(*invMultipliers,
                                                    self.XYZ2CameraMatrix)
        self.tintCorrection = tint
        self.sliderTemp.setValue(self.temp2Slider(temp))
        self.sliderTint.setValue(self.tint2Slider(tint))
        self.tempValue.setText(
            str("{:.0f}".format(self.slider2Temp(self.sliderTemp.value()))))
        self.tintValue.setText(
            str("{:.0f}".format(self.sliderTint2User(
                self.sliderTint.value()))))
        self.sliderTemp.valueChanged.connect(self.tempUpdate)
        self.sliderTint.valueChanged.connect(self.tintUpdate)
        self.sampleMultipliers = sampling
        self.dataChanged.emit(1)

    def updateLayer(self, level):
        """
        data changed event handler.
        @param level: 3: redo contrast and saturation, 2: previous + camera profile stuff, 1: all
        @type level: int
        """
        if level == 1:
            # force all
            self.layer.bufCache_HSV_CV32 = None
            self.layer.postProcessCache = None
        elif level == 2:
            # force camera profile stuff
            self.layer.bufCache_HSV_CV32 = None
        elif level == 3:
            # keep the 2 cache buffers
            pass
        # contrast curve
        cf = getattr(self, 'dockC', None)
        if cf is not None:
            if self.options['manualCurve']:
                cf.showNormal()
            else:
                cf.hide()
        # tone curve
        ct = getattr(self, 'dockT', None)
        if ct is not None:
            if self.options['cpToneCurve']:
                ct.showNormal()
            else:
                ct.hide()
        self.enableSliders()
        self.layer.applyToStack()
        self.layer.parentImage.onImageChanged()

    def enableSliders(self):
        useUserWB = self.listWidget2.options["User WB"]
        useUserExp = not self.listWidget1.options["Auto Brightness"]
        self.sliderTemp.setEnabled(useUserWB)
        self.sliderTint.setEnabled(useUserWB)
        self.sliderExp.setEnabled(useUserExp)
        # self.sliderHigh.setEnabled(useUserExp)
        self.tempValue.setEnabled(self.sliderTemp.isEnabled())
        self.tintValue.setEnabled(self.sliderTint.isEnabled())
        self.expValue.setEnabled(self.sliderExp.isEnabled())
        # self.highValue.setEnabled(self.sliderHigh.isEnabled())
        self.tempLabel.setEnabled(self.sliderTemp.isEnabled())
        self.tintLabel.setEnabled(self.sliderTint.isEnabled())
        self.expLabel.setEnabled(self.sliderExp.isEnabled())
        # self.highLabel.setEnabled(self.sliderHigh.isEnabled())

    def setDefaults(self):
        self.dngDict = self.cameraProfilesCombo.itemData(0)
        self.listWidget1.unCheckAll()
        self.listWidget2.unCheckAll()
        self.listWidget1.checkOption(self.listWidget1.intNames[0])
        self.listWidget1.checkOption(self.listWidget1.intNames[1])
        self.listWidget2.checkOption(self.listWidget2.intNames[1])
        self.listWidget3.checkOption(self.listWidget3.intNames[0])
        self.enableSliders()
        self.denoiseValue = 0  # denoising off
        self.overexpValue = 0  # clip
        self.tempCorrection = self.asShotTemp
        self.tintCorrection = 1.0
        self.expCorrection = 1.0
        # self.highCorrection = 3.0  # restoration of overexposed highlights. 0: clip 1:unclip, 2: blend, 3...: rebuild
        self.contCorrection = 0.0
        # self.noiseCorrection = 0
        self.satCorrection = 0.0
        self.brCorrection = 1.0
        # prevent multiple updates
        try:
            self.dataChanged.disconnect()
        except RuntimeError:
            pass
        self.sliderTemp.setValue(round(self.temp2Slider(self.tempCorrection)))
        self.sliderTint.setValue(round(self.tint2Slider(self.tintCorrection)))
        self.sliderExp.setValue(self.exp2Slider(self.expCorrection))
        # self.sliderHigh.setValue(self.highCorrection)
        self.sliderCont.setValue(self.cont2Slider(self.contCorrection))
        self.sliderBrightness.setValue(self.br2Slider(self.brCorrection))
        self.sliderSat.setValue(self.sat2Slider(self.satCorrection))
        self.dataChanged.connect(self.updateLayer)

    def setCameraProfilesCombo(self):
        """
        Populates the camera profile Combo box.
        for each item, text is the filename and data is the corresponding dict.
        The function returns as soon as a first item is loaded. Remainning profiles are
        loaded asynchronously.
        @return: the currently selected item data
        @rtype: dict
        """
        self.cameraProfilesCombo = QComboBox()
        files = [self.targetImage.filename]
        files.extend(getDngProfileList(self.targetImage.cameraModel()))
        if not files:
            self.cameraProfilesCombo.addItem('None', {})
            return {}
        # load a first profile
        nextInd, found = 0, False
        while nextInd < len(files) and not found:
            f = files[nextInd]
            key = basename(f)[:-4] if nextInd > 0 else 'Embedded Profile'
            d = getDngProfileDict(f)
            # filter d
            d = {k: d[k] for k in d if d[k] != ''}
            if d:
                self.cameraProfilesCombo.addItem(key, d)
                found = True
            nextInd += 1

        def load():
            # load remaining profiles
            for i, f in enumerate(files[nextInd:]):
                key = basename(
                    f)[:-4] if i + nextInd > 0 else 'Embedded Profile'
                d = getDngProfileDict(f)
                # filter d
                d = {k: d[k] for k in d if d[k] != ''}
                if d:
                    self.cameraProfilesCombo.addItem(key, d)
            self.cameraProfilesCombo.addItem('None', {})

        threading.Thread(target=load).start()

        self.cameraProfilesCombo.setSizeAdjustPolicy(
            QComboBox.SizeAdjustPolicy.AdjustToContents)
        self.cameraProfilesCombo.setMaximumWidth(150)
        self.cameraProfilesCombo.setStyleSheet(
            "QComboBox QAbstractItemView { min-width: 250px;}")
        # return the currently selected item data
        return self.cameraProfilesCombo.itemData(0)
Пример #8
0
class QTgoLayoutGroupRow(QWidget):
    group_template_changed = Signal()

    def __init__(self, force_group: ForceGroup, group: TgoLayoutGroup) -> None:
        super().__init__()
        self.grid_layout = QGridLayout()
        self.setLayout(self.grid_layout)
        self.grid_layout.setColumnStretch(0, 100)
        self.amount_selector = QSpinBox()
        self.unit_selector = QComboBox()
        self.unit_selector.setMinimumWidth(250)
        self.group_selector = QCheckBox()

        # Add all possible units with the price
        for unit_type in force_group.unit_types_for_group(group):
            self.unit_selector.addItem(
                f"{unit_type.name} [${unit_type.price}M]",
                userData=(unit_type.dcs_unit_type, unit_type.price),
            )
        # Add all possible statics with price = 0
        for static_type in force_group.statics_for_group(group):
            self.unit_selector.addItem(f"{static_type} (Static)",
                                       userData=(static_type, 0))

        if self.unit_selector.count() == 0:
            raise LayoutException("No units available for the TgoLayoutGroup")

        self.unit_selector.adjustSize()
        self.unit_selector.setEnabled(self.unit_selector.count() > 1)
        self.grid_layout.addWidget(self.unit_selector,
                                   0,
                                   0,
                                   alignment=Qt.AlignRight)
        self.grid_layout.addWidget(self.amount_selector,
                                   0,
                                   1,
                                   alignment=Qt.AlignRight)

        dcs_unit_type, price = self.unit_selector.itemData(
            self.unit_selector.currentIndex())

        self.group_layout = QTgoLayoutGroup(group, dcs_unit_type,
                                            group.group_size, price)

        self.group_selector.setChecked(self.group_layout.enabled)
        self.group_selector.setEnabled(self.group_layout.layout.optional)

        self.amount_selector.setMinimum(1)
        self.amount_selector.setMaximum(self.group_layout.layout.max_size)
        self.amount_selector.setValue(self.group_layout.amount)
        self.amount_selector.setEnabled(self.group_layout.layout.max_size > 1)

        self.grid_layout.addWidget(self.group_selector,
                                   0,
                                   2,
                                   alignment=Qt.AlignRight)

        self.amount_selector.valueChanged.connect(self.on_group_changed)
        self.unit_selector.currentIndexChanged.connect(self.on_group_changed)
        self.group_selector.stateChanged.connect(self.on_group_changed)

    def on_group_changed(self) -> None:
        self.group_layout.enabled = self.group_selector.isChecked()
        unit_type, price = self.unit_selector.itemData(
            self.unit_selector.currentIndex())
        self.group_layout.dcs_unit_type = unit_type
        self.group_layout.unit_price = price
        self.group_layout.amount = self.amount_selector.value()
        self.group_template_changed.emit()
Пример #9
0
class SelectPlayersWindow(QDialog):
    def __init__(self, parent=None):
        super(SelectPlayersWindow, self).__init__(parent)
        self.parent = parent
        self.setModal(True)
        self.setWindowTitle("Torna résztvevők")
        self.resize(520, 600)
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)
        self.read_config()

        self.create_torna_selection()

        self.nevek_layout = QHBoxLayout()
        self.layout.addLayout(self.nevek_layout)
        self.show_saved_players()
        self.show_torna_players()

        self.gomb_nev_layout = QVBoxLayout()
        self.nevek_layout.addLayout(self.gomb_nev_layout)
        self.show_current_players()

        self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonbox.clicked.connect(self.buttonbox_click)
        self.layout.addWidget(self.buttonbox)

    def create_torna_selection(self):
        self.tournaments = QComboBox()
        self.tournaments.setModelColumn(0)
        self.tournaments.currentIndexChanged.connect(self.torna_valasztas)
        self.layout.addWidget(self.tournaments)
        self.load_torna()

    def load_torna(self):
        torna = QSqlQueryModel()
        query = QSqlQuery("select * from torna_settings where aktiv=2")
        torna.setQuery(query)
        if torna.record(0).value(0):
            for i in range(torna.rowCount()):
                self.tournaments.addItem(
                    torna.record(i).value(1),
                    torna.record(i).value(0))  # a value(0) a torna_id
        else:
            print("Nincs aktív torna")

    def show_saved_players(self):
        self.saved_players = QListWidget()
        self.saved_players.setFixedHeight(500)
        self.saved_players.setFixedWidth(150)
        self.saved_players.setSortingEnabled(True)
        self.saved_players.itemDoubleClicked.connect(self.add_resztvevo)
        self.load_saved_players()
        self.nevek_layout.addWidget(self.saved_players)

    def show_torna_players(self):
        self.torna_players = QListWidget()
        self.torna_players.setFixedHeight(500)
        self.torna_players.setFixedWidth(150)
        self.torna_players.setSortingEnabled(True)
        self.torna_players.itemDoubleClicked.connect(self.add_resztvevo)
        self.load_torna_players()
        self.nevek_layout.addWidget(self.torna_players)

    def load_saved_players(self):
        players = QSqlQueryModel()
        players_query = QSqlQuery("select * from players where aktiv=1")
        players.setQuery(players_query)
        self.saved_players.clear()
        for i in range(players.rowCount()):
            item = QListWidgetItem(players.record(i).value(1))
            item.setData(Qt.UserRole, players.record(i).value(0))
            self.saved_players.addItem(item)

    def load_torna_players(self):
        players = QSqlQueryModel()
        players_query = QSqlQuery(
            "select * from torna_resztvevok where 1 group by player_id, player_name"
        )
        players.setQuery(players_query)
        self.torna_players.clear()
        for i in range(players.rowCount()):
            item = QListWidgetItem(players.record(i).value(1))
            item.setData(Qt.UserRole, players.record(i).value(0))
            self.torna_players.addItem(item)

    def add_resztvevo(self, item):
        new_item = QListWidgetItem(item)
        new_item.setData(Qt.UserRole, item.data(Qt.UserRole))
        self.current_players.addItem(new_item)
        query = QSqlQuery(
            f"insert into torna_resztvevok (player_id, player_name, torna_id) values ({new_item.data(Qt.UserRole)}, '{new_item.text()}', {self.torna_id})"
        )
        query.exec_()

    def show_current_players(self):
        query = QSqlQuery("select max(player_id) from torna_resztvevok")
        query.exec_()
        while query.next():
            self.first_new_id = int(query.value(0)) + 1
        print(self.first_new_id)
        self.add_new = QPushButton("Új")
        self.add_new.clicked.connect(self.uj_ember)
        self.current_players = QListWidget()
        self.current_players.setFixedHeight(470)
        self.current_players.setFixedWidth(150)
        self.current_players.setSortingEnabled(True)
        self.gomb_nev_layout.addWidget(self.add_new)
        self.current_players.itemDoubleClicked.connect(self.remove_resztvevo)
        self.gomb_nev_layout.addWidget(self.current_players)

    def uj_ember(self):
        ujember, ok = QInputDialog.getText(
            self, "Új versenyző",
            '<html style="font-size: 15px;">Írd be a versenyző nevét!</html>')
        if ok and len(ujember):
            item = QListWidgetItem(ujember)
            item.setData(Qt.UserRole, self.first_new_id)
            self.current_players.addItem(item)
            self.first_new_id += 1

            query = QSqlQuery(
                f"insert into torna_resztvevok (player_id, player_name, torna_id) values ({item.data(Qt.UserRole)}, '{item.text()}', {self.torna_id})"
            )
            query.exec_()

    def remove_resztvevo(self, item):
        self.current_players.takeItem(
            self.current_players.row(self.current_players.selectedItems()[0]))
        # print(item.data(Qt.UserRole), item.text())
        query = QSqlQuery(
            f"delete from torna_resztvevok where player_id={item.data(Qt.UserRole)} and torna_id={self.torna_id}"
        )
        query.exec_()

    def torna_valasztas(self, i):
        self.torna_id = self.tournaments.itemData(i)
        players = QSqlQueryModel()
        players_query = QSqlQuery(
            f"select * from torna_resztvevok where torna_id={self.torna_id}")
        players.setQuery(players_query)
        self.current_players.clear()
        for i in range(players.rowCount()):
            item = QListWidgetItem(players.record(i).value(1))
            item.setData(Qt.UserRole, players.record(i).value(0))
            self.current_players.addItem(item)

    def buttonbox_click(self, b):
        if b.text() == "OK":
            self.accept()
        elif b.text() == "Cancel":
            self.reject()

    def accept(self):
        # for i in range(self.current_players.count()):
        #     item = self.current_players.item(i)
        #     print(self.torna_id, item.data(Qt.UserRole), item.text()) # itt vannak a beszúrandó adatok
        super().accept()
        # INSERT INTO `torna_resztvevok` (`player_id`, `player_name`, `torna_id`)
        # VALUES ('1111', 'teszt_user2', '8892') ON DUPLICATE KEY UPDATE player_name='teszt_user2';
    def read_config(self):
        if os.path.exists('config.ini'):
            # Van config.ini, ki kell értékelni
            config.read('config.ini')
            self.station_id = config['DEFAULT'].get('station id')
            self.secret = config['DEFAULT'].get('secret key')
            # todo módosítani kell a torna_match táblát, hogy tartalmazza a tabla mellett a hozzá tartozó secret-et is
        else:
            # Nincs config.ini, alapértékekkel inicializálni
            msg = QMessageBox(self)
            msg.setStyleSheet("fonz-size: 20px")
            msg.setWindowTitle("Hiányzó beállítás file!")
            msg.setText(
                '<html style="font-size: 14px; color: red">Nem tudtam beolvasni a konfigurációt!<br></html>'
                +
                '<html style="font-size: 16px">Kérem módosítsa a beállításokat!</html>'
            )
            msg.exec_()
            sys.exit(1)
Пример #10
0
class TornaStatuszWindow(QDialog):
    def __init__(self, parent=None):
        super(TornaStatuszWindow, self).__init__(parent)
        self.setWindowTitle("Torna állása")
        self.setMinimumHeight(720)
        # self.setMinimumWidth(700)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.hatter = QVBoxLayout()
        self.setLayout(self.hatter)
        self.create_torna_selection()
        self.hatter.addWidget(self.tournaments)
        self.space = QSpacerItem(0, 0, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        self.hatter.addItem(self.space)

    def create_torna_selection(self):
        self.tournaments = QComboBox()
        self.tournaments.setMinimumWidth(700)
        self.tournaments.setModelColumn(0)
        self.tournaments.activated.connect(self.torna_valasztas)
        self.load_torna()

    def load_torna(self):
        torna = QSqlQueryModel()
        query = QSqlQuery("select * from torna_settings where aktiv=1")
        torna.setQuery(query)
        if torna.record(0).value(0):
            for i in range(torna.rowCount()):
                self.tournaments.addItem(
                    torna.record(i).value(1),
                    torna.record(i).value(0))  # a value(0) a torna_id

    def torna_valasztas(self, i):
        self.torna_id = self.tournaments.itemData(i)
        torna = QSqlQuery(
            f"select * from torna_settings where torna_id={self.torna_id}")
        torna.exec_()
        while torna.next():
            self.csoportok_szama = torna.value(3)
            self.sorok_szama = torna.value(4)
            self.variant = torna.value(5)
            self.sets = torna.value(7)
            self.legsperset = torna.value(8)
            self.nyereshez_kell = torna.value(8)
            self.pont_gyozelem = torna.value(11)
            self.pont_vereseg = torna.value(13)

        self.tablak = []
        for cs in range(self.csoportok_szama):
            tablasor = []
            for sor in range(self.sorok_szama):
                tablasor.append(0)
            self.tablak.append(tablasor)
        query2 = QSqlQuery(
            f"select * from torna_tablak where torna_id={self.torna_id}")
        query2.exec_()
        while query2.next():
            self.tablak[query2.value(2)][query2.value(3)] = query2.value(1)
        self.nevek = []
        for cs in range(self.csoportok_szama):
            neveksor = []
            for sor in range(self.sorok_szama):
                neveksor.append("")
            self.nevek.append(neveksor)
        query2 = QSqlQuery(
            f"select player_id, player_name from torna_resztvevok where torna_id={self.torna_id}"
        )
        query2.exec_()
        while query2.next():
            for x in range(self.csoportok_szama):
                for y in range(self.sorok_szama):
                    if query2.value(0) == self.tablak[x][y]:
                        self.nevek[x][y] = query2.value(1)

        self.create_widgets()
        self.set_layout()

    def create_widgets(self):
        # GroupMemberWidget-ek
        self.csoportok = []
        for i in range(self.csoportok_szama):  # Csoportok száma
            self.csoportoszlop = []
            for j in range(self.sorok_szama):  # fő/csoport
                self.csoportoszlop.append(GroupMemberWidget(self))
                self.csoportoszlop[j]._set_csoport_number(i)
                self.csoportoszlop[j]._set_csoport_sor(j)
                self.csoportoszlop[j]._set_player_id(self.tablak[i][j])
                self.csoportoszlop[j]._set_player_name(self.nevek[i][j])
            self.csoportok.append(self.csoportoszlop)

        # EredmenyWidget-ek
        self.eredmenyek = []
        for i in range(self.csoportok_szama):
            self.csoport_eredmeny_matrix = []
            for j in range(
                    self.sorok_szama):  # ami egyenlő az oszlopok számával!!!
                self.eredmeny_oszlop = []
                for x in range(self.sorok_szama):
                    self.eredmeny_oszlop.append(EredmenyWidget(self))
                    self.eredmeny_oszlop[x]._set_csoport_number(i)
                    self.eredmeny_oszlop[x]._set_csoport_sor(j)
                    self.eredmeny_oszlop[x]._set_csoport_oszlop(x)
                    self.eredmeny_oszlop[x]._set_p1_id(self.tablak[i][j])
                    self.eredmeny_oszlop[x]._set_p2_id(self.tablak[i][x])

                self.csoport_eredmeny_matrix.append(self.eredmeny_oszlop)
            self.eredmenyek.append(self.csoport_eredmeny_matrix)

        # SzumWidget-ek
        self.szum_eredmenyek = []
        for i in range(self.csoportok_szama):  # 2
            self.csoport_szum_eredmeny_matrix = []
            for j in range(5):  # ami egyenlő az oszlopok számával!!!
                self.szum_eredmeny_oszlop = []
                for x in range(self.sorok_szama):
                    self.szum_eredmeny_oszlop.append(SzumWidget(self))
                    # self.eredmeny_oszlop[x]._set_csoport_number(i)
                    # self.eredmeny_oszlop[x]._set_csoport_sor(x)
                    # self.eredmeny_oszlop[x]._set_csoport_oszlop(j)
                    self.szum_eredmeny_oszlop[x]._set_p_id(self.tablak[i][x])
                    # self.eredmeny_oszlop[x]._set_p2_id(self.tablak[i][x])

                self.csoport_szum_eredmeny_matrix.append(
                    self.szum_eredmeny_oszlop)
            self.szum_eredmenyek.append(self.csoport_szum_eredmeny_matrix)

        if hasattr(self, 'refresh_button'):
            pass
        else:
            self.refresh_button = QPushButton("Frissítés")
            self.refresh_button.clicked.connect(self.update_statusz)

    def set_layout(self):

        if hasattr(self, 'main_layout'):
            for i in reversed(range(self.main_layout.count())):
                if self.main_layout.itemAt(i).widget() is not None:
                    self.main_layout.itemAt(i).widget().deleteLater()
            for i in reversed(range(self.main_layout.count())):
                if self.main_layout.itemAt(i).layout() is not None:
                    self.main_layout.itemAt(i).layout().deleteLater()
        else:
            self.main_layout = QHBoxLayout()
            self.hatter.addLayout(self.main_layout)

        groups = QWidget()
        groups.setFixedWidth(((self.sorok_szama + 5) * 50) + 200)
        widgets_layout = QVBoxLayout()
        groups.setLayout(widgets_layout)

        for n in range(self.csoportok_szama):  # csoportok száma
            locals()['csoport_layout' + str(n)] = QGridLayout(
            )  # Létrehozzuk az adott sorszámú csoport layout-ját
            locals()['csoport_layout' + str(n)].setContentsMargins(0, 0, 0, 0)
            locals()['csoport_layout' + str(n)].setHorizontalSpacing(0)
            locals()['csoport_layout' + str(n)].setVerticalSpacing(0)
            widgets_layout.addLayout(locals()[
                'csoport_layout' +
                str(n)])  # Hozzáadjuk a a layout-ot a widget_layout-hoz
            locals()['csoport_layout' + str(n)].addWidget(
                QLabel("Csoport_" + str(n + 1)), 0, 0, Qt.AlignHCenter)
            sorok = len(self.csoportok[n])
            for k in range(sorok):
                locals()['csoport_layout' + str(n)].addWidget(
                    QLabel(str(k + 1)), 0, k + 1, Qt.AlignHCenter)
            locals()['csoport_layout' + str(n)].addWidget(
                QLabel("NY"), 0, sorok + 5, Qt.AlignHCenter)
            locals()['csoport_layout' + str(n)].addWidget(
                QLabel("V"), 0, sorok + 6, Qt.AlignHCenter)
            locals()['csoport_layout' + str(n)].addWidget(
                QLabel("K"), 0, sorok + 7, Qt.AlignHCenter)
            locals()['csoport_layout' + str(n)].addWidget(
                QLabel("P"), 0, sorok + 8, Qt.AlignHCenter)
            locals()['csoport_layout' + str(n)].addWidget(
                QLabel("H"), 0, sorok + 9, Qt.AlignHCenter)
            for i in range(
                    len(self.csoportok[n])
            ):  # len(self.csoportok[n]) : csoporton belüli sorok száma
                # Végigmegyünk a sorokon   :  i: sorok száma, n: csoport száma

                # N: HÁNYADIK CSOPORT, I: HÁNYADIK OSZLOP-OT TÖLTJÜK
                # a layout 1. oszlopát feltöltjük a tömbben tárolt custom widget-ekkel
                # self.csoportok[n][i] N-EDIK CSOPORT I-DIK SORÁBAN A NÉV
                locals()['csoport_layout' + str(n)].addWidget(
                    self.csoportok[n][i], i + 1, 0)
                # Itt töltjük fel az eredmény-widget-eket, és a szummákat (tombben tárolva, mint a GroupMemberWidget-ek)
                # eredmenyek[n, y, i] n: csoport, y: oszlop, i: sor
                for x in range(
                        len(self.csoportok[n])
                ):  # Ez lesz az oszlop(max = sorok száma) x: oszlop száma
                    locals()['csoport_layout' + str(n)].addWidget(
                        self.eredmenyek[n][i][x], i + 1, x + 1)
                # szum_eredmenyek[x, y, z] x: csoport, y: oszlop, z: sor
                for y in range(5):  # 5 kockát rakunk ki
                    locals()['csoport_layout' + str(n)].addWidget(
                        self.szum_eredmenyek[n][y][i], i + 1, 5 + x + y + 1)

            # locals()['csoport_layout' + str(n)].addWidget(QLabel("Csoport_" + str(n + 1)), 0, 0)

        lista_layout = QVBoxLayout()
        lista_layout.addWidget(self.refresh_button)

        scroll = QScrollArea()
        scroll.setWidget(groups)
        scroll.setFixedWidth(((self.sorok_szama + 5) * 50) + 220)
        scroll.setFixedHeight(680)

        self.main_layout.addWidget(scroll)
        self.main_layout.addLayout(lista_layout)

    def update_statusz(self):
        legek = []
        query = QSqlQuery(
            f"SELECT matches.*,torna_match.player1_id as p1,torna_match.player2_id as p2 FROM matches,\
         torna_match WHERE matches.match_id=torna_match.match_id and torna_match.torna_id={self.torna_id}"
        )
        query.exec_()
        while query.next():
            akt_leg = []
            akt_leg.append(query.value(0))  # match_id
            akt_leg.append(query.value(5))  # p1
            akt_leg.append(query.value(6))  # p2
            akt_leg.append(query.value(1))  # leg
            akt_leg.append(query.value(2))  # set
            akt_leg.append(query.value(3))  # winner
            legek.append(akt_leg)
        # Egy listában meg van az adott torna összes lejátszott leg-je
        # Kinullázzuk az eredményeket, mert a lekérdezés az összeset tudja lekérni, nem csak a legfrissebbet!!!
        for x in range(self.csoportok_szama):
            for y in range(self.sorok_szama):
                for z in range(self.sorok_szama):
                    self.eredmenyek[x][y][z]._set_leg1(0)
                    self.eredmenyek[x][y][z]._set_leg2(0)
        # Először összegezzük mindenhol a nyert legeket
        for k in legek:
            for x in range(self.csoportok_szama):
                for y in range(self.sorok_szama):
                    for z in range(self.sorok_szama):
                        if self.eredmenyek[x][y][z]._get_p1_id(
                        ) == k[1] and self.eredmenyek[x][y][z]._get_p2_id(
                        ) == k[2]:
                            if self.eredmenyek[x][y][z]._get_p1_id() == k[5]:
                                self.eredmenyek[x][y][z]._set_leg1(
                                    self.eredmenyek[x][y][z]._get_leg1() + 1)
                                self.eredmenyek[x][y][z].change_leg1_number()
                            else:
                                self.eredmenyek[x][y][z]._set_leg2(
                                    self.eredmenyek[x][y][z]._get_leg2() + 1)
                                self.eredmenyek[x][y][z].change_leg2_number()
                        # ellenfél szempontjából:
                        if self.eredmenyek[x][y][z]._get_p1_id(
                        ) == k[2] and self.eredmenyek[x][y][z]._get_p2_id(
                        ) == k[1]:
                            if self.eredmenyek[x][y][z]._get_p1_id() == k[5]:
                                self.eredmenyek[x][y][z]._set_leg1(
                                    self.eredmenyek[x][y][z]._get_leg1() + 1)
                                self.eredmenyek[x][y][z].change_leg1_number()
                            else:
                                self.eredmenyek[x][y][z]._set_leg2(
                                    self.eredmenyek[x][y][z]._get_leg2() + 1)
                                self.eredmenyek[x][y][z].change_leg2_number()
        # Megnézzük, hogy valaki megnyerte-e. Ha igen akkor a nyerésért/vereségért járó pontot rögzítjük
        for x in range(self.csoportok_szama):
            for y in range(self.sorok_szama):
                for z in range(self.sorok_szama):
                    if self.eredmenyek[x][y][z]._get_leg1(
                    ) == self.nyereshez_kell:
                        self.eredmenyek[x][y][z]._set_pontszam(
                            int(self.pont_gyozelem))
                        self.eredmenyek[x][y][z].update_osszes_pont()
                    if self.eredmenyek[x][y][z]._get_leg2(
                    ) == self.nyereshez_kell:
                        self.eredmenyek[x][y][z]._set_pontszam(
                            int(self.pont_vereseg))
                        self.eredmenyek[x][y][z].update_osszes_pont()
        # helyezések
        helyezesek = []
        for cs in range(self.csoportok_szama):
            helyezes_oszlop = []
            for oszlop in range(self.sorok_szama):
                # self.szum_eredmenyek[self._csoport_number][4][self._csoport_sor].
                self.szum_eredmenyek[cs][4][oszlop]._set_ertek(3)
Пример #11
0
class QDisasmStatusBar(QFrame):
    """
    Status and control bar for disassembly views
    """
    def __init__(self, disasm_view, parent=None):
        super().__init__(parent)

        self.disasm_view = disasm_view

        # widgets
        self._nav_toolbar: Optional[NavToolbar] = None
        self._function_label: QLabel = None
        self._options_menu: DisasmOptionsMenu = None
        self._view_combo: QComboBox = None

        # information
        self._function = None

        self._init_menu()
        self._init_widgets()

    @property
    def function(self):
        return self._function

    @function.setter
    def function(self, f):
        self._function = f

        self._update_function_address()

    @property
    def function_address(self):
        if self._function is None:
            return None
        return self._function.addr

    #
    # Initialization
    #

    def _init_widgets(self):
        self._nav_toolbar = NavToolbar(
            self.disasm_view.jump_history, self.disasm_view.jump_back,
            self.disasm_view.jump_forward,
            self.disasm_view.jump_to_history_position, True, self)

        # current function
        self._function_label = QLabel()

        self._view_combo = QComboBox(self)
        self._view_combo.addItem("Linear Disassembly", QLinearDisassembly)
        self._view_combo.addItem("Graph Disassembly", QDisassemblyGraph)
        self._view_combo.activated.connect(self._view_combo_changed)
        self.disasm_view.view_visibility_changed.connect(
            self._update_view_combo)
        self._update_view_combo()

        self._disasm_level_combo = QComboBox(self)
        self._disasm_level_combo.addItem("Machine Code",
                                         DisassemblyLevel.MachineCode)
        self._disasm_level_combo.addItem("Lifter IR",
                                         DisassemblyLevel.LifterIR)
        self._disasm_level_combo.addItem("AIL", DisassemblyLevel.AIL)
        self._disasm_level_combo.activated.connect(
            self._disasm_level_combo_changed)
        self.disasm_view.disassembly_level_changed.connect(
            self._update_disasm_level_combo)
        self._update_disasm_level_combo()

        # options button
        option_btn = QPushButton()
        option_btn.setText('Options')
        option_btn.setMenu(self._options_menu.qmenu())

        # Save image button
        saveimage_btn = QPushButton()
        saveimage_btn.setText('Save image...')
        saveimage_btn.clicked.connect(self._on_saveimage_btn_clicked)

        layout = QHBoxLayout()
        layout.setContentsMargins(2, 2, 2, 2)

        layout.addWidget(self._nav_toolbar.qtoolbar())
        layout.addWidget(self._function_label)

        layout.addStretch(0)

        layout.addWidget(saveimage_btn)
        layout.addWidget(self._view_combo)
        layout.addWidget(self._disasm_level_combo)
        layout.addWidget(option_btn)
        layout.setContentsMargins(0, 0, 0, 0)

        self.setLayout(layout)

    def _init_menu(self):
        self._options_menu = DisasmOptionsMenu(self.disasm_view)

    #
    # Private methods
    #

    def _view_combo_changed(self, index: int):
        {
            QLinearDisassembly: self.disasm_view.display_linear_viewer,
            QDisassemblyGraph: self.disasm_view.display_disasm_graph
        }[self._view_combo.itemData(index)]()

    def _update_view_combo(self):
        graph_type = type(self.disasm_view.current_graph)
        index = self._view_combo.findData(graph_type)
        self._view_combo.setCurrentIndex(index)

    def _disasm_level_combo_changed(self, index: int):
        new_level = self._disasm_level_combo.itemData(index)
        self.disasm_view.set_disassembly_level(new_level)

    def _update_disasm_level_combo(self):
        new_level = self.disasm_view.disassembly_level
        index = self._disasm_level_combo.findData(new_level)
        self._disasm_level_combo.setCurrentIndex(index)

    def _update_function_address(self):
        if self.function_address is not None:
            self._function_label.setText("Function %x" % self.function_address)

    def _on_saveimage_btn_clicked(self):

        filename, folder = QFileDialog.getSaveFileName(
            self, 'Save image...', '', 'PNG Files (*.png);;Bitmaps (*.bmp)')
        if not filename or not folder:
            return

        self.disasm_view.save_image_to(os.path.join(folder, filename))
Пример #12
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.renderArea = RenderArea()

        self.shapeComboBox = QComboBox()
        self.shapeComboBox.addItem("Polygon", RenderArea.Polygon)
        self.shapeComboBox.addItem("Rectangle", RenderArea.Rect)
        self.shapeComboBox.addItem("Rounded Rectangle", RenderArea.RoundedRect)
        self.shapeComboBox.addItem("Ellipse", RenderArea.Ellipse)
        self.shapeComboBox.addItem("Pie", RenderArea.Pie)
        self.shapeComboBox.addItem("Chord", RenderArea.Chord)
        self.shapeComboBox.addItem("Path", RenderArea.Path)
        self.shapeComboBox.addItem("Line", RenderArea.Line)
        self.shapeComboBox.addItem("Polyline", RenderArea.Polyline)
        self.shapeComboBox.addItem("Arc", RenderArea.Arc)
        self.shapeComboBox.addItem("Points", RenderArea.Points)
        self.shapeComboBox.addItem("Text", RenderArea.Text)
        self.shapeComboBox.addItem("Pixmap", RenderArea.Pixmap)

        shapeLabel = QLabel("&Shape:")
        shapeLabel.setBuddy(self.shapeComboBox)

        self.penWidthSpinBox = QSpinBox()
        self.penWidthSpinBox.setRange(0, 20)
        self.penWidthSpinBox.setSpecialValueText("0 (cosmetic pen)")

        penWidthLabel = QLabel("Pen &Width:")
        penWidthLabel.setBuddy(self.penWidthSpinBox)

        self.penStyleComboBox = QComboBox()
        self.penStyleComboBox.addItem("Solid", Qt.SolidLine)
        self.penStyleComboBox.addItem("Dash", Qt.DashLine)
        self.penStyleComboBox.addItem("Dot", Qt.DotLine)
        self.penStyleComboBox.addItem("Dash Dot", Qt.DashDotLine)
        self.penStyleComboBox.addItem("Dash Dot Dot", Qt.DashDotDotLine)
        self.penStyleComboBox.addItem("None", Qt.NoPen)

        penStyleLabel = QLabel("&Pen Style:")
        penStyleLabel.setBuddy(self.penStyleComboBox)

        self.penCapComboBox = QComboBox()
        self.penCapComboBox.addItem("Flat", Qt.FlatCap)
        self.penCapComboBox.addItem("Square", Qt.SquareCap)
        self.penCapComboBox.addItem("Round", Qt.RoundCap)

        penCapLabel = QLabel("Pen &Cap:")
        penCapLabel.setBuddy(self.penCapComboBox)

        self.penJoinComboBox = QComboBox()
        self.penJoinComboBox.addItem("Miter", Qt.MiterJoin)
        self.penJoinComboBox.addItem("Bevel", Qt.BevelJoin)
        self.penJoinComboBox.addItem("Round", Qt.RoundJoin)

        penJoinLabel = QLabel("Pen &Join:")
        penJoinLabel.setBuddy(self.penJoinComboBox)

        self.brushStyleComboBox = QComboBox()
        self.brushStyleComboBox.addItem("Linear Gradient",
                                        Qt.LinearGradientPattern)
        self.brushStyleComboBox.addItem("Radial Gradient",
                                        Qt.RadialGradientPattern)
        self.brushStyleComboBox.addItem("Conical Gradient",
                                        Qt.ConicalGradientPattern)
        self.brushStyleComboBox.addItem("Texture", Qt.TexturePattern)
        self.brushStyleComboBox.addItem("Solid", Qt.SolidPattern)
        self.brushStyleComboBox.addItem("Horizontal", Qt.HorPattern)
        self.brushStyleComboBox.addItem("Vertical", Qt.VerPattern)
        self.brushStyleComboBox.addItem("Cross", Qt.CrossPattern)
        self.brushStyleComboBox.addItem("Backward Diagonal", Qt.BDiagPattern)
        self.brushStyleComboBox.addItem("Forward Diagonal", Qt.FDiagPattern)
        self.brushStyleComboBox.addItem("Diagonal Cross", Qt.DiagCrossPattern)
        self.brushStyleComboBox.addItem("Dense 1", Qt.Dense1Pattern)
        self.brushStyleComboBox.addItem("Dense 2", Qt.Dense2Pattern)
        self.brushStyleComboBox.addItem("Dense 3", Qt.Dense3Pattern)
        self.brushStyleComboBox.addItem("Dense 4", Qt.Dense4Pattern)
        self.brushStyleComboBox.addItem("Dense 5", Qt.Dense5Pattern)
        self.brushStyleComboBox.addItem("Dense 6", Qt.Dense6Pattern)
        self.brushStyleComboBox.addItem("Dense 7", Qt.Dense7Pattern)
        self.brushStyleComboBox.addItem("None", Qt.NoBrush)

        brushStyleLabel = QLabel("&Brush Style:")
        brushStyleLabel.setBuddy(self.brushStyleComboBox)

        otherOptionsLabel = QLabel("Other Options:")
        self.antialiasingCheckBox = QCheckBox("&Antialiasing")
        self.transformationsCheckBox = QCheckBox("&Transformations")

        self.shapeComboBox.activated.connect(self.shapeChanged)
        self.penWidthSpinBox.valueChanged.connect(self.penChanged)
        self.penStyleComboBox.activated.connect(self.penChanged)
        self.penCapComboBox.activated.connect(self.penChanged)
        self.penJoinComboBox.activated.connect(self.penChanged)
        self.brushStyleComboBox.activated.connect(self.brushChanged)
        self.antialiasingCheckBox.toggled.connect(
            self.renderArea.setAntialiased)
        self.transformationsCheckBox.toggled.connect(
            self.renderArea.setTransformed)

        mainLayout = QGridLayout()
        mainLayout.setColumnStretch(0, 1)
        mainLayout.setColumnStretch(3, 1)
        mainLayout.addWidget(self.renderArea, 0, 0, 1, 4)
        mainLayout.setRowMinimumHeight(1, 6)
        mainLayout.addWidget(shapeLabel, 2, 1, Qt.AlignRight)
        mainLayout.addWidget(self.shapeComboBox, 2, 2)
        mainLayout.addWidget(penWidthLabel, 3, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penWidthSpinBox, 3, 2)
        mainLayout.addWidget(penStyleLabel, 4, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penStyleComboBox, 4, 2)
        mainLayout.addWidget(penCapLabel, 5, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penCapComboBox, 5, 2)
        mainLayout.addWidget(penJoinLabel, 6, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penJoinComboBox, 6, 2)
        mainLayout.addWidget(brushStyleLabel, 7, 1, Qt.AlignRight)
        mainLayout.addWidget(self.brushStyleComboBox, 7, 2)
        mainLayout.setRowMinimumHeight(8, 6)
        mainLayout.addWidget(otherOptionsLabel, 9, 1, Qt.AlignRight)
        mainLayout.addWidget(self.antialiasingCheckBox, 9, 2)
        mainLayout.addWidget(self.transformationsCheckBox, 10, 2)
        self.setLayout(mainLayout)

        self.shapeChanged()
        self.penChanged()
        self.brushChanged()
        self.antialiasingCheckBox.setChecked(True)

        self.setWindowTitle("Basic Drawing")

    def shapeChanged(self):
        shape = self.shapeComboBox.itemData(self.shapeComboBox.currentIndex(),
                                            IdRole)
        self.renderArea.setShape(shape)

    def penChanged(self):
        width = self.penWidthSpinBox.value()
        style = Qt.PenStyle(
            self.penStyleComboBox.itemData(
                self.penStyleComboBox.currentIndex(), IdRole))
        cap = Qt.PenCapStyle(
            self.penCapComboBox.itemData(self.penCapComboBox.currentIndex(),
                                         IdRole))
        join = Qt.PenJoinStyle(
            self.penJoinComboBox.itemData(self.penJoinComboBox.currentIndex(),
                                          IdRole))

        self.renderArea.setPen(QPen(Qt.blue, width, style, cap, join))

    def brushChanged(self):
        style = Qt.BrushStyle(
            self.brushStyleComboBox.itemData(
                self.brushStyleComboBox.currentIndex(), IdRole))

        if style == Qt.LinearGradientPattern:
            linearGradient = QLinearGradient(0, 0, 100, 100)
            linearGradient.setColorAt(0.0, Qt.white)
            linearGradient.setColorAt(0.2, Qt.green)
            linearGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(linearGradient))
        elif style == Qt.RadialGradientPattern:
            radialGradient = QRadialGradient(50, 50, 50, 70, 70)
            radialGradient.setColorAt(0.0, Qt.white)
            radialGradient.setColorAt(0.2, Qt.green)
            radialGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(radialGradient))
        elif style == Qt.ConicalGradientPattern:
            conicalGradient = QConicalGradient(50, 50, 150)
            conicalGradient.setColorAt(0.0, Qt.white)
            conicalGradient.setColorAt(0.2, Qt.green)
            conicalGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(conicalGradient))
        elif style == Qt.TexturePattern:
            self.renderArea.setBrush(QBrush(QPixmap(':/images/brick.png')))
        else:
            self.renderArea.setBrush(QBrush(Qt.green, style))
Пример #13
0
class SelectMatchWindow(QDialog):
    def __init__(self, parent=None):
        super(SelectMatchWindow, self).__init__(parent)
        self.parent = parent
        self.setModal(True)
        self.setWindowTitle("Mérkőzés választása")
        self.resize(600, 400)
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)
        self.read_config()
        self.tournaments = QComboBox()
        self.tournaments.setModelColumn(0)
        self.tournaments.currentIndexChanged.connect(self.torna_valasztas)
        self.layout.addWidget(self.tournaments)
        self.merkozesek = QListWidget()
        self.merkozesek.setFixedHeight(300)
        self.merkozesek.setFixedWidth(500)
        self.merkozesek.itemDoubleClicked.connect(self.start_game)
        self.merkozesek.itemSelectionChanged.connect(self.start_game)
        self.layout.addWidget(self.merkozesek)

        self.buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonbox.clicked.connect(self.buttonbox_click)
        self.layout.addWidget(self.buttonbox)

        self.load_torna()

    def load_torna(self):
        torna = QSqlQueryModel()
        query = QSqlQuery("select * from torna_settings where aktiv=1")
        torna.setQuery(query)
        if torna.record(0).value(0):
            for i in range(torna.rowCount()):
                self.tournaments.addItem(
                    torna.record(i).value(1),
                    torna.record(i).value(0))  # a value(0) a torna_id
        else:
            print("Nincs aktív torna")

    def torna_valasztas(self, i):
        print(self.tournaments.itemData(i))
        # matches = QSqlRelationalTableModel()
        # matches.setTable("torna_match")
        # matches.setFilter(f'a.torna_id=8889 and a.player1_id=c.player_id and a.player2_id=d.player_id and c.torna_id=a.torna_id and d.torna_id=a.torna_id and a.torna_id=b.torna_id')
        # matches.setFilter(f'torna_name = "{self.tournaments.currentText()}" and torna_resztvevok.torna_id=torna_settings.torna_id and station_id = "{self.station_id}"')
        # matches.setRelation(0, QSqlRelation("torna_settings", "torna_id", "torna_name"))
        # matches.setRelation(2, QSqlRelation("torna_resztvevok", "player_id", "player_name"))
        # matches.setRelation(3, QSqlRelation("torna_resztvevok", "player_id", "player_name"))
        # matches.setRelation(7, QSqlRelation("reged_station", "id", "station_id"))
        # matches.select()
        # print(matches)
        # self.merkozesek.clear()
        # for i in  range(matches.rowCount()):
        #     self.merkozesek.addItem(matches.record(i).value(0) + "\t" +
        #                             str(matches.record(i).value(1)) + "\t" +
        #                             matches.record(i).value(2) + "\t" +
        #                             matches.record(i).value(3) + "\t" +
        #                             matches.record(i).value(4) + "\t" +
        #                             str(matches.record(i).value(5))+ "\t" +
        #                             str(matches.record(i).value(6)))
        matches = QSqlQueryModel()
        # todo itt még nincs táblához kötve a lekérés
        matches_query = QSqlQuery(
            f'SELECT a.match_id,  b.torna_name, c.player_name as nev1, \
        d.player_name as nev2, a.variant, a.sets, a.legsperset FROM `torna_match` a, torna_settings b, torna_resztvevok c, \
        torna_resztvevok d WHERE a.torna_id={self.tournaments.itemData(i)} and a.player1_id=c.player_id and a.player2_id=d.player_id \
        and c.torna_id=a.torna_id and d.torna_id=a.torna_id and a.torna_id=b.torna_id and a.match_status<2'
        )
        matches.setQuery(matches_query)
        self.merkozesek.clear()
        for i in range(matches.rowCount()):
            self.merkozesek.addItem(
                str(matches.record(i).value(0)) + "\t" +
                matches.record(i).value(1) + "\t" +
                matches.record(i).value(2) + "\t" +
                matches.record(i).value(3) + "\t" +
                matches.record(i).value(4) + "\t" +
                str(matches.record(i).value(5)) + "\t" +
                str(matches.record(i).value(6)))

    def buttonbox_click(self, b):
        if b.text() == "OK":
            self.accept()
        elif b.text() == "Cancel":
            self.reject()

    def read_config(self):
        if os.path.exists('config.ini'):
            # Van config.ini, ki kell értékelni
            config.read('config.ini')
            self.station_id = config['DEFAULT'].get('station id')
            self.secret = config['DEFAULT'].get('secret key')
            # todo módosítani kell a torna_match táblát, hogy tartalmazza a tabla mellett a hozzá tartozó secret-et is
        else:
            # Nincs config.ini, alapértékekkel inicializálni
            msg = QMessageBox(self)
            msg.setStyleSheet("fonz-size: 20px")
            msg.setWindowTitle("Hiányzó beállítás file!")
            msg.setText(
                '<html style="font-size: 14px; color: red">Nem tudtam beolvasni a konfigurációt!<br></html>'
                +
                '<html style="font-size: 16px">Kérem módosítsa a beállításokat!</html>'
            )
            msg.exec_()
            sys.exit(1)

    def start_game(self):
        para = self.merkozesek.currentItem().text().rsplit("\t")
        p1_model = QSqlQueryModel()
        p1_query = QSqlQuery(
            f"select player_id from torna_resztvevok where player_name='{para[2]}'"
        )
        p1_model.setQuery(p1_query)
        p2_model = QSqlQueryModel()
        p2_query = QSqlQuery(
            f"select player_id from torna_resztvevok where player_name='{para[3]}'"
        )
        p2_model.setQuery(p2_query)

        params = []
        params.append(para[2])
        params.append(para[3])
        params.append(int(para[0]))
        self.match_id = int(para[0])
        params.append(int(p1_model.record(0).value(0)))
        params.append(int(p2_model.record(0).value(0)))
        params.append(para[4])
        params.append(int(para[6]))
        params.append(int(para[5]))
        params.append(0)  # hc1
        params.append(0)  # hc2
        params.append(0)  #bets_of...
        self.parent.new_game_window.params = params
        self.parent.new_game_window.refresh()

    def accept(self):
        query = QSqlQuery(
            f"update torna_match set match_status=1 where match_id={self.match_id}"
        )
        query.exec_()
        #self.match_id
        super().accept()

    def reject(self):
        self.parent.new_game_window.close()
        super().reject()
Пример #14
0
class TornaSettingsDialog(QDialog):
    def __init__(self, parent=None, torna_id=None):
        super(TornaSettingsDialog, self).__init__(parent)
        self.parent = parent
        self.setModal(True)
        self.setWindowTitle("Verseny beállítások")
        self.torna_id = torna_id
        self.main_layout = QVBoxLayout()
        self.setLayout(self.main_layout)
        if self.torna_id is not None:
            self.create_torna_selection()

        self.set_layouts()
        self.add_variables()
        self.alapertekek()
        self.add_buttonbox()

    def set_layouts(self):
        self.tartalom_layout = QHBoxLayout()
        self.main_layout.addLayout(self.tartalom_layout)
        self.layout = QVBoxLayout()
        self.gomb_layout = QVBoxLayout()
        self.tartalom_layout.addLayout(self.layout)
        self.tartalom_layout.addLayout(self.gomb_layout)

    def add_variables(self):
        self.layout.addWidget(QLabel("A verseny megnevezése:"))
        self.torna_name = QLineEdit()
        self.torna_name.setPlaceholderText("A verseny megnevezése")
        self.layout.addWidget(self.torna_name)
        self.layout.addWidget(QLabel("Legyen csoportkör?"))
        self.is_roundrobin = QCheckBox()
        self.is_roundrobin.stateChanged.connect(self.roundrobin_changed)
        self.layout.addWidget(self.is_roundrobin)
        self.layout.addWidget(QLabel("Csoportok száma:"))
        self.csoport_number = CustomSpinBox(1, 16)
        self.layout.addWidget(self.csoport_number)
        self.layout.addWidget(QLabel("Játékosok száma csoportonként:"))
        self.jatekos_per_csoport = CustomSpinBox(3, 8)
        self.layout.addWidget(self.jatekos_per_csoport)
        self.layout.addWidget(QLabel("Játéknem:"))
        self.variant = CustomSpinBox(301, 1001)
        self.layout.addWidget(self.variant)
        self.layout.addWidget(QLabel("Set-ek?:"))
        self.is_sets = QCheckBox()
        self.is_sets.stateChanged.connect(self.is_sets_changed)
        self.layout.addWidget(self.is_sets)
        self.layout.addWidget(QLabel("Set-ek száma:"))
        self.sets_number = CustomSpinBox(1, 8)
        self.sets_number.setDisabled(True)
        self.layout.addWidget(self.sets_number)
        self.layout.addWidget(QLabel("Leg-ek száma:"))
        self.legs_number = CustomSpinBox(2, 30)
        self.layout.addWidget(self.legs_number)
        self.layout.addWidget(QLabel("Best of..."))
        self.is_best = QCheckBox()
        self.layout.addWidget(self.is_best)
        self.layout.addWidget(QLabel("Döntetlen"))
        self.is_draw = QCheckBox()
        self.is_draw.stateChanged.connect(self.is_draw_changed)
        self.layout.addWidget(self.is_draw)
        self.layout.addWidget(QLabel("Pont(Győzelem):"))
        self.pont_win = CustomSpinBox(2, 5)
        self.layout.addWidget(self.pont_win)
        self.layout.addWidget(QLabel("Pont(Döntetlen):"))
        self.pont_draw = CustomSpinBox(1, 3)
        self.pont_draw.setDisabled(True)
        self.layout.addWidget(self.pont_draw)
        self.layout.addWidget(QLabel("Pont(Vereség):"))
        self.pont_lost = CustomSpinBox(0, 2)
        self.layout.addWidget(self.pont_lost)
        self.layout.addWidget(QLabel("Főág"))
        self.is_single_elim = QCheckBox()
        self.is_single_elim.stateChanged.connect(self.is_single_changed)
        self.layout.addWidget(self.is_single_elim)
        self.layout.addWidget(QLabel("Főág száma:"))
        self.num_single = CustomSpinBox(4, 128)
        self.num_single.setDisabled(True)
        self.layout.addWidget(self.num_single)
        self.layout.addWidget(QLabel("Leg-ek száma a főágon:"))
        self.leg_num_single = CustomSpinBox(3, 20)
        self.leg_num_single.setDisabled(True)
        self.layout.addWidget(self.leg_num_single)
        self.layout.addWidget(QLabel("Leg-ek száma az elődöntőben:"))
        self.leg_num_semifinal = CustomSpinBox(4, 20)
        self.leg_num_semifinal.setDisabled(True)
        self.layout.addWidget(self.leg_num_semifinal)
        self.layout.addWidget(QLabel("Leg-ek száma a döntőben:"))
        self.leg_num_final = CustomSpinBox(5, 20)
        self.leg_num_final.setDisabled(True)
        self.layout.addWidget(self.leg_num_final)
        self.layout.addWidget(QLabel("3. hely kijátszva"))
        self.is_3place = QCheckBox()
        self.is_3place.stateChanged.connect(self.is_3place_changed)
        self.is_3place.setDisabled(True)
        self.layout.addWidget(self.is_3place)
        self.layout.addWidget(QLabel("Leg-ek száma a 3. helyért:"))
        self.leg_num_3place = CustomSpinBox(4, 20)
        self.leg_num_3place.setDisabled(True)
        self.layout.addWidget(self.leg_num_3place)

    def create_torna_selection(self):
        self.tournaments = QComboBox()
        self.tournaments.setModelColumn(0)
        self.tournaments.currentIndexChanged.connect(self.torna_valasztas)
        self.main_layout.addWidget(self.tournaments)
        self.load_torna()

    def load_torna(self):
        torna = QSqlQueryModel()
        query = QSqlQuery("select * from torna_settings where aktiv=2")
        torna.setQuery(query)
        if torna.record(0).value(0):
            for i in range(torna.rowCount()):
                self.tournaments.addItem(
                    torna.record(i).value(1),
                    torna.record(i).value(0))  # a value(0) a torna_id
        else:
            print("Nincs aktív torna")

    def torna_valasztas(self, i):
        self.torna_id = self.tournaments.itemData(i)
        self.alapertekek()

    def alapertekek(self):
        if not self.torna_id:
            self.torna_name.clear()
            self.is_roundrobin.setChecked(True)
            self.csoport_number.setValue(1)
            self.jatekos_per_csoport.setValue(4)
            self.variant.setValue(501)
            self.is_sets.setChecked(False)
            self.sets_number.setValue(1)
            self.legs_number.setValue(2)
            self.is_best.setChecked(False)
            self.is_draw.setChecked(False)
            self.pont_win.setValue(2)
            self.pont_draw.setValue(1)
            self.pont_lost.setValue(0)
            self.is_single_elim.setChecked(False)
            self.num_single.setValue(8)
            self.leg_num_single.setValue(3)
            self.leg_num_semifinal.setValue(4)
            self.leg_num_final.setValue(5)
            self.is_3place.setChecked(False)
            self.leg_num_3place.setValue(4)
        else:
            model = QSqlTableModel(db=db)
            model.setTable("torna_settings")
            model.setFilter(f"torna_id={self.torna_id}")
            model.select()
            # print(model.record(0))
            self.torna_name.setText(model.record(0).value(1))
            self.is_roundrobin.setChecked(model.record(0).value(2))
            self.csoport_number.setValue(model.record(0).value(3))
            self.jatekos_per_csoport.setValue(model.record(0).value(4))
            self.variant.setValue(int(model.record(0).value(5)))
            self.is_sets.setChecked(model.record(0).value(6))
            self.sets_number.setValue(model.record(0).value(7))
            self.legs_number.setValue(model.record(0).value(8))
            self.is_best.setChecked(model.record(0).value(9))
            self.is_draw.setChecked(model.record(0).value(10))
            self.pont_win.setValue(model.record(0).value(11))
            self.pont_draw.setValue(model.record(0).value(12))
            self.pont_lost.setValue(model.record(0).value(13))
            self.is_single_elim.setChecked(model.record(0).value(14))
            self.num_single.setValue(model.record(0).value(15))
            self.leg_num_single.setValue(model.record(0).value(17))
            self.leg_num_semifinal.setValue(model.record(0).value(18))
            self.leg_num_final.setValue(model.record(0).value(20))
            self.is_3place.setChecked(model.record(0).value(16))
            self.leg_num_3place.setValue(model.record(0).value(19))

    def add_buttonbox(self):
        self.buttonbox = QDialogButtonBox()
        self.buttonbox.setOrientation(Qt.Vertical)
        self.buttonbox.addButton("Mentés", QDialogButtonBox.ActionRole)
        self.buttonbox.addButton("Alaphelyzet", QDialogButtonBox.ActionRole)
        # self.gomb_members = QPushButton("Résztvevők")
        # self.gomb_members.setDisabled(True)
        # self.buttonbox.addButton(self.gomb_members, QDialogButtonBox.ActionRole)
        # self.gomb_tabella = QPushButton("Tabella")
        # self.gomb_tabella.setDisabled(True)
        # self.buttonbox.addButton(self.gomb_tabella, QDialogButtonBox.ActionRole)
        self.buttonbox.addButton("Mégsem", QDialogButtonBox.ActionRole)
        self.buttonbox.clicked.connect(self.buttonbox_click)
        self.gomb_layout.addWidget(self.buttonbox)

    def roundrobin_changed(self, state):
        if state == Qt.Checked:
            self.csoport_number.setDisabled(False)
            self.jatekos_per_csoport.setDisabled(False)
        else:
            self.csoport_number.setDisabled(True)
            self.jatekos_per_csoport.setDisabled(True)

    def is_sets_changed(self, state):
        if state == Qt.Checked:
            self.sets_number.setDisabled(False)
        else:
            self.sets_number.setDisabled(True)

    def is_draw_changed(self, state):
        if state == Qt.Checked:
            self.pont_draw.setDisabled(False)
        else:
            self.pont_draw.setDisabled(True)

    def is_single_changed(self, state):
        # a főághoz kapcsolódó paraméterek tiltása/engedélyezése
        if state == Qt.Checked:
            self.num_single.setDisabled(False)
            self.is_3place.setDisabled(False)
            self.leg_num_single.setDisabled(False)
            self.leg_num_semifinal.setDisabled(False)
            if self.is_3place.isChecked():
                self.leg_num_3place.setDisabled(False)
            else:
                self.leg_num_3place.setDisabled(True)
            self.leg_num_final.setDisabled(False)
        else:
            self.num_single.setDisabled(True)
            self.is_3place.setDisabled(True)
            self.leg_num_single.setDisabled(True)
            self.leg_num_semifinal.setDisabled(True)
            self.leg_num_3place.setDisabled(True)
            self.leg_num_final.setDisabled(True)

    def is_3place_changed(self, state):
        if state == Qt.Checked:
            self.leg_num_3place.setDisabled(False)
        else:
            self.leg_num_3place.setDisabled(True)

    def buttonbox_click(self, b):
        if b.text() == "Mentés":
            self.save()
        elif b.text() == "Alaphelyzet":
            self.alapertekek()
        # elif b.text() == "Résztvevők":
        #     self.members()
        # elif b.text() == "Tabella":
        #     self.tabella()
        elif b.text() == "Mégsem":
            self.reject()
        else:
            pass

    def save(self):
        if not self.torna_id:
            self.insert_torna_settings()
        else:
            self.update_torna_settings()
        self.close()

    def insert_torna_settings(self):
        van_ilyen_nev = False
        if len(self.torna_name.text()) != 0:
            torna_id_model = QSqlQueryModel()
            query = QSqlQuery(
                "select torna_id, torna_name from torna_settings", db=db)
            torna_id_model.setQuery(query)
            for i in range(torna_id_model.rowCount()):
                if torna_id_model.record(i).value(1) == self.torna_name.text():
                    msg = QMessageBox(self)
                    msg.setStyleSheet("fonz-size: 20px")
                    msg.setWindowTitle("Név ütközés!")
                    msg.setText(
                        '<html style="font-size: 14px; color: red">Már van ilyen nevű verseny!<br></html>'
                        +
                        '<html style="font-size: 16px">Kérem adjon a versenynek egyedi nevet!</html>'
                    )
                    msg.exec_()
                    van_ilyen_nev = True
            if not van_ilyen_nev:
                torna_settings_model = QSqlTableModel(
                    db=db
                )  # !!!!!!! Ha több db van, akkor itt konkrétan meg kell adni
                torna_settings_model.setTable("torna_settings")
                record = torna_settings_model.record()

                record.setValue(1, self.torna_name.text())
                if self.is_roundrobin.isChecked():
                    record.setValue(2, 1)
                else:
                    record.setValue(2, 0)
                record.setValue(3, self.csoport_number.value())
                record.setValue(4, self.jatekos_per_csoport.value())
                record.setValue(5, self.variant.value())
                if self.is_sets.isChecked():
                    record.setValue(6, 1)
                else:
                    record.setValue(6, 0)
                record.setValue(7, self.sets_number.value())
                record.setValue(8, self.legs_number.value())
                # print(record.value(2))
                if self.is_best.isChecked():
                    record.setValue(9, 1)
                else:
                    record.setValue(9, 0)
                if self.is_draw.isChecked():
                    record.setValue(10, 1)
                else:
                    record.setValue(10, 0)
                record.setValue(11, self.pont_win.value())
                record.setValue(12, self.pont_draw.value())
                record.setValue(13, self.pont_lost.value())
                if self.is_single_elim.isChecked():
                    record.setValue(14, 1)
                else:
                    record.setValue(14, 0)
                record.setValue(15, self.num_single.value())
                if self.is_3place.isChecked():
                    record.setValue(16, 1)
                else:
                    record.setValue(16, 0)
                record.setValue(17, self.leg_num_single.value())
                record.setValue(18, self.leg_num_semifinal.value())
                record.setValue(19, self.leg_num_3place.value())
                record.setValue(20, self.leg_num_final.value())
                record.setValue(21, 2)
                # aktiv flag:  0: vége, 1: folyamatban, 2: szerkesztés alatt
                # print(record)
                if torna_settings_model.insertRecord(-1, record):
                    torna_settings_model.submitAll()
                else:
                    db.rollback()

                torna_id_model2 = QSqlQueryModel()
                query2 = QSqlQuery(
                    f"select torna_id from torna_settings where torna_name='{self.torna_name.text()}'",
                    db=db)
                torna_id_model2.setQuery(query2)
                self.torna_id = int(torna_id_model2.record(0).value(0))
                self.gomb_members.setDisabled(False)
        else:
            msg = QMessageBox(self)
            msg.setStyleSheet("fonz-size: 20px")
            msg.setWindowTitle("Hiányzik a verseny neve!")
            msg.setText(
                '<html style="font-size: 14px; color: red">A létrehozott versenynek kell egy elnevezés!<br></html>'
                +
                '<html style="font-size: 16px">Kérem adja meg a verseny nevét!</html>'
            )
            msg.exec_()

    def update_torna_settings(self):
        torna_settings_model = QSqlTableModel(db=db)
        torna_settings_model.setTable("torna_settings")
        record = torna_settings_model.record()
        torna_settings_model.select()
        # for x in range(torna_settings_model.rowCount()):
        #     record.setGenerated(x, False)
        record.setValue(0, self.torna_id)
        record.setValue(1, self.torna_name.text())
        if self.is_roundrobin.isChecked():
            record.setValue(2, 1)
        else:
            record.setValue(2, 0)
        record.setValue(3, self.csoport_number.value())
        record.setValue(4, self.jatekos_per_csoport.value())
        record.setValue(5, self.variant.value())
        if self.is_sets.isChecked():
            record.setValue(6, 1)
        else:
            record.setValue(6, 0)
        record.setValue(7, self.sets_number.value())
        record.setValue(8, self.legs_number.value())
        if self.is_best.isChecked():
            record.setValue(9, 1)
        else:
            record.setValue(9, 0)
        if self.is_draw.isChecked():
            record.setValue(10, 1)
        else:
            record.setValue(10, 0)
        record.setValue(11, self.pont_win.value())
        record.setValue(12, self.pont_draw.value())
        record.setValue(13, self.pont_lost.value())
        if self.is_single_elim.isChecked():
            record.setValue(14, 1)
        else:
            record.setValue(14, 0)
        record.setValue(15, self.num_single.value())
        if self.is_3place.isChecked():
            record.setValue(16, 1)
        else:
            record.setValue(16, 0)
        record.setValue(17, self.leg_num_single.value())
        record.setValue(18, self.leg_num_semifinal.value())
        record.setValue(19, self.leg_num_3place.value())
        record.setValue(20, self.leg_num_final.value())
        record.setValue(21, 2)

        for i in range(torna_settings_model.rowCount()):
            if torna_settings_model.record(i).value(0) == self.torna_id:
                # print(torna_settings_model.record(i).value(0), ":", i)
                record_number = i
        # print(record)
        if torna_settings_model.setRecord(record_number, record):
            torna_settings_model.submitAll()
        else:
            db.rollback()

    # def members(self):
    #     # todo Itt kell a verseny résztvevőit öszerakni
    #     pass
    #
    # def tabella(self):
    #     # todo Itt kell a sorsolást, tabella összeállítást megcsinálni
    #     pass

    def accept(self):
        # todo Ez majd csak a bezáráshoz kell
        super().accept()

    def reject(self):
        print("CANCEL")
        super().reject()
Пример #15
0
 def on_channel_threshold_changed(self, channel: str, index: int,
                                  sender: QComboBox) -> None:
     threshold = sender.itemData(index, Qt.UserRole)
     self._channels[channel].set_threshold(threshold)
Пример #16
0
class AudioTest(QMainWindow):

    PUSH_MODE_LABEL = "Enable push mode"
    PULL_MODE_LABEL = "Enable pull mode"
    SUSPEND_LABEL = "Suspend playback"
    RESUME_LABEL = "Resume playback"

    DurationSeconds = 1
    ToneSampleRateHz = 600
    DataSampleRateHz = 44100

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

        self.m_device = QAudioDeviceInfo.defaultOutputDevice()
        self.m_output = None

        self.initializeWindow()
        self.initializeAudio()

    def initializeWindow(self):
        layout = QVBoxLayout()

        self.m_deviceBox = QComboBox()
        self.m_deviceBox.activated[int].connect(self.deviceChanged)
        for deviceInfo in QAudioDeviceInfo.availableDevices(
                QAudio.AudioOutput):
            self.m_deviceBox.addItem(deviceInfo.deviceName(), deviceInfo)

        layout.addWidget(self.m_deviceBox)

        self.m_modeButton = QPushButton()
        self.m_modeButton.clicked.connect(self.toggleMode)
        self.m_modeButton.setText(self.PUSH_MODE_LABEL)

        layout.addWidget(self.m_modeButton)

        self.m_suspendResumeButton = QPushButton(
            clicked=self.toggleSuspendResume)
        self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)

        layout.addWidget(self.m_suspendResumeButton)

        volumeBox = QHBoxLayout()
        volumeLabel = QLabel("Volume:")
        self.m_volumeSlider = QSlider(Qt.Horizontal,
                                      minimum=0,
                                      maximum=100,
                                      singleStep=10)
        self.m_volumeSlider.valueChanged.connect(self.volumeChanged)

        volumeBox.addWidget(volumeLabel)
        volumeBox.addWidget(self.m_volumeSlider)

        layout.addLayout(volumeBox)

        window = QWidget()
        window.setLayout(layout)

        self.setCentralWidget(window)

    def initializeAudio(self):
        self.m_pullTimer = QTimer(self)
        self.m_pullTimer.timeout.connect(self.pullTimerExpired)
        self.m_pullMode = True

        self.m_format = QAudioFormat()
        self.m_format.setSampleRate(self.DataSampleRateHz)
        self.m_format.setChannelCount(1)
        self.m_format.setSampleSize(16)
        self.m_format.setCodec('audio/pcm')
        self.m_format.setByteOrder(QAudioFormat.LittleEndian)
        self.m_format.setSampleType(QAudioFormat.SignedInt)

        info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice())
        if not info.isFormatSupported(self.m_format):
            qWarning("Default format not supported - trying to use nearest")
            self.m_format = info.nearestFormat(self.m_format)

        self.m_generator = Generator(self.m_format,
                                     self.DurationSeconds * 1000000,
                                     self.ToneSampleRateHz, self)

        self.createAudioOutput()

    def createAudioOutput(self):
        self.m_audioOutput = QAudioOutput(self.m_device, self.m_format)
        self.m_audioOutput.notify.connect(self.notified)
        self.m_audioOutput.stateChanged.connect(self.handleStateChanged)

        self.m_generator.start()
        self.m_audioOutput.start(self.m_generator)
        self.m_volumeSlider.setValue(self.m_audioOutput.volume() * 100)

    def deviceChanged(self, index):
        self.m_pullTimer.stop()
        self.m_generator.stop()
        self.m_audioOutput.stop()
        self.m_device = self.m_deviceBox.itemData(index)

        self.createAudioOutput()

    def volumeChanged(self, value):
        if self.m_audioOutput is not None:
            self.m_audioOutput.setVolume(value / 100.0)

    def notified(self):
        qWarning(
            "bytesFree = %d, elapsedUSecs = %d, processedUSecs = %d" %
            (self.m_audioOutput.bytesFree(), self.m_audioOutput.elapsedUSecs(),
             self.m_audioOutput.processedUSecs()))

    def pullTimerExpired(self):
        if self.m_audioOutput is not None and self.m_audioOutput.state(
        ) != QAudio.StoppedState:
            chunks = self.m_audioOutput.bytesFree(
            ) // self.m_audioOutput.periodSize()
            for _ in range(chunks):
                data = self.m_generator.read(self.m_audioOutput.periodSize())
                if data is None or len(
                        data) != self.m_audioOutput.periodSize():
                    break

                self.m_output.write(data)

    def toggleMode(self):
        self.m_pullTimer.stop()
        self.m_audioOutput.stop()

        if self.m_pullMode:
            self.m_modeButton.setText(self.PULL_MODE_LABEL)
            self.m_output = self.m_audioOutput.start()
            self.m_pullMode = False
            self.m_pullTimer.start(20)
        else:
            self.m_modeButton.setText(self.PUSH_MODE_LABEL)
            self.m_pullMode = True
            self.m_audioOutput.start(self.m_generator)

        self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)

    def toggleSuspendResume(self):
        if self.m_audioOutput.state() == QAudio.SuspendedState:
            qWarning("status: Suspended, resume()")
            self.m_audioOutput.resume()
            self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
        elif self.m_audioOutput.state() == QAudio.ActiveState:
            qWarning("status: Active, suspend()")
            self.m_audioOutput.suspend()
            self.m_suspendResumeButton.setText(self.RESUME_LABEL)
        elif self.m_audioOutput.state() == QAudio.StoppedState:
            qWarning("status: Stopped, resume()")
            self.m_audioOutput.resume()
            self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
        elif self.m_audioOutput.state() == QAudio.IdleState:
            qWarning("status: IdleState")

    stateMap = {
        QAudio.ActiveState: "ActiveState",
        QAudio.SuspendedState: "SuspendedState",
        QAudio.StoppedState: "StoppedState",
        QAudio.IdleState: "IdleState"
    }

    def handleStateChanged(self, state):
        qWarning("state = " + self.stateMap.get(state, "Unknown"))
Пример #17
0
class AudioTest(QMainWindow):

    PUSH_MODE_LABEL = "Enable push mode"
    PULL_MODE_LABEL = "Enable pull mode"
    SUSPEND_LABEL = "Suspend playback"
    RESUME_LABEL = "Resume playback"

    DurationSeconds = 1
    ToneSampleRateHz = 600
    DataSampleRateHz = 44100

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

        self.m_device = QAudioDeviceInfo.defaultOutputDevice()
        self.m_output = None

        self.initializeWindow()
        self.initializeAudio()

    def initializeWindow(self):
        layout = QVBoxLayout()

        self.m_deviceBox = QComboBox()
        self.m_deviceBox.activated[int].connect(self.deviceChanged)
        for deviceInfo in QAudioDeviceInfo.availableDevices(QAudio.AudioOutput):
            self.m_deviceBox.addItem(deviceInfo.deviceName(), deviceInfo)

        layout.addWidget(self.m_deviceBox)

        self.m_modeButton = QPushButton()
        self.m_modeButton.clicked.connect(self.toggleMode)
        self.m_modeButton.setText(self.PUSH_MODE_LABEL)

        layout.addWidget(self.m_modeButton)

        self.m_suspendResumeButton = QPushButton(
                clicked=self.toggleSuspendResume)
        self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)

        layout.addWidget(self.m_suspendResumeButton)

        volumeBox = QHBoxLayout()
        volumeLabel = QLabel("Volume:")
        self.m_volumeSlider = QSlider(Qt.Horizontal, minimum=0, maximum=100,
                singleStep=10)
        self.m_volumeSlider.valueChanged.connect(self.volumeChanged)

        volumeBox.addWidget(volumeLabel)
        volumeBox.addWidget(self.m_volumeSlider)

        layout.addLayout(volumeBox)

        window = QWidget()
        window.setLayout(layout)

        self.setCentralWidget(window)

    def initializeAudio(self):
        self.m_pullTimer = QTimer(self)
        self.m_pullTimer.timeout.connect(self.pullTimerExpired)
        self.m_pullMode = True

        self.m_format = QAudioFormat()
        self.m_format.setSampleRate(self.DataSampleRateHz)
        self.m_format.setChannelCount(1)
        self.m_format.setSampleSize(16)
        self.m_format.setCodec('audio/pcm')
        self.m_format.setByteOrder(QAudioFormat.LittleEndian)
        self.m_format.setSampleType(QAudioFormat.SignedInt)

        info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice())
        if not info.isFormatSupported(self.m_format):
            qWarning("Default format not supported - trying to use nearest")
            self.m_format = info.nearestFormat(self.m_format)

        self.m_generator = Generator(self.m_format,
                self.DurationSeconds * 1000000, self.ToneSampleRateHz, self)

        self.createAudioOutput()

    def createAudioOutput(self):
        self.m_audioOutput = QAudioOutput(self.m_device, self.m_format)
        self.m_audioOutput.notify.connect(self.notified)
        self.m_audioOutput.stateChanged.connect(self.handleStateChanged)

        self.m_generator.start()
        self.m_audioOutput.start(self.m_generator)
        self.m_volumeSlider.setValue(self.m_audioOutput.volume() * 100)

    def deviceChanged(self, index):
        self.m_pullTimer.stop()
        self.m_generator.stop()
        self.m_audioOutput.stop()
        self.m_device = self.m_deviceBox.itemData(index)

        self.createAudioOutput()

    def volumeChanged(self, value):
        if self.m_audioOutput is not None:
            self.m_audioOutput.setVolume(value / 100.0)

    def notified(self):
        qWarning("bytesFree = %d, elapsedUSecs = %d, processedUSecs = %d" % (
                self.m_audioOutput.bytesFree(),
                self.m_audioOutput.elapsedUSecs(),
                self.m_audioOutput.processedUSecs()))

    def pullTimerExpired(self):
        if self.m_audioOutput is not None and self.m_audioOutput.state() != QAudio.StoppedState:
            chunks = self.m_audioOutput.bytesFree() // self.m_audioOutput.periodSize()
            for _ in range(chunks):
                data = self.m_generator.read(self.m_audioOutput.periodSize())
                if data is None or len(data) != self.m_audioOutput.periodSize():
                    break

                self.m_output.write(data)

    def toggleMode(self):
        self.m_pullTimer.stop()
        self.m_audioOutput.stop()

        if self.m_pullMode:
            self.m_modeButton.setText(self.PULL_MODE_LABEL)
            self.m_output = self.m_audioOutput.start()
            self.m_pullMode = False
            self.m_pullTimer.start(20)
        else:
            self.m_modeButton.setText(self.PUSH_MODE_LABEL)
            self.m_pullMode = True
            self.m_audioOutput.start(self.m_generator)

        self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)

    def toggleSuspendResume(self):
        if self.m_audioOutput.state() == QAudio.SuspendedState:
            qWarning("status: Suspended, resume()")
            self.m_audioOutput.resume()
            self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
        elif self.m_audioOutput.state() == QAudio.ActiveState:
            qWarning("status: Active, suspend()")
            self.m_audioOutput.suspend()
            self.m_suspendResumeButton.setText(self.RESUME_LABEL)
        elif self.m_audioOutput.state() == QAudio.StoppedState:
            qWarning("status: Stopped, resume()")
            self.m_audioOutput.resume()
            self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
        elif self.m_audioOutput.state() == QAudio.IdleState:
            qWarning("status: IdleState")

    stateMap = {
        QAudio.ActiveState: "ActiveState",
        QAudio.SuspendedState: "SuspendedState",
        QAudio.StoppedState: "StoppedState",
        QAudio.IdleState: "IdleState"}

    def handleStateChanged(self, state):
        qWarning("state = " + self.stateMap.get(state, "Unknown"))
Пример #18
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.proxyModel = SortFilterProxyModel()
        self.proxyModel.setDynamicSortFilter(True)

        self.sourceGroupBox = QGroupBox("Original Model")
        self.proxyGroupBox = QGroupBox("Sorted/Filtered Model")

        self.sourceView = QTreeView()
        self.sourceView.setRootIsDecorated(False)
        self.sourceView.setAlternatingRowColors(True)

        self.proxyView = QTreeView()
        self.proxyView.setRootIsDecorated(False)
        self.proxyView.setAlternatingRowColors(True)
        self.proxyView.setModel(self.proxyModel)
        self.proxyView.setSortingEnabled(True)

        self.sortCaseSensitivityCheckBox = QCheckBox("Case sensitive sorting")
        self.filterCaseSensitivityCheckBox = QCheckBox("Case sensitive filter")

        self.filterPatternLineEdit = QLineEdit()
        self.filterPatternLabel = QLabel("&Filter pattern:")
        self.filterPatternLabel.setBuddy(self.filterPatternLineEdit)

        self.filterSyntaxComboBox = QComboBox()
        self.filterSyntaxComboBox.addItem("Regular expression", QRegExp.RegExp)
        self.filterSyntaxComboBox.addItem("Wildcard", QRegExp.Wildcard)
        self.filterSyntaxComboBox.addItem("Fixed string", QRegExp.FixedString)
        self.filterSyntaxLabel = QLabel("Filter &syntax:")
        self.filterSyntaxLabel.setBuddy(self.filterSyntaxComboBox)

        self.filterColumnComboBox = QComboBox()
        self.filterColumnComboBox.addItem("Subject")
        self.filterColumnComboBox.addItem("Sender")
        self.filterColumnComboBox.addItem("Date")
        self.filterColumnLabel = QLabel("Filter &column:")
        self.filterColumnLabel.setBuddy(self.filterColumnComboBox)

        self.filterPatternLineEdit.textChanged.connect(
            self.filterRegExpChanged)
        self.filterSyntaxComboBox.currentIndexChanged.connect(
            self.filterRegExpChanged)
        self.filterColumnComboBox.currentIndexChanged.connect(
            self.filterColumnChanged)
        self.filterCaseSensitivityCheckBox.toggled.connect(
            self.filterRegExpChanged)
        self.sortCaseSensitivityCheckBox.toggled.connect(self.sortChanged)

        sourceLayout = QHBoxLayout()
        sourceLayout.addWidget(self.sourceView)
        self.sourceGroupBox.setLayout(sourceLayout)

        proxyLayout = QGridLayout()
        proxyLayout.addWidget(self.proxyView, 0, 0, 1, 3)
        proxyLayout.addWidget(self.filterPatternLabel, 1, 0)
        proxyLayout.addWidget(self.filterPatternLineEdit, 1, 1, 1, 2)
        proxyLayout.addWidget(self.filterSyntaxLabel, 2, 0)
        proxyLayout.addWidget(self.filterSyntaxComboBox, 2, 1, 1, 2)
        proxyLayout.addWidget(self.filterColumnLabel, 3, 0)
        proxyLayout.addWidget(self.filterColumnComboBox, 3, 1, 1, 2)
        proxyLayout.addWidget(self.filterCaseSensitivityCheckBox, 4, 0, 1, 2)
        proxyLayout.addWidget(self.sortCaseSensitivityCheckBox, 4, 2)
        self.proxyGroupBox.setLayout(proxyLayout)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.sourceGroupBox)
        mainLayout.addWidget(self.proxyGroupBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("Basic Sort/Filter Model")
        self.resize(500, 450)

        self.proxyView.sortByColumn(SENDER, Qt.AscendingOrder)
        self.filterColumnComboBox.setCurrentIndex(SENDER)

        self.filterPatternLineEdit.setText("Andy|Grace")
        self.filterCaseSensitivityCheckBox.setChecked(True)
        self.sortCaseSensitivityCheckBox.setChecked(True)

    def setSourceModel(self, model):
        self.proxyModel.setSourceModel(model)
        self.sourceView.setModel(model)

    def filterRegExpChanged(self):
        syntax_nr = self.filterSyntaxComboBox.itemData(
            self.filterSyntaxComboBox.currentIndex())
        syntax = QRegExp.PatternSyntax(syntax_nr)

        if self.filterCaseSensitivityCheckBox.isChecked():
            caseSensitivity = Qt.CaseSensitive
        else:
            caseSensitivity = Qt.CaseInsensitive

        regExp = QRegExp(self.filterPatternLineEdit.text(), caseSensitivity,
                         syntax)
        self.proxyModel.setFilterRegExp(regExp)

    def filterColumnChanged(self):
        self.proxyModel.setFilterKeyColumn(
            self.filterColumnComboBox.currentIndex())

    def sortChanged(self):
        if self.sortCaseSensitivityCheckBox.isChecked():
            caseSensitivity = Qt.CaseSensitive
        else:
            caseSensitivity = Qt.CaseInsensitive

        self.proxyModel.setSortCaseSensitivity(caseSensitivity)
Пример #19
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.renderArea = RenderArea()

        self.shapeComboBox = QComboBox()
        self.shapeComboBox.addItem("Polygon", RenderArea.Polygon)
        self.shapeComboBox.addItem("Rectangle", RenderArea.Rect)
        self.shapeComboBox.addItem("Rounded Rectangle", RenderArea.RoundedRect)
        self.shapeComboBox.addItem("Ellipse", RenderArea.Ellipse)
        self.shapeComboBox.addItem("Pie", RenderArea.Pie)
        self.shapeComboBox.addItem("Chord", RenderArea.Chord)
        self.shapeComboBox.addItem("Path", RenderArea.Path)
        self.shapeComboBox.addItem("Line", RenderArea.Line)
        self.shapeComboBox.addItem("Polyline", RenderArea.Polyline)
        self.shapeComboBox.addItem("Arc", RenderArea.Arc)
        self.shapeComboBox.addItem("Points", RenderArea.Points)
        self.shapeComboBox.addItem("Text", RenderArea.Text)
        self.shapeComboBox.addItem("Pixmap", RenderArea.Pixmap)

        shapeLabel = QLabel("&Shape:")
        shapeLabel.setBuddy(self.shapeComboBox)

        self.penWidthSpinBox = QSpinBox()
        self.penWidthSpinBox.setRange(0, 20)
        self.penWidthSpinBox.setSpecialValueText("0 (cosmetic pen)")

        penWidthLabel = QLabel("Pen &Width:")
        penWidthLabel.setBuddy(self.penWidthSpinBox)

        self.penStyleComboBox = QComboBox()
        self.penStyleComboBox.addItem("Solid", Qt.SolidLine)
        self.penStyleComboBox.addItem("Dash", Qt.DashLine)
        self.penStyleComboBox.addItem("Dot", Qt.DotLine)
        self.penStyleComboBox.addItem("Dash Dot", Qt.DashDotLine)
        self.penStyleComboBox.addItem("Dash Dot Dot", Qt.DashDotDotLine)
        self.penStyleComboBox.addItem("None", Qt.NoPen)

        penStyleLabel = QLabel("&Pen Style:")
        penStyleLabel.setBuddy(self.penStyleComboBox)

        self.penCapComboBox = QComboBox()
        self.penCapComboBox.addItem("Flat", Qt.FlatCap)
        self.penCapComboBox.addItem("Square", Qt.SquareCap)
        self.penCapComboBox.addItem("Round", Qt.RoundCap)

        penCapLabel = QLabel("Pen &Cap:")
        penCapLabel.setBuddy(self.penCapComboBox)

        self.penJoinComboBox = QComboBox()
        self.penJoinComboBox.addItem("Miter", Qt.MiterJoin)
        self.penJoinComboBox.addItem("Bevel", Qt.BevelJoin)
        self.penJoinComboBox.addItem("Round", Qt.RoundJoin)

        penJoinLabel = QLabel("Pen &Join:")
        penJoinLabel.setBuddy(self.penJoinComboBox)

        self.brushStyleComboBox = QComboBox()
        self.brushStyleComboBox.addItem("Linear Gradient",
                Qt.LinearGradientPattern)
        self.brushStyleComboBox.addItem("Radial Gradient",
                Qt.RadialGradientPattern)
        self.brushStyleComboBox.addItem("Conical Gradient",
                Qt.ConicalGradientPattern)
        self.brushStyleComboBox.addItem("Texture", Qt.TexturePattern)
        self.brushStyleComboBox.addItem("Solid", Qt.SolidPattern)
        self.brushStyleComboBox.addItem("Horizontal", Qt.HorPattern)
        self.brushStyleComboBox.addItem("Vertical", Qt.VerPattern)
        self.brushStyleComboBox.addItem("Cross", Qt.CrossPattern)
        self.brushStyleComboBox.addItem("Backward Diagonal", Qt.BDiagPattern)
        self.brushStyleComboBox.addItem("Forward Diagonal", Qt.FDiagPattern)
        self.brushStyleComboBox.addItem("Diagonal Cross", Qt.DiagCrossPattern)
        self.brushStyleComboBox.addItem("Dense 1", Qt.Dense1Pattern)
        self.brushStyleComboBox.addItem("Dense 2", Qt.Dense2Pattern)
        self.brushStyleComboBox.addItem("Dense 3", Qt.Dense3Pattern)
        self.brushStyleComboBox.addItem("Dense 4", Qt.Dense4Pattern)
        self.brushStyleComboBox.addItem("Dense 5", Qt.Dense5Pattern)
        self.brushStyleComboBox.addItem("Dense 6", Qt.Dense6Pattern)
        self.brushStyleComboBox.addItem("Dense 7", Qt.Dense7Pattern)
        self.brushStyleComboBox.addItem("None", Qt.NoBrush)

        brushStyleLabel = QLabel("&Brush Style:")
        brushStyleLabel.setBuddy(self.brushStyleComboBox)

        otherOptionsLabel = QLabel("Other Options:")
        self.antialiasingCheckBox = QCheckBox("&Antialiasing")
        self.transformationsCheckBox = QCheckBox("&Transformations")

        self.shapeComboBox.activated.connect(self.shapeChanged)
        self.penWidthSpinBox.valueChanged.connect(self.penChanged)
        self.penStyleComboBox.activated.connect(self.penChanged)
        self.penCapComboBox.activated.connect(self.penChanged)
        self.penJoinComboBox.activated.connect(self.penChanged)
        self.brushStyleComboBox.activated.connect(self.brushChanged)
        self.antialiasingCheckBox.toggled.connect(self.renderArea.setAntialiased)
        self.transformationsCheckBox.toggled.connect(self.renderArea.setTransformed)

        mainLayout = QGridLayout()
        mainLayout.setColumnStretch(0, 1)
        mainLayout.setColumnStretch(3, 1)
        mainLayout.addWidget(self.renderArea, 0, 0, 1, 4)
        mainLayout.setRowMinimumHeight(1, 6)
        mainLayout.addWidget(shapeLabel, 2, 1, Qt.AlignRight)
        mainLayout.addWidget(self.shapeComboBox, 2, 2)
        mainLayout.addWidget(penWidthLabel, 3, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penWidthSpinBox, 3, 2)
        mainLayout.addWidget(penStyleLabel, 4, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penStyleComboBox, 4, 2)
        mainLayout.addWidget(penCapLabel, 5, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penCapComboBox, 5, 2)
        mainLayout.addWidget(penJoinLabel, 6, 1, Qt.AlignRight)
        mainLayout.addWidget(self.penJoinComboBox, 6, 2)
        mainLayout.addWidget(brushStyleLabel, 7, 1, Qt.AlignRight)
        mainLayout.addWidget(self.brushStyleComboBox, 7, 2)
        mainLayout.setRowMinimumHeight(8, 6)
        mainLayout.addWidget(otherOptionsLabel, 9, 1, Qt.AlignRight)
        mainLayout.addWidget(self.antialiasingCheckBox, 9, 2)
        mainLayout.addWidget(self.transformationsCheckBox, 10, 2)
        self.setLayout(mainLayout)

        self.shapeChanged()
        self.penChanged()
        self.brushChanged()
        self.antialiasingCheckBox.setChecked(True)

        self.setWindowTitle("Basic Drawing")

    def shapeChanged(self):
        shape = self.shapeComboBox.itemData(self.shapeComboBox.currentIndex(),
                IdRole)
        self.renderArea.setShape(shape)

    def penChanged(self):
        width = self.penWidthSpinBox.value()
        style = Qt.PenStyle(self.penStyleComboBox.itemData(
                self.penStyleComboBox.currentIndex(), IdRole))
        cap = Qt.PenCapStyle(self.penCapComboBox.itemData(
                self.penCapComboBox.currentIndex(), IdRole))
        join = Qt.PenJoinStyle(self.penJoinComboBox.itemData(
                self.penJoinComboBox.currentIndex(), IdRole))

        self.renderArea.setPen(QPen(Qt.blue, width, style, cap, join))

    def brushChanged(self):
        style = Qt.BrushStyle(self.brushStyleComboBox.itemData(
                self.brushStyleComboBox.currentIndex(), IdRole))

        if style == Qt.LinearGradientPattern:
            linearGradient = QLinearGradient(0, 0, 100, 100)
            linearGradient.setColorAt(0.0, Qt.white)
            linearGradient.setColorAt(0.2, Qt.green)
            linearGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(linearGradient))
        elif style == Qt.RadialGradientPattern:
            radialGradient = QRadialGradient(50, 50, 50, 70, 70)
            radialGradient.setColorAt(0.0, Qt.white)
            radialGradient.setColorAt(0.2, Qt.green)
            radialGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(radialGradient))
        elif style == Qt.ConicalGradientPattern:
            conicalGradient = QConicalGradient(50, 50, 150)
            conicalGradient.setColorAt(0.0, Qt.white)
            conicalGradient.setColorAt(0.2, Qt.green)
            conicalGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(conicalGradient))
        elif style == Qt.TexturePattern:
            self.renderArea.setBrush(QBrush(QPixmap(':/images/brick.png')))
        else:
            self.renderArea.setBrush(QBrush(Qt.green, style))
Пример #20
0
class Window(QDialog):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)

        self.iconGroupBox = QGroupBox()
        self.iconLabel = QLabel()
        self.iconComboBox = QComboBox()
        self.showIconCheckBox = QCheckBox()

        self.messageGroupBox = QGroupBox()
        self.typeLabel = QLabel()
        self.durationLabel = QLabel()
        self.durationWarningLabel = QLabel()
        self.titleLabel = QLabel()
        self.bodyLabel = QLabel()

        self.typeComboBox = QComboBox()
        self.durationSpinBox = QSpinBox()
        self.titleEdit = QLineEdit()
        self.bodyEdit = QTextEdit()
        self.showMessageButton = QPushButton()

        self.minimizeAction = QAction()
        self.maximizeAction = QAction()
        self.restoreAction = QAction()
        self.quitAction = QAction()

        self.trayIcon = QSystemTrayIcon()
        self.trayIconMenu = QMenu()

        self.createIconGroupBox()
        self.createMessageGroupBox()

        self.iconLabel.setMinimumWidth(self.durationLabel.sizeHint().width())

        self.createActions()
        self.createTrayIcon()

        self.showMessageButton.clicked.connect(self.showMessage)
        self.showIconCheckBox.toggled.connect(self.trayIcon.setVisible)
        self.iconComboBox.currentIndexChanged.connect(self.setIcon)
        self.trayIcon.messageClicked.connect(self.messageClicked)
        self.trayIcon.activated.connect(self.iconActivated)

        self.mainLayout = QVBoxLayout()
        self.mainLayout.addWidget(self.iconGroupBox)
        self.mainLayout.addWidget(self.messageGroupBox)
        self.setLayout(self.mainLayout)

        self.iconComboBox.setCurrentIndex(1)
        self.trayIcon.show()

        self.setWindowTitle("Systray")
        self.resize(400, 300)

    def setVisible(self, visible):
        self.minimizeAction.setEnabled(visible)
        self.maximizeAction.setEnabled(not self.isMaximized())
        self.restoreAction.setEnabled(self.isMaximized() or not visible)
        super().setVisible(visible)

    def closeEvent(self, event):
        if not event.spontaneous() or not self.isVisible():
            return
        if self.trayIcon.isVisible():
            QMessageBox.information(self, "Systray",
                                    "The program will keep running in the system tray. "
                                    "To terminate the program, choose <b>Quit</b> in the context "
                                    "menu of the system tray entry.")
            self.hide()
            event.ignore()

    @Slot(int)
    def setIcon(self, index):
        icon = self.iconComboBox.itemIcon(index)
        self.trayIcon.setIcon(icon)
        self.setWindowIcon(icon)
        self.trayIcon.setToolTip(self.iconComboBox.itemText(index))

    @Slot(str)
    def iconActivated(self, reason):
        if reason == QSystemTrayIcon.Trigger:
            pass
        if reason == QSystemTrayIcon.DoubleClick:
            self.iconComboBox.setCurrentIndex(
                (self.iconComboBox.currentIndex() + 1) % self.iconComboBox.count()
            )
        if reason == QSystemTrayIcon.MiddleClick:
            self.showMessage()

    @Slot()
    def showMessage(self):
        self.showIconCheckBox.setChecked(True)
        selectedIcon = self.typeComboBox.itemData(self.typeComboBox.currentIndex())
        msgIcon = QSystemTrayIcon.MessageIcon(selectedIcon)

        if selectedIcon == -1:  # custom icon
            icon = QIcon(self.iconComboBox.itemIcon(self.iconComboBox.currentIndex()))
            self.trayIcon.showMessage(
                self.titleEdit.text(),
                self.bodyEdit.toPlainText(),
                icon,
                self.durationSpinBox.value() * 1000,
            )
        else:
            self.trayIcon.showMessage(
                self.titleEdit.text(),
                self.bodyEdit.toPlainText(),
                msgIcon,
                self.durationSpinBox.value() * 1000,
            )

    @Slot()
    def messageClicked(self):
        QMessageBox.information(None, "Systray",
                                "Sorry, I already gave what help I could.\n"
                                "Maybe you should try asking a human?")

    def createIconGroupBox(self):
        self.iconGroupBox = QGroupBox("Tray Icon")

        self.iconLabel = QLabel("Icon:")

        self.iconComboBox = QComboBox()
        self.iconComboBox.addItem(QIcon(":/images/bad.png"), "Bad")
        self.iconComboBox.addItem(QIcon(":/images/heart.png"), "Heart")
        self.iconComboBox.addItem(QIcon(":/images/trash.png"), "Trash")

        self.showIconCheckBox = QCheckBox("Show icon")
        self.showIconCheckBox.setChecked(True)

        iconLayout = QHBoxLayout()
        iconLayout.addWidget(self.iconLabel)
        iconLayout.addWidget(self.iconComboBox)
        iconLayout.addStretch()
        iconLayout.addWidget(self.showIconCheckBox)
        self.iconGroupBox.setLayout(iconLayout)

    def createMessageGroupBox(self):
        self.messageGroupBox = QGroupBox("Balloon Message")

        self.typeLabel = QLabel("Type:")

        self.typeComboBox = QComboBox()
        self.typeComboBox.addItem("None", QSystemTrayIcon.NoIcon)
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxInformation),
            "Information",
            QSystemTrayIcon.Information,
        )
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxWarning),
            "Warning",
            QSystemTrayIcon.Warning,
        )
        self.typeComboBox.addItem(
            self.style().standardIcon(QStyle.SP_MessageBoxCritical),
            "Critical",
            QSystemTrayIcon.Critical,
        )
        self.typeComboBox.addItem(QIcon(), "Custom icon", -1)
        self.typeComboBox.setCurrentIndex(1)

        self.durationLabel = QLabel("Duration:")

        self.durationSpinBox = QSpinBox()
        self.durationSpinBox.setRange(5, 60)
        self.durationSpinBox.setSuffix(" s")
        self.durationSpinBox.setValue(15)

        self.durationWarningLabel = QLabel("(some systems might ignore this hint)")
        self.durationWarningLabel.setIndent(10)

        self.titleLabel = QLabel("Title:")
        self.titleEdit = QLineEdit("Cannot connect to network")
        self.bodyLabel = QLabel("Body:")

        self.bodyEdit = QTextEdit()
        self.bodyEdit.setPlainText("Don't believe me. Honestly, I don't have a clue."
                                   "\nClick this balloon for details.")

        self.showMessageButton = QPushButton("Show Message")
        self.showMessageButton.setDefault(True)

        messageLayout = QGridLayout()
        messageLayout.addWidget(self.typeLabel, 0, 0)
        messageLayout.addWidget(self.typeComboBox, 0, 1, 1, 2)
        messageLayout.addWidget(self.durationLabel, 1, 0)
        messageLayout.addWidget(self.durationSpinBox, 1, 1)
        messageLayout.addWidget(self.durationWarningLabel, 1, 2, 1, 3)
        messageLayout.addWidget(self.titleLabel, 2, 0)
        messageLayout.addWidget(self.titleEdit, 2, 1, 1, 4)
        messageLayout.addWidget(self.bodyLabel, 3, 0)
        messageLayout.addWidget(self.bodyEdit, 3, 1, 2, 4)
        messageLayout.addWidget(self.showMessageButton, 5, 4)
        messageLayout.setColumnStretch(3, 1)
        messageLayout.setRowStretch(4, 1)
        self.messageGroupBox.setLayout(messageLayout)

    def createActions(self):
        self.minimizeAction = QAction("Minimize", self)
        self.minimizeAction.triggered.connect(self.hide)

        self.maximizeAction = QAction("Maximize", self)
        self.maximizeAction.triggered.connect(self.showMaximized)

        self.restoreAction = QAction("Restore", self)
        self.restoreAction.triggered.connect(self.showNormal)

        self.quitAction = QAction("Quit", self)
        self.quitAction.triggered.connect(qApp.quit)

    def createTrayIcon(self):
        self.trayIconMenu = QMenu(self)
        self.trayIconMenu.addAction(self.minimizeAction)
        self.trayIconMenu.addAction(self.maximizeAction)
        self.trayIconMenu.addAction(self.restoreAction)
        self.trayIconMenu.addSeparator()
        self.trayIconMenu.addAction(self.quitAction)

        self.trayIcon = QSystemTrayIcon(self)
        self.trayIcon.setContextMenu(self.trayIconMenu)
class QBuyGroupForGroundObjectDialog(QDialog):

    changed = QtCore.Signal()

    def __init__(self, parent, ground_object: TheaterGroundObject,
                 cp: ControlPoint, game: Game, current_group_value: int):
        super(QBuyGroupForGroundObjectDialog, self).__init__(parent)

        self.setMinimumWidth(350)
        self.ground_object = ground_object
        self.cp = cp
        self.game = game
        self.current_group_value = current_group_value

        self.setWindowTitle("Buy units @ " + self.ground_object.obj_name)
        self.setWindowIcon(EVENT_ICONS["capture"])

        self.buySamButton = QPushButton("Buy")
        self.buyArmorButton = QPushButton("Buy")
        self.buySamLayout = QGridLayout()
        self.buyArmorLayout = QGridLayout()
        self.amount = QSpinBox()
        self.buyArmorCombo = QComboBox()
        self.samCombo = QComboBox()
        self.buySamBox = QGroupBox("Buy SAM site :")
        self.buyArmorBox = QGroupBox("Buy defensive position :")

        self.init_ui()

    def init_ui(self):
        faction = self.game.player_name

        # Sams

        possible_sams = get_faction_possible_sams_generator(faction)
        for sam in possible_sams:
            self.samCombo.addItem(sam.name + " [$" + str(sam.price) + "M]",
                                  userData=sam)
        self.samCombo.currentIndexChanged.connect(self.samComboChanged)

        self.buySamLayout.addWidget(QLabel("Site Type :"), 0, 0, Qt.AlignLeft)
        self.buySamLayout.addWidget(self.samCombo,
                                    0,
                                    1,
                                    alignment=Qt.AlignRight)
        self.buySamLayout.addWidget(self.buySamButton,
                                    1,
                                    1,
                                    alignment=Qt.AlignRight)
        stretch = QVBoxLayout()
        stretch.addStretch()
        self.buySamLayout.addLayout(stretch, 2, 0)

        self.buySamButton.clicked.connect(self.buySam)

        # Armored units

        armored_units = db.find_unittype(
            PinpointStrike, faction)  # Todo : refactor this legacy nonsense
        for unit in set(armored_units):
            self.buyArmorCombo.addItem(db.unit_type_name_2(unit) + " [$" +
                                       str(db.PRICES[unit]) + "M]",
                                       userData=unit)
        self.buyArmorCombo.currentIndexChanged.connect(self.armorComboChanged)

        self.amount.setMinimum(2)
        self.amount.setMaximum(8)
        self.amount.setValue(2)
        self.amount.valueChanged.connect(self.amountComboChanged)

        self.buyArmorLayout.addWidget(QLabel("Unit type :"), 0, 0,
                                      Qt.AlignLeft)
        self.buyArmorLayout.addWidget(self.buyArmorCombo,
                                      0,
                                      1,
                                      alignment=Qt.AlignRight)
        self.buyArmorLayout.addWidget(QLabel("Group size :"),
                                      1,
                                      0,
                                      alignment=Qt.AlignLeft)
        self.buyArmorLayout.addWidget(self.amount,
                                      1,
                                      1,
                                      alignment=Qt.AlignRight)
        self.buyArmorLayout.addWidget(self.buyArmorButton,
                                      2,
                                      1,
                                      alignment=Qt.AlignRight)
        stretch2 = QVBoxLayout()
        stretch2.addStretch()
        self.buyArmorLayout.addLayout(stretch2, 3, 0)

        self.buyArmorButton.clicked.connect(self.buyArmor)

        # Do layout
        self.buySamBox.setLayout(self.buySamLayout)
        self.buyArmorBox.setLayout(self.buyArmorLayout)

        self.mainLayout = QHBoxLayout()
        self.mainLayout.addWidget(self.buySamBox)

        if self.ground_object.airbase_group:
            self.mainLayout.addWidget(self.buyArmorBox)

        self.setLayout(self.mainLayout)

        try:
            self.samComboChanged(0)
            self.armorComboChanged(0)
        except:
            pass

    def samComboChanged(self, index):
        self.buySamButton.setText("Buy [$" +
                                  str(self.samCombo.itemData(index).price) +
                                  "M] [-$" + str(self.current_group_value) +
                                  "M]")

    def armorComboChanged(self, index):
        self.buyArmorButton.setText(
            "Buy [$" + str(db.PRICES[self.buyArmorCombo.itemData(index)] *
                           self.amount.value()) + "M][-$" +
            str(self.current_group_value) + "M]")

    def amountComboChanged(self):
        self.buyArmorButton.setText("Buy [$" + str(db.PRICES[
            self.buyArmorCombo.itemData(self.buyArmorCombo.currentIndex())] *
                                                   self.amount.value()) +
                                    "M][-$" + str(self.current_group_value) +
                                    "M]")

    def buyArmor(self):
        print("Buy Armor ")
        utype = self.buyArmorCombo.itemData(self.buyArmorCombo.currentIndex())
        print(utype)
        price = db.PRICES[utype] * self.amount.value(
        ) - self.current_group_value
        if price > self.game.budget:
            self.error_money()
            self.close()
            return
        else:
            self.game.budget -= price

        # Generate Armor
        group = generate_armor_group_of_type_and_size(self.game,
                                                      self.ground_object,
                                                      utype,
                                                      int(self.amount.value()))
        self.ground_object.groups = [group]

        GameUpdateSignal.get_instance().updateBudget(self.game)

        self.changed.emit()
        self.close()

    def buySam(self):
        sam_generator = self.samCombo.itemData(self.samCombo.currentIndex())
        price = sam_generator.price - self.current_group_value
        if price > self.game.budget:
            self.error_money()
            return
        else:
            self.game.budget -= price

        # Generate SAM
        generator = sam_generator(self.game, self.ground_object)
        generator.generate()
        generated_group = generator.get_generated_group()
        self.ground_object.groups = [generated_group]

        GameUpdateSignal.get_instance().updateBudget(self.game)

        self.changed.emit()
        self.close()

    def error_money(self):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setText("Not enough money to buy these units !")
        msg.setWindowTitle("Not enough money")
        msg.setStandardButtons(QMessageBox.Ok)
        msg.setWindowFlags(Qt.WindowStaysOnTopHint)
        msg.exec_()
        self.close()
Пример #22
0
class CsoportTabla(QDialog):
    def __init__(self, parent=None):
        super(CsoportTabla, self).__init__(parent)
        self.setWindowTitle("Csoportok, ágak összeállítása")
        self.setMinimumHeight(650)
        # self.setMinimumWidth(700)
        # self.resize(800, 650)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.hatter = QVBoxLayout()
        self.setLayout(self.hatter)

        self.create_torna_selection()
        self.hatter.addWidget(self.tournaments)

        self.space = QSpacerItem(0, 0, QSizePolicy.Minimum,
                                 QSizePolicy.Expanding)
        self.hatter.addItem(self.space)
        # self.create_widgets()
        # self.set_layout()

    def create_widgets(self):
        if hasattr(self, 'resztvevok'):
            self.resztvevok.load_data(self.torna_id)
        else:
            self.resztvevok = resztvevokLista(self.torna_id)
            self.resztvevok.load_data(self.torna_id)

        # GroupMemberWidget-ek
        self.csoportok = []
        for i in range(self.csoportok_szama):  # Csoportok száma
            self.csoportoszlop = []
            for j in range(self.sorok_szama):  # fő/csoport
                self.csoportoszlop.append(GroupMemberWidget(self))
                self.csoportoszlop[j]._set_csoport_number(i)
                self.csoportoszlop[j]._set_csoport_sor(j)
                self.csoportoszlop[j]._set_sorok_szama(self.sorok_szama)
            self.csoportok.append(self.csoportoszlop)

        # EredmenyWidget-ek
        self.eredmenyek = []
        for i in range(self.csoportok_szama):
            self.csoport_eredmeny_matrix = []
            for j in range(
                    self.sorok_szama):  # ami egyenlő az oszlopok számával!!!
                self.eredmeny_oszlop = []
                for x in range(self.sorok_szama):
                    self.eredmeny_oszlop.append(EredmenyWidget(self))
                    self.eredmeny_oszlop[x]._set_csoport_number(i)
                    self.eredmeny_oszlop[x]._set_csoport_sor(x)
                    self.eredmeny_oszlop[x]._set_csoport_oszlop(j)

                self.csoport_eredmeny_matrix.append(self.eredmeny_oszlop)
            self.eredmenyek.append(self.csoport_eredmeny_matrix)

        # Gombok
        if hasattr(self, 'generate_button'):
            pass
        else:
            self.generate_button = QPushButton("Tábla véglegesítése")
            self.generate_button.clicked.connect(self.generate_match_records)

        if hasattr(self, 'autofill_button'):
            pass
        else:
            self.autofill_button = QPushButton("Automatikus kitöltés")
            self.autofill_button.clicked.connect(self.generate_boards)

    def set_layout(self):
        if hasattr(self, 'main_layout'):
            for i in reversed(range(self.main_layout.count())):
                if self.main_layout.itemAt(i).widget() is not None:
                    self.main_layout.itemAt(i).widget().deleteLater()
            for i in reversed(range(self.main_layout.count())):
                if self.main_layout.itemAt(i).layout() is not None:
                    self.main_layout.itemAt(i).layout().deleteLater()
        else:
            self.main_layout = QHBoxLayout()
            self.hatter.addLayout(self.main_layout)

        groups = QWidget()
        groups.setFixedWidth((self.sorok_szama * 50) + 200)
        widgets_layout = QVBoxLayout()
        groups.setLayout(widgets_layout)

        for n in range(self.csoportok_szama):  # csoportok száma
            locals()['csoport_layout' + str(n)] = QGridLayout(
            )  # Létrehozzuk az adott sorszámú csoport layout-ját
            locals()['csoport_layout' + str(n)].setContentsMargins(0, 0, 0, 0)
            locals()['csoport_layout' + str(n)].setHorizontalSpacing(0)
            locals()['csoport_layout' + str(n)].setVerticalSpacing(0)
            widgets_layout.addLayout(locals()[
                'csoport_layout' +
                str(n)])  # Hozzáadjuk a a layout-ot a widget_layout-hoz
            for i in range(
                    len(self.csoportok[n])
            ):  # len(self.csoportok[n]) : csoporton belüli sorok száma
                # Végigmegyünk a sorokon   :  i: sorok száma, n: csoport száma
                # a layout 1. oszlopát feltöltjük a tömbben tárolt custom widget-ekkel
                locals()['csoport_layout' + str(n)].addWidget(
                    self.csoportok[n][i], i + 1, 0)
                # Itt töltjük fel az eredmény-widget-eket (tombben tárolva, mint a GroupMemberWidget-ek) eredmenyek[x, y, z] x: csoport, y: oszlop, z: sor
                for x in range(
                        len(self.csoportok[n])
                ):  # Ez lesz az oszlop(max = sorok száma) x: oszlop száma
                    locals()['csoport_layout' + str(n)].addWidget(
                        self.eredmenyek[n][i][x], i + 1, x + 1)
            locals()['csoport_layout' + str(n)].addWidget(
                QLabel("Csoport_" + str(n + 1)), 0, 0)

        lista_layout = QVBoxLayout()
        lista_layout.addWidget(self.autofill_button)
        lista_layout.addWidget(self.resztvevok)
        lista_layout.addWidget(self.generate_button)
        # lista_layout.addWidget(self.clear_button)

        scroll = QScrollArea()
        scroll.setWidget(groups)
        scroll.setFixedWidth((self.sorok_szama * 50) + 220)
        scroll.setFixedHeight(600)
        scroll.updateGeometry()

        self.main_layout.addWidget(scroll)
        self.main_layout.addLayout(lista_layout)

    def create_torna_selection(self):
        self.tournaments = QComboBox()
        self.tournaments.setMinimumWidth(500)
        self.tournaments.setModelColumn(0)
        self.tournaments.activated.connect(self.torna_valasztas)
        self.load_torna()

    def load_torna(self):
        torna = QSqlQueryModel()
        query = QSqlQuery("select * from torna_settings where aktiv=2")
        torna.setQuery(query)
        if torna.record(0).value(0):
            for i in range(torna.rowCount()):
                self.tournaments.addItem(
                    torna.record(i).value(1),
                    torna.record(i).value(0))  # a value(0) a torna_id

    def torna_valasztas(self, i):
        self.torna_id = self.tournaments.itemData(i)
        torna = QSqlQuery(
            f"select * from torna_settings where torna_id={self.torna_id}")
        torna.exec_()
        while torna.next():
            self.csoportok_szama = torna.value(3)
            self.sorok_szama = torna.value(4)
            self.variant = torna.value(5)
            self.sets = torna.value(7)
            self.legsperset = torna.value(8)

        self.create_widgets()
        self.set_layout()
        # self.hatter.activate()

    def clear_all_torna_match(self):
        print("Rekordok törlése")
        query = QSqlQuery(f"delete from torna_match where torna_id={torna_id}")
        query.exec_()

    def write_tables(self):
        tabla_rekordok = []
        for cs in range(len(self.csoportok)):
            for sor in range(len(self.csoportok[cs])):
                if self.csoportok[cs][sor]._get_player_id() != 0:
                    tabla_rekord = []
                    tabla_rekord.append(self.torna_id)
                    tabla_rekord.append(
                        self.csoportok[cs][sor]._get_player_id())
                    tabla_rekord.append(
                        self.csoportok[cs][sor]._get_csoport_number())
                    tabla_rekord.append(
                        self.csoportok[cs][sor]._get_csoport_sor())
                    tabla_rekordok.append(tabla_rekord)

        insertDataQuery = QSqlQuery()
        insertDataQuery.prepare(""" 
            insert into torna_tablak (
                  torna_id,
                  player_id,
                  csoport_number,
                  csoport_sor
            )
            values (?, ?, ?, ?)
            """)
        for x in range(len(tabla_rekordok)):
            for i in range(len(tabla_rekordok[x])):
                insertDataQuery.addBindValue(tabla_rekordok[x][i])
            insertDataQuery.exec_()

        query = QSqlQuery(
            f"update torna_settings set aktiv=1 where torna_id={self.torna_id}"
        )
        query.exec_()

    def generate_boards(self):
        sorrend = []
        for i in range(self.resztvevok.count()):
            item = self.resztvevok.item(i)
            sorrend.append([item.text(), item.data(1)])
        ujsorrend = sample(sorrend, len(sorrend))
        # print(ujsorrend)
        # print(self.csoportok_szama, self.sorok_szama)
        # valami ilyesmi kell
        # self._player_name = stream.readQString()
        # self._player_id = stream.readInt16()  # sor eseten p1, oszlopnál p2
        atrakott = self.resztvevok.count()
        for j in range(self.sorok_szama):
            for i in range(self.csoportok_szama):
                if atrakott > 0:
                    atrakott -= 1
                    self.csoportok[i][j]._set_player_name(
                        ujsorrend[atrakott][0])
                    self.csoportok[i][j]._set_player_id(ujsorrend[atrakott][1])
                    # print("csoport:", self.csoportok[i][j]._csoport_number, "sor:", self.csoportok[i][j]._csoport_sor, "j-sor", j, "i-csoport:", i)
                    for x in range(self.sorok_szama):
                        self.eredmenyek[i][j][x]._set_p1_id(
                            ujsorrend[atrakott][1])
                        self.eredmenyek[i][x][j]._set_p2_id(
                            ujsorrend[atrakott][1])
                else:
                    break
            if atrakott == 0:
                break
        self.resztvevok.clear()

    def generate_match_records(self):
        match_rekords = []
        csoport_tabla = [6, 5, 4, 3, 2,
                         1]  # todo táblához rendeléshez kell majd
        for cs in range(self.csoportok_szama):
            for sor in range(self.sorok_szama):
                for oszlop in range(sor + 1, self.sorok_szama):
                    if self.eredmenyek[cs][sor][oszlop]._get_p1_id(
                    ) != 0 and self.eredmenyek[cs][sor][oszlop]._get_p2_id(
                    ) != 0:
                        match_id = (10000 * self.torna_id) + (
                            100 *
                            int(self.eredmenyek[cs][sor][oszlop]._get_p1_id())
                        ) + int(self.eredmenyek[cs][sor][oszlop]._get_p2_id())
                        match_rekord = []
                        match_rekord.append(self.torna_id)
                        match_rekord.append(match_id)
                        match_rekord.append(
                            self.eredmenyek[cs][sor][oszlop]._get_p1_id())
                        match_rekord.append(
                            self.eredmenyek[cs][sor][oszlop]._get_p2_id())
                        match_rekord.append(self.variant)
                        match_rekord.append(self.sets)
                        match_rekord.append(self.legsperset)
                        match_rekord.append(csoport_tabla[cs])
                        match_rekords.append(match_rekord)

        insertDataQuery = QSqlQuery()
        insertDataQuery.prepare(""" 
            insert into torna_match (
                  torna_id,
                  match_id,
                  player1_id,
                  player2_id,
                  variant,
                  sets,
                  legsperset,
                  tabla
            )
            values (?, ?, ?, ?, ?, ?, ?, ?)
            """)
        for x in range(len(match_rekords)):
            for i in range(len(match_rekords[x])):
                insertDataQuery.addBindValue(match_rekords[x][i])
            insertDataQuery.exec_()

        self.write_tables()
Пример #23
0
class QGroundObjectBuyMenu(QDialog):
    layout_changed_signal = Signal(QTgoLayout)

    def __init__(
        self,
        parent: QWidget,
        ground_object: TheaterGroundObject,
        game: Game,
        current_group_value: int,
    ) -> None:
        super().__init__(parent)

        self.setMinimumWidth(350)

        self.setWindowTitle("Buy ground object @ " + ground_object.obj_name)
        self.setWindowIcon(EVENT_ICONS["capture"])

        self.mainLayout = QGridLayout()
        self.setLayout(self.mainLayout)

        self.force_group_selector = QComboBox()
        self.force_group_selector.setMinimumWidth(250)
        self.layout_selector = QComboBox()
        self.layout_selector.setMinimumWidth(250)

        # Get the layouts and fill the combobox
        tasks = []
        if isinstance(ground_object, SamGroundObject):
            role = GroupRole.AIR_DEFENSE
        elif isinstance(ground_object, VehicleGroupGroundObject):
            role = GroupRole.GROUND_FORCE
        elif isinstance(ground_object, EwrGroundObject):
            role = GroupRole.AIR_DEFENSE
            tasks.append(GroupTask.EARLY_WARNING_RADAR)
        else:
            raise NotImplementedError(
                f"Unhandled TGO type {ground_object.__class__}")

        if not tasks:
            tasks = role.tasks

        for group in game.blue.armed_forces.groups_for_tasks(tasks):
            self.force_group_selector.addItem(group.name, userData=group)
        self.force_group_selector.setEnabled(
            self.force_group_selector.count() > 1)
        self.force_group_selector.adjustSize()
        force_group = self.force_group_selector.itemData(
            self.force_group_selector.currentIndex())

        for layout in force_group.layouts:
            self.layout_selector.addItem(layout.name, userData=layout)
        self.layout_selector.adjustSize()
        self.layout_selector.setEnabled(len(force_group.layouts) > 1)
        selected_template = self.layout_selector.itemData(
            self.layout_selector.currentIndex())

        self.theater_layout = QTgoLayout(selected_template, force_group)

        self.layout_selector.currentIndexChanged.connect(self.layout_changed)
        self.force_group_selector.currentIndexChanged.connect(
            self.force_group_changed)

        template_selector_layout = QGridLayout()
        template_selector_layout.addWidget(QLabel("Armed Forces Group:"), 0, 0,
                                           Qt.AlignLeft)
        template_selector_layout.addWidget(self.force_group_selector,
                                           0,
                                           1,
                                           alignment=Qt.AlignRight)
        template_selector_layout.addWidget(QLabel("Layout:"), 1, 0,
                                           Qt.AlignLeft)
        template_selector_layout.addWidget(self.layout_selector,
                                           1,
                                           1,
                                           alignment=Qt.AlignRight)
        self.mainLayout.addLayout(template_selector_layout, 0, 0)

        self.template_layout = QGroundObjectTemplateLayout(
            game,
            ground_object,
            self.theater_layout,
            self.layout_changed_signal,
            current_group_value,
        )
        self.template_layout.close_dialog_signal.connect(self.close_dialog)
        self.mainLayout.addWidget(self.template_layout, 1, 0)
        self.setLayout(self.mainLayout)

    def force_group_changed(self) -> None:
        # Prevent ComboBox from firing change Events
        self.layout_selector.blockSignals(True)
        unit_group = self.force_group_selector.itemData(
            self.force_group_selector.currentIndex())
        self.layout_selector.clear()
        for layout in unit_group.layouts:
            self.layout_selector.addItem(layout.name, userData=layout)
        self.layout_selector.adjustSize()
        # Enable if more than one template is available
        self.layout_selector.setEnabled(len(unit_group.layouts) > 1)
        # Enable Combobox Signals again
        self.layout_selector.blockSignals(False)
        self.layout_changed()

    def layout_changed(self) -> None:
        self.layout()
        self.theater_layout.layout = self.layout_selector.itemData(
            self.layout_selector.currentIndex())
        self.theater_layout.force_group = self.force_group_selector.itemData(
            self.force_group_selector.currentIndex())
        self.layout_changed_signal.emit(self.theater_layout)

    def close_dialog(self) -> None:
        self.accept()