class SpinBoxPySlot(UsesQApplication, BasicPySlotCase):
        """Tests the connection of python slots to QSpinBox signals"""

        def setUp(self):
            super(SpinBoxPySlot, self).setUp()
            self.spin = QSpinBox()

        def tearDown(self):
            del self.spin
            super(SpinBoxPySlot, self).tearDown()

        def testSpinBoxValueChanged(self):
            """Connection of a python slot to QSpinBox.valueChanged(int)"""
            QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb)
            self.args = [3]
            self.spin.emit(SIGNAL('valueChanged(int)'), *self.args)
            self.assert_(self.called)

        def testSpinBoxValueChangedImplicit(self):
            """Indirect qt signal emission using QSpinBox.setValue(int)"""
            QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb)
            self.args = [42]
            self.spin.setValue(self.args[0])
            self.assert_(self.called)

        def atestSpinBoxValueChangedFewArgs(self):
            """Emission of signals with fewer arguments than needed"""
            # XXX: PyQt4 crashes on the assertRaises
            QObject.connect(self.spin, SIGNAL('valueChanged(int)'), self.cb)
            self.args = (554,)
            self.assertRaises(TypeError, self.spin.emit, SIGNAL('valueChanged(int)'))
Esempio n. 2
0
    class SpinBoxPySignal(UsesQApplication):
        """Tests the connection of python signals to QSpinBox qt slots."""

        def setUp(self):
            super(SpinBoxPySignal, self).setUp()
            self.obj = Dummy()
            self.spin = QSpinBox()
            self.spin.setValue(0)

        def tearDown(self):
            super(SpinBoxPySignal, self).tearDown()
            del self.obj
            del self.spin

        def testValueChanged(self):
            """Emission of a python signal to QSpinBox setValue(int)"""
            QObject.connect(self.obj, SIGNAL("dummy(int)"), self.spin, SLOT("setValue(int)"))
            self.assertEqual(self.spin.value(), 0)

            self.obj.emit(SIGNAL("dummy(int)"), 4)
            self.assertEqual(self.spin.value(), 4)

        def testValueChangedMultiple(self):
            """Multiple emissions of a python signal to QSpinBox setValue(int)"""
            QObject.connect(self.obj, SIGNAL("dummy(int)"), self.spin, SLOT("setValue(int)"))
            self.assertEqual(self.spin.value(), 0)

            self.obj.emit(SIGNAL("dummy(int)"), 4)
            self.assertEqual(self.spin.value(), 4)

            self.obj.emit(SIGNAL("dummy(int)"), 77)
            self.assertEqual(self.spin.value(), 77)
Esempio n. 3
0
 def testSpinButton(self):
     #Connecting a lambda to a QPushButton.clicked()
     obj = QSpinBox()
     ctr = Control()
     arg = 444
     func = lambda x: setattr(ctr, 'arg', 444)
     QObject.connect(obj, SIGNAL('valueChanged(int)'), func)
     obj.setValue(444)
     self.assertEqual(ctr.arg, arg)
     QObject.disconnect(obj, SIGNAL('valueChanged(int)'), func)
        def testSetValueIndirect(self):
            """Indirect signal emission: QSpinBox using valueChanged(int)/setValue(int)"""
            spinSend = QSpinBox()
            spinRec = QSpinBox()

            spinRec.setValue(5)

            QObject.connect(spinSend, SIGNAL('valueChanged(int)'), spinRec, SLOT('setValue(int)'))
            self.assertEqual(spinRec.value(), 5)
            spinSend.setValue(3)
            self.assertEqual(spinRec.value(), 3)
            self.assertEqual(spinSend.value(), 3)
        def testSetValue(self):
            """Direct signal emission: QSpinBox using valueChanged(int)/setValue(int)"""
            spinSend = QSpinBox()
            spinRec = QSpinBox()

            spinRec.setValue(5)
            spinSend.setValue(42)

            QObject.connect(spinSend, SIGNAL('valueChanged(int)'), spinRec, SLOT('setValue(int)'))
            self.assertEqual(spinRec.value(), 5)
            self.assertEqual(spinSend.value(), 42)
            spinSend.emit(SIGNAL('valueChanged(int)'), 3)

            self.assertEqual(spinRec.value(), 3)
            #Direct emission shouldn't change the value of the emitter
            self.assertEqual(spinSend.value(), 42)

            spinSend.emit(SIGNAL('valueChanged(int)'), 66)
            self.assertEqual(spinRec.value(), 66)
            self.assertEqual(spinSend.value(), 42)
Esempio n. 6
0
class DownloadComponent(QGroupBox):
    reportFormatChanged = Signal(ReportWriter)
    saveCompleted = Signal(bool)

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

        self._report_writer = None
        self._report_writer_thread = ReportWriterThread()
        self._report_writer_thread.completed.connect(self._saveCompleted)
        
        self._progress_message = ProgressMessageBox(self.parentWidget(), "Export des données en cours...", "Export des données en cours...", 0, 0)

        self._report_types = {
            "summary": {"name": "Résumé", "description": "Le résumé inclu les statistiques générales sur les images analysées"},
            "full": {"name": "Complet", "description": "Le rapport complet inclu les statistiques détaillées sur les images analysées"},
            "annotations": {"name": "Annotations", "description": "Converti les résultats de l'analyse en annotation utilisable pour l'entrainement"}
        }
        self._report_formats = {
            "summary": {
                "PDF": {"type": "Document PDF", "extension": "*.pdf"},
                "Texte": {"type": "Fichier texte", "extension": "*.txt"}
            },
            "full": {
                "CSV": {"type": "Fichier CSV", "extension": "*.csv"},
                "JSON": {"type": "Fichier JSON", "extension": "*.json"},
                "XML": {"type": "Fichier XML", "extension": "*.xml"},
            },
            "annotations": {
                "Annotations YOLOv4": {"type": "Fichier zip", "extension": "*.zip"}
            }
        }
        self._default_report_type = "summary"

        self.setTitle("Paramètres")
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)

        self._form_layout = QFormLayout()
        self._form_layout.setHorizontalSpacing(20)
        self._form_layout.setVerticalSpacing(14)

        self._report_type_cbox = QComboBox()
        for report_type, v in self._report_types.items():
            self._report_type_cbox.addItem(v["name"], report_type)

        self._form_layout.addRow("Type de rapport :", self._report_type_cbox)

        self._info_text = QLabel(self._report_types[self._default_report_type]["description"])
        self._info_text.setObjectName("info")
        self._form_layout.addRow(self._info_text)

        self._report_format_cbox = QComboBox()
        for format, data in self._report_formats[self._default_report_type].items():
            self._report_format_cbox.addItem(format, data)

        self._form_layout.addRow("Format du rapport :", self._report_format_cbox)

        self._detection_shape_cbox = QComboBox()
        self._detection_shape_cbox.addItem("Rectangle", "rectangle")
        self._detection_shape_cbox.addItem("Cercle", "circle")
        self._detection_shape_cbox.hide()

        self._separator_cbox = QComboBox()
        self._separator_cbox.addItem("Point virgule", ";")
        self._separator_cbox.addItem("Virgule", ",")
        self._separator_cbox.hide()

        self._nb_keeped_spinbox = QSpinBox(self)
        self._nb_keeped_spinbox.setRange(1, 1)
        self._nb_keeped_spinbox.hide()

        download_button = StylizedButton("Télécharger", "blue")
        download_button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)

        button_layout = QHBoxLayout()
        button_layout.setAlignment(Qt.AlignRight)
        button_layout.addWidget(download_button)

        main_layout = QVBoxLayout(self)
        main_layout.addLayout(self._form_layout)
        main_layout.addStretch(1)
        main_layout.addLayout(button_layout)

        # Signals
        download_button.clicked.connect(self._exportReport)
        self._report_type_cbox.currentIndexChanged.connect(self._reportTypeChanged)
        self._report_format_cbox.currentTextChanged.connect(self._reportFormatChanged)
        self._detection_shape_cbox.currentIndexChanged.connect(self._reportParamsChanged)
        self._separator_cbox.currentIndexChanged.connect(self._reportParamsChanged)

    def reset(self, analysis: Analysis):
        self._analysis = analysis

        self._report_type_cbox.setCurrentIndex(0)
        self._report_format_cbox.setCurrentIndex(0)
        self._nb_keeped_spinbox.setMaximum(analysis.imagesWithDetections())
        self._nb_keeped_spinbox.setValue(min(100, analysis.imagesWithDetections()))
        self._loadWriter()

    def _loadWriter(self):
        format_text = self._report_format_cbox.currentText()
        if format_text == "PDF":
            self._report_writer = PDFReportWriter(self._analysis)
        
        elif format_text == "Texte":
            self._report_writer = TextReportWriter(self._analysis)

        elif format_text == "CSV":
            self._report_writer = CSVReportWriter(self._analysis, self._separator_cbox.currentData(), self._detection_shape_cbox.currentData())

        elif format_text == "JSON":
            self._report_writer = JSONReportWriter(self._analysis, shape=self._detection_shape_cbox.currentData())
        
        elif format_text == "XML":
            self._report_writer = XMLReportWriter(self._analysis, shape=self._detection_shape_cbox.currentData())

        elif format_text == "Annotations YOLOv4":
            self._report_writer = Yolov4AnnotationsWriter(self._analysis)

        self.reportFormatChanged.emit(self._report_writer)

    @Slot(int)
    def _reportTypeChanged(self, index: int):
        report_type = self._report_type_cbox.currentData()
        self._info_text.setText(self._report_types[report_type]["description"])

        self._report_format_cbox.clear()
        for format, data in self._report_formats[report_type].items():
            self._report_format_cbox.addItem(format, data)

        if report_type == "summary":
            self._showDetectionShape(False)
            self._showSeparator(False)
            self._showKeepedNumber(False)
        elif report_type == "full":
            self._showDetectionShape(True)
            self._showKeepedNumber(False)
        elif report_type == "annotations":
            self._showDetectionShape(False)
            self._showSeparator(False)
            self._showKeepedNumber(True)
    
    @Slot(str)
    def _reportFormatChanged(self, format: str):
        if format == "CSV":
            self._showSeparator(True)
        else: # JSON & XSML
            self._showSeparator(False)

        self._loadWriter()

    def _showDetectionShape(self, show: bool):
        self._showRow("Détection :", self._detection_shape_cbox, show)

    def _showSeparator(self, show: bool):
        self._showRow("Séparateur :", self._separator_cbox, show)

    def _showKeepedNumber(self, show: bool):
        self._showRow("Images à exporter :", self._nb_keeped_spinbox, show)

    def _showRow(self, label: str, widget: QWidget, show: bool):
        if show and not widget.isVisible():
            widget.show()
            self._form_layout.addRow(label, widget)
        elif not show and widget.isVisible():
            label = self._form_layout.labelForField(widget)
            widget.hide()
            label.hide()
            self._form_layout.removeWidget(widget)
            self._form_layout.removeWidget(label)
            del label

    @Slot(int)
    def _reportParamsChanged(self, index: int):
        self._loadWriter()

    @Slot()
    def _exportReport(self):
        report_type = self._report_type_cbox.currentData()
        if report_type == "annotations":
            self._report_writer.setKeep(self._nb_keeped_spinbox.value())

        error = self._report_writer.checkErrors()
        if error:
            QMessageBox.warning(self.parentWidget(), "Impossible de générer le rapport", error)
            return

        filename = self._analysis.parameters().name()
        report_format = self._report_format_cbox.currentData()

        path = QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation) + "/" + filename
        filter = "Fichier %s (%s)" % (report_format["type"], report_format["extension"])

        result = QFileDialog.getSaveFileName(self, "Enregistrer le fichier", path, filter)
        
        filepath = result[0]
        if filepath == '':
            return

        self._report_writer_thread.start(self._report_writer, filepath)
        self._progress_message.exec_()

    @Slot()
    def _saveCompleted(self, success: bool):
        if self._progress_message:
            self._progress_message.close()
        
        self.saveCompleted.emit(success)
Esempio n. 7
0
class segmentForm(baseForm):
    """
    Segmentation (grabcut) form
    """
    layerTitle = "Segmentation"
    iterDefault = 3
    contourMarginDefault = 1
    @classmethod
    def getNewWindow(cls, targetImage=None, layer=None, mainForm=None):
        wdgt = segmentForm(layer=layer)
        return wdgt

    def __init__(self, layer=None):
        super(segmentForm, self).__init__()
        self.setWindowTitle('grabcut')
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.setMinimumSize(200, 200)
        self.setAttribute(Qt.WA_DeleteOnClose)
        # link back to image layer
        self.layer = weakProxy(layer)
        pushButton = QPushButton('apply')
        # button slot
        def f():
            self.layer.noSegment = False
            self.layer.applyToStack()
            window.label.img.onImageChanged()
            # do manual segmentation only
            layer.noSegment = True
        pushButton.clicked.connect(f)

        pushButton1 = QPushButton('Reset')
        pushButton1.clicked.connect(lambda : self.reset())

        self.spBox = QSpinBox()
        self.spBox.setRange(1,10)
        # spBox Slot
        def f2(iterCount):
            self.spBox.valueChanged.disconnect()
            self.dataChanged.emit()
            self.spBox.valueChanged.connect(f2)
        self.spBox.valueChanged.connect(f2)
        spBoxLabel = QLabel()
        spBoxLabel.setText('Iterations')

        self.spBox1 = QSpinBox()
        self.spBox1.setRange(0, 20)
        spBox1Label = QLabel()
        spBox1Label.setText('Contour Margin')
        # spBox1 slot
        def f1(margin):
            self.spBox1.valueChanged.disconnect()
            self.dataChanged.emit()
            self.spBox1.valueChanged.connect(f1)
        self.spBox1.valueChanged.connect(f1)

        # options
        optionList1, optionNames1 = ['Clipping Layer'], ['Clipping Layer']
        self.listWidget1 = optionsWidget(options=optionList1, optionNames=optionNames1, exclusive=False)
        self.options = self.listWidget1.options
        # option changed slot
        def g(item):
            self.layer.isClipping = self.options['Clipping Layer']
            self.layer.applyToStack()
            self.layer.parentImage.onImageChanged()
        self.listWidget1.onSelect = g

        # attributes initialized in setDefaults, declared here
        # for the sake of correctness
        self.start = None
        self.nbIter = None
        self.contourMargin = None

        # layout
        hLay = QHBoxLayout()
        hLay.addWidget(spBoxLabel)
        hLay.addWidget(self.spBox)
        hLay.addStretch(1)
        hLay1 = QHBoxLayout()
        hLay1.addWidget(spBox1Label)
        hLay1.addWidget(self.spBox1)
        hLay1.addStretch(1)
        h2 = QHBoxLayout()
        h2.addWidget(self.listWidget1)
        vLay = QVBoxLayout()
        vLay.setAlignment(Qt.AlignTop)
        vLay.setContentsMargins(20, 8, 20, 25)  # left, top, right, bottom
        vLay.addLayout(hLay)
        vLay.addLayout(hLay1)
        vLay.addLayout(h2)
        h3 = QHBoxLayout()
        h3.addWidget(pushButton)
        h3.addWidget(pushButton1)
        vLay.addLayout(h3)
        self.setLayout(vLay)
        self.setDefaults()
        self.setWhatsThis(
""" <b>Object extraction</b><br>  
  Select the object to extract with the rectangle Marquee Tool. Next, click the Apply button.<br>
  Correct (roughly) if needed the foreground (FG) and the background (BG) regions using the FG and BG tools (Ctrl to undo) and click again the Apply button.<br>
  To get a smoother contour increase the value of the Contour Margin and click the Apply Button.<br>
  By default the mask is displayed as a color mask. To view it as an opacity mask, right click on the Segmentation layer row in the right pane and check Enable Mask As > Opacity Mask in the context menu.
  Use the same context menu to copy/paste the object to a new image layer or the mask to another layer.<br>
  
"""
                        )  # end setWhatsThis

    def setDefaults(self):
        # prevent multiple updates
        try:
            self.dataChanged.disconnect()
        except RuntimeError:
            pass
        self.listWidget1.unCheckAll()
        self.spBox.setValue(self.iterDefault)
        self.spBox1.setValue(self.contourMarginDefault)
        self.start = True
        self.dataChanged.connect(self.updateLayer)
        # self.dataChanged.emit() # TODO 30/10/18 removed validate

    def updateLayer(self):
        self.nbIter = self.spBox.value()
        self.contourMargin = self.spBox1.value()

    def reset(self):
        layer = self.layer
        layer.maskIsEnabled = True
        layer.maskIsSelected = True
        # mask pixels are not yet painted as FG or BG
        # so we mark them as invalid
        layer.mask.fill(vImage.defaultColor_Invalid)
        layer.paintedMask = layer.mask.copy()
        layer.isClipping = False
        self.setDefaults()
        self.dataChanged.emit()  # TODO added 30/10/18 validate
        layer.updatePixmap()
Esempio n. 8
0
class QSettingsWindow(QDialog):

    def __init__(self, game: Game):
        super(QSettingsWindow, self).__init__()

        self.game = game
        self.pluginsPage = None
        self.pluginsOptionsPage = None
        self.campaign_management_page = QWidget()

        self.setModal(True)
        self.setWindowTitle("Settings")
        self.setWindowIcon(CONST.ICONS["Settings"])
        self.setMinimumSize(600, 250)

        self.initUi()

    def initUi(self):
        self.layout = QGridLayout()

        self.categoryList = QListView()
        self.right_layout = QStackedLayout()

        self.categoryList.setMaximumWidth(175)

        self.categoryModel = QStandardItemModel(self.categoryList)

        self.categoryList.setIconSize(QSize(32, 32))

        self.initDifficultyLayout()
        difficulty = QStandardItem("Difficulty")
        difficulty.setIcon(CONST.ICONS["Missile"])
        difficulty.setEditable(False)
        difficulty.setSelectable(True)
        self.categoryModel.appendRow(difficulty)
        self.right_layout.addWidget(self.difficultyPage)

        self.init_campaign_management_layout()
        campaign_management = QStandardItem("Campaign Management")
        campaign_management.setIcon(CONST.ICONS["Money"])
        campaign_management.setEditable(False)
        campaign_management.setSelectable(True)
        self.categoryModel.appendRow(campaign_management)
        self.right_layout.addWidget(self.campaign_management_page)

        self.initGeneratorLayout()
        generator = QStandardItem("Mission Generator")
        generator.setIcon(CONST.ICONS["Generator"])
        generator.setEditable(False)
        generator.setSelectable(True)
        self.categoryModel.appendRow(generator)
        self.right_layout.addWidget(self.generatorPage)

        self.initCheatLayout()
        cheat = QStandardItem("Cheat Menu")
        cheat.setIcon(CONST.ICONS["Cheat"])
        cheat.setEditable(False)
        cheat.setSelectable(True)
        self.categoryModel.appendRow(cheat)
        self.right_layout.addWidget(self.cheatPage)

        self.pluginsPage = PluginsPage()
        plugins = QStandardItem("LUA Plugins")
        plugins.setIcon(CONST.ICONS["Plugins"])
        plugins.setEditable(False)
        plugins.setSelectable(True)
        self.categoryModel.appendRow(plugins)
        self.right_layout.addWidget(self.pluginsPage)

        self.pluginsOptionsPage = PluginOptionsPage()
        pluginsOptions = QStandardItem("LUA Plugins Options")
        pluginsOptions.setIcon(CONST.ICONS["PluginsOptions"])
        pluginsOptions.setEditable(False)
        pluginsOptions.setSelectable(True)
        self.categoryModel.appendRow(pluginsOptions)
        self.right_layout.addWidget(self.pluginsOptionsPage)

        self.categoryList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.categoryList.setModel(self.categoryModel)
        self.categoryList.selectionModel().setCurrentIndex(self.categoryList.indexAt(QPoint(1,1)), QItemSelectionModel.Select)
        self.categoryList.selectionModel().selectionChanged.connect(self.onSelectionChanged)


        self.layout.addWidget(self.categoryList, 0, 0, 1, 1)
        self.layout.addLayout(self.right_layout, 0, 1, 5, 1)

        self.setLayout(self.layout)

    def init(self):
        pass

    def initDifficultyLayout(self):

        self.difficultyPage = QWidget()
        self.difficultyLayout = QVBoxLayout()
        self.difficultyLayout.setAlignment(Qt.AlignTop)
        self.difficultyPage.setLayout(self.difficultyLayout)

        # DCS AI difficulty settings
        self.aiDifficultySettings = QGroupBox("AI Difficulty")
        self.aiDifficultyLayout = QGridLayout()
        self.playerCoalitionSkill = QComboBox()
        self.enemyCoalitionSkill = QComboBox()
        self.enemyAASkill = QComboBox()
        for skill in CONST.SKILL_OPTIONS:
            self.playerCoalitionSkill.addItem(skill)
            self.enemyCoalitionSkill.addItem(skill)
            self.enemyAASkill.addItem(skill)

        self.playerCoalitionSkill.setCurrentIndex(CONST.SKILL_OPTIONS.index(self.game.settings.player_skill))
        self.enemyCoalitionSkill.setCurrentIndex(CONST.SKILL_OPTIONS.index(self.game.settings.enemy_skill))
        self.enemyAASkill.setCurrentIndex(CONST.SKILL_OPTIONS.index(self.game.settings.enemy_vehicle_skill))

        self.player_income = TenthsSpinSlider(
            "Player income multiplier", 1, 50,
            int(self.game.settings.player_income_multiplier * 10))
        self.player_income.spinner.valueChanged.connect(self.applySettings)
        self.enemy_income = TenthsSpinSlider(
            "Enemy income multiplier", 1, 50,
            int(self.game.settings.enemy_income_multiplier * 10))
        self.enemy_income.spinner.valueChanged.connect(self.applySettings)

        self.playerCoalitionSkill.currentIndexChanged.connect(self.applySettings)
        self.enemyCoalitionSkill.currentIndexChanged.connect(self.applySettings)
        self.enemyAASkill.currentIndexChanged.connect(self.applySettings)

        # Mission generation settings related to difficulty
        self.missionSettings = QGroupBox("Mission Difficulty")
        self.missionLayout = QGridLayout()

        self.manpads = QCheckBox()
        self.manpads.setChecked(self.game.settings.manpads)
        self.manpads.toggled.connect(self.applySettings)

        self.noNightMission = QCheckBox()
        self.noNightMission.setChecked(self.game.settings.night_disabled)
        self.noNightMission.toggled.connect(self.applySettings)

        # DCS Mission options
        self.missionRestrictionsSettings = QGroupBox("Mission Restrictions")
        self.missionRestrictionsLayout = QGridLayout()

        self.difficultyLabel = QComboBox()
        [self.difficultyLabel.addItem(t) for t in CONST.LABELS_OPTIONS]
        self.difficultyLabel.setCurrentIndex(CONST.LABELS_OPTIONS.index(self.game.settings.labels))
        self.difficultyLabel.currentIndexChanged.connect(self.applySettings)

        self.mapVisibiitySelection = QComboBox()
        self.mapVisibiitySelection.addItem("All", ForcedOptions.Views.All)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.All:
            self.mapVisibiitySelection.setCurrentIndex(0)
        self.mapVisibiitySelection.addItem("Fog of War", ForcedOptions.Views.Allies)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.Allies:
            self.mapVisibiitySelection.setCurrentIndex(1)
        self.mapVisibiitySelection.addItem("Allies Only", ForcedOptions.Views.OnlyAllies)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.OnlyAllies:
            self.mapVisibiitySelection.setCurrentIndex(2)
        self.mapVisibiitySelection.addItem("Own Aircraft Only", ForcedOptions.Views.MyAircraft)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.MyAircraft:
            self.mapVisibiitySelection.setCurrentIndex(3)
        self.mapVisibiitySelection.addItem("Map Only", ForcedOptions.Views.OnlyMap)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.OnlyMap:
            self.mapVisibiitySelection.setCurrentIndex(4)
        self.mapVisibiitySelection.currentIndexChanged.connect(self.applySettings)

        self.ext_views = QCheckBox()
        self.ext_views.setChecked(self.game.settings.external_views_allowed)
        self.ext_views.toggled.connect(self.applySettings)

        self.aiDifficultyLayout.addWidget(QLabel("Player coalition skill"), 0, 0)
        self.aiDifficultyLayout.addWidget(self.playerCoalitionSkill, 0, 1, Qt.AlignRight)
        self.aiDifficultyLayout.addWidget(QLabel("Enemy coalition skill"), 1, 0)
        self.aiDifficultyLayout.addWidget(self.enemyCoalitionSkill, 1, 1, Qt.AlignRight)
        self.aiDifficultyLayout.addWidget(QLabel("Enemy AA and vehicles skill"), 2, 0)
        self.aiDifficultyLayout.addWidget(self.enemyAASkill, 2, 1, Qt.AlignRight)
        self.aiDifficultyLayout.addLayout(self.player_income, 3, 0)
        self.aiDifficultyLayout.addLayout(self.enemy_income, 4, 0)
        self.aiDifficultySettings.setLayout(self.aiDifficultyLayout)
        self.difficultyLayout.addWidget(self.aiDifficultySettings)

        self.missionLayout.addWidget(QLabel("Manpads on frontlines"), 0, 0)
        self.missionLayout.addWidget(self.manpads, 0, 1, Qt.AlignRight)
        self.missionLayout.addWidget(QLabel("No night missions"), 1, 0)
        self.missionLayout.addWidget(self.noNightMission, 1, 1, Qt.AlignRight)
        self.missionSettings.setLayout(self.missionLayout)
        self.difficultyLayout.addWidget(self.missionSettings)

        self.missionRestrictionsLayout.addWidget(QLabel("In Game Labels"), 0, 0)
        self.missionRestrictionsLayout.addWidget(self.difficultyLabel, 0, 1, Qt.AlignRight)
        self.missionRestrictionsLayout.addWidget(QLabel("Map visibility options"), 1, 0)
        self.missionRestrictionsLayout.addWidget(self.mapVisibiitySelection, 1, 1, Qt.AlignRight)
        self.missionRestrictionsLayout.addWidget(QLabel("Allow external views"), 2, 0)
        self.missionRestrictionsLayout.addWidget(self.ext_views, 2, 1, Qt.AlignRight)
        self.missionRestrictionsSettings.setLayout(self.missionRestrictionsLayout)
        self.difficultyLayout.addWidget(self.missionRestrictionsSettings)

    def init_campaign_management_layout(self) -> None:
        campaign_layout = QVBoxLayout()
        campaign_layout.setAlignment(Qt.AlignTop)
        self.campaign_management_page.setLayout(campaign_layout)

        general = QGroupBox("General")
        campaign_layout.addWidget(general)

        general_layout = QGridLayout()
        general.setLayout(general_layout)

        def set_restict_weapons_by_date(value: bool) -> None:
            self.game.settings.restrict_weapons_by_date = value

        restrict_weapons = QCheckBox()
        restrict_weapons.setChecked(self.game.settings.restrict_weapons_by_date)
        restrict_weapons.toggled.connect(set_restict_weapons_by_date)

        tooltip_text = (
            "Restricts weapon availability based on the campaign date. Data is "
            "extremely incomplete so does not affect all weapons."
        )
        restrict_weapons.setToolTip(tooltip_text)
        restrict_weapons_label = QLabel("Restrict weapons by date (WIP)")
        restrict_weapons_label.setToolTip(tooltip_text)

        general_layout.addWidget(restrict_weapons_label, 0, 0)
        general_layout.addWidget(restrict_weapons, 0, 1, Qt.AlignRight)

        automation = QGroupBox("HQ Automation")
        campaign_layout.addWidget(automation)

        automation_layout = QGridLayout()
        automation.setLayout(automation_layout)

        def set_runway_automation(value: bool) -> None:
            self.game.settings.automate_runway_repair = value

        def set_front_line_automation(value: bool) -> None:
            self.game.settings.automate_front_line_reinforcements = value

        def set_aircraft_automation(value: bool) -> None:
            self.game.settings.automate_aircraft_reinforcements = value

        runway_repair = QCheckBox()
        runway_repair.setChecked(
            self.game.settings.automate_runway_repair)
        runway_repair.toggled.connect(set_runway_automation)

        automation_layout.addWidget(QLabel("Automate runway repairs"), 0, 0)
        automation_layout.addWidget(runway_repair, 0, 1, Qt.AlignRight)

        front_line = QCheckBox()
        front_line.setChecked(
            self.game.settings.automate_front_line_reinforcements)
        front_line.toggled.connect(set_front_line_automation)

        automation_layout.addWidget(
            QLabel("Automate front-line purchases"), 1, 0)
        automation_layout.addWidget(front_line, 1, 1, Qt.AlignRight)

        aircraft = QCheckBox()
        aircraft.setChecked(
            self.game.settings.automate_aircraft_reinforcements)
        aircraft.toggled.connect(set_aircraft_automation)

        automation_layout.addWidget(QLabel("Automate aircraft purchases"), 2, 0)
        automation_layout.addWidget(aircraft, 2, 1, Qt.AlignRight)

    def initGeneratorLayout(self):
        self.generatorPage = QWidget()
        self.generatorLayout = QVBoxLayout()
        self.generatorLayout.setAlignment(Qt.AlignTop)
        self.generatorPage.setLayout(self.generatorLayout)

        self.gameplay = QGroupBox("Gameplay")
        self.gameplayLayout = QGridLayout()
        self.gameplayLayout.setAlignment(Qt.AlignTop)
        self.gameplay.setLayout(self.gameplayLayout)

        self.supercarrier = QCheckBox()
        self.supercarrier.setChecked(self.game.settings.supercarrier)
        self.supercarrier.toggled.connect(self.applySettings)

        self.generate_marks = QCheckBox()
        self.generate_marks.setChecked(self.game.settings.generate_marks)
        self.generate_marks.toggled.connect(self.applySettings)

        self.never_delay_players = QCheckBox()
        self.never_delay_players.setChecked(
            self.game.settings.never_delay_player_flights)
        self.never_delay_players.toggled.connect(self.applySettings)
        self.never_delay_players.setToolTip(
            "When checked, player flights with a delayed start time will be "
            "spawned immediately. AI wingmen may begin startup immediately."
        )

        self.gameplayLayout.addWidget(QLabel("Use Supercarrier Module"), 0, 0)
        self.gameplayLayout.addWidget(self.supercarrier, 0, 1, Qt.AlignRight)
        self.gameplayLayout.addWidget(QLabel("Put Objective Markers on Map"), 1, 0)
        self.gameplayLayout.addWidget(self.generate_marks, 1, 1, Qt.AlignRight)
        self.gameplayLayout.addWidget(
            QLabel("Never delay player flights"), 2, 0)
        self.gameplayLayout.addWidget(self.never_delay_players, 2, 1,
                                      Qt.AlignRight)

        start_type_label = QLabel(
            "Default start type for AI aircraft:<br /><strong>Warning: " +
            "Any option other than Cold breaks OCA/Aircraft missions.</strong>"
        )
        start_type_label.setToolTip(START_TYPE_TOOLTIP)
        start_type = StartTypeComboBox(self.game.settings)
        start_type.setCurrentText(self.game.settings.default_start_type)

        self.gameplayLayout.addWidget(start_type_label, 3, 0)
        self.gameplayLayout.addWidget(start_type, 3, 1)

        self.performance = QGroupBox("Performance")
        self.performanceLayout = QGridLayout()
        self.performanceLayout.setAlignment(Qt.AlignTop)
        self.performance.setLayout(self.performanceLayout)

        self.smoke = QCheckBox()
        self.smoke.setChecked(self.game.settings.perf_smoke_gen)
        self.smoke.toggled.connect(self.applySettings)

        self.red_alert = QCheckBox()
        self.red_alert.setChecked(self.game.settings.perf_red_alert_state)
        self.red_alert.toggled.connect(self.applySettings)

        self.arti = QCheckBox()
        self.arti.setChecked(self.game.settings.perf_artillery)
        self.arti.toggled.connect(self.applySettings)

        self.moving_units = QCheckBox()
        self.moving_units.setChecked(self.game.settings.perf_moving_units)
        self.moving_units.toggled.connect(self.applySettings)

        self.infantry = QCheckBox()
        self.infantry.setChecked(self.game.settings.perf_infantry)
        self.infantry.toggled.connect(self.applySettings)

        self.destroyed_units = QCheckBox()
        self.destroyed_units.setChecked(self.game.settings.perf_destroyed_units)
        self.destroyed_units.toggled.connect(self.applySettings)

        self.culling = QCheckBox()
        self.culling.setChecked(self.game.settings.perf_culling)
        self.culling.toggled.connect(self.applySettings)

        self.culling_distance = QSpinBox()
        self.culling_distance.setMinimum(10)
        self.culling_distance.setMaximum(10000)
        self.culling_distance.setValue(self.game.settings.perf_culling_distance)
        self.culling_distance.valueChanged.connect(self.applySettings)

        self.culling_do_not_cull_carrier = QCheckBox()
        self.culling_do_not_cull_carrier.setChecked(self.game.settings.perf_do_not_cull_carrier)
        self.culling_do_not_cull_carrier.toggled.connect(self.applySettings)

        self.performanceLayout.addWidget(QLabel("Smoke visual effect on frontline"), 0, 0)
        self.performanceLayout.addWidget(self.smoke, 0, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("SAM starts in RED alert mode"), 1, 0)
        self.performanceLayout.addWidget(self.red_alert, 1, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Artillery strikes"), 2, 0)
        self.performanceLayout.addWidget(self.arti, 2, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Moving ground units"), 3, 0)
        self.performanceLayout.addWidget(self.moving_units, 3, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Generate infantry squads along vehicles"), 4, 0)
        self.performanceLayout.addWidget(self.infantry, 4, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Include destroyed units carcass"), 6, 0)
        self.performanceLayout.addWidget(self.destroyed_units, 6, 1, alignment=Qt.AlignRight)

        self.performanceLayout.addWidget(QHorizontalSeparationLine(), 7, 0, 1, 2)
        self.performanceLayout.addWidget(QLabel("Culling of distant units enabled"), 8, 0)
        self.performanceLayout.addWidget(self.culling, 8, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Culling distance (km)"), 9, 0)
        self.performanceLayout.addWidget(self.culling_distance, 9, 1, alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Do not cull carrier's surroundings"), 10, 0)
        self.performanceLayout.addWidget(self.culling_do_not_cull_carrier, 10, 1, alignment=Qt.AlignRight)

        self.generatorLayout.addWidget(self.gameplay)
        self.generatorLayout.addWidget(QLabel("Disabling settings below may improve performance, but will impact the overall quality of the experience."))
        self.generatorLayout.addWidget(self.performance)


    def initCheatLayout(self):

        self.cheatPage = QWidget()
        self.cheatLayout = QVBoxLayout()
        self.cheatPage.setLayout(self.cheatLayout)

        self.cheat_options = CheatSettingsBox(self.game, self.applySettings)
        self.cheatLayout.addWidget(self.cheat_options)

        self.moneyCheatBox = QGroupBox("Money Cheat")
        self.moneyCheatBox.setAlignment(Qt.AlignTop)
        self.moneyCheatBoxLayout = QGridLayout()
        self.moneyCheatBox.setLayout(self.moneyCheatBoxLayout)

        cheats_amounts = [25, 50, 100, 200, 500, 1000, -25, -50, -100, -200]
        for i, amount in enumerate(cheats_amounts):
            if amount > 0:
                btn = QPushButton("Cheat +" + str(amount) + "M")
                btn.setProperty("style", "btn-success")
            else:
                btn = QPushButton("Cheat " + str(amount) + "M")
                btn.setProperty("style", "btn-danger")
            btn.clicked.connect(self.cheatLambda(amount))
            self.moneyCheatBoxLayout.addWidget(btn, i/2, i%2)  
        self.cheatLayout.addWidget(self.moneyCheatBox, stretch=1)

    def cheatLambda(self, amount):
        return lambda: self.cheatMoney(amount)

    def cheatMoney(self, amount):
        logging.info("CHEATING FOR AMOUNT : " + str(amount) + "M")
        self.game.budget += amount
        if amount > 0:
            self.game.informations.append(Information("CHEATER", "You are a cheater and you should feel bad", self.game.turn))
        else:
            self.game.informations.append(Information("CHEATER", "You are still a cheater !", self.game.turn))
        GameUpdateSignal.get_instance().updateGame(self.game)

    def applySettings(self):
        self.game.settings.player_skill = CONST.SKILL_OPTIONS[self.playerCoalitionSkill.currentIndex()]
        self.game.settings.enemy_skill = CONST.SKILL_OPTIONS[self.enemyCoalitionSkill.currentIndex()]
        self.game.settings.enemy_vehicle_skill = CONST.SKILL_OPTIONS[self.enemyAASkill.currentIndex()]
        self.game.settings.player_income_multiplier = self.player_income.value
        self.game.settings.enemy_income_multiplier = self.enemy_income.value
        self.game.settings.manpads = self.manpads.isChecked()
        self.game.settings.labels = CONST.LABELS_OPTIONS[self.difficultyLabel.currentIndex()]
        self.game.settings.night_disabled = self.noNightMission.isChecked()
        self.game.settings.map_coalition_visibility = self.mapVisibiitySelection.currentData()
        self.game.settings.external_views_allowed = self.ext_views.isChecked()
        self.game.settings.generate_marks = self.generate_marks.isChecked()
        self.game.settings.never_delay_player_flights = self.never_delay_players.isChecked()

        self.game.settings.supercarrier = self.supercarrier.isChecked()

        self.game.settings.perf_red_alert_state = self.red_alert.isChecked()
        self.game.settings.perf_smoke_gen = self.smoke.isChecked()
        self.game.settings.perf_artillery = self.arti.isChecked()
        self.game.settings.perf_moving_units = self.moving_units.isChecked()
        self.game.settings.perf_infantry = self.infantry.isChecked()
        self.game.settings.perf_destroyed_units = self.destroyed_units.isChecked()

        self.game.settings.perf_culling = self.culling.isChecked()
        self.game.settings.perf_culling_distance = int(self.culling_distance.value())
        self.game.settings.perf_do_not_cull_carrier = self.culling_do_not_cull_carrier.isChecked()

        self.game.settings.show_red_ato = self.cheat_options.show_red_ato
        self.game.settings.enable_frontline_cheats = self.cheat_options.show_frontline_cheat
        self.game.settings.enable_base_capture_cheat = self.cheat_options.show_base_capture_cheat

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

    def onSelectionChanged(self):
        index = self.categoryList.selectionModel().currentIndex().row()
        self.right_layout.setCurrentIndex(index)
Esempio n. 9
0
class QSettingsWindow(QDialog):
    def __init__(self, game: Game):
        super(QSettingsWindow, self).__init__()

        self.game = game

        self.setModal(True)
        self.setWindowTitle("Settings")
        self.setWindowIcon(CONST.ICONS["Settings"])
        self.setMinimumSize(600, 250)

        self.initUi()

    def initUi(self):
        self.layout = QGridLayout()

        self.categoryList = QListView()
        self.right_layout = QStackedLayout()

        self.categoryList.setMaximumWidth(175)

        self.categoryModel = QStandardItemModel(self.categoryList)

        difficulty = QStandardItem("Difficulty")
        difficulty.setIcon(CONST.ICONS["Missile"])
        difficulty.setEditable(False)
        difficulty.setSelectable(True)

        generator = QStandardItem("Mission Generator")
        generator.setIcon(CONST.ICONS["Generator"])
        generator.setEditable(False)
        generator.setSelectable(True)

        cheat = QStandardItem("Cheat Menu")
        cheat.setIcon(CONST.ICONS["Cheat"])
        cheat.setEditable(False)
        cheat.setSelectable(True)

        self.categoryList.setIconSize(QSize(32, 32))
        self.categoryModel.appendRow(difficulty)
        self.categoryModel.appendRow(generator)
        self.categoryModel.appendRow(cheat)

        self.categoryList.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.categoryList.setModel(self.categoryModel)
        self.categoryList.selectionModel().setCurrentIndex(
            self.categoryList.indexAt(QPoint(1, 1)),
            QItemSelectionModel.Select)
        self.categoryList.selectionModel().selectionChanged.connect(
            self.onSelectionChanged)

        self.initDifficultyLayout()
        self.initGeneratorLayout()
        self.initCheatLayout()

        self.right_layout.addWidget(self.difficultyPage)
        self.right_layout.addWidget(self.generatorPage)
        self.right_layout.addWidget(self.cheatPage)

        self.layout.addWidget(self.categoryList, 0, 0, 1, 1)
        self.layout.addLayout(self.right_layout, 0, 1, 5, 1)

        self.setLayout(self.layout)

    def init(self):
        pass

    def initDifficultyLayout(self):

        self.difficultyPage = QWidget()
        self.difficultyLayout = QGridLayout()
        self.difficultyLayout.setAlignment(Qt.AlignTop)
        self.difficultyPage.setLayout(self.difficultyLayout)

        self.playerCoalitionSkill = QComboBox()
        self.enemyCoalitionSkill = QComboBox()
        self.enemyAASkill = QComboBox()
        for skill in CONST.SKILL_OPTIONS:
            self.playerCoalitionSkill.addItem(skill)
            self.enemyCoalitionSkill.addItem(skill)
            self.enemyAASkill.addItem(skill)

        self.playerCoalitionSkill.setCurrentIndex(
            CONST.SKILL_OPTIONS.index(self.game.settings.player_skill))
        self.enemyCoalitionSkill.setCurrentIndex(
            CONST.SKILL_OPTIONS.index(self.game.settings.enemy_skill))
        self.enemyAASkill.setCurrentIndex(
            CONST.SKILL_OPTIONS.index(self.game.settings.enemy_vehicle_skill))

        self.playerCoalitionSkill.currentIndexChanged.connect(
            self.applySettings)
        self.enemyCoalitionSkill.currentIndexChanged.connect(
            self.applySettings)
        self.enemyAASkill.currentIndexChanged.connect(self.applySettings)

        self.difficultyLayout.addWidget(QLabel("Player coalition skill"), 0, 0)
        self.difficultyLayout.addWidget(self.playerCoalitionSkill, 0, 1,
                                        Qt.AlignRight)
        self.difficultyLayout.addWidget(QLabel("Enemy skill"), 1, 0)
        self.difficultyLayout.addWidget(self.enemyCoalitionSkill, 1, 1,
                                        Qt.AlignRight)
        self.difficultyLayout.addWidget(QLabel("Enemy AA and vehicles skill"),
                                        2, 0)
        self.difficultyLayout.addWidget(self.enemyAASkill, 2, 1, Qt.AlignRight)

        self.difficultyLabel = QComboBox()
        [self.difficultyLabel.addItem(t) for t in CONST.LABELS_OPTIONS]
        self.difficultyLabel.setCurrentIndex(
            CONST.LABELS_OPTIONS.index(self.game.settings.labels))
        self.difficultyLabel.currentIndexChanged.connect(self.applySettings)

        self.difficultyLayout.addWidget(QLabel("In Game Labels"), 3, 0)
        self.difficultyLayout.addWidget(self.difficultyLabel, 3, 1,
                                        Qt.AlignRight)

        self.noNightMission = QCheckBox()
        self.noNightMission.setChecked(self.game.settings.night_disabled)
        self.noNightMission.toggled.connect(self.applySettings)
        self.difficultyLayout.addWidget(QLabel("No night missions"), 4, 0)
        self.difficultyLayout.addWidget(self.noNightMission, 4, 1,
                                        Qt.AlignRight)

        self.mapVisibiitySelection = QComboBox()
        self.mapVisibiitySelection.addItem("All", ForcedOptions.Views.All)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.All:
            self.mapVisibiitySelection.setCurrentIndex(0)
        self.mapVisibiitySelection.addItem("Fog of War",
                                           ForcedOptions.Views.Allies)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.Allies:
            self.mapVisibiitySelection.setCurrentIndex(1)
        self.mapVisibiitySelection.addItem("Allies Only",
                                           ForcedOptions.Views.OnlyAllies)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.OnlyAllies:
            self.mapVisibiitySelection.setCurrentIndex(2)
        self.mapVisibiitySelection.addItem("Own Aircraft Only",
                                           ForcedOptions.Views.MyAircraft)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.MyAircraft:
            self.mapVisibiitySelection.setCurrentIndex(3)
        self.mapVisibiitySelection.addItem("Map Only",
                                           ForcedOptions.Views.OnlyMap)
        if self.game.settings.map_coalition_visibility == ForcedOptions.Views.OnlyMap:
            self.mapVisibiitySelection.setCurrentIndex(4)
        self.mapVisibiitySelection.currentIndexChanged.connect(
            self.applySettings)
        self.difficultyLayout.addWidget(QLabel("Map visibility options"), 5, 0)
        self.difficultyLayout.addWidget(self.mapVisibiitySelection, 5, 1,
                                        Qt.AlignRight)

        self.ext_views = QCheckBox()
        self.ext_views.setChecked(self.game.settings.external_views_allowed)
        self.ext_views.toggled.connect(self.applySettings)
        self.difficultyLayout.addWidget(QLabel("Allow external views"), 6, 0)
        self.difficultyLayout.addWidget(self.ext_views, 6, 1, Qt.AlignRight)

    def initGeneratorLayout(self):
        self.generatorPage = QWidget()
        self.generatorLayout = QVBoxLayout()
        self.generatorLayout.setAlignment(Qt.AlignTop)
        self.generatorPage.setLayout(self.generatorLayout)

        self.gameplay = QGroupBox("Gameplay")
        self.gameplayLayout = QGridLayout()
        self.gameplayLayout.setAlignment(Qt.AlignTop)
        self.gameplay.setLayout(self.gameplayLayout)

        self.supercarrier = QCheckBox()
        self.supercarrier.setChecked(self.game.settings.supercarrier)
        self.supercarrier.toggled.connect(self.applySettings)

        self.generate_marks = QCheckBox()
        self.generate_marks.setChecked(self.game.settings.generate_marks)
        self.generate_marks.toggled.connect(self.applySettings)

        self.gameplayLayout.addWidget(QLabel("Use Supercarrier Module"), 0, 0)
        self.gameplayLayout.addWidget(self.supercarrier, 0, 1, Qt.AlignRight)
        self.gameplayLayout.addWidget(QLabel("Put Objective Markers on Map"),
                                      1, 0)
        self.gameplayLayout.addWidget(self.generate_marks, 1, 1, Qt.AlignRight)

        self.performance = QGroupBox("Performance")
        self.performanceLayout = QGridLayout()
        self.performanceLayout.setAlignment(Qt.AlignTop)
        self.performance.setLayout(self.performanceLayout)

        self.smoke = QCheckBox()
        self.smoke.setChecked(self.game.settings.perf_smoke_gen)
        self.smoke.toggled.connect(self.applySettings)

        self.red_alert = QCheckBox()
        self.red_alert.setChecked(self.game.settings.perf_red_alert_state)
        self.red_alert.toggled.connect(self.applySettings)

        self.arti = QCheckBox()
        self.arti.setChecked(self.game.settings.perf_artillery)
        self.arti.toggled.connect(self.applySettings)

        self.moving_units = QCheckBox()
        self.moving_units.setChecked(self.game.settings.perf_moving_units)
        self.moving_units.toggled.connect(self.applySettings)

        self.infantry = QCheckBox()
        self.infantry.setChecked(self.game.settings.perf_infantry)
        self.infantry.toggled.connect(self.applySettings)

        self.ai_parking_start = QCheckBox()
        self.ai_parking_start.setChecked(
            self.game.settings.perf_ai_parking_start)
        self.ai_parking_start.toggled.connect(self.applySettings)

        self.culling = QCheckBox()
        self.culling.setChecked(self.game.settings.perf_culling)
        self.culling.toggled.connect(self.applySettings)

        self.culling_distance = QSpinBox()
        self.culling_distance.setMinimum(50)
        self.culling_distance.setMaximum(10000)
        self.culling_distance.setValue(
            self.game.settings.perf_culling_distance)
        self.culling_distance.valueChanged.connect(self.applySettings)

        self.performanceLayout.addWidget(
            QLabel("Smoke visual effect on frontline"), 0, 0)
        self.performanceLayout.addWidget(self.smoke,
                                         0,
                                         1,
                                         alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(
            QLabel("SAM starts in RED alert mode"), 1, 0)
        self.performanceLayout.addWidget(self.red_alert,
                                         1,
                                         1,
                                         alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Artillery strikes"), 2, 0)
        self.performanceLayout.addWidget(self.arti,
                                         2,
                                         1,
                                         alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Moving ground units"), 3, 0)
        self.performanceLayout.addWidget(self.moving_units,
                                         3,
                                         1,
                                         alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(
            QLabel("Generate infantry squads along vehicles"), 4, 0)
        self.performanceLayout.addWidget(self.infantry,
                                         4,
                                         1,
                                         alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(
            QLabel(
                "AI planes parking start (AI starts in flight if disabled)"),
            5, 0)
        self.performanceLayout.addWidget(self.ai_parking_start,
                                         5,
                                         1,
                                         alignment=Qt.AlignRight)

        self.performanceLayout.addWidget(QHorizontalSeparationLine(), 6, 0, 1,
                                         2)
        self.performanceLayout.addWidget(
            QLabel("Culling of distant units enabled"), 7, 0)
        self.performanceLayout.addWidget(self.culling,
                                         7,
                                         1,
                                         alignment=Qt.AlignRight)
        self.performanceLayout.addWidget(QLabel("Culling distance (km)"), 8, 0)
        self.performanceLayout.addWidget(self.culling_distance,
                                         8,
                                         1,
                                         alignment=Qt.AlignRight)

        self.generatorLayout.addWidget(self.gameplay)
        self.generatorLayout.addWidget(
            QLabel(
                "Disabling settings below may improve performance, but will impact the overall quality of the experience."
            ))
        self.generatorLayout.addWidget(self.performance)

    def initCheatLayout(self):

        self.cheatPage = QWidget()
        self.cheatLayout = QGridLayout()
        self.cheatPage.setLayout(self.cheatLayout)

        self.moneyCheatBox = QGroupBox("Money Cheat")
        self.moneyCheatBox.setAlignment(Qt.AlignTop)
        self.moneyCheatBoxLayout = QGridLayout()
        self.moneyCheatBox.setLayout(self.moneyCheatBoxLayout)

        self.cheat25M = QPushButton("Cheat +25M")
        self.cheat50M = QPushButton("Cheat +50M")
        self.cheat100M = QPushButton("Cheat +100M")
        self.cheat200M = QPushButton("Cheat +200M")
        self.cheat500M = QPushButton("Cheat +500M")
        self.cheat1000M = QPushButton("Cheat +1000M")

        self.cheat25M.clicked.connect(lambda: self.cheatMoney(25))
        self.cheat50M.clicked.connect(lambda: self.cheatMoney(50))
        self.cheat100M.clicked.connect(lambda: self.cheatMoney(100))
        self.cheat200M.clicked.connect(lambda: self.cheatMoney(200))
        self.cheat500M.clicked.connect(lambda: self.cheatMoney(500))
        self.cheat1000M.clicked.connect(lambda: self.cheatMoney(1000))

        self.moneyCheatBoxLayout.addWidget(self.cheat25M, 0, 0)
        self.moneyCheatBoxLayout.addWidget(self.cheat50M, 0, 1)
        self.moneyCheatBoxLayout.addWidget(self.cheat100M, 1, 0)
        self.moneyCheatBoxLayout.addWidget(self.cheat200M, 1, 1)
        self.moneyCheatBoxLayout.addWidget(self.cheat500M, 2, 0)
        self.moneyCheatBoxLayout.addWidget(self.cheat1000M, 2, 1)

        self.cheatLayout.addWidget(self.moneyCheatBox, 0, 0)

    def cheatMoney(self, amount):
        self.game.budget += amount
        self.game.informations.append(
            Information("CHEATER", "You are a cheater and you should feel bad",
                        self.game.turn))
        GameUpdateSignal.get_instance().updateGame(self.game)

    def applySettings(self):
        self.game.settings.player_skill = CONST.SKILL_OPTIONS[
            self.playerCoalitionSkill.currentIndex()]
        self.game.settings.enemy_skill = CONST.SKILL_OPTIONS[
            self.enemyCoalitionSkill.currentIndex()]
        self.game.settings.enemy_vehicle_skill = CONST.SKILL_OPTIONS[
            self.enemyAASkill.currentIndex()]
        self.game.settings.labels = CONST.LABELS_OPTIONS[
            self.difficultyLabel.currentIndex()]
        self.game.settings.night_disabled = self.noNightMission.isChecked()
        self.game.settings.map_coalition_visibility = self.mapVisibiitySelection.currentData(
        )
        self.game.settings.external_views_allowed = self.ext_views.isChecked()
        self.game.settings.generate_marks = self.generate_marks.isChecked()

        print(self.game.settings.map_coalition_visibility)

        self.game.settings.supercarrier = self.supercarrier.isChecked()

        self.game.settings.perf_red_alert_state = self.red_alert.isChecked()
        self.game.settings.perf_smoke_gen = self.smoke.isChecked()
        self.game.settings.perf_artillery = self.arti.isChecked()
        self.game.settings.perf_moving_units = self.moving_units.isChecked()
        self.game.settings.perf_infantry = self.infantry.isChecked()
        self.game.settings.perf_ai_parking_start = self.ai_parking_start.isChecked(
        )

        self.game.settings.perf_culling = self.culling.isChecked()
        self.game.settings.perf_culling_distance = int(
            self.culling_distance.value())

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

    def onSelectionChanged(self):
        index = self.categoryList.selectionModel().currentIndex().row()
        self.right_layout.setCurrentIndex(index)
Esempio n. 10
0
class JointStatePublisherGui(QWidget):
    sliderUpdateTrigger = Signal()

    def __init__(self, title, jsp, num_rows=0):
        super(JointStatePublisherGui, self).__init__()
        self.jsp = jsp
        self.joint_map = {}
        self.vlayout = QVBoxLayout(self)
        self.scrollable = QWidget()
        self.gridlayout = QGridLayout()
        self.scroll = QScrollArea()
        self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.scroll.setWidgetResizable(True)

        font = QFont("Helvetica", 9, QFont.Bold)

        ### Generate sliders ###
        sliders = []
        for name in self.jsp.joint_list:
            if name not in self.jsp.free_joints:
                continue
            joint = self.jsp.free_joints[name]

            if joint['min'] == joint['max']:
                continue

            joint_layout = QVBoxLayout()
            row_layout = QHBoxLayout()

            label = QLabel(name)
            label.setFont(font)
            row_layout.addWidget(label)
            display = QLineEdit("0.00")
            display.setAlignment(Qt.AlignRight)
            display.setFont(font)
            display.setReadOnly(True)
            row_layout.addWidget(display)

            joint_layout.addLayout(row_layout)

            slider = QSlider(Qt.Horizontal)

            slider.setFont(font)
            slider.setRange(0, RANGE)
            slider.setValue(RANGE / 2)

            joint_layout.addWidget(slider)

            self.joint_map[name] = {
                'slidervalue': 0,
                'display': display,
                'slider': slider,
                'joint': joint
            }
            # Connect to the signal provided by QSignal
            slider.valueChanged.connect(self.onValueChanged)
            sliders.append(joint_layout)

        # Determine number of rows to be used in grid
        self.num_rows = num_rows
        # if desired num of rows wasn't set, default behaviour is a vertical layout
        if self.num_rows == 0:
            self.num_rows = len(sliders)  # equals VBoxLayout
        # Generate positions in grid and place sliders there
        self.positions = self.generate_grid_positions(len(sliders),
                                                      self.num_rows)
        for item, pos in zip(sliders, self.positions):
            self.gridlayout.addLayout(item, *pos)

        # Set zero positions read from parameters
        self.center()

        # Synchronize slider and displayed value
        self.sliderUpdate(None)

        # Set up a signal for updating the sliders based on external joint info
        self.sliderUpdateTrigger.connect(self.updateSliders)

        self.scrollable.setLayout(self.gridlayout)
        self.scroll.setWidget(self.scrollable)
        self.vlayout.addWidget(self.scroll)

        # Buttons for randomizing and centering sliders and
        # Spinbox for on-the-fly selecting number of rows
        self.randbutton = QPushButton('Randomize', self)
        self.randbutton.clicked.connect(self.randomize_event)
        self.vlayout.addWidget(self.randbutton)
        self.ctrbutton = QPushButton('Center', self)
        self.ctrbutton.clicked.connect(self.center_event)
        self.vlayout.addWidget(self.ctrbutton)
        self.maxrowsupdown = QSpinBox()
        self.maxrowsupdown.setMinimum(1)
        self.maxrowsupdown.setMaximum(len(sliders))
        self.maxrowsupdown.setValue(self.num_rows)
        self.maxrowsupdown.lineEdit().setReadOnly(
            True)  # don't edit it by hand to avoid weird resizing of window
        self.maxrowsupdown.valueChanged.connect(self.reorggrid_event)
        self.vlayout.addWidget(self.maxrowsupdown)
        self.setLayout(self.vlayout)

    @pyqtSlot(int)
    def onValueChanged(self, event):
        # A slider value was changed, but we need to change the joint_info metadata.
        for name, joint_info in self.joint_map.items():
            joint_info['slidervalue'] = joint_info['slider'].value()
            joint = joint_info['joint']
            joint['position'] = self.sliderToValue(joint_info['slidervalue'],
                                                   joint)
            joint_info['display'].setText("%.2f" % joint['position'])

    @pyqtSlot()
    def updateSliders(self):
        self.update_sliders()

    def update_sliders(self):
        for name, joint_info in self.joint_map.items():
            joint = joint_info['joint']
            joint_info['slidervalue'] = self.valueToSlider(
                joint['position'], joint)
            joint_info['slider'].setValue(joint_info['slidervalue'])

    def center_event(self, event):
        self.center()

    def center(self):
        rospy.loginfo("Centering")
        for name, joint_info in self.joint_map.items():
            joint = joint_info['joint']
            joint_info['slider'].setValue(
                self.valueToSlider(joint['zero'], joint))

    def reorggrid_event(self, event):
        self.reorganize_grid(event)

    def reorganize_grid(self, number_of_rows):
        self.num_rows = number_of_rows

        # Remove items from layout (won't destroy them!)
        items = []
        for pos in self.positions:
            item = self.gridlayout.itemAtPosition(*pos)
            items.append(item)
            self.gridlayout.removeItem(item)

        # Generate new positions for sliders and place them in their new spots
        self.positions = self.generate_grid_positions(len(items),
                                                      self.num_rows)
        for item, pos in zip(items, self.positions):
            self.gridlayout.addLayout(item, *pos)

    def generate_grid_positions(self, num_items, num_rows):
        if num_rows == 0:
            return []
        positions = [
            (y, x)
            for x in range(int((math.ceil(float(num_items) / num_rows))))
            for y in range(num_rows)
        ]
        positions = positions[:num_items]
        return positions

    def randomize_event(self, event):
        self.randomize()

    def randomize(self):
        rospy.loginfo("Randomizing")
        for name, joint_info in self.joint_map.items():
            joint = joint_info['joint']
            joint_info['slider'].setValue(
                self.valueToSlider(random.uniform(joint['min'], joint['max']),
                                   joint))

    def sliderUpdate(self, event):
        for name, joint_info in self.joint_map.items():
            joint_info['slidervalue'] = joint_info['slider'].value()
        self.update_sliders()

    def valueToSlider(self, value, joint):
        return (value - joint['min']) * float(RANGE) / (joint['max'] -
                                                        joint['min'])

    def sliderToValue(self, slider, joint):
        pctvalue = slider / float(RANGE)
        return joint['min'] + (joint['max'] - joint['min']) * pctvalue
Esempio n. 11
0
class TeamworkPropertiesDialog(QDialog):
    def __init__(self):
        super().__init__(GlobalAccess().get_main_window())
        self.time_format = 'hh:mm:ss'

    def exec_(self):
        self.init_ui()
        return super().exec_()

    def init_ui(self):
        # self.setFixedWidth(500)
        self.setWindowTitle(_('Teamwork'))
        # self.setWindowIcon(QIcon(icon_dir('sportident.png')))
        self.setSizeGripEnabled(False)
        self.setModal(True)

        self.tab_widget = QTabWidget()

        # client/server
        self.teamwork_tab = QWidget()
        self.teamwork_layout = QFormLayout()
        self.teamwork_item_host = QLineEdit()
        self.teamwork_item_port = QSpinBox()
        self.teamwork_item_port.setMinimum(0)
        self.teamwork_item_port.setMaximum(65535)
        self.teamwork_item_token = QLineEdit()
        self.teamwork_groupbox = QGroupBox()
        self.teamwork_groupbox.setTitle(_('Type connection'))
        self.teamwork_groupbox_layout = QFormLayout()
        self.teamwork_item_client = QRadioButton(_('Client'))
        self.teamwork_item_server = QRadioButton(_('Server'))
        self.teamwork_groupbox_layout.addRow(self.teamwork_item_client)
        self.teamwork_groupbox_layout.addRow(self.teamwork_item_server)
        self.teamwork_groupbox.setLayout(self.teamwork_groupbox_layout)

        self.teamwork_layout.addRow(QLabel(_('Host')), self.teamwork_item_host)
        self.teamwork_layout.addRow(QLabel(_('Port')), self.teamwork_item_port)
        # self.teamwork_layout.addRow(QLabel(_('Token')), self.teamwork_item_token)
        self.teamwork_layout.addRow(self.teamwork_groupbox)
        self.teamwork_tab.setLayout(self.teamwork_layout)

        self.tab_widget.addTab(self.teamwork_tab, _('Client/Server'))

        def cancel_changes():
            self.close()

        def apply_changes():
            try:
                self.apply_changes_impl()
            except Exception as e:
                logging.error(str(e))
            self.close()

        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        self.button_ok = button_box.button(QDialogButtonBox.Ok)
        self.button_ok.setText(_('OK'))
        self.button_ok.clicked.connect(apply_changes)
        self.button_cancel = button_box.button(QDialogButtonBox.Cancel)
        self.button_cancel.setText(_('Cancel'))
        self.button_cancel.clicked.connect(cancel_changes)

        self.layout = QFormLayout(self)
        self.layout.addRow(self.tab_widget)
        self.layout.addRow(button_box)

        self.set_values_from_model()

        self.show()

    def set_values_from_model(self):
        obj = race()

        # teamwork
        teamwork_host = obj.get_setting('teamwork_host', 'localhost')
        teamwork_port = obj.get_setting('teamwork_port', 50010)
        teamwork_token = obj.get_setting('teamwork_token',
                                         str(uuid.uuid4())[:8])
        teamwork_type_connection = obj.get_setting('teamwork_type_connection',
                                                   'client')

        self.teamwork_item_host.setText(teamwork_host)
        self.teamwork_item_port.setValue(teamwork_port)
        self.teamwork_item_token.setText(teamwork_token)
        if teamwork_type_connection == 'client':
            self.teamwork_item_client.setChecked(True)
        elif teamwork_type_connection == 'server':
            self.teamwork_item_server.setChecked(True)

    def apply_changes_impl(self):
        obj = race()

        # teamwork
        teamwork_host = self.teamwork_item_host.text()
        teamwork_port = self.teamwork_item_port.value()
        teamwork_token = self.teamwork_item_token.text()
        teamwork_type_connection = 'client'
        if self.teamwork_item_server.isChecked():
            teamwork_type_connection = 'server'

        obj.set_setting('teamwork_host', teamwork_host)
        obj.set_setting('teamwork_port', teamwork_port)
        obj.set_setting('teamwork_token', teamwork_token)
        obj.set_setting('teamwork_type_connection', teamwork_type_connection)
Esempio n. 12
0
class MainWindow(QMainWindow, design.Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        # Уточнить необходимость наличия (если краши - удалить)
        self.dialog = None

        self.spinbox = []
        self.doublebox = []
        self.box_row = None

        self.baseInfo.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.resultTable.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.addItemBtn.clicked.connect(self.add_new_element)
        self.addXlsBtn.clicked.connect(self.input_database)
        self.changeItemBtn.clicked.connect(self.change_item)
        self.deleteBaseBtn.clicked.connect(self.delete_base)
        self.deleteItemBtn.clicked.connect(self.delete_item_from_base)
        self.printBtn.clicked.connect(self.print_specification)
        self.workBtn.clicked.connect(self.upd_result_table)

        self.BDBox.currentTextChanged.connect(self.show_chosen_bd)
        self.categoryBox.currentTextChanged.connect(self.current_text_changed)
        self.countryBox.currentTextChanged.connect(self.current_text_changed)

        self.listWidget.itemChanged.connect(self.item_selection_changed)

        self.create_bd.triggered.connect(self.clear_all)
        self.exit_action.triggered.connect(sys.exit)
        self.load_bd.triggered.connect(self.load_xls)
        self.save_bd.triggered.connect(self.save_xls)

        self.baseInfo.cellClicked.connect(self.signal_delete)

        self.ru_lang.toggled.connect(self.change_language_in_table)

    def add_new_element(self):
        # Вызывает класс добавления нового элемента и, если успешно, обновляет отображаемую таблицу
        index_base = self.BDBox.currentIndex()
        self.dialog = AddElementClass([index_base])

        if self.dialog.exec() == QDialog.Accepted:
            self.show_chosen_bd()

    def algo(self, df):
        # bug скорее всего, достаточно заменить название на RU, роли не играет же?
        df['Итог'] = 1

        sum_res = self.maxValue.text()
        sum_res = float(sum_res.replace(",", "."))

        for item in range(len(df['цена $'])):
            if ',' in str(df['цена $'].iloc[item]):
                df['цена $'].iloc[item] = str(df['цена $'].iloc[item]).replace(',', '.')
        df['цена $'] = df['цена $'].astype(float)
        df['Количество'] = df['Количество'].astype(int)
        items_ratio = 3.5  # Допустимое отношение максимального кол-ва элементов к минимальному
        price_ratio = 0.01  # Допустимое различие между заданной и полученной суммой

        finish = True
        max_item = sys.maxsize
        max_name = None

        # Проверка на достижимость суммы выбранным поддатасетом?
        df['total'] = df['Количество'] * df['цена $']
        agg = df['total'].aggregate(np.sum)
        if agg < sum_res:
            print("Ne, dont work")  # Соответственно, вопрос к обработке
            return

        agg = df['цена $'].aggregate(np.sum)
        if agg > sum_res:
            print("Always too much")
            return

        prob = LpProblem('Sell', LpMaximize)  # Objective function

        if self.ru_lang.isChecked():
            inv_items = list(df['Название RU'])  # Variable name
        else:
            inv_items = list(df['Name EN'])
        inv_items.sort()

        items = dict(zip(inv_items, df['Количество']))  # Function
        prices = dict(zip(inv_items, df['цена $']))

        inv_vars = LpVariable.dicts('Var', inv_items, lowBound=1, cat='Integer')

        prob += lpSum([prices[i] * inv_vars[i] for i in inv_items])
        prob += lpSum([prices[i] * inv_vars[i] for i in inv_items]) <= sum_res, 'Общая функция'

        for val in items:
            prob += inv_vars[val] <= items[val], val+' Demand'

        # values_check = [None,None]
        values_list = []
        old_values = None
        while finish:
            if max_name:
                prob += inv_vars[max_name] <= max_item

            prob.solve()
            values_list = []

            print('The optimal answer\n'+'-'*70)
            for v in prob.variables():
                item = v.varValue
                if item > 0:
                    values_list.append(item)

            if len(values_list) < len(inv_items):
                '''
                Причина, почему просто вернуть:
                Можно было бы обработать, но продавать одновременно одни и те же
                позиции, но с разными ценами/кол-вом - бред. Поэтому просто
                вернуть и не обращать внимания.
                '''
                print("баг с одинаковыми названиями")
                return

            max_item = max(values_list) - 1
            balance = float(max_item / min(values_list))
            max_name = inv_items[values_list.index(max(values_list))]
            print(values_list, max_item, max_name)

            t = list(prices.values())

            if len(values_list) == len(t):
                price_res = [t[i] * values_list[i] for i in range(len(t))]
                price_res = sum(price_res)

            else:
                # В настройках функции стоит, что минимум должен быть один элемент.
                # Если уже меньше, чем нужно - то значит 100% ошибка. Значит выходим.
                print("Обыграть перевызов функции с новым датасетом")
                return

            if old_values == values_list:
                '''
                Тут два варианта развития событий:
                1. Утыкаемся в невозможность на второй итерации. Во времени
                не теряем, так что можно и вывести результаты.
                2. Важнее, но маловероятнее - если долго считаем и упираемся.
                Обидно терять прогресс, лучше вывести что получилось.
                '''
                print("Stop NOW")
                if price_res < sum_res:
                    finish = False
                else:
                    return

            self.result_label.setText(str(('%.2f' % price_res)))
            curr_price_ratio = (sum_res - price_res) / sum_res
            if balance <= items_ratio and curr_price_ratio <= price_ratio:
                finish = False

            old_values = values_list

        print("Ответ:") # пока что, для отладки
        for i in range(len(values_list)):
            print(inv_items[i], ":, ", values_list[i])

        return values_list

    def change_item(self):
        #name = self.BDBox.currentText()
        #index_base = listOfXls.loc[listOfXls['Name'] == name]
        #index_base = index_base.index[0]
        index_base = self.return_index()
        #index_base = self.BDBox.currentIndex()

        index_row = self.baseInfo.currentRow()
        modified_row = base[index_base].loc[index_row]
        modified_row = modified_row.to_list()
        modified_row.insert(0, index_base)
        modified_row.insert(1, index_row)

        self.dialog = AddElementClass(modified_row)

        if self.dialog.exec() == QDialog.Accepted:
            self.show_chosen_bd()
            self.changeItemBtn.setEnabled(False)
            self.deleteItemBtn.setEnabled(False)

    def change_language_in_table(self):
        # Переключает язык в базе, если там есть элементы
        self.changeItemBtn.setEnabled(False)
        self.deleteItemBtn.setEnabled(False)
        if self.baseInfo.rowCount() > 0:
            self.show_chosen_bd()
        return

    def clear_all(self):
        # Функция для создания новой сессии
        global listOfXls
        self.categoryBox.blockSignals(True)
        self.countryBox.blockSignals(True)
        self.BDBox.blockSignals(True)

        if len(base) > 0:
            msg = QMessageBox.question(self, "Новая сессия",
                                             "Вы действительно хотите начать работу с новой базой?",
                                             QMessageBox.Yes | QMessageBox.No)

            if msg == QMessageBox.No:
                self.categoryBox.blockSignals(False)
                self.countryBox.blockSignals(False)
                self.BDBox.blockSignals(False)
                return

        base.clear()
        listOfXls = listOfXls[0:0]
        countries.clear()
        categories.clear()
        self.update_boxes()
        self.update_list(listOfXls)
        self.categoryBox.blockSignals(False)
        self.countryBox.blockSignals(False)
        self.BDBox.setEnabled(False)
        self.BDBox.blockSignals(False)

        self.workBtn.setEnabled(False)
        self.printBtn.setEnabled(False)
        self.deleteBaseBtn.setEnabled(False)
        self.addItemBtn.setEnabled(False)
        self.changeItemBtn.setEnabled(False)
        self.deleteItemBtn.setEnabled(False)
        self.langBox.setEnabled(False)
        self.baseInfo.setRowCount(0)

        self.resultTable.setRowCount(0)
        self.positions.setValue(1)
        self.maxValue.setValue(1.00)
        self.result_label.setText("")

    def current_text_changed(self):
        # Переопределение функции выбранного элемента комбобокса
        # для заполнения срезами таблицы listOfXls
        print("changed")
        current_category = self.categoryBox.currentText()
        current_country = self.countryBox.currentText()

        temp_df = listOfXls  # проверить насчёт копии

        if current_category != 'Все':
            temp_df = temp_df[temp_df.Category.astype(str).str.contains(current_category)]
        if current_country != 'Все':
            temp_df = temp_df[temp_df.Country.astype(str).str.contains(current_country)]
        temp_df = temp_df.reset_index()
        if not temp_df.empty:
            self.update_list(temp_df)
        else:
            self.listWidget.clear()

        self.update_bd_list(temp_df)
        return
        # Нумерация остаётся как взяли (т.е. 2,5... вместо 0,1...). Норм?

    def delete_base(self):
        global listOfXls
        msg = QMessageBox.question(self, 'Удаление базы',
                                   'Вы действительно хотите удалить эту базу?',
                                   QMessageBox.Yes | QMessageBox.No)

        if msg == QMessageBox.Yes:
            index_base = self.BDBox.currentIndex() - 1
            base.pop(index_base)
            listOfXls.drop(index_base, inplace=True)
            listOfXls = listOfXls.reset_index(drop=True)
            self.update_boxes()
            self.update_list()
            if len(base) == 0:
                self.workBtn.setEnabled(False)
                self.printBtn.setEnabled(False)

    def delete_item_from_base(self):
        #index_base = self.BDBox.currentIndex()

        #name = self.BDBox.currentText()
        #index_base = listOfXls.loc[listOfXls['Name'] == name]
        #index_base = index_base.index[0]
        index_base = self.return_index()

        index_item = self.baseInfo.currentRow()
        if index_item >= 0:
            base[index_base] = base[index_base].drop(index=index_item).reset_index(drop=True)
            self.baseInfo.removeRow(index_item)
            if len(base[index_base]) == 0:
                self.changeItemBtn.setEnabled(False)
                self.deleteItemBtn.setEnabled(False)

    def input_database(self):
        self.dialog = InputDBClass()
        # Блокируем сигналы, чтобы нормально заполнялись боксы после их изменений
        self.categoryBox.blockSignals(True)
        self.countryBox.blockSignals(True)

        if self.dialog.exec() == QDialog.Accepted:
            self.update_boxes()
            self.update_list()
            self.BDBox.setEnabled(True)
            self.current_text_changed()
            self.workBtn.setEnabled(True)
            # self.update_bd_list()

        self.categoryBox.blockSignals(False)
        self.countryBox.blockSignals(False)

    def item_selection_changed(self, item):
        # Изменение состояния "включения" в базе (галочки в листбоксе)
        item_index = listOfXls.loc[listOfXls['Name'] == item.text()]
        item_index = item_index.index[0]

        if not item.checkState():
            listOfXls['Activated'].iloc[item_index] = False
        else:
            listOfXls['Activated'].iloc[item_index] = True

    def load_xls(self):
        global base, listOfXls, countries, categories
        self.categoryBox.blockSignals(True)
        self.countryBox.blockSignals(True)

        bd_path = QFileDialog.getOpenFileName(self, "Выберите БД", filter="*.xlsx")
        if bd_path[0]:
            if not listOfXls.empty:
                self.clear_all()
            bd_item = pd.ExcelFile(bd_path[0], engine='openpyxl')
            listOfXls = pd.concat([listOfXls, bd_item.parse('info')]).copy()

            categories = listOfXls.Category.unique().tolist()
            countries = listOfXls.Country.unique().tolist()
            categories = list(map(str, categories))
            countries = list(map(str, countries))
            for it in listOfXls.index:
                name = listOfXls.Name[it]
                new_base = bd_item.parse(name)
                base.append(new_base)
            self.update_list()
            self.update_boxes()
            self.BDBox.setEnabled(True)
            self.workBtn.setEnabled(True)
            self.langBox.setEnabled(True)
            self.current_text_changed()

        self.categoryBox.blockSignals(False)
        self.countryBox.blockSignals(False)

    def print_specification(self):
        doc = DocxTemplate("Data\Templates\spec_template.docx")
        date = datetime.today().strftime('%d.%m.%Y')
        tbl_contents = []

        num_rows = self.resultTable.rowCount()
        for i in range(num_rows):
            label = i+1
            name = self.resultTable.item(i, 0).text()
            piece = "шт/ рс"
            #nums = self.resultTable.item(i, 1).text()
            nums = self.spinbox[i].value()
            #price = self.resultTable.item(i, 2).text()
            price = self.doublebox[i].value()
            total = self.resultTable.item(i, 3).text()
            tbl_contents.append({'label': label, 'cols': [name, piece, nums, price, total]})

        total_price = ('%.2f' % float(self.result_label.text()))
        context = {'date': date,
                   'total_price': total_price,
                   'tbl_contents': tbl_contents}
        doc.render(context)

        doc_result = QFileDialog.getSaveFileName(self, "Сохраните файл:", filter="*.docx")
        if doc_result[0]:
            doc.save(doc_result[0])
            QMessageBox.information(self, "Сохранение файла", "Файл сохранён успешно!")
            os.startfile(doc_result[0])

    def return_index(self):
        name = self.BDBox.currentText()
        index_base = listOfXls.loc[listOfXls['Name'] == name]
        index_base = index_base.index[0]
        return index_base

    def save_xls(self):
        if not base:  # base = []
            return
        xls_result = QFileDialog.getSaveFileName(self, "Сохраните файл:", filter="*.xlsx")
        if xls_result[0]:
            with pd.ExcelWriter(xls_result[0]) as writer:
                listOfXls.to_excel(writer, sheet_name='info', index=False)
                for table in range(len(base)):
                    table_name = listOfXls.iloc[table].Name
                    base[table].to_excel(writer, sheet_name=table_name, index=False)

    def set_item(self, item, status):
        # Пока просто выставляет пустой элемент, переписать под заполнение
        # из класса InputDBClass

        # Каким образом - смотреть, что выбрано в категориях и делать срез
        # с пандаса и вставлять его поэлементно
        # Подумать на тему того, чтобы изначально был пункт "Все",
        # и как это красиво можно связать со структурами
        # (в плане редактирования, чтобы не удалить случайно)
        checkbox_item = QListWidgetItem(item)
        checkbox_item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
        if status:
            checkbox_item.setCheckState(Qt.Checked)
        else:
            checkbox_item.setCheckState(Qt.Unchecked)
        self.listWidget.addItem(checkbox_item)

    def show_chosen_bd(self):
        name = self.BDBox.currentText()
        index = listOfXls.loc[listOfXls['Name'] == name]
        if not index.empty:
            self.deleteBaseBtn.setEnabled(True)
            self.addItemBtn.setEnabled(True)
            self.langBox.setEnabled(True)
            self.baseInfo.setRowCount(0)
            self.baseInfo.clearContents()
            self.baseInfo.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
            self.baseInfo.setColumnWidth(1, 80)
            self.baseInfo.setColumnWidth(2, 80)
            index = index.index[0]
            target = base[index]
            for i, row in target.iterrows():
                # row_name = row['Название']
                if self.ru_lang.isChecked():
                    row_name = row['Название RU']
                else:
                    row_name = row['Name EN']
                row_number = str(int(row['Количество']))

                row_price = str(row['цена $'])
                if "," in row_price:
                    row_price = str(row['цена $']).replace(',', '.')
                    row_price = float(row_price)
                    row_price = str(f"{row_price:.{2}f}")
                row_price = row_price.replace('.', ',')
                self.baseInfo.setRowCount(i+1)
                self.baseInfo.setItem(i, 0, QTableWidgetItem(row_name))
                self.baseInfo.setItem(i, 1, QTableWidgetItem(row_number))
                self.baseInfo.setItem(i, 2, QTableWidgetItem(row_price))
        else:
            self.baseInfo.setRowCount(0)
            self.changeItemBtn.setEnabled(False)
            self.deleteItemBtn.setEnabled(False)
            self.deleteBaseBtn.setEnabled(False)
            self.addItemBtn.setEnabled(False)

    def signal_delete(self):
        # Фиксирует сигнал нажатие на элемент подбазы и даёт доступ
        # на редактирование\удаление элемента (если было недоступно)
        self.changeItemBtn.setEnabled(True)
        self.deleteItemBtn.setEnabled(True)

    def update_bd_list(self, df):
        # Функция для обновления списка баз в комбобоксе BDBox (самый правый)
        self.categoryBox.blockSignals(True)

        self.BDBox.clear()
        self.BDBox.addItem("Выберите базу...")
        name = df['Name']
        if not name.empty:
            self.BDBox.setEnabled(True)
            for item in name:
                self.BDBox.addItem(item)
        else:
            self.BDBox.setEnabled(False)
        self.categoryBox.blockSignals(False)

    def update_boxes(self):
        # Функция, вызываемая при добавлении\изменении категориальных признаков
        # для обновления списков на главном окне
        self.categoryBox.clear()
        self.categoryBox.addItem("Все")

        for item in categories:
            self.categoryBox.addItem(item)

        self.countryBox.clear()
        self.countryBox.addItem("Все")
        for item in countries:
            self.countryBox.addItem(item)

    def update_list(self, *args):
        # Функция для вывода списка (по фильтрам)
        if args:
            db = args[0]
        else:
            db = listOfXls

        self.listWidget.clear()
        for item in range(len(db)):
            name = db.loc[item].Name
            status = db.loc[item].Activated
            self.set_item(name, status)

    def upd_result_table(self):
        """
        В чём суть: сначала формируем общий фрейм, откуда брать вырезку.
        Вырезка берётся как df.sample(n=count), count = число позиций
        Соответственно, берем только те, которые "включены"
        И, наверное, добавляется столбец с индексом/названием, чтобы потом
        взять и изменить количество при необходимости в исходном месте

        Сразу же: надо сделать так, чтобы нельзя было запросить позиций
        больше, чем есть в проге. То есть, сейчас лимит 20, а пускай у нас
        лежит 5 позиций. И чтобы не было такого, мол max = размер если меньше 20.

        """
        self.spinbox = []
        self.doublebox = []

        activated = listOfXls[listOfXls.Activated.astype(str).str.contains('True')]
        if activated.empty:
            QMessageBox.warning(self, "Ошибка", "Ни одна база не активна", QMessageBox.Ok)
            return
        self.result_label.setText("")
        finish_alg = False
        count_tries = 0
        while not finish_alg:
            if count_tries > 20:
                QMessageBox.warning(self, "Ошибка", "Не считается:( Возможно, что-то не так с данными", QMessageBox.Ok)
                self.printBtn.setEnabled(False)
                return

            full_list = base[0].copy()
            full_list = full_list[0:0]
            for it in activated.index:
                full_list = pd.concat([full_list, base[it]]).copy()

            count = int(self.positions.text())

            # print(full_list.sample(n = count))
            self.resultTable.setRowCount(0)

            if len(full_list) < count:
                QMessageBox.warning(self, "Ошибка", "Позиций в базах меньше, чем запрашивается", QMessageBox.Ok)
                return

            full_list = full_list.sample(n=count)
            # Возможно, индексы надо и сохранить, но тут хз
            full_list = full_list.reset_index()



            # А тут идёт блок расчётов, потому что заполнять нужно с итогом
            '''
            import tkinter.messagebox
            try:
                nums = self.algo(full_list)
                tkinter.messagebox.showinfo('Save', 'Ok')
            except:
                import traceback
                tkinter.messagebox.showinfo("ERROR", traceback.format_exc())
                raise
            '''
            nums = self.algo(full_list)
            if nums:
                for i, row in full_list.iterrows():
                    row_name = row['Название RU'] + '/' + row['Name EN']
                    row_number = str(int(nums[i]))

                    row_price = str('%.2f' % row['цена $'])

                    total = row['цена $']*int(nums[i])
                    total = ('%.2f' % total)
                    row_total = str(total)

                    self.resultTable.setRowCount(self.resultTable.rowCount() + 1)
                    self.resultTable.setItem(i, 0, QTableWidgetItem(row_name))
                    # self.resultTable.setItem(i, 1, QTableWidgetItem(row_number))
                    # self.resultTable.setItem(i, 2, QTableWidgetItem(row_price))

                    self.cur_sbox = QSpinBox()
                    self.cur_sbox.setMinimum(1)
                    self.cur_sbox.setMaximum(99999)
                    self.cur_sbox.setValue(int(row_number))
                    self.resultTable.setCellWidget(i, 1, self.cur_sbox)
                    self.spinbox.append(self.cur_sbox)

                    self.cur_dbox = QDoubleSpinBox()
                    self.cur_dbox.setMaximum(99999999.99)
                    self.cur_dbox.setValue(float(row_price))
                    self.resultTable.setCellWidget(i, 2, self.cur_dbox)
                    self.doublebox.append(self.cur_dbox)

                    self.cur_sbox.valueChanged.connect(self.spins_changed)
                    self.cur_dbox.valueChanged.connect(self.spins_changed)

                    self.resultTable.setItem(i, 3, QTableWidgetItem(row_total))

                finish_alg = True
            count_tries += 1
        self.printBtn.setEnabled(True)
        self.resultTable.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.resultTable.setColumnWidth(1, 80)
        self.resultTable.setColumnWidth(2, 80)
        self.resultTable.setColumnWidth(3, 80)

    def spins_changed(self, value):
        row = self.resultTable.currentRow()
        num = self.spinbox[row].value()
        price = self.doublebox[row].value()
        total = int(num) * float(price)
        total = ('%.2f' % total)
        row_total = str(total)
        self.resultTable.setItem(row, 3, QTableWidgetItem(row_total))

        sum_price = 0
        for i in range(0, self.resultTable.rowCount()):
            price_pack = self.resultTable.item(i, 3)
            price_pack = price_pack.text()
            sum_price += float(price_pack)
        self.result_label.setText(str(sum_price))
        '''
Esempio n. 13
0
class CloningWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(CloningWidget, self).__init__(parent)

        self.detector_combo = QComboBox()
        self.detector_combo.addItems(
            [self.tr('BRISK'),
             self.tr('ORB'),
             self.tr('AKAZE')])
        self.detector_combo.setCurrentIndex(0)
        self.detector_combo.setToolTip(
            self.tr('Algorithm used for localization and description'))
        self.response_spin = QSpinBox()
        self.response_spin.setRange(0, 100)
        self.response_spin.setSuffix(self.tr('%'))
        self.response_spin.setValue(90)
        self.response_spin.setToolTip(
            self.tr('Maximum keypoint response to perform matching'))
        self.matching_spin = QSpinBox()
        self.matching_spin.setRange(1, 100)
        self.matching_spin.setSuffix(self.tr('%'))
        self.matching_spin.setValue(20)
        self.matching_spin.setToolTip(
            self.tr('Maximum metric difference to accept matching'))
        self.distance_spin = QSpinBox()
        self.distance_spin.setRange(1, 100)
        self.distance_spin.setSuffix(self.tr('%'))
        self.distance_spin.setValue(15)
        self.distance_spin.setToolTip(
            self.tr('Maximum distance between matches in the same cluster'))
        self.cluster_spin = QSpinBox()
        self.cluster_spin.setRange(1, 20)
        self.cluster_spin.setValue(5)
        self.cluster_spin.setToolTip(
            self.tr('Minimum number of keypoints to create a new cluster'))
        self.nolines_check = QCheckBox(self.tr('Hide lines'))
        self.nolines_check.setToolTip(self.tr('Disable match line drawing'))
        self.process_button = QToolButton()
        self.process_button.setText(self.tr('Process'))
        self.process_button.setToolTip(self.tr('Perform automatic detection'))
        modify_font(self.process_button, bold=True)
        self.status_label = QLabel()
        self.mask_label = QLabel()
        self.mask_button = QToolButton()
        self.mask_button.setText(self.tr('Load mask...'))
        self.mask_button.setToolTip(
            self.tr('Load an image to be used as mask'))
        self.onoff_button = QToolButton()
        self.onoff_button.setText(self.tr('OFF'))
        self.onoff_button.setCheckable(True)
        self.onoff_button.setToolTip(self.tr('Toggle keypoint detection mask'))

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.gray = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        self.total = self.kpts = self.desc = self.matches = self.clusters = self.mask = None
        self.canceled = False

        self.detector_combo.currentIndexChanged.connect(self.update_detector)
        self.response_spin.valueChanged.connect(self.update_detector)
        self.matching_spin.valueChanged.connect(self.update_matching)
        self.distance_spin.valueChanged.connect(self.update_cluster)
        self.cluster_spin.valueChanged.connect(self.update_cluster)
        self.nolines_check.stateChanged.connect(self.process)
        self.process_button.clicked.connect(self.process)
        self.mask_button.clicked.connect(self.load_mask)
        self.onoff_button.toggled.connect(self.toggle_mask)
        self.onoff_button.setEnabled(False)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Detector:')))
        top_layout.addWidget(self.detector_combo)
        top_layout.addWidget(QLabel(self.tr('Response:')))
        top_layout.addWidget(self.response_spin)
        top_layout.addWidget(QLabel(self.tr('Matching:')))
        top_layout.addWidget(self.matching_spin)
        top_layout.addWidget(QLabel(self.tr('Distance:')))
        top_layout.addWidget(self.distance_spin)
        top_layout.addWidget(QLabel(self.tr('Cluster:')))
        top_layout.addWidget(self.cluster_spin)
        top_layout.addWidget(self.nolines_check)
        top_layout.addStretch()

        bottom_layout = QHBoxLayout()
        bottom_layout.addWidget(self.process_button)
        bottom_layout.addWidget(self.status_label)
        bottom_layout.addStretch()
        bottom_layout.addWidget(self.mask_button)
        bottom_layout.addWidget(self.onoff_button)

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addLayout(bottom_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def toggle_mask(self, checked):
        self.onoff_button.setText('ON' if checked else 'OFF')
        if checked:
            self.viewer.update_processed(
                cv.merge([c * self.mask for c in cv.split(self.image)]))
        else:
            self.viewer.update_processed(self.image)
        self.update_detector()

    def load_mask(self):
        filename, basename, mask = load_image(self)
        if filename is None:
            return
        if self.image.shape[:-1] != mask.shape[:-1]:
            QMessageBox.critical(
                self, self.tr('Error'),
                self.tr('Image and mask must have the same size!'))
            return
        _, self.mask = cv.threshold(cv.cvtColor(mask, cv.COLOR_BGR2GRAY), 0, 1,
                                    cv.THRESH_BINARY)
        self.onoff_button.setEnabled(True)
        self.onoff_button.setChecked(True)
        self.mask_button.setText('"{}"'.format(splitext(basename)[0]))
        self.mask_button.setToolTip(self.tr('Current detection mask image'))

    def update_detector(self):
        self.total = self.kpts = self.desc = self.matches = self.clusters = None
        self.status_label.setText('')
        self.process_button.setEnabled(True)

    def update_matching(self):
        self.matches = self.clusters = None
        self.process_button.setEnabled(True)

    def update_cluster(self):
        self.clusters = None
        self.process_button.setEnabled(True)

    def cancel(self):
        self.canceled = True
        self.total = self.kpts = self.desc = self.matches = self.clusters = None
        self.status_label.setText(self.tr('Processing interrupted!'))
        modify_font(self.status_label, bold=False, italic=False)

    def process(self):
        start = time()
        self.status_label.setText(self.tr('Processing, please wait...'))
        algorithm = self.detector_combo.currentIndex()
        response = 100 - self.response_spin.value()
        matching = self.matching_spin.value() / 100 * 255
        distance = self.distance_spin.value() / 100
        cluster = self.cluster_spin.value()
        modify_font(self.status_label, bold=False, italic=True)
        QCoreApplication.processEvents()

        if self.kpts is None:
            if algorithm == 0:
                detector = cv.BRISK_create()
            elif algorithm == 1:
                detector = cv.ORB_create()
            elif algorithm == 2:
                detector = cv.AKAZE_create()
            else:
                return
            mask = self.mask if self.onoff_button.isChecked() else None
            self.kpts, self.desc = detector.detectAndCompute(self.gray, mask)
            self.total = len(self.kpts)
            responses = np.array([k.response for k in self.kpts])
            strongest = (cv.normalize(responses, None, 0, 100, cv.NORM_MINMAX)
                         >= response).flatten()
            self.kpts = list(compress(self.kpts, strongest))
            self.desc = self.desc[strongest]

        if self.matches is None:
            matcher = cv.BFMatcher_create(cv.NORM_HAMMING, True)
            self.matches = matcher.radiusMatch(self.desc, self.desc, matching)
            if self.matches is None:
                self.status_label.setText(
                    self.tr('No keypoint match found with current settings'))
                modify_font(self.status_label, italic=False, bold=True)
                return
            self.matches = [
                item for sublist in self.matches for item in sublist
            ]
            self.matches = [
                m for m in self.matches if m.queryIdx != m.trainIdx
            ]

        if self.clusters is None:
            self.clusters = []
            total = len(self.matches)
            min_dist = distance * np.min(self.gray.shape) / 2
            progress = QProgressDialog(self.tr('Clustering matches...'),
                                       self.tr('Cancel'), 0, total, self)
            progress.canceled.connect(self.cancel)
            progress.setWindowModality(Qt.WindowModal)
            for i in range(total):
                match0 = self.matches[i]
                query0 = match0.queryIdx
                train0 = match0.trainIdx
                group = [match0]
                a0 = np.array(self.kpts[query0].pt)
                b0 = np.array(self.kpts[train0].pt)
                d0 = np.linalg.norm(a0 - b0)
                if d0 < min_dist:
                    continue
                for j in range(i + 1, total):
                    match1 = self.matches[j]
                    query1 = match1.queryIdx
                    train1 = match1.trainIdx
                    if query1 == train0 and train1 == query0:
                        continue
                    a1 = np.array(self.kpts[query1].pt)
                    b1 = np.array(self.kpts[train1].pt)
                    d1 = np.linalg.norm(a1 - b1)
                    if d1 < min_dist or np.abs(d0 - d1) > min_dist:
                        continue
                    aa = np.linalg.norm(a0 - a1)
                    bb = np.linalg.norm(b0 - b1)
                    ab = np.linalg.norm(a0 - b1)
                    ba = np.linalg.norm(b0 - a1)
                    smallest = np.partition(np.array([aa, bb, ab, ba]), 1)[:2]
                    if np.all(np.logical_and(smallest > 0,
                                             smallest < min_dist)):
                        for g in group:
                            if g.queryIdx == train1 and g.trainIdx == query1:
                                break
                        else:
                            group.append(match1)
                if len(group) >= cluster:
                    self.clusters.append(group)
                progress.setValue(i)
                if self.canceled:
                    self.canceled = False
                    return
            progress.setValue(total)

        output = np.copy(self.image)
        hsv = np.zeros((1, 1, 3))
        nolines = self.nolines_check.isChecked()
        angles = []
        for c in self.clusters:
            for m in c:
                ka = self.kpts[m.queryIdx]
                pa = tuple(map(int, ka.pt))
                sa = int(np.round(ka.size))
                kb = self.kpts[m.trainIdx]
                pb = tuple(map(int, kb.pt))
                sb = int(np.round(kb.size))
                angle = np.arctan2(pb[1] - pa[1], pb[0] - pa[0])
                if angle < 0:
                    angle += np.pi
                angles.append(angle)
                hsv[0, 0, 0] = angle / np.pi * 180
                hsv[0, 0, 1] = 255
                hsv[0, 0, 2] = m.distance / matching * 255
                rgb = cv.cvtColor(hsv.astype(np.uint8), cv.COLOR_HSV2BGR)
                rgb = tuple([int(x) for x in rgb[0, 0]])
                cv.circle(output, pa, sa, rgb, 1, cv.LINE_AA)
                cv.circle(output, pb, sb, rgb, 1, cv.LINE_AA)
                if not nolines:
                    cv.line(output, pa, pb, rgb, 1, cv.LINE_AA)

        regions = 0
        if angles:
            angles = np.reshape(np.array(angles, dtype=np.float32),
                                (len(angles), 1))
            if np.std(angles) < 0.1:
                regions = 1
            else:
                criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER,
                            10, 1.0)
                attempts = 10
                flags = cv.KMEANS_PP_CENTERS
                compact = [
                    cv.kmeans(angles, k, None, criteria, attempts, flags)[0]
                    for k in range(1, 11)
                ]
                compact = cv.normalize(np.array(compact), None, 0, 1,
                                       cv.NORM_MINMAX)
                regions = np.argmax(compact < 0.005) + 1
        self.viewer.update_processed(output)
        self.process_button.setEnabled(False)
        modify_font(self.status_label, italic=False, bold=True)
        self.status_label.setText(
            self.
            tr('Keypoints: {} --> Filtered: {} --> Matches: {} --> Clusters: {} --> Regions: {}'
               .format(self.total, len(self.kpts), len(self.matches),
                       len(self.clusters), regions)))
        self.info_message.emit(
            self.tr('Copy-Move Forgery = {}'.format(elapsed_time(start))))
Esempio n. 14
0
class GroupEditDialog(QDialog):
    def __init__(self, group, is_new=False):
        super().__init__(GlobalAccess().get_main_window())
        assert (isinstance(group, Group))
        self.current_object = group
        self.is_new = is_new
        self.time_format = 'hh:mm:ss'

    def exec_(self):
        self.init_ui()
        self.set_values_from_model()
        return super().exec_()

    def init_ui(self):
        self.setWindowTitle(_('Group properties'))
        self.setWindowIcon(QIcon(config.ICON))
        self.setSizeGripEnabled(False)
        self.setModal(True)

        self.layout = QFormLayout(self)

        self.label_name = QLabel(_('Name'))
        self.item_name = QLineEdit()
        self.item_name.textChanged.connect(self.check_name)
        self.layout.addRow(self.label_name, self.item_name)

        self.label_full_name = QLabel(_('Full name'))
        self.item_full_name = QLineEdit()
        self.layout.addRow(self.label_full_name, self.item_full_name)

        self.label_course = QLabel(_('Course'))
        self.item_course = AdvComboBox()
        self.item_course.addItems(get_race_courses())
        self.layout.addRow(self.label_course, self.item_course)

        self.label_is_any_course = QLabel(_('Is any course'))
        self.item_is_any_course = QCheckBox()
        self.item_is_any_course.stateChanged.connect(self.is_any_course_update)
        self.layout.addRow(self.label_is_any_course, self.item_is_any_course)

        self.label_sex = QLabel(_('Sex'))
        self.item_sex = AdvComboBox()
        self.item_sex.addItems(Sex.get_titles())
        self.layout.addRow(self.label_sex, self.item_sex)

        self.label_age_min = QLabel(_('Min age'))
        self.item_age_min = QSpinBox()
        # self.layout.addRow(self.label_age_min, self.item_age_min)

        self.label_age_max = QLabel(_('Max age'))
        self.item_age_max = QSpinBox()
        # self.layout.addRow(self.label_age_max, self.item_age_max)

        self.label_year_min = QLabel(_('Min year'))
        self.item_year_min = QSpinBox()
        self.item_year_min.setMaximum(date.today().year)
        self.item_year_min.editingFinished.connect(self.year_change)
        self.layout.addRow(self.label_year_min, self.item_year_min)

        self.label_year_max = QLabel(_('Max year'))
        self.item_year_max = QSpinBox()
        self.item_year_max.setMaximum(date.today().year)
        self.item_year_max.editingFinished.connect(self.year_change)
        self.layout.addRow(self.label_year_max, self.item_year_max)

        self.label_max_time = QLabel(_('Max time'))
        self.item_max_time = QTimeEdit()
        self.item_max_time.setDisplayFormat(self.time_format)
        self.layout.addRow(self.label_max_time, self.item_max_time)

        self.label_corridor = QLabel(_('Start corridor'))
        self.item_corridor = QSpinBox()
        self.layout.addRow(self.label_corridor, self.item_corridor)

        self.label_corridor_order = QLabel(_('Order in corridor'))
        self.item_corridor_order = QSpinBox()
        self.layout.addRow(self.label_corridor_order, self.item_corridor_order)

        self.label_start_interval = QLabel(_('Start interval'))
        self.item_start_interval = QTimeEdit()
        self.item_start_interval.setDisplayFormat(self.time_format)
        self.layout.addRow(self.label_start_interval, self.item_start_interval)

        self.label_price = QLabel(_('Start fee'))
        self.item_price = QSpinBox()
        self.item_price.setSingleStep(50)
        self.item_price.setMaximum(Limit.PRICE)
        self.layout.addRow(self.label_price, self.item_price)

        self.type_label = QLabel(_('Type'))
        self.type_combo = AdvComboBox()
        self.type_combo.addItems(RaceType.get_titles())
        self.layout.addRow(self.type_label, self.type_combo)

        self.rank_checkbox = QCheckBox(_('Rank calculation'))
        self.rank_button = QPushButton(_('Configuration'))
        self.layout.addRow(self.rank_checkbox, self.rank_button)

        def cancel_changes():
            self.close()

        def apply_changes():
            try:
                self.apply_changes_impl()
            except Exception as e:
                logging.error(str(e))
            self.close()

        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        self.button_ok = button_box.button(QDialogButtonBox.Ok)
        self.button_ok.setText(_('OK'))
        self.button_ok.clicked.connect(apply_changes)
        self.button_cancel = button_box.button(QDialogButtonBox.Cancel)
        self.button_cancel.setText(_('Cancel'))
        self.button_cancel.clicked.connect(cancel_changes)
        self.layout.addRow(button_box)

        self.show()
        self.button_ok.setFocus()

    def check_name(self):
        name = self.item_name.text()
        self.button_ok.setDisabled(False)
        if name and name != self.current_object.name:
            group = find(race().groups, name=name)
            if group:
                self.button_ok.setDisabled(True)

    def year_change(self):
        """
        Convert 2 digits of year to 4
        2 -> 2002
        11 - > 2011
        33 -> 1933
        56 -> 1956
        98 - > 1998
        0 -> 0 exception!
        """
        widget = self.sender()
        assert isinstance(widget, QSpinBox)
        year = widget.value()
        if 0 < year < 100:
            cur_year = date.today().year
            new_year = cur_year - cur_year % 100 + year
            if new_year > cur_year:
                new_year -= 100
            widget.setValue(new_year)

    def is_any_course_update(self):
        if self.item_is_any_course.isChecked():
            self.item_course.setDisabled(True)
        else:
            self.item_course.setDisabled(False)

    def set_values_from_model(self):

        self.item_name.setText(self.current_object.name)

        if self.current_object.long_name:
            self.item_full_name.setText(self.current_object.long_name)
        if self.current_object.course:
            self.item_course.setCurrentText(self.current_object.course.name)
        if self.current_object.sex:
            self.item_sex.setCurrentText(self.current_object.sex.get_title())
        if self.current_object.min_age:
            self.item_age_min.setValue(self.current_object.min_age)
        if self.current_object.max_age:
            self.item_age_max.setValue(self.current_object.max_age)
        if self.current_object.min_year:
            self.item_year_min.setValue(self.current_object.min_year)
        if self.current_object.max_year:
            self.item_year_max.setValue(self.current_object.max_year)
        if self.current_object.max_time:
            self.item_max_time.setTime(
                time_to_qtime(self.current_object.max_time))
        if self.current_object.start_interval:
            self.item_start_interval.setTime(
                time_to_qtime(self.current_object.start_interval))
        if self.current_object.start_corridor:
            self.item_corridor.setValue(self.current_object.start_corridor)
        if self.current_object.order_in_corridor:
            self.item_corridor_order.setValue(
                self.current_object.order_in_corridor)
        if self.current_object.price:
            self.item_price.setValue(self.current_object.price)

        self.item_is_any_course.setChecked(self.current_object.is_any_course)
        self.rank_checkbox.setChecked(self.current_object.ranking.is_active)
        self.type_combo.setCurrentText(race().get_type(
            self.current_object).get_title())

        def rank_configuration():
            group = self.current_object
            GroupRankingDialog(group).exec_()

        self.rank_button.clicked.connect(rank_configuration)

    def apply_changes_impl(self):
        group = self.current_object
        assert (isinstance(group, Group))
        if self.is_new:
            race().groups.insert(0, group)

        if group.name != self.item_name.text():
            group.name = self.item_name.text()

        if group.long_name != self.item_full_name.text():
            group.long_name = self.item_full_name.text()

        if (group.course is not None and group.course.name != self.item_course.currentText()) \
                or (group.course is None and len(self.item_course.currentText()) > 0):
            group.course = find(race().courses,
                                name=self.item_course.currentText())

        if group.sex.get_title() != self.item_sex.currentText():
            group.sex = Sex(self.item_sex.currentIndex())

        if group.min_age != self.item_age_min.value():
            group.min_age = self.item_age_min.value()

        if group.max_age != self.item_age_max.value():
            group.max_age = self.item_age_max.value()

        if group.min_year != self.item_year_min.value():
            group.min_year = self.item_year_min.value()

        if group.max_year != self.item_year_max.value():
            group.max_year = self.item_year_max.value()

        if group.start_corridor != self.item_corridor.value():
            group.start_corridor = self.item_corridor.value()

        if group.order_in_corridor != self.item_corridor_order.value():
            group.order_in_corridor = self.item_corridor_order.value()

        if group.price != self.item_price.value():
            group.price = self.item_price.value()

        time = time_to_otime(self.item_start_interval.time())
        if group.start_interval != time:
            group.start_interval = time

        time = time_to_otime(self.item_max_time.time())

        if group.max_time != time:
            group.max_time = time

        if group.ranking.is_active != self.rank_checkbox.isChecked():
            group.ranking.is_active = self.rank_checkbox.isChecked()

        t = RaceType.get_by_name(self.type_combo.currentText())
        selected_type = t if t is not None else group.get_type()
        if group.get_type() != selected_type:
            group.set_type(selected_type)

        group.is_any_course = self.item_is_any_course.isChecked()

        ResultCalculation(race()).set_rank(group)
        Teamwork().send(group.to_dict())
Esempio n. 15
0
class MedianWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(MedianWidget, self).__init__(parent)

        self.variance_spin = QSpinBox()
        self.variance_spin.setRange(0, 50)
        self.variance_spin.setValue(10)
        self.threshold_spin = QDoubleSpinBox()
        self.threshold_spin.setRange(0, 1)
        self.threshold_spin.setValue(0.45)
        self.threshold_spin.setSingleStep(0.01)
        self.showprob_check = QCheckBox(self.tr('Probability map'))
        self.filter_check = QCheckBox(self.tr('Speckle filter'))
        self.filter_check.setChecked(True)
        self.process_button = QPushButton(self.tr('Process'))
        self.avgprob_label = QLabel(self.tr('Press "Process" to start'))

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Min variance:')))
        top_layout.addWidget(self.variance_spin)
        top_layout.addWidget(QLabel(self.tr('Threshold:')))
        top_layout.addWidget(self.threshold_spin)
        top_layout.addWidget(self.showprob_check)
        top_layout.addWidget(self.filter_check)
        top_layout.addWidget(self.process_button)
        # top_layout.addWidget(self.avgprob_label)
        top_layout.addStretch()

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.gray = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        self.prob = self.var = None
        self.block = 64
        self.canceled = False

        self.process_button.clicked.connect(self.prepare)
        self.variance_spin.valueChanged.connect(self.process)
        self.threshold_spin.valueChanged.connect(self.process)
        self.showprob_check.stateChanged.connect(self.process)
        self.filter_check.stateChanged.connect(self.process)

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def prepare(self):
        modelfile = 'models/median_b{}.mdl'.format(self.block)
        try:
            model = load(modelfile)
        except FileNotFoundError:
            QMessageBox.critical(
                self, self.tr('Error'),
                self.tr('Model not found ("{}")!'.format(modelfile)))
            return
        limit = model.best_ntree_limit if hasattr(model,
                                                  'best_ntree_limit') else None
        columns = model._features_count
        if columns == 8:
            levels = 1
            windows = 1
        elif columns == 24:
            levels = 3
            windows = 1
        elif columns == 96:
            levels = 3
            windows = 4
        elif columns == 128:
            levels = 4
            windows = 4
        else:
            QMessageBox.critical(self, self.tr('Error'),
                                 self.tr('Unknown model format!'))
            return

        padded = pad_image(self.gray, self.block)
        rows, cols = padded.shape
        self.prob = np.zeros(
            ((rows // self.block) + 1, (cols // self.block) + 1))
        self.var = np.zeros_like(self.prob)
        progress = QProgressDialog(self.tr('Detecting median filter...'),
                                   self.tr('Cancel'), 0, self.prob.size, self)
        progress.canceled.connect(self.cancel)
        progress.setWindowModality(Qt.WindowModal)
        k = 0
        self.canceled = False
        for i in range(0, rows, self.block):
            for j in range(0, cols, self.block):
                roi = padded[i:i + self.block, j:j + self.block]
                x = np.reshape(get_features(roi, levels, windows),
                               (1, columns))
                y = model.predict_proba(x, ntree_limit=limit)[0, 1]
                ib = i // self.block
                jb = j // self.block
                self.var[ib, jb] = np.var(roi)
                self.prob[ib, jb] = y
                if self.canceled:
                    self.prob = self.var = None
                    progress.close()
                    return
                progress.setValue(k)
                k += 1
        progress.close()
        self.process()

    def cancel(self):
        self.canceled = True

    def process(self):
        if self.prob is None:
            return
        mask = self.var < self.variance_spin.value()
        if self.filter_check.isChecked():
            prob = cv.medianBlur(self.prob.astype(np.float32), 3)
        else:
            prob = self.prob.astype(np.float32)
        if self.showprob_check.isChecked():
            output = np.repeat(prob[:, :, np.newaxis], 3, axis=2)
            output[mask] = 0
        else:
            thr = self.threshold_spin.value()
            output = np.zeros((prob.shape[0], prob.shape[1], 3))
            blue, green, red = cv.split(output)
            blue[mask] = 1
            green[prob < thr] = 1
            green[mask] = 0
            red[prob >= thr] = 1
            red[mask] = 0
            output = cv.merge((blue, green, red))
        output = cv.convertScaleAbs(output, None, 255)
        output = cv.resize(output, None, None, self.block, self.block,
                           cv.INTER_LINEAR)
        self.viewer.update_processed(
            np.copy(output[:self.image.shape[0], :self.image.shape[1]]))
        avgprob = cv.mean(prob, 1 - mask.astype(np.uint8))[0] * 100
        self.avgprob_label.setText(self.tr(
            'Average = {:.2f}%'.format(avgprob)))
        modify_font(self.avgprob_label, italic=False, bold=True)
        self.process_button.setEnabled(False)
Esempio n. 16
0
class PersonEditDialog(QDialog):
    GROUP_NAME = ''
    ORGANIZATION_NAME = ''

    def __init__(self, person, is_new=False):
        super().__init__(GlobalAccess().get_main_window())
        self.is_ok = {}
        assert (isinstance(person, Person))
        self.current_object = person
        self.is_new = is_new

        self.time_format = 'hh:mm:ss'
        time_accuracy = race().get_setting('time_accuracy', 0)
        if time_accuracy:
            self.time_format = 'hh:mm:ss.zzz'

    def exec_(self):
        self.init_ui()
        self.set_values_from_model()
        return super().exec_()

    def init_ui(self):
        self.setWindowTitle(_('Entry properties'))
        self.setWindowIcon(QIcon(config.ICON))
        self.setSizeGripEnabled(False)
        self.setModal(True)

        self.layout = QFormLayout(self)
        self.label_surname = QLabel(_('Last name'))
        self.item_surname = QLineEdit()
        self.layout.addRow(self.label_surname, self.item_surname)

        self.label_name = QLabel(_('First name'))
        self.item_name = AdvComboBox()
        self.item_name.addItems(get_names())
        self.layout.addRow(self.label_name, self.item_name)

        self.label_group = QLabel(_('Group'))
        self.item_group = AdvComboBox()
        self.item_group.addItems(get_race_groups())
        self.layout.addRow(self.label_group, self.item_group)

        self.label_team = QLabel(_('Team'))
        self.item_team = AdvComboBox()
        self.item_team.addItems(get_race_teams())
        self.layout.addRow(self.label_team, self.item_team)

        use_birthday = Config().configuration.get('use_birthday', False)
        if use_birthday:
            self.label_birthday = QLabel(_('Birthday'))
            self.item_birthday = QDateEdit()
            self.item_birthday.setDate(date.today())
            self.item_birthday.setMaximumDate(date.today())
            self.layout.addRow(self.label_birthday, self.item_birthday)
        else:
            self.label_year = QLabel(_('Year of birth'))
            self.item_year = QSpinBox()
            self.item_year.setMinimum(0)
            self.item_year.setMaximum(date.today().year)
            self.item_year.editingFinished.connect(self.year_change)
            self.layout.addRow(self.label_year, self.item_year)

        self.label_qual = QLabel(_('Qualification'))
        self.item_qual = AdvComboBox()
        for i in list(Qualification):
            self.item_qual.addItem(i.get_title())
        self.layout.addRow(self.label_qual, self.item_qual)

        self.is_ok['bib'] = True
        self.label_bib = QLabel(_('Bib'))
        self.item_bib = QSpinBox()
        self.item_bib.setMinimum(0)
        self.item_bib.setMaximum(Limit.BIB)
        self.item_bib.valueChanged.connect(self.check_bib)
        self.layout.addRow(self.label_bib, self.item_bib)

        self.label_bib_info = QLabel('')
        self.layout.addRow(QLabel(''), self.label_bib_info)

        self.label_start = QLabel(_('Start time'))
        self.item_start = QTimeEdit()
        self.item_start.setDisplayFormat(self.time_format)
        self.layout.addRow(self.label_start, self.item_start)

        self.label_start_group = QLabel(_('Start group'))
        self.item_start_group = QSpinBox()
        self.item_start_group.setMinimum(0)
        self.item_start_group.setMaximum(99)
        self.layout.addRow(self.label_start_group, self.item_start_group)

        self.is_ok['card'] = True
        self.label_card = QLabel(_('Punch card #'))
        self.item_card = QSpinBox()
        self.item_card.setMinimum(0)
        self.item_card.setMaximum(9999999)
        self.item_card.valueChanged.connect(self.check_card)
        self.layout.addRow(self.label_card, self.item_card)

        self.label_card_info = QLabel('')
        self.layout.addRow(QLabel(''), self.label_card_info)

        self.item_rented = QCheckBox(_('rented card'))
        self.item_paid = QCheckBox(_('is paid'))
        self.item_out_of_competition = QCheckBox(_('out of competition'))
        self.item_personal = QCheckBox(_('personal participation'))
        self.layout.addRow(self.item_rented, self.item_out_of_competition)
        self.layout.addRow(self.item_paid, self.item_personal)

        self.label_comment = QLabel(_('Comment'))
        self.item_comment = QTextEdit()
        self.item_comment.setTabChangesFocus(True)
        self.layout.addRow(self.label_comment, self.item_comment)

        def cancel_changes():
            self.close()

        def apply_changes():
            try:
                self.apply_changes_impl()
            except Exception as e:
                logging.error(str(e))
            self.close()

        button_box = QDialogButtonBox(QDialogButtonBox.Ok
                                      | QDialogButtonBox.Cancel)
        self.button_ok = button_box.button(QDialogButtonBox.Ok)
        self.button_ok.setText(_('OK'))
        self.button_ok.clicked.connect(apply_changes)
        self.button_cancel = button_box.button(QDialogButtonBox.Cancel)
        self.button_cancel.setText(_('Cancel'))
        self.button_cancel.clicked.connect(cancel_changes)
        self.layout.addRow(button_box)

        self.show()

    def year_change(self):
        """
        Convert 2 digits of year to 4
        2 -> 2002
        11 - > 2011
        33 -> 1933
        56 -> 1956
        98 - > 1998
        0 -> 0 exception!
        """
        widget = self.sender()
        assert isinstance(widget, QSpinBox)
        year = widget.value()
        if 0 < year < 100:
            cur_year = date.today().year
            new_year = cur_year - cur_year % 100 + year
            if new_year > cur_year:
                new_year -= 100
            widget.setValue(new_year)

    def items_ok(self):
        ret = True
        for item_name in self.is_ok.keys():
            if self.is_ok[item_name] is not True:
                ret = False
                break
        return ret

    def check_bib(self):
        bib = self.item_bib.value()
        self.label_bib_info.setText('')
        if bib:
            person = find(race().persons, bib=bib)
            if person:
                if person.bib == self.current_object.bib:
                    self.button_ok.setEnabled(True)
                    return
                self.button_ok.setDisabled(True)
                self.is_ok['bib'] = False
                info = '{}\n{}'.format(_('Number already exists'),
                                       person.full_name)
                if person.group:
                    info = '{}\n{}: {}'.format(info, _('Group'),
                                               person.group.name)
                self.label_bib_info.setText(info)
            else:
                self.label_bib_info.setText(_('Number is unique'))
                self.is_ok['bib'] = True
                if self.items_ok():
                    self.button_ok.setEnabled(True)
        else:
            self.button_ok.setEnabled(True)

    def check_card(self):
        number = self.item_card.value()
        self.label_card_info.setText('')
        if number:
            person = None
            for _p in race().persons:
                if _p.card_number and _p.card_number == number:
                    person = _p
                    break
            if person:
                if person.card_number == self.current_object.card_number:
                    self.button_ok.setEnabled(True)
                    return
                self.button_ok.setDisabled(True)
                self.is_ok['card'] = False
                info = '{}\n{}'.format(_('Card number already exists'),
                                       person.full_name)
                if person.group:
                    info = '{}\n{}: {}'.format(info, _('Group'),
                                               person.group.name)
                if person.bib:
                    info = '{}\n{}: {}'.format(info, _('Bib'), person.bib)
                self.label_card_info.setText(info)
            else:
                self.label_card_info.setText(_('Card number is unique'))
                self.is_ok['card'] = True
                if self.items_ok():
                    self.button_ok.setEnabled(True)
        else:
            self.button_ok.setEnabled(True)

    def set_values_from_model(self):
        self.item_surname.setText(self.current_object.surname)
        self.item_surname.selectAll()
        self.item_name.setCurrentText(self.current_object.name)
        if self.current_object.group is not None:
            self.item_group.setCurrentText(self.current_object.group.name)
        else:
            self.item_group.setCurrentText(self.GROUP_NAME)
        if self.current_object.organization is not None:
            self.item_team.setCurrentText(
                self.current_object.organization.name)
        else:
            self.item_team.setCurrentText(self.ORGANIZATION_NAME)
        if self.current_object.qual:
            self.item_qual.setCurrentText(self.current_object.qual.get_title())
        if self.current_object.bib:
            self.item_bib.setValue(int(self.current_object.bib))
        if self.current_object.start_time is not None:
            time = time_to_qtime(self.current_object.start_time)
            self.item_start.setTime(time)
        if self.current_object.start_group is not None:
            self.item_start_group.setValue(int(
                self.current_object.start_group))

        if self.current_object.card_number:
            self.item_card.setValue(self.current_object.card_number)

        self.item_out_of_competition.setChecked(
            self.current_object.is_out_of_competition)
        self.item_paid.setChecked(self.current_object.is_paid)
        self.item_paid.setChecked(self.current_object.is_paid)
        self.item_personal.setChecked(self.current_object.is_personal)
        self.item_rented.setChecked(self.current_object.is_rented_card)

        self.item_comment.setText(self.current_object.comment)

        use_birthday = Config().configuration.get('use_birthday', False)
        if use_birthday:
            if self.current_object.birth_date:
                self.item_birthday.setDate(self.current_object.birth_date)
        else:
            if self.current_object.get_year():
                self.item_year.setValue(self.current_object.get_year())

    def apply_changes_impl(self):
        person = self.current_object
        assert (isinstance(person, Person))
        if self.is_new:
            race().persons.insert(0, person)
        if person.name != self.item_name.currentText():
            person.name = self.item_name.currentText()
        if person.surname != self.item_surname.text():
            person.surname = self.item_surname.text()
        if (person.group is not None and person.group.name != self.item_group.currentText()) or\
                (person.group is None and len(self.item_group.currentText()) > 0):
            person.group = find(race().groups,
                                name=self.item_group.currentText())
        if (person.organization is not None and person.organization.name != self.item_team.currentText()) or \
                (person.organization is None and len(self.item_team.currentText()) > 0):
            organization = find(race().organizations,
                                name=self.item_team.currentText())
            if organization is None:
                organization = Organization()
                organization.name = self.item_team.currentText()
                race().organizations.append(organization)
                Teamwork().send(organization.to_dict())
            person.organization = organization
        if person.qual.get_title() != self.item_qual.currentText():
            person.qual = Qualification.get_qual_by_name(
                self.item_qual.currentText())
        if person.bib != self.item_bib.value():
            person.bib = self.item_bib.value()

        new_time = time_to_otime(self.item_start.time())
        if person.start_time != new_time:
            person.start_time = new_time

        if person.start_group != self.item_start_group.value(
        ) and self.item_start_group.value():
            person.start_group = self.item_start_group.value()

        if (not person.card_number or int(person.card_number) != self.item_card.value()) \
                and self.item_card.value:
            race().person_card_number(person, self.item_card.value())

        if person.is_out_of_competition != self.item_out_of_competition.isChecked(
        ):
            person.is_out_of_competition = self.item_out_of_competition.isChecked(
            )

        if person.is_paid != self.item_paid.isChecked():
            person.is_paid = self.item_paid.isChecked()

        if person.is_rented_card != self.item_rented.isChecked():
            person.is_rented_card = self.item_rented.isChecked()

        if person.is_personal != self.item_personal.isChecked():
            person.is_personal = self.item_personal.isChecked()

        if person.comment != self.item_comment.toPlainText():
            person.comment = self.item_comment.toPlainText()

        use_birthday = Config().configuration.get('use_birthday', False)
        if use_birthday:
            new_birthday = qdate_to_date(self.item_birthday.date())
            if person.birth_date != new_birthday and new_birthday:
                if person.birth_date or new_birthday != date.today():
                    person.birth_date = new_birthday
        else:
            if person.get_year() != self.item_year.value():
                person.set_year(self.item_year.value())

        ResultCalculation(race()).process_results()
        Teamwork().send(person.to_dict())
Esempio n. 17
0
class MainWindow(QMainWindow):
    def __init__(self) -> None:
        QMainWindow.__init__(self)
        self.lib_chapters = self.__create_libchapters()
        self.prefs = Prefs()
        self.current_file: Optional[str] = None
        self.current_file_type: Optional[str] = None

        # UI components
        self.setWindowTitle(libchapters.APPLICATION_NAME)
        self.setMinimumSize(480, 320)
        self.resize(900, 500)
        self.__create_menu()

        self.podcast_title = QLineEdit()
        self.episode_title = QLineEdit()
        self.episode_number = QSpinBox()
        self.episode_number.setMaximumWidth(55)

        self.chapters_table_view = QTableView()
        self.chapters_table_model = ChaptersTableModel(
            self.chapters_table_view)
        self.chapters_table_view.setModel(self.chapters_table_model)
        self.chapters_table_view.horizontalHeader().setStretchLastSection(True)

        self.add_chapter_button = QPushButton("Add")
        self.add_chapter_button.clicked.connect(
            self.chapters_table_model.add_chapter)

        self.delete_chapter_button = QPushButton("Delete")
        self.delete_chapter_button.clicked.connect(
            self.chapters_table_model.remove_selected_chapters)

        self.progress_bar = QProgressBar()

        self.setCentralWidget(self.__create_center_widget())

        self.__create_status_bar()

    def __create_libchapters(self) -> LibChapters:
        listener = LibChaptersListener()
        listener.signals.encode_started.connect(self.__encode_started)
        listener.signals.encode_progress.connect(self.__encode_progress)
        listener.signals.encode_complete.connect(self.__encode_complete)
        listener.signals.read_metadata_started.connect(
            self.__read_metadata_started)
        listener.signals.read_metadata_complete.connect(
            self.__read_metadata_complete)
        listener.signals.write_mp3_file_started.connect(
            self.__write_mp3_started)
        listener.signals.write_mp3_file_progress.connect(
            self.__write_mp3_progress)
        listener.signals.write_mp3_file_complete.connect(
            self.__write_mp3_complete)
        return LibChapters(listener)

    def __create_center_widget(self) -> QWidget:
        episode_info_layout = QFormLayout()
        episode_info_layout.addRow("Podcast Title:", self.podcast_title)
        episode_info_layout.addRow("Episode Title:", self.episode_title)
        episode_info_layout.addRow("Episode Number:", self.episode_number)

        add_remove_chapters_layout = QHBoxLayout()
        add_remove_chapters_layout.addWidget(self.add_chapter_button)
        add_remove_chapters_layout.addWidget(self.delete_chapter_button)
        add_remove_chapters_layout.setAlignment(Qt.AlignLeft)

        center_widget_layout = QVBoxLayout()
        center_widget_layout.addLayout(episode_info_layout)
        center_widget_layout.addWidget(self.chapters_table_view)
        center_widget_layout.addLayout(add_remove_chapters_layout)

        center_widget = QWidget()
        center_widget.setLayout(center_widget_layout)

        return center_widget

    def __create_menu(self) -> None:
        menu_bar = self.menuBar()
        file_menu = menu_bar.addMenu("File")

        import_action = file_menu.addAction("Import Audio...")
        import_action.setShortcut(QKeySequence("Ctrl+I"))
        import_action.triggered.connect(self.__import_audio)

        open_file_action = file_menu.addAction("Open...")
        open_file_action.setShortcut(QKeySequence("Ctrl+O"))
        open_file_action.triggered.connect(self.__open_file)

        file_menu.addSeparator()

        save_action = file_menu.addAction("Save")
        save_action.setShortcut(QKeySequence("Ctrl+S"))
        save_action.triggered.connect(self.__save_current_file)

        save_as_action = file_menu.addAction("Save As...")
        save_as_action.setShortcut(QKeySequence("Ctrl+Shift+S"))
        save_as_action.triggered.connect(self.__save_current_file_as)

        file_menu.addSeparator()

        exit_action = file_menu.addAction("Exit")
        exit_action.setShortcut(QKeySequence("Alt+f4"))
        exit_action.triggered.connect(QCoreApplication.quit)

        help_menu = menu_bar.addMenu("Help")
        documentation_action = help_menu.addAction("Open Documentation...")
        documentation_action.triggered.connect(
            lambda: QDesktopServices.openUrl(libchapters.DOCUMENTATION))
        help_menu.addSeparator()
        about_action = help_menu.addAction("About...")
        about_action.triggered.connect(self.__show_about_dialog)

    def __create_status_bar(self) -> None:
        status_bar = self.statusBar()
        status_bar.addPermanentWidget(self.progress_bar)

    def __import_audio(self) -> None:
        file = self.__show_open_dialog("*.wav")
        if file:
            self.__set_current_file(file, "wav")
            self.lib_chapters.read_metadata_from_wav_file(file)
            self.lib_chapters.encode_wav_file(file)

    def __open_file(self) -> None:
        file = self.__show_open_dialog("*.mp3")
        if file:
            self.__set_current_file(file, "mp3")
            self.lib_chapters.read_metadata_from_mp3_file(file)

    def __encode_started(self) -> None:
        self.progress_bar.setValue(0)
        self.statusBar().showMessage("Importing file...")

    def __encode_progress(self, progress: int) -> None:
        self.progress_bar.setValue(progress)

    def __encode_complete(self) -> None:
        self.centralWidget().setDisabled(False)
        self.menuBar().setDisabled(False)
        self.statusBar().showMessage("Import complete")

    def __read_metadata_started(self) -> None:
        self.chapters_table_view.setDisabled(True)

    def __read_metadata_complete(self, metadata: MetaData) -> None:
        self.chapters_table_view.setDisabled(False)
        if metadata.podcast_title:
            self.podcast_title.setText(metadata.podcast_title)
        else:
            self.podcast_title.clear()

        if metadata.episode_title:
            self.episode_title.setText(metadata.episode_title)
        else:
            self.episode_title.clear()

        if metadata.episode_number:
            self.episode_number.setValue(metadata.episode_number)
        else:
            self.episode_number.clear()

        if metadata.chapters:
            self.chapters_table_model.set_chapters(metadata.chapters)
        else:
            self.chapters_table_model.clear_chapters()

    def __save_current_file(self) -> None:
        if self.current_file:
            meta_data = MetaData(
                podcast_title=self.podcast_title.text(),
                episode_title=self.episode_title.text(),
                episode_number=self.episode_number.value(),
                chapters=self.chapters_table_model.get_chapters())

            if self.current_file_type == "wav":
                output_file = self.__show_save_dialog("*.mp3")
                if output_file:
                    self.lib_chapters.write_mp3_data_with_metadata(
                        meta_data, output_file)
            elif self.current_file_type == "mp3":
                self.lib_chapters.write_metadata_to_file(
                    meta_data, self.current_file)

    def __save_current_file_as(self) -> None:
        if self.current_file:
            output_file = self.__show_save_dialog("*.mp3")
            if output_file:
                meta_data = MetaData(
                    podcast_title=self.podcast_title.text(),
                    episode_title=self.episode_title.text(),
                    episode_number=self.episode_number.value(),
                    chapters=self.chapters_table_model.get_chapters())

                if self.current_file_type == "wav":
                    self.lib_chapters.write_mp3_data_with_metadata(
                        meta_data, output_file)
                elif self.current_file_type == "mp3":
                    self.lib_chapters.copy_mp3_with_metadata(
                        self.current_file, output_file, meta_data)

    def __write_mp3_started(self) -> None:
        self.menuBar().setDisabled(True)
        self.centralWidget().setDisabled(True)
        self.progress_bar.setValue(0)
        self.statusBar().showMessage("Saving MP3...")

    def __write_mp3_progress(self, progress: int) -> None:
        self.progress_bar.setValue(progress)

    def __write_mp3_complete(self, path_to_mp3: str) -> None:
        self.menuBar().setDisabled(False)
        self.centralWidget().setDisabled(False)
        self.__set_current_file(path_to_mp3, "mp3")
        self.statusBar().showMessage("Save complete")

    def __show_about_dialog(self) -> None:
        about_dialog = AboutDialog(self)
        about_dialog.show()

    def __set_current_file(self, current_file: str,
                           current_file_type: str) -> None:
        self.current_file = current_file
        self.current_file_type = current_file_type
        self.setWindowTitle(
            f"{libchapters.APPLICATION_NAME} - {os.path.basename(current_file)}"
        )

    def __show_open_dialog(self, type_filter: str) -> Optional[str]:
        file, _ = QFileDialog.getOpenFileName(
            parent=self,
            dir=self.prefs.get_pref_open_dir(),
            filter=type_filter)

        if file:
            self.prefs.set_pref_open_dir(file)

        return file

    def __show_save_dialog(self, type_filter: str) -> Optional[str]:
        file, _ = QFileDialog.getSaveFileName(
            parent=self,
            dir=self.prefs.get_pref_save_dir(),
            filter=type_filter)

        if file:
            self.prefs.set_pref_save_dir(file)

        return file
Esempio n. 18
0
class ElaWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(ElaWidget, self).__init__(parent)

        self.quality_spin = QSpinBox()
        self.quality_spin.setRange(1, 100)
        self.quality_spin.setSuffix(self.tr(" %"))
        self.quality_spin.setToolTip(self.tr("JPEG reference quality level"))
        self.scale_spin = QSpinBox()
        self.scale_spin.setRange(1, 100)
        self.scale_spin.setSuffix(" %")
        self.scale_spin.setToolTip(self.tr("Output multiplicative gain"))
        self.contrast_spin = QSpinBox()
        self.contrast_spin.setRange(0, 100)
        self.contrast_spin.setSuffix(" %")
        self.contrast_spin.setToolTip(self.tr("Output tonality compression"))
        self.linear_check = QCheckBox(self.tr("Linear"))
        self.linear_check.setToolTip(self.tr("Linearize absolute difference"))
        self.gray_check = QCheckBox(self.tr("Grayscale"))
        self.gray_check.setToolTip(self.tr("Desaturated output"))
        default_button = QPushButton(self.tr("Default"))
        default_button.setToolTip(self.tr("Revert to default parameters"))

        params_layout = QHBoxLayout()
        params_layout.addWidget(QLabel(self.tr("Quality:")))
        params_layout.addWidget(self.quality_spin)
        params_layout.addWidget(QLabel(self.tr("Scale:")))
        params_layout.addWidget(self.scale_spin)
        params_layout.addWidget(QLabel(self.tr("Contrast:")))
        params_layout.addWidget(self.contrast_spin)
        params_layout.addWidget(self.linear_check)
        params_layout.addWidget(self.gray_check)
        params_layout.addWidget(default_button)
        params_layout.addStretch()

        self.image = image
        self.original = image.astype(np.float32) / 255
        self.compressed = None
        self.viewer = ImageViewer(self.image, self.image)
        self.default()

        self.quality_spin.valueChanged.connect(self.preprocess)
        self.scale_spin.valueChanged.connect(self.process)
        self.contrast_spin.valueChanged.connect(self.process)
        self.linear_check.stateChanged.connect(self.process)
        self.gray_check.stateChanged.connect(self.process)
        default_button.clicked.connect(self.default)

        main_layout = QVBoxLayout()
        main_layout.addLayout(params_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def preprocess(self):
        quality = self.quality_spin.value()
        self.compressed = compress_jpg(self.image, quality)
        self.process()

    def process(self):
        start = time()
        scale = self.scale_spin.value()
        contrast = int(self.contrast_spin.value() / 100 * 128)
        linear = self.linear_check.isChecked()
        grayscale = self.gray_check.isChecked()
        if not linear:
            difference = cv.absdiff(self.original, self.compressed.astype(np.float32) / 255)
            ela = cv.convertScaleAbs(cv.sqrt(difference) * 255, None, scale / 20)
        else:
            ela = cv.convertScaleAbs(cv.subtract(self.compressed, self.image), None, scale)
        ela = cv.LUT(ela, create_lut(contrast, contrast))
        if grayscale:
            ela = desaturate(ela)
        self.viewer.update_processed(ela)
        self.info_message.emit(self.tr(f"Error Level Analysis = {elapsed_time(start)}"))

    def default(self):
        self.blockSignals(True)
        self.linear_check.setChecked(False)
        self.gray_check.setChecked(False)
        self.quality_spin.setValue(75)
        self.scale_spin.setValue(50)
        self.contrast_spin.setValue(25)
        self.blockSignals(False)
        self.preprocess()
Esempio n. 19
0
class OptionsDock(QDockWidget):
    def __init__(self, model, FM, parent=None):
        super(OptionsDock, self).__init__(parent)

        self.model = model
        self.FM = FM
        self.mw = parent

        self.setSizePolicy(QSizePolicy.Fixed,
                           QSizePolicy.Expanding)  # Doesn't work?
        self.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea
                             | QtCore.Qt.RightDockWidgetArea)

        # Create Controls
        self.createOriginBox()
        self.createOptionsBox()
        self.createResolutionBox()

        # Create submit button
        self.applyButton = QPushButton("Apply Changes")
        self.applyButton.setMinimumHeight(self.FM.height() *
                                          1.6)  # Mac bug fix
        self.applyButton.clicked.connect(self.mw.applyChanges)

        # Create Zoom box
        self.zoomBox = QSpinBox()
        self.zoomBox.setSuffix(' %')
        self.zoomBox.setRange(25, 2000)
        self.zoomBox.setValue(100)
        self.zoomBox.setSingleStep(25)
        self.zoomBox.valueChanged.connect(self.mw.editZoom)
        self.zoomLayout = QHBoxLayout()
        self.zoomLayout.addWidget(QLabel('Zoom:'))
        self.zoomLayout.addWidget(self.zoomBox)
        self.zoomLayout.setContentsMargins(0, 0, 0, 0)
        self.zoomWidget = QWidget()
        self.zoomWidget.setLayout(self.zoomLayout)

        # Create Layout
        self.dockLayout = QVBoxLayout()
        self.dockLayout.addWidget(self.originGroupBox)
        self.dockLayout.addWidget(self.optionsGroupBox)
        self.dockLayout.addWidget(self.resGroupBox)
        self.dockLayout.addWidget(self.applyButton)
        self.dockLayout.addStretch()
        self.dockLayout.addWidget(HorizontalLine())
        self.dockLayout.addWidget(self.zoomWidget)

        self.optionsWidget = QWidget()
        self.optionsWidget.setLayout(self.dockLayout)
        self.setWidget(self.optionsWidget)

    def createOriginBox(self):

        # X Origin
        self.xOrBox = QDoubleSpinBox()
        self.xOrBox.setDecimals(9)
        self.xOrBox.setRange(-99999, 99999)
        self.xOrBox.valueChanged.connect(
            lambda value: self.mw.editSingleOrigin(value, 0))

        # Y Origin
        self.yOrBox = QDoubleSpinBox()
        self.yOrBox.setDecimals(9)
        self.yOrBox.setRange(-99999, 99999)
        self.yOrBox.valueChanged.connect(
            lambda value: self.mw.editSingleOrigin(value, 1))

        # Z Origin
        self.zOrBox = QDoubleSpinBox()
        self.zOrBox.setDecimals(9)
        self.zOrBox.setRange(-99999, 99999)
        self.zOrBox.valueChanged.connect(
            lambda value: self.mw.editSingleOrigin(value, 2))

        # Origin Form Layout
        self.orLayout = QFormLayout()
        self.orLayout.addRow('X:', self.xOrBox)
        self.orLayout.addRow('Y:', self.yOrBox)
        self.orLayout.addRow('Z:', self.zOrBox)
        #self.orLayout.setVerticalSpacing(4)
        self.orLayout.setLabelAlignment(QtCore.Qt.AlignLeft)
        self.orLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow)

        # Origin Group Box
        self.originGroupBox = QGroupBox('Origin')
        self.originGroupBox.setLayout(self.orLayout)

    def createOptionsBox(self):

        # Width
        self.widthBox = QDoubleSpinBox(self)
        self.widthBox.setRange(.1, 99999)
        self.widthBox.valueChanged.connect(self.mw.editWidth)

        # Height
        self.heightBox = QDoubleSpinBox(self)
        self.heightBox.setRange(.1, 99999)
        self.heightBox.valueChanged.connect(self.mw.editHeight)

        # ColorBy
        self.colorbyBox = QComboBox(self)
        self.colorbyBox.addItem("material")
        self.colorbyBox.addItem("cell")
        self.colorbyBox.currentTextChanged[str].connect(self.mw.editColorBy)

        # Basis
        self.basisBox = QComboBox(self)
        self.basisBox.addItem("xy")
        self.basisBox.addItem("xz")
        self.basisBox.addItem("yz")
        self.basisBox.currentTextChanged.connect(self.mw.editBasis)

        # Advanced Color Options
        self.colorOptionsButton = QPushButton('Color Options...')
        self.colorOptionsButton.setMinimumHeight(self.FM.height() * 1.6)
        self.colorOptionsButton.clicked.connect(self.mw.showColorDialog)

        # Options Form Layout
        self.opLayout = QFormLayout()
        self.opLayout.addRow('Width:', self.widthBox)
        self.opLayout.addRow('Height:', self.heightBox)
        self.opLayout.addRow('Basis:', self.basisBox)
        self.opLayout.addRow('Color By:', self.colorbyBox)
        self.opLayout.addRow(self.colorOptionsButton)
        self.opLayout.setLabelAlignment(QtCore.Qt.AlignLeft)
        self.opLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow)

        # Options Group Box
        self.optionsGroupBox = QGroupBox('Options')
        self.optionsGroupBox.setLayout(self.opLayout)

    def createResolutionBox(self):

        # Horizontal Resolution
        self.hResBox = QSpinBox(self)
        self.hResBox.setRange(1, 99999)
        self.hResBox.setSingleStep(25)
        self.hResBox.setSuffix(' px')
        self.hResBox.valueChanged.connect(self.mw.editHRes)

        # Vertical Resolution
        self.vResLabel = QLabel('Pixel Height:')
        self.vResBox = QSpinBox(self)
        self.vResBox.setRange(1, 99999)
        self.vResBox.setSingleStep(25)
        self.vResBox.setSuffix(' px')
        self.vResBox.valueChanged.connect(self.mw.editVRes)

        # Ratio checkbox
        self.ratioCheck = QCheckBox("Fixed Aspect Ratio", self)
        self.ratioCheck.stateChanged.connect(self.mw.toggleAspectLock)

        # Resolution Form Layout
        self.resLayout = QFormLayout()
        self.resLayout.addRow(self.ratioCheck)
        self.resLayout.addRow('Pixel Width:', self.hResBox)
        self.resLayout.addRow(self.vResLabel, self.vResBox)
        self.resLayout.setLabelAlignment(QtCore.Qt.AlignLeft)
        self.resLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow)

        # Resolution Group Box
        self.resGroupBox = QGroupBox("Resolution")
        self.resGroupBox.setLayout(self.resLayout)

    def updateDock(self):
        self.updateOrigin()
        self.updateWidth()
        self.updateHeight()
        self.updateColorBy()
        self.updateBasis()
        self.updateAspectLock()
        self.updateHRes()
        self.updateVRes()

    def updateOrigin(self):
        self.xOrBox.setValue(self.model.activeView.origin[0])
        self.yOrBox.setValue(self.model.activeView.origin[1])
        self.zOrBox.setValue(self.model.activeView.origin[2])

    def updateWidth(self):
        self.widthBox.setValue(self.model.activeView.width)

    def updateHeight(self):
        self.heightBox.setValue(self.model.activeView.height)

    def updateColorBy(self):
        self.colorbyBox.setCurrentText(self.model.activeView.colorby)

    def updateBasis(self):
        self.basisBox.setCurrentText(self.model.activeView.basis)

    def updateAspectLock(self):
        if self.model.activeView.aspectLock:
            self.ratioCheck.setChecked(True)
            self.vResBox.setDisabled(True)
            self.vResLabel.setDisabled(True)
        else:
            self.ratioCheck.setChecked(False)
            self.vResBox.setDisabled(False)
            self.vResLabel.setDisabled(False)

    def updateHRes(self):
        self.hResBox.setValue(self.model.activeView.hRes)

    def updateVRes(self):
        self.vResBox.setValue(self.model.activeView.vRes)

    def revertToCurrent(self):
        cv = self.model.currentView

        self.xOrBox.setValue(cv.origin[0])
        self.yOrBox.setValue(cv.origin[1])
        self.zOrBox.setValue(cv.origin[2])

        self.widthBox.setValue(cv.width)
        self.heightBox.setValue(cv.height)

    def resizeEvent(self, event):
        self.mw.resizeEvent(event)

    def hideEvent(self, event):
        self.mw.resizeEvent(event)

    def showEvent(self, event):
        self.mw.resizeEvent(event)

    def moveEvent(self, event):
        self.mw.resizeEvent(event)
Esempio n. 20
0
class GameSettingsDialog(QDialog):
    def __init__(self, parent=None):
        super(GameSettingsDialog, self).__init__(parent)
        self.parent = parent
        self.setModal(True)
        self.setWindowTitle("Game settings")
        self.create_widgets()
        self.set_layouts()

    def create_widgets(self):
        self.label_player1 = QLabel("Player 1")
        self.input_player1_name = QLineEdit()
        self.input_player1_name.setPlaceholderText("Player 1")
        self.input_player1_name.setFocus()
        self.player1_completer = QCompleter()
        self.input_player1_name.setCompleter(self.player1_completer)

        self.label_player2 = QLabel("Player 2")
        self.input_player2_name = QLineEdit()
        self.input_player2_name.setPlaceholderText("Player 2")
        self.player2_completer = QCompleter()
        self.input_player2_name.setCompleter(self.player2_completer)
        # player widget-ek feltültése a db-ben szereplő nevekkel, autocomplete-hez
        self.get_player_name()

        self.gomb_301 = QRadioButton("301")
        self.gomb_401 = QRadioButton("401")
        self.gomb_501 = QRadioButton("501")
        self.gomb_501.setChecked(True)
        self.gomb_701 = QRadioButton("701")

        self.label_bestof = QLabel("Best Of.. (Egyébként First To..)")
        self.best_of = QCheckBox()

        self.spin_legs = QSpinBox()
        self.spin_legs.setValue(3)
        self.spin_legs.setMinimum(1)
        self.spin_legs.setMaximum(21)

        self.spin_sets = QSpinBox()
        self.spin_sets.setValue(1)
        self.spin_sets.setMinimum(1)
        self.spin_sets.setMaximum(15)

        self.handi1 = QSpinBox()
        self.handi1.setValue(0)
        self.handi1.setMinimum(-100)
        self.handi1.setMaximum(100)

        self.handi2 = QSpinBox()
        self.handi2.setValue(0)
        self.handi2.setMinimum(-100)
        self.handi2.setMaximum(100)

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

    def set_layouts(self):
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        self.kontener_names = QHBoxLayout()
        self.kontener_names.addWidget(self.label_player1)
        self.kontener_names.addWidget(self.input_player1_name)
        self.kontener_names.addWidget(self.label_player2)
        self.kontener_names.addWidget(self.input_player2_name)

        self.kontener_buttons = QHBoxLayout()
        self.kontener_buttons.addWidget(self.gomb_301)
        self.kontener_buttons.addWidget(self.gomb_401)
        self.kontener_buttons.addWidget(self.gomb_501)
        self.kontener_buttons.addWidget(self.gomb_701)

        self.bestof_layout = QHBoxLayout()
        self.bestof_layout.addWidget(self.label_bestof)
        self.bestof_layout.addWidget(self.best_of)

        self.kontener_szovegek1 = QVBoxLayout()
        self.kontener_szovegek1.addWidget(
            QLabel("Leave Player 2 blank for single player"))
        self.kontener_szovegek1.addWidget(QLabel("Variant"))

        self.kontener_sets = QHBoxLayout()
        self.kontener_sets.addWidget(QLabel("Legs per set: "))
        self.kontener_sets.addWidget(self.spin_legs)
        self.kontener_sets.addWidget(QLabel("Number os sets: "))
        self.kontener_sets.addWidget(self.spin_sets)

        self.kontener_handi = QHBoxLayout()
        self.kontener_handi.addWidget(QLabel("Handicap (1)"))
        self.kontener_handi.addWidget(self.handi1)
        self.kontener_handi.addWidget(QLabel("Handicap (2)"))
        self.kontener_handi.addWidget(self.handi2)

        self.layout.addLayout(self.kontener_names)
        self.layout.addLayout(self.kontener_szovegek1)
        self.layout.addLayout(self.kontener_buttons)
        self.layout.addLayout(self.bestof_layout)
        self.layout.addLayout(self.kontener_sets)
        self.layout.addLayout(self.kontener_handi)
        self.layout.addWidget(self.buttonbox)

    def get_player_name(self):
        player_name_model = QSqlQueryModel()
        query = QSqlQuery(
            "SELECT player_name  FROM players where type='local' and aktiv=1 order by player_name",
            db=db)
        player_name_model.setQuery(query)
        self.player1_completer.setModel(player_name_model)
        self.player2_completer.setModel(player_name_model)

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

    def alapertekek(self):
        self.input_player1_name.setText("")
        self.input_player1_name.setPlaceholderText("Player 1 name")
        self.input_player2_name.setText("")
        self.input_player2_name.setPlaceholderText("Player 2 name")
        self.gomb_501.setChecked(True)
        self.best_of.setChecked(False)
        self.spin_legs.setValue(3)
        self.spin_sets.setValue(1)
        self.handi1.setValue(0)
        self.handi2.setValue(0)

    def accept(self):
        params = []
        m_id = p1_id = p2_id = set = leg = hc1 = hc2 = 0
        var = ""
        player1 = self.input_player1_name.text()
        player2 = self.input_player2_name.text()
        # todo A MATCH_ID-T VALAMI EGYEDI MÓDON KELL GENERÁLNI(pl. az időbélyeg bizonyos részével)
        m_id = random.randint(10, 1000000)
        leg = self.spin_legs.value()
        set = self.spin_sets.value()
        hc1 = self.handi1.value()
        hc2 = self.handi2.value()
        if self.gomb_301.isChecked():
            var = "301"
        elif self.gomb_401.isChecked():
            var = "401"
        elif self.gomb_501.isChecked():
            var = "501"
        else:
            var = "701"

        if self.best_of.isChecked():
            bestof = 1
        else:
            bestof = 0

        if len(player1) == 0:
            p1_id = 1
            player1 = "Player 1"
        else:
            player1_id_model = QSqlQueryModel()
            query1 = QSqlQuery(
                f"SELECT player_id FROM players where player_name = '{player1}' and type='local' and aktiv=1",
                db=db)
            player1_id_model.setQuery(query1)
            # todo megnézni, hogy sima query.exec_ -el hogyan működik, lehet-e ellenőrizni, hogy üres vagy nem
            if player1_id_model.record(0).value(0):
                p1_id = int(player1_id_model.record(0).value(0))
            else:
                # todo beszúrás előtt ellenőritni, hogy egyedi-e. Létezhet versenyen felvitt ugyanolyan név
                player_model1 = QSqlTableModel()
                player_model1.setTable("players")
                rec_play1 = player_model1.record()
                rec_play1.remove(0)
                rec_play1.setValue(0, player1)
                rec_play1.setValue(1, 'local')
                rec_play1.setValue(2, 1)
                if player_model1.insertRecord(-1, rec_play1):
                    player_model1.submitAll()
                else:
                    db.rollback()
                query1 = QSqlQuery(
                    f"SELECT player_id FROM players where player_name = '{player1}' and type='local' and aktiv=1",
                    db=db)
                player1_id_model.setQuery(query1)
                # todo megnézni, hogy sima query.exec_ -el hogyan működik, lehet-e ellenőrizni, hogy üres vagy nem
                p1_id = int(player1_id_model.record(0).value(0))

        if len(player2) == 0:
            p2_id = 2
            player2 = "Player 2"
        else:
            player2_id_model = QSqlQueryModel()
            query2 = QSqlQuery(
                f"SELECT player_id FROM players where player_name = '{player2}' and type='local' and aktiv=1",
                db=db)
            player2_id_model.setQuery(query2)
            # todo megnézni, hogy sima query.exec_ -el hogyan működik, lehet-e ellenőrizni, hogy üres vagy nem
            if player2_id_model.record(0).value(0):
                p2_id = int(player2_id_model.record(0).value(0))
            else:
                player_model2 = QSqlTableModel()
                player_model2.setTable("players")
                rec_play2 = player_model2.record()
                rec_play2.remove(0)
                rec_play2.setValue(0, player2)
                rec_play2.setValue(1, 'local')
                rec_play2.setValue(2, 1)
                if player_model2.insertRecord(-1, rec_play2):
                    player_model2.submitAll()
                else:
                    db.rollback()
                query2 = QSqlQuery(
                    f"SELECT player_id FROM players where player_name = '{player2}' and type='local' and aktiv=1",
                    db=db)
                player2_id_model.setQuery(query2)
                # todo megnézni, hogy sima query.exec_ -el hogyan működik, lehet-e ellenőrizni, hogy üres vagy nem
                p2_id = int(player2_id_model.record(0).value(0))

        # Match paremeterek rögzítése
        now = QDateTime.currentDateTime()
        match_model = QSqlTableModel()
        match_model.setTable("match_settings")
        # todo Best Of... nincs db-ben tárolva
        record = match_model.record()
        record.setValue(0, m_id)
        record.setValue(1, p1_id)
        record.setValue(2, p2_id)
        record.setValue(3, var)
        record.setValue(4, leg)
        record.setValue(5, set)
        record.setValue(6, hc1)
        record.setValue(7, hc2)
        record.setValue(8, now)
        if match_model.insertRecord(-1, record):
            match_model.submitAll()
        else:
            db.rollback()
        params.append(player1)
        params.append(player2)
        params.append(m_id)
        params.append(p1_id)
        params.append(p2_id)
        params.append(var)
        params.append(leg)
        params.append(set)
        params.append(hc1)
        params.append(hc2)
        params.append(bestof)
        self.parent.new_game_window.params = params
        self.parent.new_game_window.refresh()
        super().accept()

    def reject(self):
        self.parent.new_game_window.close()
        super().reject()
Esempio n. 21
0
class ColorDialog(QDialog):
    def __init__(self, model, FM, parent=None):
        super(ColorDialog, self).__init__(parent)

        self.setWindowTitle('Color Options')

        self.model = model
        self.FM = FM
        self.mw = parent

        self.createDialogLayout()

    def createDialogLayout(self):

        self.createGeneralTab()

        self.cellTable = self.createDomainTable(self.mw.cellsModel)
        self.matTable = self.createDomainTable(self.mw.materialsModel)
        self.cellTab = self.createDomainTab(self.cellTable)
        self.matTab = self.createDomainTab(self.matTable)

        self.tabs = QTabWidget()
        self.tabs.setMaximumHeight(800)
        self.tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.tabs.addTab(self.generalTab, 'General')
        self.tabs.addTab(self.cellTab, 'Cells')
        self.tabs.addTab(self.matTab, 'Materials')

        self.createButtonBox()

        self.colorDialogLayout = QVBoxLayout()
        #self.colorDialogLayout.setContentsMargins(0, 0, 0, 0)
        self.colorDialogLayout.addWidget(self.tabs)
        self.colorDialogLayout.addWidget(self.buttonBox)
        self.setLayout(self.colorDialogLayout)

    def createGeneralTab(self):

        # Masking options
        self.maskingCheck = QCheckBox('')
        self.maskingCheck.stateChanged.connect(self.mw.toggleMasking)

        self.maskColorButton = QPushButton()
        self.maskColorButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.maskColorButton.setFixedWidth(self.FM.width("XXXXXXXXXX"))
        self.maskColorButton.setFixedHeight(self.FM.height() * 1.5)
        self.maskColorButton.clicked.connect(self.mw.editMaskingColor)

        # Highlighting options
        self.hlCheck = QCheckBox('')
        self.hlCheck.stateChanged.connect(self.mw.toggleHighlighting)

        self.hlColorButton = QPushButton()
        self.hlColorButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.hlColorButton.setFixedWidth(self.FM.width("XXXXXXXXXX"))
        self.hlColorButton.setFixedHeight(self.FM.height() * 1.5)
        self.hlColorButton.clicked.connect(self.mw.editHighlightColor)

        self.alphaBox = QDoubleSpinBox()
        self.alphaBox.setRange(0, 1)
        self.alphaBox.setSingleStep(.05)
        self.alphaBox.valueChanged.connect(self.mw.editAlpha)

        self.seedBox = QSpinBox()
        self.seedBox.setRange(1, 999)
        self.seedBox.valueChanged.connect(self.mw.editSeed)

        # General options
        self.bgButton = QPushButton()
        self.bgButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.bgButton.setFixedWidth(self.FM.width("XXXXXXXXXX"))
        self.bgButton.setFixedHeight(self.FM.height() * 1.5)
        self.bgButton.clicked.connect(self.mw.editBackgroundColor)

        self.colorbyBox = QComboBox(self)
        self.colorbyBox.addItem("material")
        self.colorbyBox.addItem("cell")
        self.colorbyBox.currentTextChanged[str].connect(self.mw.editColorBy)

        formLayout = QFormLayout()
        formLayout.setAlignment(QtCore.Qt.AlignHCenter)
        formLayout.setFormAlignment(QtCore.Qt.AlignHCenter)
        formLayout.setLabelAlignment(QtCore.Qt.AlignLeft)
        #formLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow)

        formLayout.addRow('Masking:', self.maskingCheck)
        formLayout.addRow('Mask Color:', self.maskColorButton)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Highlighting:', self.hlCheck)
        formLayout.addRow('Highlight Color:', self.hlColorButton)
        formLayout.addRow('Highlight Alpha:', self.alphaBox)
        formLayout.addRow('Highlight Seed:', self.seedBox)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Background Color:          ', self.bgButton)
        formLayout.addRow('Color Plot By:', self.colorbyBox)

        generalLayout = QHBoxLayout()
        innerWidget = QWidget()
        generalLayout.setAlignment(QtCore.Qt.AlignVCenter)
        innerWidget.setLayout(formLayout)
        generalLayout.addStretch(1)
        generalLayout.addWidget(innerWidget)
        generalLayout.addStretch(1)

        self.generalTab = QWidget()
        self.generalTab.setLayout(generalLayout)

    def createDomainTable(self, domainmodel):

        domainTable = QTableView()
        domainTable.setModel(domainmodel)
        domainTable.setItemDelegate(DomainDelegate(domainTable))
        domainTable.verticalHeader().setVisible(False)
        domainTable.resizeColumnsToContents()
        domainTable.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        domainTable.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Stretch)

        return domainTable

    def createDomainTab(self, domaintable):

        domainTab = QWidget()
        domainTab.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        domainLayout = QVBoxLayout()
        domainLayout.addWidget(domaintable)
        domainTab.setLayout(domainLayout)

        return domainTab

    def createButtonBox(self):

        applyButton = QPushButton("Apply Changes")
        applyButton.clicked.connect(self.mw.applyChanges)
        closeButton = QPushButton("Close")
        closeButton.clicked.connect(self.hide)

        buttonLayout = QHBoxLayout()
        buttonLayout.addStretch(1)
        buttonLayout.addWidget(applyButton)
        buttonLayout.addWidget(closeButton)

        self.buttonBox = QWidget()
        self.buttonBox.setLayout(buttonLayout)

    def updateDialogValues(self):

        self.updateMasking()
        self.updateMaskingColor()
        self.updateHighlighting()
        self.updateHighlightColor()
        self.updateAlpha()
        self.updateSeed()
        self.updateBackgroundColor()
        self.updateColorBy()

        self.updateDomainTabs()

    def updateMasking(self):
        masking = self.model.activeView.masking

        self.maskingCheck.setChecked(masking)
        self.maskColorButton.setDisabled(not masking)

        if masking:
            self.cellTable.showColumn(4)
            self.matTable.showColumn(4)
        else:
            self.cellTable.hideColumn(4)
            self.matTable.hideColumn(4)

    def updateMaskingColor(self):
        color = self.model.activeView.maskBackground
        self.maskColorButton.setStyleSheet("border-radius: 8px;"
                                           "background-color: rgb%s" %
                                           (str(color)))

    def updateHighlighting(self):
        highlighting = self.model.activeView.highlighting

        self.hlCheck.setChecked(highlighting)
        self.hlColorButton.setDisabled(not highlighting)
        self.alphaBox.setDisabled(not highlighting)
        self.seedBox.setDisabled(not highlighting)

        if highlighting:
            self.cellTable.showColumn(5)
            self.cellTable.hideColumn(2)
            self.cellTable.hideColumn(3)
            self.matTable.showColumn(5)
            self.matTable.hideColumn(2)
            self.matTable.hideColumn(3)
        else:
            self.cellTable.hideColumn(5)
            self.cellTable.showColumn(2)
            self.cellTable.showColumn(3)
            self.matTable.hideColumn(5)
            self.matTable.showColumn(2)
            self.matTable.showColumn(3)

    def updateHighlightColor(self):
        color = self.model.activeView.highlightBackground
        self.hlColorButton.setStyleSheet("border-radius: 8px;"
                                         "background-color: rgb%s" %
                                         (str(color)))

    def updateAlpha(self):
        self.alphaBox.setValue(self.model.activeView.highlightAlpha)

    def updateSeed(self):
        self.seedBox.setValue(self.model.activeView.highlightSeed)

    def updateBackgroundColor(self):
        color = self.model.activeView.plotBackground
        self.bgButton.setStyleSheet("border-radius: 8px;"
                                    "background-color: rgb%s" % (str(color)))

    def updateColorBy(self):
        self.colorbyBox.setCurrentText(self.model.activeView.colorby)

    def updateDomainTabs(self):
        self.cellTable.setModel(self.mw.cellsModel)
        self.matTable.setModel(self.mw.materialsModel)
Esempio n. 22
0
class ElaWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(ElaWidget, self).__init__(parent)

        self.quality_spin = QSpinBox()
        self.quality_spin.setRange(0, 100)
        self.quality_spin.setSuffix(self.tr(' %'))
        self.quality_spin.setToolTip(self.tr('JPEG reference quality level'))
        self.scale_spin = QSpinBox()
        self.scale_spin.setRange(1, 100)
        self.scale_spin.setSuffix(' %')
        self.scale_spin.setToolTip(self.tr('Output multiplicative gain'))
        self.contrast_spin = QSpinBox()
        self.contrast_spin.setRange(0, 100)
        self.contrast_spin.setSuffix(' %')
        self.contrast_spin.setToolTip(self.tr('Output tonality compression'))
        self.equalize_check = QCheckBox(self.tr('Equalized'))
        self.equalize_check.setToolTip(self.tr('Apply histogram equalization'))
        self.gray_check = QCheckBox(self.tr('Grayscale'))
        self.gray_check.setToolTip(self.tr('Desaturated output'))
        default_button = QPushButton(self.tr('Default'))
        default_button.setToolTip(self.tr('Revert to default parameters'))

        params_layout = QHBoxLayout()
        params_layout.addWidget(QLabel(self.tr('Quality:')))
        params_layout.addWidget(self.quality_spin)
        params_layout.addWidget(QLabel(self.tr('Scale:')))
        params_layout.addWidget(self.scale_spin)
        params_layout.addWidget(QLabel(self.tr('Contrast:')))
        params_layout.addWidget(self.contrast_spin)
        params_layout.addWidget(self.equalize_check)
        params_layout.addWidget(self.gray_check)
        params_layout.addWidget(default_button)
        params_layout.addStretch()

        self.image = image
        self.original = image.astype(np.float32) / 255
        self.viewer = ImageViewer(self.image, self.image)
        self.default()

        self.quality_spin.valueChanged.connect(self.process)
        self.scale_spin.valueChanged.connect(self.process)
        self.contrast_spin.valueChanged.connect(self.process)
        self.equalize_check.stateChanged.connect(self.process)
        self.gray_check.stateChanged.connect(self.process)
        default_button.clicked.connect(self.default)

        main_layout = QVBoxLayout()
        main_layout.addLayout(params_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def process(self):
        start = time()
        quality = self.quality_spin.value()
        scale = self.scale_spin.value() / 20
        contrast = int(self.contrast_spin.value() / 100 * 128)
        equalize = self.equalize_check.isChecked()
        grayscale = self.gray_check.isChecked()
        self.scale_spin.setEnabled(not equalize)
        self.contrast_spin.setEnabled(not equalize)
        compressed = compress_jpeg(self.image, quality).astype(np.float32) / 255
        difference = cv.absdiff(self.original, compressed)
        if equalize:
            ela = equalize_img((difference * 255).astype(np.uint8))
        else:
            ela = cv.convertScaleAbs(cv.sqrt(difference) * 255, None, scale)
            ela = cv.LUT(ela, create_lut(contrast, contrast))
        if grayscale:
            ela = desaturate(ela)
        self.viewer.update_processed(ela)
        self.info_message.emit(self.tr('Error Level Analysis = {}'.format(elapsed_time(start))))

    def default(self):
        self.blockSignals(True)
        self.equalize_check.setChecked(False)
        self.gray_check.setChecked(False)
        self.quality_spin.setValue(75)
        self.scale_spin.setValue(50)
        self.contrast_spin.setValue(20)
        self.process()
        self.blockSignals(False)
Esempio n. 23
0
class ResultEditDialog(QDialog):
    def __init__(self, result, is_new=False):
        super().__init__(GlobalAccess().get_main_window())
        assert (isinstance(result, Result))
        self.current_object = result
        self.is_new = is_new

        self.time_format = 'hh:mm:ss'
        time_accuracy = race().get_setting('time_accuracy', 0)
        if time_accuracy:
            self.time_format = 'hh:mm:ss.zzz'

    def exec_(self):
        self.init_ui()
        self.set_values_from_model()
        return super().exec_()

    def init_ui(self):
        self.setWindowTitle(_('Result'))
        self.setWindowIcon(QIcon(config.ICON))
        self.setSizeGripEnabled(False)
        self.setModal(True)
        self.setMaximumWidth(300)

        self.layout = QFormLayout(self)

        self.item_created_at = QTimeEdit()
        self.item_created_at.setDisplayFormat(self.time_format)
        self.item_created_at.setReadOnly(True)

        self.item_card_number = QSpinBox()
        self.item_card_number.setMaximum(9999999)

        self.item_bib = QSpinBox()
        self.item_bib.setMaximum(Limit.BIB)
        self.item_bib.valueChanged.connect(self.show_person_info)

        self.label_person_info = QLabel('')

        self.item_days = QSpinBox()
        self.item_days.setMaximum(365)

        self.item_finish = QTimeEdit()
        self.item_finish.setDisplayFormat(self.time_format)

        self.item_start = QTimeEdit()
        self.item_start.setDisplayFormat(self.time_format)

        self.item_result = QLineEdit()
        self.item_result.setEnabled(False)

        self.item_credit = QTimeEdit()
        self.item_credit.setDisplayFormat(self.time_format)

        self.item_penalty = QTimeEdit()
        self.item_penalty.setDisplayFormat(self.time_format)

        self.item_penalty_laps = QSpinBox()
        self.item_penalty_laps.setMaximum(1000000)

        self.item_status = QComboBox()
        self.item_status.addItems(ResultStatus.get_titles())

        self.item_status_comment = AdvComboBox()
        self.item_status_comment.setMaximumWidth(300)
        self.item_status_comment.view().setMinimumWidth(600)
        self.item_status_comment.addItems(StatusComments().get_all())
        for i, k in enumerate(StatusComments().get_all()):
            self.item_status_comment.setItemData(i, k, Qt.ToolTipRole)

        more24 = race().get_setting('time_format_24', 'less24') == 'more24'
        self.splits = SplitsText(more24=more24)

        self.layout.addRow(QLabel(_('Created at')), self.item_created_at)
        if self.current_object.is_punch():
            self.layout.addRow(QLabel(_('Card')), self.item_card_number)
        self.layout.addRow(QLabel(_('Bib')), self.item_bib)
        self.layout.addRow(QLabel(''), self.label_person_info)
        if more24:
            self.layout.addRow(QLabel(_('Days')), self.item_days)
        self.layout.addRow(QLabel(_('Start')), self.item_start)
        self.layout.addRow(QLabel(_('Finish')), self.item_finish)
        self.layout.addRow(QLabel(_('Credit')), self.item_credit)
        self.layout.addRow(QLabel(_('Penalty')), self.item_penalty)
        self.layout.addRow(QLabel(_('Penalty legs')), self.item_penalty_laps)
        self.layout.addRow(QLabel(_('Result')), self.item_result)
        self.layout.addRow(QLabel(_('Status')), self.item_status)
        self.layout.addRow(QLabel(_('Comment')), self.item_status_comment)

        if self.current_object.is_punch():
            start_source = race().get_setting('system_start_source', 'protocol')
            finish_source = race().get_setting('system_finish_source', 'station')
            if start_source == 'protocol' or start_source == 'cp':
                self.item_start.setDisabled(True)
            if finish_source == 'cp':
                self.item_finish.setDisabled(True)
            self.layout.addRow(self.splits.widget)

        def cancel_changes():
            self.close()

        def apply_changes():
            try:
                self.apply_changes_impl()
            except Exception as e:
                logging.error(str(e))
            self.close()

        button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_ok = button_box.button(QDialogButtonBox.Ok)
        self.button_ok.setText(_('OK'))
        self.button_ok.clicked.connect(apply_changes)
        self.button_cancel = button_box.button(QDialogButtonBox.Cancel)
        self.button_cancel.setText(_('Cancel'))
        self.button_cancel.clicked.connect(cancel_changes)

        if self.current_object.person:
            button_person = button_box.addButton(_('Entry properties'), QDialogButtonBox.ActionRole)
            button_person.clicked.connect(self.open_person)

        self.layout.addRow(button_box)

        self.show()
        self.item_bib.setFocus()

    def show_person_info(self):
        bib = self.item_bib.value()
        self.label_person_info.setText('')
        if bib:
            person = find(race().persons, bib=bib)
            if person:
                info = person.full_name
                if person.group:
                    info = '{}\n{}: {}'.format(info, _('Group'), person.group.name)
                if person.card_number:
                    info = '{}\n{}: {}'.format(info, _('Card'), person.card_number)
                self.label_person_info.setText(info)
            else:
                self.label_person_info.setText(_('not found'))

    def set_values_from_model(self):
        if self.current_object.is_punch():
            if self.current_object.card_number:
                self.item_card_number.setValue(int(self.current_object.card_number))
            self.splits.splits(self.current_object.splits)
            self.splits.show()
        if self.current_object.created_at:
            self.item_created_at.setTime(time_to_qtime(datetime.fromtimestamp(self.current_object.created_at)))
        if self.current_object.finish_time:
            self.item_finish.setTime(time_to_qtime(self.current_object.finish_time))
        if self.current_object.start_time is not None:
            self.item_start.setTime(time_to_qtime(self.current_object.start_time))
        if self.current_object.finish_time:
            self.item_result.setText(str(self.current_object.get_result()))
        if self.current_object.credit_time is not None:
            self.item_credit.setTime(time_to_qtime(self.current_object.credit_time))
        if self.current_object.penalty_time is not None:
            self.item_penalty.setTime(time_to_qtime(self.current_object.penalty_time))
        if self.current_object.penalty_laps:
            self.item_penalty_laps.setValue(self.current_object.penalty_laps)
        self.item_bib.setValue(self.current_object.get_bib())

        self.item_days.setValue(self.current_object.days)

        self.item_status.setCurrentText(self.current_object.status.get_title())

        self.item_status_comment.setCurrentText(self.current_object.status_comment)

        self.item_bib.selectAll()

    def open_person(self):
        try:
            PersonEditDialog(self.current_object.person).exec_()
        except Exception as e:
            logging.error(str(e))

    def apply_changes_impl(self):
        result = self.current_object
        if self.is_new:
            race().results.insert(0, result)

        if result.is_punch():
            if result.card_number != self.item_card_number.value():
                result.card_number = self.item_card_number.value()

            new_splits = self.splits.splits()
            if len(result.splits) == len(new_splits):
                for i, split in enumerate(result.splits):
                    if split != new_splits[i]:
                        break
            result.splits = new_splits

        time_ = time_to_otime(self.item_finish.time())
        if result.finish_time != time_:
            result.finish_time = time_

        time_ = time_to_otime(self.item_start.time())
        if result.start_time != time_:
            result.start_time = time_

        time_ = time_to_otime(self.item_credit.time())
        if result.credit_time != time_:
            result.credit_time = time_

        time_ = time_to_otime(self.item_penalty.time())
        if result.penalty_time != time_:
            result.penalty_time = time_

        if result.penalty_laps != self.item_penalty_laps.value():
            result.penalty_laps = self.item_penalty_laps.value()

        cur_bib = -1
        new_bib = self.item_bib.value()
        if result.person:
            cur_bib = result.person.bib

        if new_bib == 0:
            if result.person and result.is_punch():
                if result.person.card_number == result.card_number:
                    result.person.card_number = 0
            result.person = None
        elif cur_bib != new_bib:
            new_person = find(race().persons, bib=new_bib)
            if new_person is not None:
                assert isinstance(new_person, Person)
                if result.person:
                    if result.is_punch():
                        result.person.card_number = 0
                result.person = new_person
                if result.is_punch():
                    race().person_card_number(result.person, result.card_number)
            result.bib = new_bib

            GlobalAccess().get_main_window().get_result_table().model().init_cache()

        if self.item_days.value() != result.days:
            result.days = self.item_days.value()

        result.status = ResultStatus.get_by_name(self.item_status.currentText())

        status = StatusComments().remove_hint(self.item_status_comment.currentText())
        if result.status_comment != status:
            result.status_comment = status

        if result.is_punch():
            result.clear()
            try:
                ResultChecker.checking(result)
                ResultChecker.calculate_penalty(result)
                if result.person and result.person.group:
                    GroupSplits(race(), result.person.group).generate(True)
            except ResultCheckerException as e:
                logging.error(str(e))
        ResultCalculation(race()).process_results()
        Teamwork().send(result.to_dict())
Esempio n. 24
0
class WaveletWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(WaveletWidget, self).__init__(parent)

        self.family_combo = QComboBox()
        self.family_combo.addItems([
            self.tr("Daubechies"),
            self.tr("Symlets"),
            self.tr("Coiflets"),
            self.tr("Biorthogonal")
        ])
        self.wavelet_combo = QComboBox()
        self.wavelet_combo.setMinimumWidth(70)
        self.threshold_spin = QSpinBox()
        self.threshold_spin.setRange(0, 100)
        self.threshold_spin.setSuffix("%")
        self.mode_combo = QComboBox()
        self.mode_combo.addItems([
            self.tr("Soft"),
            self.tr("Hard"),
            self.tr("Garrote"),
            self.tr("Greater"),
            self.tr("Less")
        ])
        self.level_spin = QSpinBox()

        self.image = image
        self.coeffs = None
        self.viewer = ImageViewer(self.image, self.image)
        self.update_wavelet()

        self.family_combo.activated.connect(self.update_wavelet)
        self.wavelet_combo.activated.connect(self.update_level)
        self.threshold_spin.valueChanged.connect(self.compute_idwt)
        self.mode_combo.activated.connect(self.compute_idwt)
        self.level_spin.valueChanged.connect(self.compute_idwt)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr("Family:")))
        top_layout.addWidget(self.family_combo)
        top_layout.addWidget(QLabel(self.tr("Wavelet:")))
        top_layout.addWidget(self.wavelet_combo)
        top_layout.addWidget(QLabel(self.tr("Threshold:")))
        top_layout.addWidget(self.threshold_spin)
        top_layout.addWidget(QLabel(self.tr("Mode:")))
        top_layout.addWidget(self.mode_combo)
        top_layout.addWidget(QLabel(self.tr("Level:")))
        top_layout.addWidget(self.level_spin)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def update_wavelet(self):
        self.wavelet_combo.clear()
        family = self.family_combo.currentIndex()
        if family == 0:
            self.wavelet_combo.addItems([f"db{i}" for i in range(1, 21)])
        elif family == 1:
            self.wavelet_combo.addItems([f"sym{i}" for i in range(2, 21)])
        elif family == 2:
            self.wavelet_combo.addItems([f"coif{i}" for i in range(1, 6)])
        else:
            types = [
                "1.1",
                "1.3",
                "1.5",
                "2.2",
                "2.4",
                "2.6",
                "2.8",
                "3.1",
                "3.3",
                "3.5",
                "3.7",
                "3.9",
                "4.4",
                "5.5",
                "6.8",
            ]
            self.wavelet_combo.addItems([f"bior{t}" for t in types])
        self.update_level()

    def update_level(self):
        wavelet = self.wavelet_combo.currentText()
        max_level = pywt.dwtn_max_level(self.image.shape[:-1], wavelet)
        self.level_spin.blockSignals(True)
        self.level_spin.setRange(1, max_level)
        self.level_spin.setValue(max_level // 2)
        self.level_spin.blockSignals(False)
        self.compute_dwt()

    def compute_dwt(self):
        wavelet = self.wavelet_combo.currentText()
        self.coeffs = pywt.wavedec2(self.image[:, :, 0], wavelet)
        self.compute_idwt()

    def compute_idwt(self):
        thr = self.threshold_spin.value()
        if thr > 0:
            level = self.level_spin.value()
            coeffs = deepcopy(self.coeffs)
            threshold = self.threshold_spin.value() / 100
            mode = self.mode_combo.currentText().lower()
            for i in range(1, level + 1):
                octave = [None] * 3
                for j in range(3):
                    plane = coeffs[-i][j]
                    t = threshold * np.max(np.abs(plane))
                    octave[j] = pywt.threshold(plane, t, mode)
                coeffs[-i] = tuple(octave)
        else:
            coeffs = self.coeffs
        wavelet = self.wavelet_combo.currentText()
        image = cv.cvtColor(
            pywt.waverec2(coeffs, wavelet).astype(np.uint8), cv.COLOR_GRAY2BGR)
        self.viewer.update_processed(image)
Esempio n. 25
0
class GradientWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(GradientWidget, self).__init__(parent)
        self.intensity_spin = QSpinBox()
        self.intensity_spin.setRange(0, 100)
        self.intensity_spin.setValue(95)
        self.intensity_spin.setSuffix(self.tr(' %'))
        self.intensity_spin.setToolTip(self.tr('Tonality compression amount'))
        self.blue_combo = QComboBox()
        self.blue_combo.addItems([self.tr('None'), self.tr('Flat'), self.tr('Abs'), self.tr('Norm')])
        self.blue_combo.setCurrentIndex(2)
        self.blue_combo.setToolTip(self.tr('Blue component inclusion mode'))
        self.invert_check = QCheckBox(self.tr('Invert'))
        self.invert_check.setToolTip(self.tr('Reverse lighting direction'))
        self.equalize_check = QCheckBox(self.tr('Equalize'))
        self.equalize_check.setToolTip(self.tr('Apply histogram equalization'))

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.dx, self.dy = cv.spatialGradient(cv.cvtColor(self.image, cv.COLOR_BGR2GRAY))
        self.process()

        self.intensity_spin.valueChanged.connect(self.process)
        self.blue_combo.currentIndexChanged.connect(self.process)
        self.invert_check.stateChanged.connect(self.process)
        self.equalize_check.stateChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Intensity:')))
        top_layout.addWidget(self.intensity_spin)
        top_layout.addWidget(QLabel(self.tr('Blue channel:')))
        top_layout.addWidget(self.blue_combo)
        top_layout.addWidget(self.invert_check)
        top_layout.addWidget(self.equalize_check)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)

        self.setLayout(main_layout)

    def process(self):
        start = time()
        intensity = int(self.intensity_spin.value() / 100 * 127)
        invert = self.invert_check.isChecked()
        equalize = self.equalize_check.isChecked()
        self.intensity_spin.setEnabled(not equalize)
        blue_mode = self.blue_combo.currentIndex()
        if invert:
            dx = (-self.dx).astype(np.float32)
            dy = (-self.dy).astype(np.float32)
        else:
            dx = (+self.dx).astype(np.float32)
            dy = (+self.dy).astype(np.float32)
        dx_abs = np.abs(dx)
        dy_abs = np.abs(dy)
        red = ((dx / np.max(dx_abs) * 127) + 127).astype(np.uint8)
        green = ((dy / np.max(dy_abs) * 127) + 127).astype(np.uint8)
        if blue_mode == 0:
            blue = np.zeros_like(red)
        elif blue_mode == 1:
            blue = np.full_like(red, 255)
        elif blue_mode == 2:
            blue = norm_mat(dx_abs + dy_abs)
        elif blue_mode == 3:
            blue = norm_mat(np.linalg.norm(cv.merge((red, green)), axis=2))
        else:
            blue = None
        gradient = cv.merge([blue, green, red])
        if equalize:
            gradient = equalize_img(gradient)
        elif intensity > 0:
            gradient = cv.LUT(gradient, create_lut(intensity, intensity))
        self.viewer.update_processed(gradient)
        self.info_message.emit(self.tr('Luminance Gradient = {}'.format(elapsed_time(start))))
Esempio n. 26
0
class GradientWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(GradientWidget, self).__init__(parent)
        self.levels_spin = QSpinBox()
        self.levels_spin.setRange(-1, 16)
        self.levels_spin.setSpecialValueText(self.tr('Auto'))
        self.levels_spin.setValue(-1)
        self.invert_check = QCheckBox(self.tr('Invert'))
        self.abs_check = QCheckBox(self.tr('Absolute'))

        self.grad_viewer = ImageViewer(image, image)
        self.image = image
        self.process()

        self.levels_spin.valueChanged.connect(self.process)
        self.invert_check.toggled.connect(self.process)
        self.abs_check.toggled.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Levels:')))
        top_layout.addWidget(self.levels_spin)
        top_layout.addWidget(self.invert_check)
        top_layout.addWidget(self.abs_check)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.grad_viewer)

        self.setLayout(main_layout)

    def process(self):
        intensity = self.levels_spin.value()
        invert = self.invert_check.isChecked()
        absolute = self.abs_check.isChecked()
        self.levels_spin.setEnabled(not absolute)
        self.invert_check.setEnabled(not absolute)

        gray = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        diff_x = cv.Scharr(gray, cv.CV_32F, 1, 0)
        diff_y = cv.Scharr(gray, cv.CV_32F, 0, 1)
        diff_z = cv.normalize(np.abs(diff_x + diff_y), None, 0, 255,
                              cv.NORM_MINMAX)
        diff_z = cv.LUT(diff_z.astype(np.uint8), create_lut(0, 90))
        grad_x = +diff_x if invert else -diff_x
        grad_y = +diff_y if invert else -diff_y
        grad_z = diff_z

        if not absolute:
            min_x, max_x, _, _ = cv.minMaxLoc(grad_x)
            lim_x = max(abs(min_x), abs(max_x))
            grad_x = (grad_x / lim_x + 1) * 127
            min_y, max_y, _, _ = cv.minMaxLoc(grad_y)
            lim_y = max(abs(min_y), abs(max_y))
            grad_y = (grad_y / lim_y + 1) * 127
        else:
            grad_x = cv.normalize(np.abs(grad_x), None, 0, 255, cv.NORM_MINMAX)
            grad_y = cv.normalize(np.abs(grad_y), None, 0, 255, cv.NORM_MINMAX)
        grad_x = grad_x.astype(np.uint8)
        grad_y = grad_y.astype(np.uint8)

        if intensity >= 0 and not absolute:
            max_intensity = self.levels_spin.maximum()
            low = 127 - (max_intensity - intensity)
            high = 127 + (max_intensity - intensity)
            lut_xy = create_lut(low, high)
            grad_x = cv.LUT(grad_x, lut_xy)
            grad_y = cv.LUT(grad_y, lut_xy)
        else:
            grad_x = cv.equalizeHist(grad_x)
            grad_y = cv.equalizeHist(grad_y)
        gradient = np.stack((grad_z, grad_x, grad_y), axis=2)
        self.grad_viewer.update_processed(gradient)
Esempio n. 27
0
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.attach_event()
        self.setAcceptDrops(True)
        
    def init_ui(self):
        # Define & Configure Components
        normal_button_size = QSize(80, 24)
        icon_button_size = QSize(24, 24)
        icon_size = QSize(18, 18)
        
        self.central_widget = QWidget()
        self.central_layout = QGridLayout()
        self.central_widget.setLayout(self.central_layout)

        self.tab_group_widget = QTabWidget()
        self.tab_group_widget.setMinimumSize(400, 0)
        self.tab_group_widget.setFixedHeight(150)
        self.tab1_name = '스폰서 변환'
        self.tab2_name = '싱크 조절(초)'
        self.tab3_name = '싱크 조절(%)'

        self.tab_page_1 = QWidget()
        self.tab_grid_1 = QGridLayout()
        self.tab1_search_label = QLabel('검색 텍스트')
        self.tab1_search = QLineEdit()
        self.tab1_sponsor = QWidget()
        self.tab1_sponsor_layout = QHBoxLayout()
        self.tab1_sponsor_layout.setContentsMargins(0, 0, 0, 0)
        self.tab1_sponsor_label = QLabel('스폰서 영상 길이')
        self.tab1_sponsor_value = QDoubleSpinBox()
        self.tab1_sponsor_value.setFixedWidth(60)
        self.tab1_sponsor_value.setMinimum(-1000000000)
        self.tab1_sponsor_value.setValue(10)
        self.tab1_offset = QWidget()
        self.tab1_offset_layout = QHBoxLayout()
        self.tab1_offset_layout.setContentsMargins(0, 0, 0, 0)
        self.tab1_offset_label = QLabel('라인 오프셋')
        self.tab1_offset_value = QSpinBox()
        self.tab1_offset_value.setMinimum(-1000000000)
        self.tab1_offset_value.setValue(2)
        self.tab1_offset_value.setFixedWidth(50)
        self.tab1_ignore = QWidget()
        self.tab1_ignore_layout = QHBoxLayout()
        self.tab1_ignore_layout.setContentsMargins(0, 0, 0, 0)
        self.tab1_ignore_label1 = QLabel('시작부터')
        self.tab1_ignore_value = QSpinBox()
        self.tab1_ignore_value.setFixedWidth(50)
        self.tab1_ignore_value.setValue(5)
        self.tab1_ignore_label2 = QLabel('줄 ')
        self.tab1_ignore_sec = QSpinBox()
        self.tab1_ignore_sec.setFixedWidth(60)
        self.tab1_ignore_sec.setMaximum(1000)
        self.tab1_ignore_sec.setValue(90)
        self.tab1_ignore_label3 = QLabel('초 무시하기')
        self.tab1_add_button = QPushButton('추가하기')

        self.tab_page_2 = QWidget()
        self.tab_grid_2 = QGridLayout()
        self.tab2_shift = QWidget()
        self.tab2_shift_layout = QHBoxLayout()
        self.tab2_shift_layout.setContentsMargins(0, 0, 0, 0)
        self.tab2_shift_label1 = QLabel('자막 싱크')
        self.tab2_shift_value = QDoubleSpinBox()
        self.tab2_shift_value.setFixedWidth(60)
        self.tab2_shift_label2 = QLabel('초 ')
        self.tab2_slow_radio = QRadioButton('느리게')
        self.tab2_slow_radio.setChecked(True)
        self.tab2_fast_radio = QRadioButton('빠르게')
        self.tab2_add_button = QPushButton('추가하기')

        self.tab_page_3 = QWidget()
        self.tab_grid_3 = QGridLayout()
        self.tab3_speed_label1 = QLabel('자막 싱크')
        self.tab3_speed_value = QSpinBox()
        self.tab3_speed_value.setFixedWidth(70)
        self.tab3_speed_value.setRange(1, 1000)
        self.tab3_speed_value.setValue(100)
        self.tab3_speed_label2 = QLabel('%')
        self.tab3_add_button = QPushButton('추가하기')

        self.que_label = QLabel('작업 목록')
        self.que_label.setFixedHeight(24)
        self.que_widget = QWidget()
        self.que_widget.setFixedHeight(114)
        self.que_layout = QGridLayout()
        self.que_layout.setContentsMargins(0, 0, 0, 0)
        self.que_list = QTreeWidget()
        self.que_list.setHeaderLabels(['작업', '옵션'])
        self.que_delete_button = QPushButton(QIcon(':/remove.png'), '')
        self.que_delete_button.setFixedSize(icon_button_size)
        self.que_delete_button.setIconSize(icon_size)
        self.que_delete_button.setToolTip('목록 삭제')
        self.que_up_button = QPushButton(QIcon(':/up.png'), '')
        self.que_up_button.setIconSize(icon_size)
        self.que_up_button.setFixedSize(icon_button_size)
        self.que_up_button.setToolTip('위로')
        self.que_down_button = QPushButton(QIcon(':/down.png'), '')
        self.que_down_button.setIconSize(icon_size)
        self.que_down_button.setFixedSize(icon_button_size)
        self.que_down_button.setToolTip('아래로')
        self.que_clear_button = QPushButton(QIcon(':/clear.png'), '')
        self.que_clear_button.setIconSize(icon_size)
        self.que_clear_button.setFixedSize(icon_button_size)
        self.que_clear_button.setToolTip('비우기')

        self.file_label = QLabel('파일 목록')
        self.file_label.setFixedHeight(24)
        self.file_widget = QWidget()
        self.file_layout = QGridLayout()
        self.file_layout.setContentsMargins(0, 0, 0, 0)
        self.file_list = QTreeWidget()
        self.file_list.setAcceptDrops(True)
        self.file_list.setHeaderLabels(['이름', '경로'])
        self.file_file_open = QPushButton(QIcon(':/file.png'), '')
        self.file_file_open.setFixedSize(icon_button_size)
        self.file_file_open.setIconSize(icon_size)
        self.file_file_open.setToolTip('파일 열기')
        self.file_dir_open = QPushButton(QIcon(':/folder.png'), '')
        self.file_dir_open.setFixedSize(icon_button_size)
        self.file_dir_open.setIconSize(icon_size)
        self.file_dir_open.setToolTip('폴더 열기')
        self.file_delete = QPushButton(QIcon(':/remove.png'), '')
        self.file_delete.setFixedSize(icon_button_size)
        self.file_delete.setIconSize(icon_size)
        self.file_delete.setToolTip('목록 삭제')
        self.file_clear = QPushButton(QIcon(':/clear.png'), '')
        self.file_clear.setFixedSize(icon_button_size)
        self.file_clear.setIconSize(icon_size)
        self.file_clear.setToolTip('비우기')
        self.file_encode = QPushButton(QIcon(':/encode.png'), '')
        self.file_encode.setFixedSize(icon_button_size)
        self.file_encode.setIconSize(icon_size)
        self.file_encode.setToolTip('인코딩 설정')

        self.save_widget = QGroupBox('저장 옵션')
        self.save_widget.setMinimumSize(400, 0)
        self.save_widget.setFixedHeight(82)
        self.save_layout = QGridLayout()
        self.save_orig_radio = QRadioButton('원본 위치에 저장')
        self.save_orig_radio.setChecked(True)
        self.save_strip = QCheckBox('싱크 꼬임 무시')
        self.save_strip.setToolTip('싱크 꼬임을 무시하고 모든 자막을 보존합니다.')
        self.save_dir_radio = QRadioButton('다른 위치에 저장')
        self.save_dir_line = QLineEdit()
        self.save_dir_find = QPushButton('...')
        self.save_dir_find.setFixedWidth(40)

        self.ok_button = QPushButton('적용')
        self.ok_button.setFixedSize(normal_button_size)
        self.cancel_button = QPushButton('취소')
        self.cancel_button.setFixedSize(normal_button_size)

        # Display GUI Components
        self.central_layout.addWidget(self.tab_group_widget, 0, 0, 1, 3)
        self.central_layout.addWidget(self.que_label, 1, 0, 1, 3)
        self.central_layout.addWidget(self.que_widget, 2, 0, 1, 3)
        self.central_layout.addWidget(self.file_label, 3, 0, 1, 3)
        self.central_layout.addWidget(self.file_widget, 4, 0, 1, 3)
        self.central_layout.addWidget(self.save_widget, 5, 0, 1, 3)
        self.central_layout.addWidget(self.ok_button, 6, 1, 1, 1)
        self.central_layout.addWidget(self.cancel_button, 6, 2, 1, 1)

        self.tab_group_widget.addTab(self.tab_page_1, QIcon(), self.tab1_name)
        self.tab_group_widget.addTab(self.tab_page_2, QIcon(), self.tab2_name)
        self.tab_group_widget.addTab(self.tab_page_3, QIcon(), self.tab3_name)

        self.tab_page_1.setLayout(self.tab_grid_1)
        self.tab_grid_1.addWidget(self.tab1_search_label, 0, 0, 1, 1)
        self.tab_grid_1.addWidget(self.tab1_search, 0, 1, 1, 2)
        self.tab_grid_1.addWidget(self.tab1_sponsor, 1, 1, 1, 1)
        self.tab_grid_1.addWidget(self.tab1_offset, 1, 2, 1, 1)
        self.tab_grid_1.addWidget(self.tab1_ignore, 2, 1, 1, 2)
        self.tab_grid_1.addWidget(self.tab1_add_button, 3, 0, 1, 3)
        self.tab1_sponsor.setLayout(self.tab1_sponsor_layout)
        self.tab1_sponsor_layout.addWidget(self.tab1_sponsor_label)
        self.tab1_sponsor_layout.addWidget(self.tab1_sponsor_value)
        self.tab1_sponsor_layout.addStretch(1)
        self.tab1_offset.setLayout(self.tab1_offset_layout)
        self.tab1_offset_layout.addWidget(self.tab1_offset_label)
        self.tab1_offset_layout.addWidget(self.tab1_offset_value)
        self.tab1_offset_layout.addStretch(1)
        self.tab1_ignore.setLayout(self.tab1_ignore_layout)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_label1)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_value)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_label2)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_sec)
        self.tab1_ignore_layout.addWidget(self.tab1_ignore_label3)
        self.tab1_ignore_layout.addStretch(1)

        self.tab_page_2.setLayout(self.tab_grid_2)
        self.tab_grid_2.setRowStretch(0, 1)
        self.tab_grid_2.addWidget(self.tab2_shift, 1, 0, 2, 1)
        self.tab_grid_2.addWidget(self.tab2_slow_radio, 1, 1, 1, 1)
        self.tab_grid_2.addWidget(self.tab2_fast_radio, 2, 1, 1, 1)
        self.tab_grid_2.setColumnStretch(2, 1)
        self.tab_grid_2.setRowStretch(3, 1)
        self.tab_grid_2.addWidget(self.tab2_add_button, 4, 0, 1, 3)
        self.tab2_shift.setLayout(self.tab2_shift_layout)
        self.tab2_shift_layout.addWidget(self.tab2_shift_label1)
        self.tab2_shift_layout.addWidget(self.tab2_shift_value)
        self.tab2_shift_layout.addWidget(self.tab2_shift_label2)

        self.tab_page_3.setLayout(self.tab_grid_3)
        self.tab_grid_3.setRowStretch(0, 1)
        self.tab_grid_3.addWidget(self.tab3_speed_label1, 1, 0, 1, 1)
        self.tab_grid_3.addWidget(self.tab3_speed_value, 1, 1, 1, 1)
        self.tab_grid_3.addWidget(self.tab3_speed_label2, 1, 2, 1, 1)
        self.tab_grid_3.setColumnStretch(3, 1)
        self.tab_grid_3.setRowStretch(2, 1)
        self.tab_grid_3.addWidget(self.tab3_add_button, 3, 0, 1, 4)

        self.que_widget.setLayout(self.que_layout)
        self.que_layout.addWidget(self.que_list, 0, 0, 4, 1)
        self.que_layout.addWidget(self.que_delete_button, 0, 1, 1, 1)
        self.que_layout.addWidget(self.que_up_button, 1, 1, 1, 1)
        self.que_layout.addWidget(self.que_down_button, 2, 1, 1, 1)
        self.que_layout.addWidget(self.que_clear_button, 3, 1, 1, 1)

        self.file_widget.setLayout(self.file_layout)
        self.file_layout.addWidget(self.file_list, 0, 0, 6, 1)
        self.file_layout.addWidget(self.file_file_open, 0, 1, 1, 1)
        self.file_layout.addWidget(self.file_dir_open, 1, 1, 1, 1)
        self.file_layout.addWidget(self.file_delete, 2, 1, 1, 1)
        self.file_layout.addWidget(self.file_clear, 3, 1, 1, 1)
        self.file_layout.addWidget(self.file_encode, 5, 1, 1, 1)

        self.save_widget.setLayout(self.save_layout)
        self.save_layout.addWidget(self.save_orig_radio, 0, 0, 1, 1)
        self.save_layout.setColumnStretch(1, 1)
        self.save_layout.addWidget(self.save_strip, 0, 2, 1, 2)
        self.save_layout.addWidget(self.save_dir_radio, 1, 0, 1, 1)
        self.save_layout.addWidget(self.save_dir_line, 1, 1, 1, 2)
        self.save_layout.addWidget(self.save_dir_find, 1, 3, 1, 1)

        self.setWindowTitle('Batch SAMI Sync v0.2')
        self.setCentralWidget(self.central_widget)
        self.adjustSize()

    def attach_event(self):
        # Default encoding hack
        self.encoding = '자동'

        # Define and Connect event handlers
        def tab1_add():
            sponsor_text = self.tab1_search.text()
            sponsor_time = self.tab1_sponsor_value.value()
            line_offset = self.tab1_offset_value.value()
            line_ignore = self.tab1_ignore_value.value()
            time_ignore = self.tab1_ignore_sec.value()
            data = [1, sponsor_time, sponsor_text, line_offset, line_ignore, time_ignore]
            item = QTreeWidgetItem(self.que_list, [self.tab1_name, '스폰서 영상 시간 : ' + str(sponsor_time) + '초, 오프셋 : ' + str(line_offset) + '줄, 시작부터 ' + str(line_ignore) + '번째 줄, ' + str(time_ignore) + '초 무시 - 검색어 : ' + sponsor_text])
            item.setData(2, 2, data)

        def tab2_add():
            shift_time = self.tab2_shift_value.value()
            shift_direction = self.tab2_fast_radio.isChecked()
            direction_text = '빠르게' if shift_direction else '느리게'
            data = [2, shift_time, shift_direction]
            item = QTreeWidgetItem(self.que_list, [self.tab2_name, '자막 싱크 ' + str(shift_time) + '초 ' + direction_text])
            item.setData(2, 2, data)

        def tab3_add():
            speed_rate = self.tab3_speed_value.value()
            data = [3, speed_rate]
            item = QTreeWidgetItem(self.que_list, [self.tab3_name, '자막 속도 ' + str(speed_rate) + '%'])
            item.setData(2, 2, data)

        def file_open():
            selected = QFileDialog.getOpenFileNames(self, "자막 파일 선택", "", "SAMI Files (*.smi);;All Files (*)")
            for file in selected[0]:
                name = ntpath.basename(file)
                Utils.insert_list(self.file_list, name, file)

        def dir_open():
            selected = QFileDialog.getExistingDirectory(self, "자막 폴더 선택")
            for paths, subdirs, files in os.walk(selected):
                for file in files:
                    if fnmatch(file, '*.smi'):
                        name = ntpath.basename(file)
                        Utils.insert_list(self.file_list, name, file)

        def open_encode_dialog():
            self.dialog = QInputDialog(self)
            self.dialog.setWindowTitle('인코딩 설정')
            self.dialog.setLabelText('텍스트 인코딩 설정')
            self.dialog.setComboBoxItems(['자동', 'EUC-KR', 'UTF-8', 'UTF-16LE', 'UTF-16BE', '직접 입력'])
            self.dialog.show()

            self.dialog.textValueChanged.connect(type_encode)
            self.dialog.textValueSelected.connect(set_encode)

        def type_encode(text):
            if text == '직접 입력':
                self.dialog.setComboBoxItems([])
                self.dialog.setComboBoxEditable(True)

        def set_encode(text):
            self.encoding = text

        def save_dir():
            selected = QFileDialog.getExistingDirectory(self, "저장 위치 선택")
            self.save_dir_line.setText(selected)

        def apply():
            self.ok_button.setEnabled(False)
            ques = Utils.read_list(self.que_list, False)
            files = Utils.read_list(self.file_list, False)
            strip = False if self.save_strip.isChecked() else True
            log = []
            for file in files:
                try:
                    text = Utils.launch_que(file[1], ques, self.encoding, strip)
                    if len(text):
                        if self.save_orig_radio.isChecked():
                            savepath = file[1]
                        else:
                            savepath = self.save_dir_line.text() + '/' + file[0]
                        Utils.save_file(savepath, text)
                except Exception as e:
                    log.append(file[0] + ' 처리 오류 : ' + str(e))
            if log:
                ScrollMessageBox(QMessageBox.Warning, 'Batch SAMI Sync', "\n".join(log))

            else:
                QMessageBox.information(self, 'Batch SAMI Sync', '변환 완료!')
            self.ok_button.setEnabled(True)

        self.tab1_add_button.clicked.connect(tab1_add)
        self.tab2_add_button.clicked.connect(tab2_add)
        self.tab3_add_button.clicked.connect(tab3_add)
        self.que_delete_button.clicked.connect(lambda: Utils.delete_list(self.que_list))
        self.que_clear_button.clicked.connect(lambda: Utils.clear_list(self.que_list))
        self.que_up_button.clicked.connect(lambda: Utils.up_list(self.que_list))
        self.que_down_button.clicked.connect(lambda: Utils.down_list(self.que_list))
        self.file_file_open.clicked.connect(file_open)
        self.file_dir_open.clicked.connect(dir_open)
        self.file_delete.clicked.connect(lambda: Utils.delete_list(self.file_list))
        self.file_clear.clicked.connect(lambda: Utils.clear_list(self.file_list))
        self.file_encode.clicked.connect(open_encode_dialog)
        self.save_dir_find.clicked.connect(save_dir)
        self.ok_button.clicked.connect(apply)
        self.cancel_button.clicked.connect(sys.exit)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls:
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            event.setDropAction(Qt.CopyAction)
            event.accept()
            for url in event.mimeData().urls():
                if url.isLocalFile():
                    file = str(url.toLocalFile())
                    if fnmatch(file, '*.smi'):
                        name = ntpath.basename(file)
                        Utils.insert_list(self.file_list, name, file)
                    elif not fnmatch(file, '*.*'):
                        for paths, subdirs, files in os.walk(file):
                            for file in files:
                                if fnmatch(file, '*.smi'):
                                    name = ntpath.basename(file)
                                    Utils.insert_list(self.file_list, name, file)

        else:
            event.ignore()
Esempio n. 28
0
class GradientWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(GradientWidget, self).__init__(parent)
        self.intensity_spin = QSpinBox()
        self.intensity_spin.setRange(0, 127)
        self.intensity_spin.setValue(90)
        self.blue_combo = QComboBox()
        self.blue_combo.addItems(
            [self.tr('None'),
             self.tr('Flat'),
             self.tr('Norm')])
        self.invert_check = QCheckBox(self.tr('Invert'))
        self.equalize_check = QCheckBox(self.tr('Equalize'))

        self.grad_viewer = ImageViewer(image, image)
        self.image = image
        self.process()

        self.intensity_spin.valueChanged.connect(self.process)
        self.blue_combo.currentIndexChanged.connect(self.process)
        self.invert_check.stateChanged.connect(self.process)
        self.equalize_check.stateChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Intensity:')))
        top_layout.addWidget(self.intensity_spin)
        top_layout.addWidget(QLabel(self.tr('Blue channel:')))
        top_layout.addWidget(self.blue_combo)
        top_layout.addWidget(self.invert_check)
        top_layout.addWidget(self.equalize_check)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.grad_viewer)

        self.setLayout(main_layout)

    def process(self):
        intensity = self.intensity_spin.value()
        invert = self.invert_check.isChecked()
        equalize = self.equalize_check.isChecked()
        blue_mode = self.blue_combo.currentIndex()
        dx, dy = cv.spatialGradient(cv.cvtColor(self.image, cv.COLOR_BGR2GRAY))
        if invert:
            dx = -dx
            dy = -dy
        red = ((dx.astype(np.float32) / np.max(np.abs(dx)) * 127) +
               127).astype(np.uint8)
        green = ((dy.astype(np.float32) / np.max(np.abs(dy)) * 127) +
                 127).astype(np.uint8)
        if blue_mode == 0:
            blue = np.zeros_like(red)
        elif blue_mode == 1:
            blue = np.full_like(red, 255)
        elif blue_mode == 2:
            blue = normalize_mat(np.linalg.norm(cv.merge((red, green)),
                                                axis=2))
        else:
            blue = None
        gradient = cv.merge([blue, green, red])
        if intensity > 0:
            gradient = cv.LUT(gradient, create_lut(intensity, intensity))
        if equalize:
            gradient = equalize_image(gradient)
        self.grad_viewer.update_processed(gradient)
Esempio n. 29
0
class RandomDatasetGenerator(QDialog):
    logger = logging.getLogger("root.ui.RandomGeneratorWidget")
    gui_logger = logging.getLogger("GUI")

    def __init__(self, parent=None):
        super().__init__(parent=parent, f=Qt.Window)
        self.setWindowTitle(self.tr("Dataset Generator"))
        self.last_n_components = 0
        self.components = []  # typing.List[RandomGeneratorComponentWidget]
        self.component_series = []
        self.init_ui()
        self.target = LOESS
        self.minimum_size_input.setValue(0.02)
        self.maximum_size_input.setValue(2000.0)
        self.n_classes_input.setValue(101)
        self.precision_input.setValue(4)

        self.file_dialog = QFileDialog(parent=self)
        self.update_timer = QTimer()
        self.update_timer.timeout.connect(lambda: self.update_chart(True))
        self.cancel_flag = False

    def init_ui(self):
        self.setAttribute(Qt.WA_StyledBackground, True)
        self.main_layout = QGridLayout(self)
        # self.main_layout.setContentsMargins(0, 0, 0, 0)

        self.sampling_group = QGroupBox(self.tr("Sampling"))
        # self.control_group.setFixedSize(400, 160)
        self.control_layout = QGridLayout(self.sampling_group)
        self.minimum_size_label = QLabel(self.tr("Minimum Size [μm]"))
        self.minimum_size_input = QDoubleSpinBox()
        self.minimum_size_input.setDecimals(2)
        self.minimum_size_input.setRange(1e-4, 1e6)
        self.minimum_size_input.setValue(0.0200)
        self.maximum_size_label = QLabel(self.tr("Maximum Size [μm]"))
        self.maximum_size_input = QDoubleSpinBox()
        self.maximum_size_input.setDecimals(2)
        self.maximum_size_input.setRange(1e-4, 1e6)
        self.maximum_size_input.setValue(2000.0000)
        self.control_layout.addWidget(self.minimum_size_label, 0, 0)
        self.control_layout.addWidget(self.minimum_size_input, 0, 1)
        self.control_layout.addWidget(self.maximum_size_label, 0, 2)
        self.control_layout.addWidget(self.maximum_size_input, 0, 3)
        self.n_classes_label = QLabel(self.tr("N<sub>classes</sub>"))
        self.n_classes_input = QSpinBox()
        self.n_classes_input.setRange(10, 1e4)
        self.n_classes_input.setValue(101)
        self.precision_label = QLabel(self.tr("Data Precision"))
        self.precision_input = QSpinBox()
        self.precision_input.setRange(2, 8)
        self.precision_input.setValue(4)
        self.control_layout.addWidget(self.n_classes_label, 1, 0)
        self.control_layout.addWidget(self.n_classes_input, 1, 1)
        self.control_layout.addWidget(self.precision_label, 1, 2)
        self.control_layout.addWidget(self.precision_input, 1, 3)
        self.component_number_label = QLabel(self.tr("N<sub>components</sub>"))
        self.component_number_input = QSpinBox()
        self.component_number_input.setRange(1, 10)
        self.component_number_input.valueChanged.connect(
            self.on_n_components_changed)
        self.preview_button = QPushButton(qta.icon("mdi.animation-play"),
                                          self.tr("Preview"))
        self.preview_button.clicked.connect(self.on_preview_clicked)
        self.control_layout.addWidget(self.component_number_label, 2, 0)
        self.control_layout.addWidget(self.component_number_input, 2, 1)
        self.control_layout.addWidget(self.preview_button, 2, 2, 1, 2)
        self.main_layout.addWidget(self.sampling_group, 0, 0)

        self.save_group = QGroupBox(self.tr("Save"))
        # self.save_group.setFixedHeight(160)
        self.save_layout = QGridLayout(self.save_group)
        self.n_samples_label = QLabel(self.tr("N<sub>samples</sub>"))
        self.n_samples_input = QSpinBox()
        self.n_samples_input.setRange(100, 100000)
        self.save_layout.addWidget(self.n_samples_label, 0, 0)
        self.save_layout.addWidget(self.n_samples_input, 0, 1)

        self.cancel_button = QPushButton(qta.icon("mdi.cancel"),
                                         self.tr("Cancel"))
        self.cancel_button.setEnabled(False)
        self.cancel_button.clicked.connect(self.on_cancel_clicked)
        self.generate_button = QPushButton(qta.icon("mdi.cube-send"),
                                           self.tr("Generate"))
        self.generate_button.clicked.connect(self.on_generate_clicked)
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setOrientation(Qt.Horizontal)
        self.progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        self.save_layout.addWidget(self.cancel_button, 1, 0)
        self.save_layout.addWidget(self.generate_button, 1, 1)
        self.save_layout.addWidget(self.progress_bar, 2, 0, 1, 2)
        self.main_layout.addWidget(self.save_group, 0, 1)

        self.param_group = QGroupBox("Random Parameter")
        # self.param_group.setFixedWidth(400)
        self.param_layout = QGridLayout(self.param_group)
        self.main_layout.addWidget(self.param_group, 1, 0)

        self.preview_group = QGroupBox(self.tr("Preview"))
        self.chart_layout = QGridLayout(self.preview_group)

        self.chart = MixedDistributionChart(parent=self, toolbar=False)
        self.chart_layout.addWidget(self.chart, 0, 0)
        self.chart.setSizePolicy(QSizePolicy.MinimumExpanding,
                                 QSizePolicy.MinimumExpanding)
        self.main_layout.addWidget(self.preview_group, 1, 1)

    @staticmethod
    def to_points(x, y):
        return [QPointF(x_value, y_value) for x_value, y_value in zip(x, y)]

    def on_n_components_changed(self, n_components: int):
        if self.last_n_components < n_components:
            for component_index in range(self.last_n_components, n_components):
                component = RandomGeneratorComponentWidget(
                    name=f"AC{component_index+1}")
                component.value_changed.connect(self.on_value_changed)
                self.param_layout.addWidget(component, component_index + 1, 0)
                self.components.append(component)

        if self.last_n_components > n_components:
            for i in range(n_components, self.last_n_components):
                before_component = self.components[i]
                before_component.value_changed.disconnect(
                    self.on_value_changed)
                self.param_layout.removeWidget(before_component)
                # if not hide, the widget will still display on screen
                before_component.hide()
                self.components.pop(n_components)

        self.last_n_components = n_components

    def on_preview_clicked(self):
        if self.update_timer.isActive():
            self.preview_button.setText(self.tr("Preview"))
            self.update_timer.stop()
            self.update_chart()
        else:
            self.preview_button.setText(self.tr("Stop"))
            self.update_timer.start(200)

    def on_cancel_clicked(self):
        self.cancel_flag = True

    def on_generate_clicked(self):
        if self.update_timer.isActive():
            self.preview_button.setText(self.tr("Preview"))
            self.update_timer.stop()
            self.update_chart()

        filename, _ = self.file_dialog.getSaveFileName(
            self, self.tr("Choose a filename to save the generated dataset"),
            None, "Microsoft Excel (*.xlsx)")
        if filename is None or filename == "":
            return
        n_samples = self.n_samples_input.value()
        dataset = self.get_random_dataset(n_samples)
        # generate samples
        self.cancel_button.setEnabled(True)
        self.generate_button.setEnabled(False)
        format_str = self.tr("Generating {0} samples: %p%").format(n_samples)
        self.progress_bar.setFormat(format_str)
        self.progress_bar.setValue(0)

        def cancel():
            self.progress_bar.setFormat(self.tr("Task canceled"))
            self.progress_bar.setValue(0)
            self.cancel_button.setEnabled(False)
            self.generate_button.setEnabled(True)
            self.cancel_flag = False

        samples = []
        for i in range(n_samples):
            if self.cancel_flag:
                cancel()
                return
            sample = dataset.get_sample(i)
            samples.append(sample)
            progress = (i + 1) / n_samples * 50
            self.progress_bar.setValue(progress)
            QCoreApplication.processEvents()

        # save file to excel file
        format_str = self.tr("Writing {0} samples to excel file: %p%").format(
            n_samples)
        self.progress_bar.setFormat(format_str)
        self.progress_bar.setValue(50)

        wb = openpyxl.Workbook()
        prepare_styles(wb)

        ws = wb.active
        ws.title = self.tr("README")
        description = \
            """
            This Excel file was generated by QGrain ({0}).

            Please cite:
            Liu, Y., Liu, X., Sun, Y., 2021. QGrain: An open-source and easy-to-use software for the comprehensive analysis of grain size distributions. Sedimentary Geology 423, 105980. https://doi.org/10.1016/j.sedgeo.2021.105980

            It contanins n_components + 3 sheets:
            1. The first sheet is the random settings which were used to generate random parameters.
            2. The second sheet is the generated dataset.
            3. The third sheet is random parameters which were used to calulate the component distributions and their mixture.
            4. The left sheets are the component distributions of all samples.

            Artificial dataset
                Using skew normal distribution as the base distribution of each component (i.e. end-member).
                Skew normal distribution has three parameters, shape, location and scale.
                Where shape controls the skewness, location and scale are simliar to that of the Normal distribution.
                When shape = 0, it becomes Normal distribution.
                The weight parameter controls the fraction of the component, where fraction_i = weight_i / sum(weight_i).
                By assigning the mean and std of each parameter, random parameters was generate by the `scipy.stats.truncnorm.rvs` function of Scipy.

            Sampling settings
                Minimum size [μm]: {1},
                Maximum size [μm]: {2},
                N_classes: {3},
                Precision: {4},
                Noise: {5},
                N_samples: {6}

            """.format(QGRAIN_VERSION,
                       self.minimum_size_input.value(),
                       self.maximum_size_input.value(),
                       self.n_classes_input.value(),
                       self.precision_input.value(),
                       self.precision_input.value()+1,
                       n_samples)

        def write(row, col, value, style="normal_light"):
            cell = ws.cell(row + 1, col + 1, value=value)
            cell.style = style

        lines_of_desc = description.split("\n")
        for row, line in enumerate(lines_of_desc):
            write(row, 0, line, style="description")
        ws.column_dimensions[column_to_char(0)].width = 200

        ws = wb.create_sheet(self.tr("Random Settings"))
        write(0, 0, self.tr("Parameter"), style="header")
        ws.merge_cells(start_row=1, start_column=1, end_row=2, end_column=1)
        write(0, 1, self.tr("Shape"), style="header")
        ws.merge_cells(start_row=1, start_column=2, end_row=1, end_column=3)
        write(0, 3, self.tr("Location"), style="header")
        ws.merge_cells(start_row=1, start_column=4, end_row=1, end_column=5)
        write(0, 5, self.tr("Scale"), style="header")
        ws.merge_cells(start_row=1, start_column=6, end_row=1, end_column=7)
        write(0, 7, self.tr("Weight"), style="header")
        ws.merge_cells(start_row=1, start_column=8, end_row=1, end_column=9)
        ws.column_dimensions[column_to_char(0)].width = 16
        for col in range(1, 9):
            ws.column_dimensions[column_to_char(col)].width = 16
            if col % 2 == 0:
                write(1, col, self.tr("Mean"), style="header")
            else:
                write(1, col, self.tr("STD"), style="header")
        for row, comp_params in enumerate(self.target, 2):
            if row % 2 == 1:
                style = "normal_dark"
            else:
                style = "normal_light"
            write(row, 0, self.tr("Component{0}").format(row - 1), style=style)
            for i, key in enumerate(["shape", "loc", "scale", "weight"]):
                mean, std = comp_params[key]
                write(row, i * 2 + 1, mean, style=style)
                write(row, i * 2 + 2, std, style=style)

        ws = wb.create_sheet(self.tr("Dataset"))
        write(0, 0, self.tr("Sample Name"), style="header")
        ws.column_dimensions[column_to_char(0)].width = 24
        for col, value in enumerate(dataset.classes_μm, 1):
            write(0, col, value, style="header")
            ws.column_dimensions[column_to_char(col)].width = 10
        for row, sample in enumerate(samples, 1):
            if row % 2 == 0:
                style = "normal_dark"
            else:
                style = "normal_light"
            write(row, 0, sample.name, style=style)
            for col, value in enumerate(sample.distribution, 1):
                write(row, col, value, style=style)

            if self.cancel_flag:
                cancel()
                return
            progress = 50 + (row / n_samples) * 10
            self.progress_bar.setValue(progress)
            QCoreApplication.processEvents()

        ws = wb.create_sheet(self.tr("Parameters"))
        write(0, 0, self.tr("Sample Name"), style="header")
        ws.merge_cells(start_row=1, start_column=1, end_row=2, end_column=1)
        ws.column_dimensions[column_to_char(0)].width = 24
        for i in range(dataset.n_components):
            write(0,
                  4 * i + 1,
                  self.tr("Component{0}").format(i + 1),
                  style="header")
            ws.merge_cells(start_row=1,
                           start_column=4 * i + 2,
                           end_row=1,
                           end_column=4 * i + 5)
            for j, header_name in enumerate([
                    self.tr("Shape"),
                    self.tr("Location"),
                    self.tr("Scale"),
                    self.tr("Weight")
            ]):
                write(1, 4 * i + 1 + j, header_name, style="header")
                ws.column_dimensions[column_to_char(4 * i + 1 + j)].width = 16
        for row, sample in enumerate(samples, 2):
            if row % 2 == 1:
                style = "normal_dark"
            else:
                style = "normal_light"
            write(row, 0, sample.name, style=style)
            for i, comp_param in enumerate(sample.parameter.components):
                write(row, 4 * i + 1, comp_param.shape, style=style)
                write(row, 4 * i + 2, comp_param.loc, style=style)
                write(row, 4 * i + 3, comp_param.scale, style=style)
                write(row, 4 * i + 4, comp_param.weight, style=style)
            if self.cancel_flag:
                cancel()
                return
            progress = 60 + (row / n_samples) * 10
            self.progress_bar.setValue(progress)
            QCoreApplication.processEvents()

        for i in range(dataset.n_components):
            ws = wb.create_sheet(self.tr("Component{0}").format(i + 1))
            write(0, 0, self.tr("Sample Name"), style="header")
            ws.column_dimensions[column_to_char(0)].width = 24
            for col, value in enumerate(dataset.classes_μm, 1):
                write(0, col, value, style="header")
                ws.column_dimensions[column_to_char(col)].width = 10
            for row, sample in enumerate(samples, 1):
                if row % 2 == 0:
                    style = "normal_dark"
                else:
                    style = "normal_light"
                write(row, 0, sample.name, style=style)
                for col, value in enumerate(sample.components[i].distribution,
                                            1):
                    write(row, col, value, style=style)
            if self.cancel_flag:
                cancel()
                return
            progress = 70 + (
                (i * n_samples + row) / n_samples * dataset.n_components) * 30
            self.progress_bar.setValue(progress)
            QCoreApplication.processEvents()
        wb.save(filename)
        wb.close()

        self.progress_bar.setValue(100)
        self.progress_bar.setFormat(self.tr("Task finished"))
        self.cancel_button.setEnabled(False)
        self.generate_button.setEnabled(True)

    @property
    def target(self):
        return [comp.target for comp in self.components]

    @target.setter
    def target(self, values):
        if len(values) != len(self.components):
            self.component_number_input.setValue(len(values))
        for comp, comp_target in zip(self.components, values):
            comp.blockSignals(True)
            comp.target = comp_target
            comp.blockSignals(False)
        self.update_chart()

    def get_random_sample(self):
        dataset = self.get_random_dataset(n_samples=1)
        sample = dataset.get_sample(0)
        sample.name = self.tr("Artificial Sample")
        return sample

    def get_random_mean(self):
        dataset = self.get_random_dataset(n_samples=1)
        random_setting = RandomSetting(self.target)
        sample = dataset.get_sample_by_params(self.tr("Artificial Sample"),
                                              random_setting.mean_param)
        return sample

    def get_random_dataset(self, n_samples):
        min_μm = self.minimum_size_input.value()
        max_μm = self.maximum_size_input.value()
        n_classes = self.n_classes_input.value()
        if min_μm == max_μm:
            return
        if min_μm > max_μm:
            min_μm, max_μm = max_μm, min_μm
        precision = self.precision_input.value()
        noise = precision + 1

        dataset = get_random_dataset(target=self.target,
                                     n_samples=n_samples,
                                     min_μm=min_μm,
                                     max_μm=max_μm,
                                     n_classes=n_classes,
                                     precision=precision,
                                     noise=noise)
        return dataset

    def on_value_changed(self):
        self.update_chart()

    def update_chart(self, random=False):
        if not random:
            sample = self.get_random_mean()
        else:
            sample = self.get_random_sample()
        self.chart.show_model(sample.view_model)

    def closeEvent(self, event):
        if self.cancel_button.isEnabled():
            self.on_cancel_clicked()
        event.accept()
Esempio n. 30
0
def get_widget_by_type(obj):
	if type(obj) == int:
		widget = QSpinBox()
		widget.setRange(INT_RANGE_MIN, INT_RANGE_MAX)
		widget.setSingleStep(INT_RANGE_STEP)
		widget.setValue(obj)
		widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)

	elif type(obj) == float:
		widget = QDoubleSpinBox()
		widget.setRange(FLOAT_RANGE_MIN, FLOAT_RANGE_MAX)
		widget.setSingleStep(FLOAT_RANGE_STEP)
		widget.setValue(obj)
		widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)

	elif type(obj) == str:
		widget = QLineEdit()
		widget.setText(obj)

	elif type(obj) == bool:
		widget = QCheckBox()
		widget.setChecked(obj)

	elif type(obj) == list:
		widget = QComboBox()
		widget.addItems(obj)
		widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)

	elif type(obj) == tuple:
		widget = QFrame()

		if len(obj) <= 3:
			box = QHBoxLayout()
		else:
			box = QVBoxLayout()
		box.setMargin(0)

		for item in obj:
			value_widget = QLabel(f"{item}")
			value_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
			value_widget.setObjectName("tuple")

			box.addWidget(value_widget)

		widget.setLayout(box)

	elif type(obj) == dict:
		widget = QFrame()

		# If less than 3 items, lay it out horizontally else vertically
		# if len(obj) <= 3:
		# 	box = QHBoxLayout()
		# else:
		# 	box = QVBoxLayout()
		# box.setMargin(0)

		grid = QGridLayout()
		grid.setMargin(0)

		row = 0
		for key in obj:
			label = QLabel(f"{key.capitalize()}:")
			grid.addWidget(label, row, 0)
			
			value_widget = get_widget_by_type(obj[key])
			value_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
			grid.addWidget(value_widget, row, 1)

			try:
				value_widget.setRange(INT_RANGE_MIN, INT_RANGE_MAX)
				value_widget.setSingleStep(INT_RANGE_STEP)
				value_widget.setValue(obj[key])
			except:
				pass

			row += 1

		widget.setLayout(grid)

	# TODO: Lists inside of lists. Should probably use QTreeView
	# elif type(obj) == list:
	# 	widget = []
	# 	for l in obj:
	# 		widget.append(QComboBox())
	# 		widget[-1].addItems(obj)
	# 		widget[-1].setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
	
	return widget
Esempio n. 31
0
class SettingsEditionDialog(QDialog):

    languages = {"Français": "fr", "English": "en"}

    def __init__(self):
        QDialog.__init__(self)

        self.setWindowTitle(tr("btn_config"))
        self.setFixedSize(QSize(700, 675))

        # Retrieve current settings
        self.settings = AssetManager.getInstance().config_to_dico(
            AssetManager.getInstance().get_config_parser())
        self.__restart_needed = False
        self.__restore_required = False

        # Version
        self.lab_version = QLabel(self.settings['main']['version'])

        # Language
        self.combo_language = QComboBox()
        self.combo_language.addItems(list(self.languages.keys()))
        for lang in self.languages:  # Look for the current language to select it
            if self.languages[lang] == self.settings['main']['language']:
                self.combo_language.setCurrentText(lang)
                break

        # CSV separator
        self.csv_sep_edit = QLineEdit()
        self.csv_sep_edit.setMaxLength(2)
        self.csv_sep_edit.setFixedWidth(25)
        self.csv_sep_edit.setAlignment(Qt.AlignCenter)
        self.csv_sep_edit.setText(self.settings['main']['csv_separator'])

        # BDD path
        self.btn_bdd_path = QPushButton(self.settings['main']['bdd_path'])
        self.btn_bdd_path.clicked.connect(self.choose_bdd_path)

        # Port
        self.wepapp_port = QSpinBox()
        self.wepapp_port.setMinimum(1024)
        self.wepapp_port.setMaximum(65535)
        self.wepapp_port.setValue(int(self.settings['webapp']['port']))

        # Colors
        self.tile_color = ColorChooser(self.settings['colors']['tile'])
        self.hovered_tile_color = ColorChooser(
            self.settings['colors']['hovered_tile'])
        self.hovered_empty_tile_color = ColorChooser(
            self.settings['colors']['hovered_empty_tile'])
        self.dragged_tile_color = ColorChooser(
            self.settings['colors']['dragged_tile'])
        self.drag_selected_tile_color = ColorChooser(
            self.settings['colors']['drag_selected_tile'])
        self.selected_tile_color = ColorChooser(
            self.settings['colors']['selected_tile'])
        self.tile_text_color = ColorChooser(
            self.settings['colors']['tile_text'])
        self.room_bg_color = ColorChooser(self.settings['colors']['room_bg'])
        self.room_grid_color = ColorChooser(
            self.settings['colors']['room_grid'])
        self.main_bg_color = ColorChooser(self.settings['colors']['main_bg'])
        self.board_bg_color = ColorChooser(self.settings['colors']['board_bg'])

        self.attr_colors = ""  # Chosen colors
        self.attributes_colors_chooser = AttrColorsChooser(
            self.settings['colors']['attr_colors'].split())

        # Sizes
        # Desk sizes
        self.desk_size_h = QSpinBox()
        self.desk_size_h.setMinimum(10)
        self.desk_size_h.setMaximum(200)
        self.desk_size_h.setValue(int(self.settings['size']['desk_height']))
        self.desk_size_h.setFixedWidth(50)

        self.desk_size_w = QSpinBox()
        self.desk_size_w.setMinimum(10)
        self.desk_size_w.setMaximum(200)
        self.desk_size_w.setValue(int(self.settings['size']['desk_width']))
        self.desk_size_w.setFixedWidth(50)

        # Font size
        self.desk_font_size = QSpinBox()
        self.desk_font_size.setMinimum(4)
        self.desk_font_size.setValue(int(self.settings['size']['font_size']))
        self.desk_font_size.setFixedWidth(50)

        # Grid rows
        self.grid_rows = QSpinBox()
        self.grid_rows.setMinimum(1)
        self.grid_rows.setMaximum(40)
        self.grid_rows.setValue(int(
            self.settings['size']['default_room_rows']))
        self.grid_rows.setFixedWidth(50)

        # Grid columns
        self.grid_cols = QSpinBox()
        self.grid_cols.setMinimum(1)
        self.grid_cols.setMaximum(40)
        self.grid_cols.setValue(
            int(self.settings['size']['default_room_columns']))
        self.grid_cols.setFixedWidth(50)

        # --- Buttons ---

        # Confirm button
        self.ok_btn = QPushButton(tr("btn_save"))
        self.ok_btn.clicked.connect(self.accept)
        self.ok_btn.setFixedWidth(200)
        self.ok_btn.setFocus()

        # Cancel button
        self.cancel_btn = QPushButton(tr("btn_cancel"))
        self.cancel_btn.clicked.connect(self.reject)
        self.cancel_btn.setFixedWidth(200)

        # Restore defaults button
        self.restore_btn = QPushButton(tr("btn_restore"))
        self.restore_btn.clicked.connect(self.__restore)
        self.restore_btn.setFixedWidth(200)

        self.__set_layout()

    def __set_layout(self) -> None:
        """
        Sets the dialog layout
        """
        # Main layout
        layout = QVBoxLayout()
        layout.setMargin(0)
        layout.addSpacing(5)

        # Main section
        main_layout = SettingsFormLayout()
        main_layout.addRow(tr("app_version"), self.lab_version)
        main_layout.addRow(tr("language"), self.combo_language)
        main_layout.addRow(tr("csv_sep"), self.csv_sep_edit)
        main_layout.addRow(tr("bdd_path"), self.btn_bdd_path)

        # Web app
        widget_port = QWidget()
        layout_port = QHBoxLayout()
        layout_port.setMargin(0)
        layout_port.addWidget(self.wepapp_port)
        layout_port.addWidget(WarningToolTip("shutdown_required"))
        widget_port.setLayout(layout_port)
        main_layout.addRow(tr("web_port"), widget_port)

        layout.addLayout(main_layout)
        Separator(self.width(), layout)

        # Colors
        colors_layout1 = SettingsFormLayout()
        colors_layout1.addRow(tr("tile"), self.tile_color)
        colors_layout1.addRow(tr("hovered_tile"), self.hovered_tile_color)
        colors_layout1.addRow(tr("hovered_empty_tile"),
                              self.hovered_empty_tile_color)
        colors_layout1.addRow(tr("dragged_tile"), self.dragged_tile_color)
        colors_layout1.addRow(tr("drag_selected_tile"),
                              self.drag_selected_tile_color)
        colors_layout1.addRow(tr("selected_tile"), self.selected_tile_color)

        colors_layout2 = SettingsFormLayout()
        colors_layout2.addRow(tr("tile_text"), self.tile_text_color)
        colors_layout2.addRow(tr("room_bg"), self.room_bg_color)
        colors_layout2.addRow(tr("room_grid"), self.room_grid_color)
        colors_layout2.addRow(tr("main_bg"), self.main_bg_color)
        colors_layout2.addRow(tr("board_bg"), self.board_bg_color)

        colors_layout = QHBoxLayout()
        colors_layout.setMargin(0)
        colors_layout.addLayout(colors_layout1)
        colors_layout.addLayout(colors_layout2)

        layout.addLayout(colors_layout)
        layout.addSpacing(15)

        colors_layout3 = SettingsFormLayout()
        colors_layout3.setMargin(0)
        colors_layout3.addRow(tr("attr_colors"),
                              self.attributes_colors_chooser)
        layout.addLayout(colors_layout3)

        Separator(self.width(), layout)

        # size data
        sizes_layout = SettingsFormLayout()
        sizes_layout.setMargin(0)

        widget_desk = QWidget()
        layout_desk = QHBoxLayout()
        layout_desk.setMargin(0)
        layout_desk.addWidget(self.desk_size_h)
        layout_desk.addWidget(self.desk_size_w)
        layout_desk.addWidget(WarningToolTip("dangerous_parameter"))
        widget_desk.setLayout(layout_desk)
        sizes_layout.addRow(tr("desk_size"), widget_desk)

        sizes_layout.addRow(tr("font_size"), self.desk_font_size)

        widget_rows = QWidget()
        layout_rows = QHBoxLayout()
        layout_rows.setMargin(0)
        layout_rows.addWidget(self.grid_rows)
        layout_rows.addWidget(WarningToolTip("dangerous_parameter"))
        widget_rows.setLayout(layout_rows)
        sizes_layout.addRow(tr("grid_rows"), widget_rows)

        widget_cols = QWidget()
        layout_cols = QHBoxLayout()
        layout_cols.setMargin(0)
        layout_cols.addWidget(self.grid_cols)
        layout_cols.addWidget(WarningToolTip("dangerous_parameter"))
        widget_cols.setLayout(layout_cols)
        sizes_layout.addRow(tr("grid_cols"), widget_cols)

        layout.addLayout(sizes_layout)

        Separator(self.width(), layout)

        # Buttons
        layout_buttons = QHBoxLayout()
        layout_buttons.addWidget(self.ok_btn)
        layout_buttons.addWidget(self.restore_btn)
        layout_buttons.addWidget(self.cancel_btn)

        layout.addLayout(layout_buttons)
        layout.addSpacing(5)
        self.setLayout(layout)

        self.setStyleSheet(get_stylesheet("dialog2"))

    def __restore(self) -> None:
        """
        Restore default parameters before closing dialog
        """
        self.__restart_needed = True
        self.__restore_required = True
        self.accept()

    def __new_settings(self) -> dict:
        """
        Retrieves the new settings to use
        """
        settings = self.settings

        # Language
        language = self.languages[self.combo_language.currentText()]
        if language != settings['main']['language']:
            settings['main']['language'] = language
            self.__restart_needed = True

        # CSV separator
        settings['main']['csv_separator'] = self.csv_sep_edit.text()

        # BDD path
        if self.btn_bdd_path.text() != settings['main']['bdd_path']:
            if self.btn_bdd_path.text().endswith("sdc_db"):
                settings['main']['bdd_path'] = self.btn_bdd_path.text()
            else:
                settings['main']['bdd_path'] = ""
            self.__restart_needed = True

        # Port
        if str(self.wepapp_port.value()) != settings['webapp']['port']:
            settings['webapp']['port'] = str(self.wepapp_port.value())

        # Colors
        settings['colors']['tile'] = self.tile_color.get_color()
        settings['colors']['hovered_tile'] = self.hovered_tile_color.get_color(
        )
        settings['colors'][
            'hovered_empty_tile'] = self.hovered_empty_tile_color.get_color()
        settings['colors']['dragged_tile'] = self.dragged_tile_color.get_color(
        )
        settings['colors'][
            'drag_selected_tile'] = self.drag_selected_tile_color.get_color()
        settings['colors'][
            'selected_tile'] = self.selected_tile_color.get_color()
        settings['colors']['tile_text'] = self.tile_text_color.get_color()
        settings['colors']['room_grid'] = self.room_grid_color.get_color()

        if self.room_bg_color.get_color() != settings['colors']['room_bg']:
            settings['colors']['room_bg'] = self.room_bg_color.get_color()
            self.__restart_needed = True

        if self.main_bg_color.get_color() != settings['colors']['main_bg']:
            settings['colors']['main_bg'] = self.main_bg_color.get_color()
            self.__restart_needed = True

        if self.board_bg_color.get_color() != settings['colors']['board_bg']:
            settings['colors']['board_bg'] = self.board_bg_color.get_color()
            self.__restart_needed = True

        settings['colors']['attr_colors'] = self.attr_colors

        # Size settings

        if str(self.desk_size_h.value()) != settings['size']['desk_height']:
            settings['size']['desk_height'] = str(self.desk_size_h.value())
            self.__restart_needed = True
        if str(self.desk_size_w.value()) != settings['size']['desk_width']:
            settings['size']['desk_width'] = str(self.desk_size_w.value())
            self.__restart_needed = True
        if str(self.desk_font_size.value()) != settings['size']['font_size']:
            settings['size']['font_size'] = str(self.desk_font_size.value())
            #self.__restart_needed = False
        if str(self.grid_rows.value()
               ) != settings['size']['default_room_rows']:
            settings['size']['default_room_rows'] = str(self.grid_rows.value())
            self.__restart_needed = True
        if str(self.grid_cols.value()
               ) != settings['size']['default_room_columns']:
            settings['size']['default_room_columns'] = str(
                self.grid_cols.value())
            self.__restart_needed = True

        return settings

    def new_config(self) -> ConfigParser:
        """
        Retrieves the new config parser object
        """
        conf = ConfigParser()
        conf.read_dict(self.__new_settings())

        return conf

    def need_restart(self):
        return self.__restart_needed

    def restore_default(self) -> bool:
        return self.__restore_required

    def accept(self) -> None:
        """
        Performs actions before calling parent's accept method
        """
        self.attr_colors = self.attributes_colors_chooser.get_colors_to_str()
        super().accept()

    def choose_bdd_path(self) -> None:
        """
        Opens a file chooser to select the bdd path. Then sets the name as button text.
        """
        bdd_path = QFileDialog.getOpenFileName(self, tr("bdd_path"),
                                               self.btn_bdd_path.text())[0]

        if bdd_path:
            self.btn_bdd_path.setText(bdd_path)
Esempio n. 32
0
    def initialise(self):
        self.settingsFile = os.path.join(self.findNukeHomeDir(),
                                         "deadline_settings.ini")
        print("Loading settings: " + self.settingsFile)

        # Initialize the submission settings.
        self.settings = QSettings(self.settingsFile, QSettings.IniFormat)

        print("Grabbing submitter info...")
        try:
            dcOutput = CallDeadlineCommand([
                "-prettyJSON",
                "-GetSubmissionInfo",
                "Pools",
                "Groups",
                "MaxPriority",
                "TaskLimit",
                "UserHomeDir",
                "RepoDir:submission/Hiero/Main",
                "RepoDir:submission/Integration/Main",
            ],
                                           useDeadlineBg=True)
            output = json.loads(dcOutput, encoding="utf-8")
        except ValueError as e:
            print("Unable to get submitter info from Deadline:\n\n" +
                  e.message)
            raise

        if output["ok"]:
            self.submissionInfo = output["result"]
        else:
            raise ValueError(
                "DeadlineCommand returned a bad result and was unable to grab the submitter info.\n\n"
                + output["result"])

        # Get the Deadline temp directory.
        deadlineHome = self.submissionInfo["UserHomeDir"].strip()
        self.deadlineTemp = os.path.join(deadlineHome, "temp")

        self.integrationDir = self.submissionInfo["RepoDirs"][
            "submission/Integration/Main"].strip()

        # Get maximum priority.
        maximumPriority = self.submissionInfo["MaxPriority"]

        # Collect the pools and groups.
        pools = self.submissionInfo["Pools"]

        secondaryPools = [""]
        secondaryPools.extend(pools)

        groups = self.submissionInfo["Groups"]

        # Set up the other default arrays.
        onJobComplete = ("Nothing", "Archive", "Delete")
        nukeVersions = ("6.0", "6.1", "6.2", "6.3", "6.4", "7.0", "7.1", "7.2",
                        "7.3", "7.4", "8.0", "8.1", "8.2", "8.3", "8.4", "9.0",
                        "9.1", "9.2", "9.3", "9.4", "10.0", "10.1", "10.2",
                        "10.3", "10.4", "11.0", "11.1", "11.2", "11.3")
        buildsToForce = ("None", "32bit", "64bit")

        # Main Window
        mainWindow = hiero.ui.mainWindow()
        dialog = QDialog(mainWindow)
        self.dialog = dialog
        dialog.setWindowTitle("Submit to Deadline (and render with Nuke)")

        # Main Layout
        topLayout = QVBoxLayout()
        dialog.setLayout(topLayout)
        tabWidget = QTabWidget(dialog)

        jobTab = QWidget()
        jobTabLayout = QVBoxLayout()
        jobTab.setLayout(jobTabLayout)

        # Job Info Layout
        jobInfoGroupBox = QGroupBox("Job Description")
        jobTabLayout.addWidget(jobInfoGroupBox)
        jobInfoLayout = QGridLayout()
        jobInfoGroupBox.setLayout(jobInfoLayout)

        # Job Name
        jobInfoLayout.addWidget(QLabel("Job Name"), 0, 0)
        jobNameWidget = QLineEdit(self.settings.value("JobName", ""))
        jobInfoLayout.addWidget(jobNameWidget, 0, 1)

        # Comment
        jobInfoLayout.addWidget(QLabel("Comment"), 1, 0)
        commentWidget = QLineEdit(self.settings.value("Comment", ""))
        jobInfoLayout.addWidget(commentWidget, 1, 1)

        # Department
        jobInfoLayout.addWidget(QLabel("Department"), 2, 0)
        departmentWidget = QLineEdit(self.settings.value("Department", ""))
        jobInfoLayout.addWidget(departmentWidget, 2, 1)

        # Job Options Layout
        jobOptionsGroupBox = QGroupBox("Job Options")
        jobTabLayout.addWidget(jobOptionsGroupBox)
        jobOptionsLayout = QGridLayout()
        jobOptionsGroupBox.setLayout(jobOptionsLayout)

        # Pool
        jobOptionsLayout.addWidget(QLabel("Pool"), 0, 0)
        poolWidget = QComboBox()
        for pool in pools:
            poolWidget.addItem(pool)

        defaultPool = self.settings.value("Pool", "none")
        defaultIndex = poolWidget.findText(defaultPool)
        if defaultIndex != -1:
            poolWidget.setCurrentIndex(defaultIndex)

        jobOptionsLayout.addWidget(poolWidget, 0, 1, 1, 3)

        # Secondary Pool
        jobOptionsLayout.addWidget(QLabel("Secondary Pool"), 1, 0)
        secondaryPoolWidget = QComboBox()
        for secondaryPool in secondaryPools:
            secondaryPoolWidget.addItem(secondaryPool)

        defaultSecondaryPool = self.settings.value("SecondaryPool", "")
        defaultIndex = secondaryPoolWidget.findText(defaultSecondaryPool)
        if defaultIndex != -1:
            secondaryPoolWidget.setCurrentIndex(defaultIndex)

        jobOptionsLayout.addWidget(secondaryPoolWidget, 1, 1, 1, 3)

        # Group
        jobOptionsLayout.addWidget(QLabel("Group"), 2, 0)
        groupWidget = QComboBox()
        for group in groups:
            groupWidget.addItem(group)

        defaultGroup = self.settings.value("Group", "none")
        defaultIndex = groupWidget.findText(defaultGroup)
        if defaultIndex != -1:
            groupWidget.setCurrentIndex(defaultIndex)

        jobOptionsLayout.addWidget(groupWidget, 2, 1, 1, 3)

        # Priority
        initPriority = int(self.settings.value("Priority", "50"))
        if initPriority > maximumPriority:
            initPriority = maximumPriority / 2

        jobOptionsLayout.addWidget(QLabel("Priority"), 3, 0)
        priorityWidget = QSpinBox()
        priorityWidget.setRange(0, maximumPriority)
        priorityWidget.setValue(initPriority)
        jobOptionsLayout.addWidget(priorityWidget, 3, 1)

        # Task Timeout
        jobOptionsLayout.addWidget(QLabel("Task Timeout"), 4, 0)
        taskTimeoutWidget = QSpinBox()
        taskTimeoutWidget.setRange(0, 1000000)
        taskTimeoutWidget.setValue(int(self.settings.value("TaskTimeout",
                                                           "0")))
        jobOptionsLayout.addWidget(taskTimeoutWidget, 4, 1)

        # Auto Task Timeout
        autoTaskTimeoutWidget = QCheckBox("Enable Auto Task Timeout")
        autoTaskTimeoutWidget.setChecked(
            strtobool(self.settings.value("AutoTaskTimeout", "False")))
        jobOptionsLayout.addWidget(autoTaskTimeoutWidget, 4, 2)

        # Concurrent Tasks
        jobOptionsLayout.addWidget(QLabel("Concurrent Tasks"), 5, 0)
        concurrentTasksWidget = QSpinBox()
        concurrentTasksWidget.setRange(1, 16)
        concurrentTasksWidget.setValue(
            int(self.settings.value("ConcurrentTasks", "1")))
        jobOptionsLayout.addWidget(concurrentTasksWidget, 5, 1)

        # Limit Tasks To Slave's Task Limit
        limitConcurrentTasksWidget = QCheckBox(
            "Limit Tasks To Slave's Task Limit")
        limitConcurrentTasksWidget.setChecked(
            strtobool(self.settings.value("LimitConcurrentTasks", "True")))
        jobOptionsLayout.addWidget(limitConcurrentTasksWidget, 5, 2)

        # Machine Limit
        jobOptionsLayout.addWidget(QLabel("Machine Limit"), 6, 0)
        machineLimitWidget = QSpinBox()
        machineLimitWidget.setRange(0, 1000000)
        machineLimitWidget.setValue(
            int(self.settings.value("MachineLimit", "1")))
        jobOptionsLayout.addWidget(machineLimitWidget, 6, 1)

        # Machine List Is A Blacklist
        isBlacklistWidget = QCheckBox("Machine List Is A Blacklist")
        isBlacklistWidget.setChecked(
            strtobool(self.settings.value("IsBlacklist", "False")))
        jobOptionsLayout.addWidget(isBlacklistWidget, 6, 2)

        # Machine List
        jobOptionsLayout.addWidget(QLabel("Machine List"), 7, 0)
        machineListWidget = QLineEdit(self.settings.value("MachineList", ""))
        jobOptionsLayout.addWidget(machineListWidget, 7, 1, 1, 2)

        def browseMachineList():
            output = CallDeadlineCommand(
                ["-selectmachinelist",
                 str(machineListWidget.text())], False)
            output = output.replace("\r", "").replace("\n", "")
            if output != "Action was cancelled by user":
                machineListWidget.setText(output)

        machineListButton = QPushButton("Browse")
        machineListButton.pressed.connect(browseMachineList)
        jobOptionsLayout.addWidget(machineListButton, 7, 3)

        # Limits
        jobOptionsLayout.addWidget(QLabel("Limits"), 8, 0)
        limitsWidget = QLineEdit(self.settings.value("Limits", ""))
        jobOptionsLayout.addWidget(limitsWidget, 8, 1, 1, 2)

        def browseLimitList():
            output = CallDeadlineCommand(
                ["-selectlimitgroups",
                 str(limitsWidget.text())], False)
            output = output.replace("\r", "").replace("\n", "")
            if output != "Action was cancelled by user":
                limitsWidget.setText(output)

        limitsButton = QPushButton("Browse")
        limitsButton.pressed.connect(browseLimitList)
        jobOptionsLayout.addWidget(limitsButton, 8, 3)

        # On Job Complete
        jobOptionsLayout.addWidget(QLabel("On Job Complete"), 9, 0)
        onJobCompleteWidget = QComboBox()
        for option in onJobComplete:
            onJobCompleteWidget.addItem(option)

        defaultOption = self.settings.value("OnJobComplete", "Nothing")
        defaultIndex = onJobCompleteWidget.findText(defaultOption)
        if defaultIndex != -1:
            onJobCompleteWidget.setCurrentIndex(defaultIndex)

        jobOptionsLayout.addWidget(onJobCompleteWidget, 9, 1)

        # Submit Job As Suspended
        submitSuspendedWidget = QCheckBox("Submit Job As Suspended")
        submitSuspendedWidget.setChecked(
            strtobool(self.settings.value("SubmitSuspended", "False")))
        jobOptionsLayout.addWidget(submitSuspendedWidget, 9, 2)

        # Nuke Options
        nukeOptionsGroupBox = QGroupBox("Nuke Options")
        jobTabLayout.addWidget(nukeOptionsGroupBox)
        nukeOptionsLayout = QGridLayout()
        nukeOptionsGroupBox.setLayout(nukeOptionsLayout)

        # Version
        nukeOptionsLayout.addWidget(QLabel("Version"), 0, 0)
        versionWidget = QComboBox()
        for version in nukeVersions:
            versionWidget.addItem(version)

        defaultVersion = self.settings.value("Version", "7.0")
        defaultIndex = versionWidget.findText(defaultVersion)
        if defaultIndex != -1:
            versionWidget.setCurrentIndex(defaultIndex)

        nukeOptionsLayout.addWidget(versionWidget, 0, 1)

        # Submit Nuke Script File With Job
        submitScriptWidget = QCheckBox("Submit Nuke Script File With Job")
        submitScriptWidget.setChecked(
            strtobool(self.settings.value("SubmitScript", "False")))
        nukeOptionsLayout.addWidget(submitScriptWidget, 0, 2)

        # Build To Force
        nukeOptionsLayout.addWidget(QLabel("Build To Force"), 1, 0)
        buildWidget = QComboBox()
        for build in buildsToForce:
            buildWidget.addItem(build)

        defaultBuild = self.settings.value("Build", "None")
        defaultIndex = buildWidget.findText(defaultBuild)
        if defaultIndex != -1:
            buildWidget.setCurrentIndex(defaultIndex)

        nukeOptionsLayout.addWidget(buildWidget, 1, 1)

        # Render With NukeX
        useNukeXWidget = QCheckBox("Render With NukeX")
        useNukeXWidget.setChecked(
            strtobool(self.settings.value("UseNukeX", "False")))
        nukeOptionsLayout.addWidget(useNukeXWidget, 1, 2)

        # Max RAM Usage (MB)
        nukeOptionsLayout.addWidget(QLabel("Max RAM Usage (MB)"), 2, 0)
        memoryWidget = QSpinBox()
        memoryWidget.setRange(0, 5000)
        memoryWidget.setValue(int(self.settings.value("Memory", "0")))
        nukeOptionsLayout.addWidget(memoryWidget, 2, 1)

        # Continue On Error
        continueOnErrorWidget = QCheckBox("Continue On Error")
        continueOnErrorWidget.setChecked(
            strtobool(self.settings.value("ContinueOnError", "False")))
        nukeOptionsLayout.addWidget(continueOnErrorWidget, 2, 2)

        # Threads
        nukeOptionsLayout.addWidget(QLabel("Threads"), 3, 0)
        threadsWidget = QSpinBox()
        threadsWidget.setRange(0, 256)
        threadsWidget.setValue(int(self.settings.value("Threads", "0")))
        nukeOptionsLayout.addWidget(threadsWidget, 3, 1)

        # Use Batch Mode
        batchModeWidget = QCheckBox("Use Batch Mode")
        batchModeWidget.setChecked(
            strtobool(self.settings.value("BatchMode", "False")))
        nukeOptionsLayout.addWidget(batchModeWidget, 3, 2)

        # Frames Per Task
        nukeOptionsLayout.addWidget(QLabel("Frames Per Task"), 4, 0)
        framesPerTaskWidget = QSpinBox()
        framesPerTaskWidget.setRange(1, 1000000)
        framesPerTaskWidget.setValue(
            int(self.settings.value("FramesPerTask", "1")))
        nukeOptionsLayout.addWidget(framesPerTaskWidget, 4, 1)
        nukeOptionsLayout.addWidget(
            QLabel("(this only affects non-movie jobs)"), 4, 2)

        tabWidget.addTab(jobTab, "Job Options")

        # Button Box (Extra work required to get the custom ordering we want)
        self.pipelineToolStatusLabel.setAlignment(Qt.AlignRight
                                                  | Qt.AlignVCenter)
        pipelineToolStatus = self.retrievePipelineToolStatus()
        self.updatePipelineToolStatusLabel(pipelineToolStatus)

        integrationButton = QPushButton("Pipeline Tools")
        integrationButton.clicked.connect(self.OpenIntegrationWindow)

        submitButton = QPushButton("Submit")
        submitButton.clicked.connect(dialog.accept)
        submitButton.setDefault(True)

        cancelButton = QPushButton("Cancel")
        cancelButton.clicked.connect(dialog.reject)

        buttonGroupBox = QGroupBox()
        buttonLayout = QGridLayout()
        buttonLayout.setColumnStretch(
            0, 1)  # Makes the pipeline status label expand, not the buttons
        buttonGroupBox.setLayout(buttonLayout)
        buttonGroupBox.setAlignment(Qt.AlignRight)
        buttonGroupBox.setFlat(True)
        buttonLayout.addWidget(self.pipelineToolStatusLabel, 0, 0)
        buttonLayout.addWidget(integrationButton, 0, 1)
        buttonLayout.addWidget(submitButton, 0, 2)
        buttonLayout.addWidget(cancelButton, 0, 3)

        topLayout.addWidget(tabWidget)
        topLayout.addWidget(buttonGroupBox)

        # Show the dialog.
        result = (dialog.exec_() == QDialog.DialogCode.Accepted)
        if result:
            # Need to pass integration dir path to render task
            self.settings.setValue("IntegrationDir", self.integrationDir)

            self.settings.setValue("JobName", jobNameWidget.text())
            self.settings.setValue("Comment", commentWidget.text())
            self.settings.setValue("Department", departmentWidget.text())
            self.settings.setValue("Pool", poolWidget.currentText())
            self.settings.setValue("SecondaryPool",
                                   secondaryPoolWidget.currentText())
            self.settings.setValue("Group", groupWidget.currentText())
            self.settings.setValue("Priority", priorityWidget.value())
            self.settings.setValue("TaskTimeout", taskTimeoutWidget.value())
            self.settings.setValue("AutoTaskTimeout",
                                   str(autoTaskTimeoutWidget.isChecked()))
            self.settings.setValue("ConcurrentTasks",
                                   concurrentTasksWidget.value())
            self.settings.setValue("LimitConcurrentTasks",
                                   str(limitConcurrentTasksWidget.isChecked()))
            self.settings.setValue("MachineLimit", machineLimitWidget.value())
            self.settings.setValue("IsBlacklist",
                                   str(isBlacklistWidget.isChecked()))
            self.settings.setValue("MachineList", machineListWidget.text())
            self.settings.setValue("Limits", limitsWidget.text())
            self.settings.setValue("OnJobComplete",
                                   onJobCompleteWidget.currentText())
            self.settings.setValue("SubmitSuspended",
                                   str(submitSuspendedWidget.isChecked()))
            self.settings.setValue("Version", versionWidget.currentText())
            self.settings.setValue("SubmitScript",
                                   str(submitScriptWidget.isChecked()))
            self.settings.setValue("Build", buildWidget.currentText())
            self.settings.setValue("UseNukeX", str(useNukeXWidget.isChecked()))
            self.settings.setValue("FramesPerTask",
                                   framesPerTaskWidget.value())
            self.settings.setValue("ContinueOnError",
                                   str(continueOnErrorWidget.isChecked()))
            self.settings.setValue("Threads", threadsWidget.value())
            self.settings.setValue("BatchMode",
                                   str(batchModeWidget.isChecked()))
            self.settings.setValue("Memory", memoryWidget.value())

            print("Saving settings: " + self.settingsFile)
            self.settings.sync()
        else:
            print("Submission canceled")
            self.settings = None
            # Not sure if there is a better way to stop the export process. This works, but it leaves all the tasks
            # in the Queued state.
            self.setError("Submission was canceled")
Esempio n. 33
0
class StreamFieldsWidget(QDialog):
    """
    A stream widget containing schema-specific properties.
    """
    def __init__(self, parent):
        super().__init__()
        self.setParent(parent)
        self.setLayout(QGridLayout())
        self.setWindowModality(Qt.WindowModal)
        self.setModal(True)
        self.minimum_spinbox_value = 0
        self.maximum_spinbox_value = 100_000_000
        self.advanced_options_enabled = False

        self.hs00_unimplemented_label = QLabel(
            "hs00 (Event histograms) has not yet been fully implemented.")

        self.schema_label = QLabel("Schema: ")
        self.schema_combo = QComboBox()

        self.topic_label = QLabel("Topic: ")
        self.topic_line_edit = QLineEdit()
        self.topic_line_edit.setPlaceholderText(
            "[broker][:port, default=9092]/topic")

        self.source_label = QLabel("Source: ")
        self.source_line_edit = QLineEdit()

        self.array_size_label = QLabel("Array size")
        self.array_size_spinbox = QSpinBox()
        self.array_size_spinbox.setMaximum(np.iinfo(np.int32).max)

        self.type_label = QLabel("Type: ")
        self.type_combo = QComboBox()
        self.type_combo.addItems(F142_TYPES)

        self.value_units_edit = QLineEdit()
        self.value_units_label = QLabel("Value Units:")

        self.show_advanced_options_button = QPushButton(
            text="Show/hide advanced options")
        self.show_advanced_options_button.setCheckable(True)
        self.show_advanced_options_button.clicked.connect(
            self.advanced_options_button_clicked)

        self._set_up_f142_group_box()
        self._set_up_ev42_group_box()

        self.scalar_radio = QRadioButton(text="Scalar")
        self.scalar_radio.clicked.connect(partial(self._show_array_size,
                                                  False))
        self.scalar_radio.setChecked(True)
        self.scalar_radio.clicked.emit()

        self.array_radio = QRadioButton(text="Array")
        self.array_radio.clicked.connect(partial(self._show_array_size, True))

        self.schema_combo.currentTextChanged.connect(self._schema_type_changed)
        self.schema_combo.addItems([e.value for e in WriterModules])

        self.ok_button = QPushButton("OK")
        self.ok_button.clicked.connect(self.parent().close)

        self.layout().addWidget(self.schema_label, 0, 0)
        self.layout().addWidget(self.schema_combo, 0, 1)

        self.layout().addWidget(self.topic_label, 1, 0)
        self.layout().addWidget(self.topic_line_edit, 1, 1)

        self.layout().addWidget(self.source_label, 2, 0)
        self.layout().addWidget(self.source_line_edit, 2, 1)

        self.layout().addWidget(self.value_units_label, 3, 0)
        self.layout().addWidget(self.value_units_edit, 3, 1)
        self.value_units_label.setVisible(False)
        self.value_units_edit.setVisible(False)

        self.layout().addWidget(self.type_label, 4, 0)
        self.layout().addWidget(self.type_combo, 4, 1)

        self.layout().addWidget(self.scalar_radio, 5, 0)
        self.layout().addWidget(self.array_radio, 5, 1)

        self.layout().addWidget(self.array_size_label, 6, 0)
        self.layout().addWidget(self.array_size_spinbox, 6, 1)

        self.layout().addWidget(self.hs00_unimplemented_label, 7, 0, 1, 2)

        # Spans both rows
        self.layout().addWidget(self.show_advanced_options_button, 8, 0, 1, 2)
        self.layout().addWidget(self.f142_advanced_group_box, 9, 0, 1, 2)

        self.layout().addWidget(self.ev42_advanced_group_box, 10, 0, 1, 2)

        self.layout().addWidget(self.ok_button, 11, 0, 1, 2)

        self._schema_type_changed(self.schema_combo.currentText())

    def advanced_options_button_clicked(self):
        self._show_advanced_options(
            show=self.show_advanced_options_button.isChecked())

    def _set_up_ev42_group_box(self):
        """
        Sets up the UI for ev42 advanced options.
        """
        self.ev42_nexus_elements = [
            NEXUS_INDICES_INDEX_EVERY_MB,
            NEXUS_INDICES_INDEX_EVERY_KB,
            NEXUS_CHUNK_CHUNK_MB,
            NEXUS_CHUNK_CHUNK_KB,
        ]

        self.ev42_nexus_to_spinner_ui_element = {}

        self.ev42_advanced_group_box = QGroupBox(
            parent=self.show_advanced_options_button)
        self.ev42_advanced_group_box.setLayout(QFormLayout())

        self.ev42_adc_pulse_debug_label = QLabel(ADC_PULSE_DEBUG)
        self.ev42_adc_pulse_debug_checkbox = QCheckBox()

        self.ev42_advanced_group_box.layout().addRow(
            self.ev42_adc_pulse_debug_label,
            self.ev42_adc_pulse_debug_checkbox)

        self.add_labels_and_spinboxes_for_advanced_options(
            self.ev42_nexus_elements,
            self.ev42_advanced_group_box,
            self.ev42_nexus_to_spinner_ui_element,
        )

    def add_labels_and_spinboxes_for_advanced_options(self, elements,
                                                      group_box,
                                                      nexus_to_spinner):
        for nexus_string in elements:
            label = QLabel(nexus_string)
            spinner = QSpinBox()
            spinner.setRange(self.minimum_spinbox_value,
                             self.maximum_spinbox_value)

            group_box.layout().addRow(label, spinner)

            nexus_to_spinner[nexus_string] = spinner

    def _set_up_f142_group_box(self):
        """
        Sets up the UI for the f142 advanced options.
        """
        self.f142_advanced_group_box = QGroupBox(
            parent=self.show_advanced_options_button)
        self.f142_advanced_group_box.setLayout(QFormLayout())
        self.f142_nexus_to_spinner_ui_element = {}

        self.f142_nexus_elements = [
            NEXUS_INDICES_INDEX_EVERY_MB,
            NEXUS_INDICES_INDEX_EVERY_KB,
            STORE_LATEST_INTO,
        ]

        self.add_labels_and_spinboxes_for_advanced_options(
            self.f142_nexus_elements,
            self.f142_advanced_group_box,
            self.f142_nexus_to_spinner_ui_element,
        )

    def _show_advanced_options(self, show):
        schema = self.schema_combo.currentText()
        if schema == WriterModules.F142.value:
            self.f142_advanced_group_box.setVisible(show)
        elif schema == WriterModules.EV42.value:
            self.ev42_advanced_group_box.setVisible(show)
        self.advanced_options_enabled = show

    def _show_array_size(self, show: bool):
        self.array_size_spinbox.setVisible(show)
        self.array_size_label.setVisible(show)

    def _schema_type_changed(self, schema: str):
        self.parent().setWindowTitle(f"Editing {schema} stream field")
        self.hs00_unimplemented_label.setVisible(False)
        self.f142_advanced_group_box.setVisible(False)
        self.ev42_advanced_group_box.setVisible(False)
        self.show_advanced_options_button.setVisible(False)
        self.show_advanced_options_button.setChecked(False)
        self.value_units_label.setVisible(False)
        self.value_units_edit.setVisible(False)
        if schema == WriterModules.F142.value:
            self.value_units_label.setVisible(True)
            self.value_units_edit.setVisible(True)
            self._set_edits_visible(True, True)
            self.show_advanced_options_button.setVisible(True)
            self.f142_advanced_group_box.setVisible(False)
        elif schema == WriterModules.EV42.value:
            self._set_edits_visible(True, False)
            self.show_advanced_options_button.setVisible(True)
            self.ev42_advanced_group_box.setVisible(False)
        elif schema == WriterModules.HS00.value:
            self._set_edits_visible(True, False)
            self.hs00_unimplemented_label.setVisible(True)
        elif schema == WriterModules.NS10.value:
            self._set_edits_visible(True, False, "nicos/<device>/<parameter>")
        elif (schema == WriterModules.TDCTIME.value
              or schema == WriterModules.SENV.value):
            self._set_edits_visible(True, False)

    def _set_edits_visible(self, source: bool, type: bool, source_hint=None):
        self.source_label.setVisible(source)
        self.source_line_edit.setVisible(source)
        self.type_label.setVisible(type)
        self.type_combo.setVisible(type)
        self.array_radio.setVisible(type)
        self.scalar_radio.setVisible(type)
        if source_hint:
            self.source_line_edit.setPlaceholderText(source_hint)
        else:
            self.source_line_edit.setPlaceholderText("")

    def get_stream_group(self) -> h5py.Group:
        """
        Create the stream group with a temporary in-memory HDF5 file.
        :return: The created HDF group.
        """

        temp_file = create_temporary_in_memory_file()
        group = temp_file.create_group("children")
        group.create_dataset(name="type", dtype=STRING_DTYPE, data="stream")
        stream_group = group.create_group(
            self.parent().parent().field_name_edit.text())
        stream_group.attrs[CommonAttrs.NX_CLASS] = CommonAttrs.NC_STREAM
        stream_group.create_dataset(name="topic",
                                    dtype=STRING_DTYPE,
                                    data=self.topic_line_edit.text())
        stream_group.create_dataset(
            name="writer_module",
            dtype=STRING_DTYPE,
            data=self.schema_combo.currentText(),
        )

        schema = self.schema_combo.currentText()
        stream_group.create_dataset("source",
                                    dtype=STRING_DTYPE,
                                    data=self.source_line_edit.text())

        if schema == WriterModules.F142.value:
            self._create_f142_fields(stream_group)
        elif schema == WriterModules.EV42.value:
            self._create_ev42_fields(stream_group)
        return stream_group

    def _create_ev42_fields(self, stream_group: h5py.Group):
        """
        Create ev42 fields in the given group if advanced options are specified.
        :param stream_group: The group to apply fields to.
        """
        if self.advanced_options_enabled:
            if self.ev42_adc_pulse_debug_checkbox.isChecked():
                stream_group.create_dataset(
                    ADC_PULSE_DEBUG,
                    dtype=bool,
                    data=self.ev42_adc_pulse_debug_checkbox.isChecked(),
                )
            self._create_dataset_from_spinner(
                stream_group, self.ev42_nexus_to_spinner_ui_element)

    def _create_f142_fields(self, stream_group: h5py.Group):
        """
        Create f142 fields in the given group if advanced options are specified.
        :param stream_group: The group to apply fields to.
        """
        stream_group.create_dataset("type",
                                    dtype=STRING_DTYPE,
                                    data=self.type_combo.currentText())
        if self.array_radio.isChecked():
            stream_group.create_dataset("array_size",
                                        data=self.array_size_spinbox.value())
        if self.value_units_edit.text():
            stream_group.create_dataset("value_units",
                                        data=self.value_units_edit.text())
        if self.advanced_options_enabled:
            self._create_dataset_from_spinner(
                stream_group, self.f142_nexus_to_spinner_ui_element)

    @staticmethod
    def _create_dataset_from_spinner(stream_group: h5py.Group,
                                     nexus_to_spinner_dict: Dict[str,
                                                                 QSpinBox]):
        for (nexus_string, ui_element) in nexus_to_spinner_dict.items():
            if ui_element.value() > 0:
                stream_group.create_dataset(nexus_string,
                                            dtype=int,
                                            data=ui_element.value())

    def fill_in_existing_ev42_fields(self, field: h5py.Group):
        """
        Fill in specific existing ev42 fields into the new UI field.
        :param field: The stream group
        :param new_ui_field: The new UI field to be filled in
        """
        all_ev42_elements = list(self.ev42_nexus_elements)
        all_ev42_elements.append(ADC_PULSE_DEBUG)

        if check_if_advanced_options_should_be_enabled(all_ev42_elements,
                                                       field):
            self._show_advanced_options(True)
            if ADC_PULSE_DEBUG in field.keys():
                self.ev42_adc_pulse_debug_checkbox.setChecked(
                    bool(field[ADC_PULSE_DEBUG][()]))

            fill_in_advanced_options(
                self.ev42_nexus_to_spinner_ui_element.items(), field)

    def fill_in_existing_f142_fields(self, field: h5py.Group):
        """
        Fill in specific existing f142 fields into the new UI field.
        :param field: The stream group
        :param new_ui_field: The new UI field to be filled in
        """
        self.type_combo.setCurrentText(field["type"][()])
        if "array_size" in field.keys():
            self.array_radio.setChecked(True)
            self.scalar_radio.setChecked(False)
            self.array_size_spinbox.setValue(field["array_size"][()])
        else:
            self.array_radio.setChecked(False)
            self.scalar_radio.setChecked(True)

        if check_if_advanced_options_should_be_enabled(
                self.f142_nexus_elements, field):
            self._show_advanced_options(True)
            fill_in_advanced_options(
                self.f142_nexus_to_spinner_ui_element.items(), field)

    def update_existing_stream_info(self, field: h5py.Group):
        """
        Fill in stream fields and properties into the new UI field.
        :param field: The stream group
        :param new_ui_field: The new UI field to be filled in
        """
        schema = field["writer_module"][()]
        self.schema_combo.setCurrentText(str(schema))
        self.topic_line_edit.setText(str(field["topic"][()]))
        self.source_line_edit.setText(str(field["source"][()]))
        if schema == WriterModules.F142.value:
            self.fill_in_existing_f142_fields(field)
        elif schema == WriterModules.EV42.value:
            self.fill_in_existing_ev42_fields(field)
Esempio n. 34
0
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_faction

        # 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.name)  # 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):
        logging.info("Buying Armor ")
        utype = self.buyArmorCombo.itemData(self.buyArmorCombo.currentIndex())
        logging.info(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()
        self.ground_object.groups = list(generator.groups)

        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()
Esempio n. 35
0
class MagnifierWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(MagnifierWidget, self).__init__(parent)

        self.equalize_radio = QRadioButton(self.tr('Equalization'))
        self.equalize_radio.setToolTip(self.tr('RGB histogram equalization'))
        self.contrast_radio = QRadioButton(self.tr('Auto Contrast'))
        self.contrast_radio.setToolTip(self.tr('Compress luminance tonality'))
        self.centile_spin = QSpinBox()
        self.centile_spin.setRange(0, 100)
        self.centile_spin.setValue(20)
        self.centile_spin.setSuffix(self.tr(' %'))
        self.centile_spin.setToolTip(self.tr('Histogram percentile amount'))
        self.channel_check = QCheckBox(self.tr('By channel'))
        self.channel_check.setToolTip(self.tr('Independent RGB compression'))
        self.equalize_radio.setChecked(True)
        self.last_radio = self.equalize_radio

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.change()

        self.viewer.viewChanged.connect(self.process)
        self.equalize_radio.clicked.connect(self.change)
        self.contrast_radio.clicked.connect(self.change)
        self.centile_spin.valueChanged.connect(self.change)
        self.channel_check.stateChanged.connect(self.change)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Mode:')))
        top_layout.addWidget(self.equalize_radio)
        top_layout.addWidget(self.contrast_radio)
        top_layout.addWidget(self.centile_spin)
        top_layout.addWidget(self.channel_check)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def process(self, rect):
        y1 = rect.top()
        y2 = rect.bottom()
        x1 = rect.left()
        x2 = rect.right()
        roi = self.image[y1:y2, x1:x2]
        if self.equalize_radio.isChecked():
            self.centile_spin.setEnabled(False)
            self.channel_check.setEnabled(False)
            roi = equalize_img(roi)
            self.last_radio = self.equalize_radio
        elif self.contrast_radio.isChecked():
            self.centile_spin.setEnabled(True)
            self.channel_check.setEnabled(True)
            centile = self.centile_spin.value() / 200
            if self.channel_check.isChecked():
                roi = cv.merge(
                    [cv.LUT(c, auto_lut(c, centile)) for c in cv.split(roi)])
            else:
                roi = cv.LUT(
                    roi, auto_lut(cv.cvtColor(roi, cv.COLOR_BGR2GRAY),
                                  centile))
            self.last_radio = self.contrast_radio
        else:
            self.last_radio.setChecked(True)
            return
        processed = np.copy(self.image)
        processed[y1:y2, x1:x2] = roi
        self.viewer.update_processed(processed)

    def change(self):
        self.process(self.viewer.get_rect())
Esempio n. 36
0
class MainWindow(QMainWindow):

    def __init__(self, app, parent=None):
        super(MainWindow, self).__init__(parent)
        self.imagesDir = app.dir + '/images/'
        self.setWindowIcon(QIcon(self.imagesDir + 'icon.png'))
        self.path = ''

        self.settings = QSettings()
        self.lastDir = self.settings.value('lastDir', '')

        self.setMinimumWidth(540)

        self.supportedFormats = []
        for f in QImageReader.supportedImageFormats():
            self.supportedFormats.append(str(f.data(), encoding="utf-8"))

        self.fileWatcher = QFileSystemWatcher()
        self.fileWatcher.fileChanged.connect(self.fileChanged)

        # widgets
        self.showPixmapWidget = None

        self.tileWidthSpinBox = QSpinBox()
        self.tileWidthSpinBox.setValue(16)
        self.tileWidthSpinBox.setFixedWidth(50)
        self.tileWidthSpinBox.setMinimum(1)

        self.tileHeightSpinBox = QSpinBox()
        self.tileHeightSpinBox.setValue(16)
        self.tileHeightSpinBox.setFixedWidth(50)
        self.tileHeightSpinBox.setMinimum(1)

        self.paddingSpinBox = QSpinBox()
        self.paddingSpinBox.setFixedWidth(50)
        self.paddingSpinBox.setMinimum(1)

        self.transparentCheckbox = QCheckBox("Transparent")
        self.transparentCheckbox.setChecked(True)
        self.transparentCheckbox.stateChanged.connect(self.transparentChanged)

        self.backgroundColorEdit = ColorEdit()
        self.backgroundColorEdit.setEnabled(False)
        self.backgroundColorLabel = QLabel("Background color:")
        self.backgroundColorLabel.setEnabled(False)

        self.forcePotCheckBox = QCheckBox("Force PoT")
        self.forcePotCheckBox.setChecked(True)
        self.forcePotCheckBox.stateChanged.connect(self.forcePotChanged)

        self.reorderTilesCheckBox = QCheckBox("Reorder tiles")

        self.generateAndExportButton = QPushButton("Generate and export")
        self.generateAndExportButton.setFixedHeight(32)
        self.generateAndExportButton.clicked.connect(self.generateAndExportClicked)
        self.generateAndExportButton.setEnabled(False)

        self.pixmapWidget = PixmapWidget()
        self.pixmapWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.pixmapWidget.setPixmap(self.createDropTextPixmap())
        self.pixmapWidget.dropSignal.connect(self.fileDropped)
        self.pixmapWidget.setMinimumHeight(300)

        # load settings
        self.tileWidthSpinBox.setValue(int(self.settings.value('tileWidth', 16)))
        self.tileHeightSpinBox.setValue(int(self.settings.value('tileHeight', 16)))
        self.paddingSpinBox.setValue(int(self.settings.value('padding', 1)))
        self.forcePotCheckBox.setChecked(True if self.settings.value('forcePot', 'true') == 'true' else False)
        self.reorderTilesCheckBox.setChecked(True if self.settings.value('reorderTiles', 'false') == 'true' else False)
        self.transparentCheckbox.setChecked(True if self.settings.value('transparent', 'false') == 'true' else False)
        self.backgroundColorEdit.setColorText(str(self.settings.value('backgroundColor', '#FF00FF')))
        self.restoreGeometry(QByteArray(self.settings.value('MainWindow/geometry')))
        self.restoreState(QByteArray(self.settings.value('MainWindow/windowState')))

        # layout
        hl1 = QHBoxLayout()
        hl1.setContentsMargins(5, 5, 5, 5)
        hl1.addWidget(QLabel("Tile width:"))
        hl1.addSpacing(5)
        hl1.addWidget(self.tileWidthSpinBox)
        hl1.addSpacing(15)
        hl1.addWidget(QLabel("Tile height:"))
        hl1.addSpacing(5)
        hl1.addWidget(self.tileHeightSpinBox)
        hl1.addSpacing(15)
        hl1.addWidget(QLabel("Padding:"))
        hl1.addSpacing(5)
        hl1.addWidget(self.paddingSpinBox)
        hl1.addSpacing(15)
        hl1.addWidget(self.forcePotCheckBox)
        hl1.addSpacing(15)
        hl1.addWidget(self.reorderTilesCheckBox)
        hl1.addStretch()

        hl2 = QHBoxLayout()
        hl2.setContentsMargins(5, 5, 5, 5)
        hl2.addWidget(self.transparentCheckbox)
        hl2.addSpacing(15)
        hl2.addWidget(self.backgroundColorLabel)
        hl2.addSpacing(5)
        hl2.addWidget(self.backgroundColorEdit)
        hl2.addStretch()

        hl3 = QHBoxLayout()
        hl3.setContentsMargins(5, 5, 5, 5)
        hl3.addWidget(self.generateAndExportButton)

        vl = QVBoxLayout()
        vl.setContentsMargins(0, 0, 0, 0)
        vl.setSpacing(0)
        vl.addLayout(hl1)
        vl.addLayout(hl2)
        vl.addWidget(self.pixmapWidget)
        vl.addLayout(hl3)

        w = QWidget()
        w.setLayout(vl)
        self.setCentralWidget(w)

        self.setTitle()

    def setTitle(self):
        p = ' - ' + os.path.basename(self.path) if self.path else ''
        self.setWindowTitle(QCoreApplication.applicationName() + ' ' + QCoreApplication.applicationVersion() + p)

    def createDropTextPixmap(self):
        pixmap = QPixmap(481, 300)
        pixmap.fill(QColor("#333333"))
        painter = QPainter(pixmap)
        font = QFont("Arial")
        font.setPixelSize(28)
        font.setBold(True)
        fm = QFontMetrics(font)
        painter.setFont(font)
        painter.setPen(QPen(QColor("#888888"), 1))
        text = "Drop the tileset image here"
        x = (pixmap.width()-fm.width(text))/2
        y = (pixmap.height()+fm.height())/2
        painter.drawText(x, y, text)
        del painter
        return pixmap

    def fileDropped(self, path):
        path = str(path)
        name, ext = os.path.splitext(path)
        ext = ext[1:]
        if not ext in self.supportedFormats:
            QMessageBox.warning(self, "Warning", "The dropped file is not supported")
            return
        pixmap = QPixmap(path)
        if pixmap.isNull():
            QMessageBox.warning(self, "Warning", "Can't load the image")
            return
        if self.path:
            self.fileWatcher.removePath(self.path)
        self.path = path
        self.fileWatcher.addPath(self.path)
        self.pixmapWidget.setPixmap(pixmap)
        self.generateAndExportButton.setEnabled(True)
        self.setTitle()
        self.activateWindow()

    def fileChanged(self, path):
        #self.fileDropped(path)
        pass

    def transparentChanged(self):
        e = self.transparentCheckbox.isChecked()
        self.backgroundColorEdit.setEnabled(not e)
        self.backgroundColorLabel.setEnabled(not e)

    def forcePotChanged(self):
        e = self.forcePotCheckBox.isChecked()
        self.reorderTilesCheckBox.setEnabled(e)

    def generateAndExportClicked(self):

        g = Generator()
        g.tileWidth = self.tileWidthSpinBox.value()
        g.tileHeight = self.tileHeightSpinBox.value()
        g.forcePot = self.forcePotCheckBox.isChecked()
        g.isTransparent = self.transparentCheckbox.isChecked()
        g.bgColor = self.backgroundColorEdit.getColor()
        g.reorder = self.reorderTilesCheckBox.isChecked()
        g.padding = self.paddingSpinBox.value()

        target = g.create(self.pixmapWidget.pixmap);

        # export
        self.lastDir = os.path.dirname(self.path)
        targetPath = QFileDialog.getSaveFileName(self, 'Export', self.lastDir, 'PNG (*.png)')
        if targetPath:
            target.save(targetPath[0])
            showPixmap = QPixmap.fromImage(target)
            if self.showPixmapWidget:
                self.showPixmapWidget.deleteLater()
                del self.showPixmapWidget
            self.showPixmapWidget = PixmapWidget()
            self.showPixmapWidget.setWindowIcon(self.windowIcon())
            self.showPixmapWidget.setWindowTitle(os.path.basename(targetPath[0]))
            self.showPixmapWidget.resize(showPixmap.width(), showPixmap.height())
            self.showPixmapWidget.setPixmap(showPixmap)
            self.showPixmapWidget.show()

    def closeEvent(self, event):
        if self.showPixmapWidget:
            self.showPixmapWidget.close()

        # save settings
        self.settings.setValue('tileWidth', self.tileWidthSpinBox.value())
        self.settings.setValue('tileHeight', self.tileHeightSpinBox.value())
        self.settings.setValue('padding', self.paddingSpinBox.value())
        self.settings.setValue('forcePot', self.forcePotCheckBox.isChecked())
        self.settings.setValue('reorderTiles', self.reorderTilesCheckBox.isChecked())
        self.settings.setValue('transparent', self.transparentCheckbox.isChecked())
        self.settings.setValue('backgroundColor', self.backgroundColorEdit.getColor().name())
        self.settings.setValue('lastDir', self.lastDir)
        self.settings.setValue('MainWindow/geometry', self.saveGeometry())
        self.settings.setValue('MainWindow/windowState', self.saveState())

        super(MainWindow, self).closeEvent(event)