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)'))
Example #2
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)
Example #4
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)
Example #5
0
class EventPropertiesDialog(QDialog):
    def __init__(self):
        super().__init__(GlobalAccess().get_main_window())

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

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

        self.layout = QFormLayout(self)

        self.label_main_title = QLabel(_('Main title'))
        self.item_main_title = QLineEdit()
        self.layout.addRow(self.label_main_title, self.item_main_title)

        self.label_sub_title = QLabel(_('Sub title'))
        self.item_sub_title = QTextEdit()
        self.item_sub_title.setMaximumHeight(100)
        self.layout.addRow(self.label_sub_title, self.item_sub_title)

        self.label_start_date = QLabel(_('Start date'))
        self.item_start_date = QDateTimeEdit()
        self.item_start_date.setDisplayFormat('yyyy.MM.dd HH:mm:ss')
        self.layout.addRow(self.label_start_date, self.item_start_date)

        self.label_end_date = QLabel(_('End date'))
        # self.item_end_date = QCalendarWidget()
        self.item_end_date = QDateTimeEdit()
        self.item_end_date.setDisplayFormat('yyyy.MM.dd HH:mm:ss')
        self.layout.addRow(self.label_end_date, self.item_end_date)

        self.label_location = QLabel(_('Location'))
        self.item_location = QLineEdit()
        self.layout.addRow(self.label_location, self.item_location)

        self.label_type = QLabel(_('Event type'))
        self.item_type = AdvComboBox()
        self.item_type.addItems(RaceType.get_titles())
        self.layout.addRow(self.label_type, self.item_type)

        self.label_relay_legs = QLabel(_('Relay legs'))
        self.item_relay_legs = QSpinBox()
        self.item_relay_legs.setMinimum(1)
        self.item_relay_legs.setMaximum(20)
        self.item_relay_legs.setValue(3)
        self.layout.addRow(self.label_relay_legs, self.item_relay_legs)

        self.item_type.currentTextChanged.connect(self.change_type)

        self.label_refery = QLabel(_('Chief referee'))
        self.item_refery = QLineEdit()
        self.layout.addRow(self.label_refery, self.item_refery)

        self.label_secretary = QLabel(_('Secretary'))
        self.item_secretary = QLineEdit()
        self.layout.addRow(self.label_secretary, self.item_secretary)

        self.label_url = QLabel(_('URL'))
        self.item_url = QLineEdit()
        self.layout.addRow(self.label_url, self.item_url)

        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.set_values_from_model()

        self.show()

    def change_type(self):
        flag = self.item_type.currentText() == RaceType.RELAY.get_title()
        self.label_relay_legs.setVisible(flag)
        self.item_relay_legs.setVisible(flag)

    def set_values_from_model(self):
        obj = race()
        self.item_main_title.setText(str(obj.data.title))
        self.item_sub_title.setText(str(obj.data.description))
        self.item_location.setText(str(obj.data.location))
        self.item_url.setText(str(obj.data.url))
        self.item_refery.setText(str(obj.data.chief_referee))
        self.item_secretary.setText(str(obj.data.secretary))
        self.item_start_date.setDateTime(obj.data.get_start_datetime())
        self.item_end_date.setDateTime(obj.data.get_end_datetime())
        self.item_type.setCurrentText(obj.data.race_type.get_title())
        self.item_relay_legs.setValue(obj.data.relay_leg_count)
        self.change_type()

    def apply_changes_impl(self):
        obj = race()

        start_date = self.item_start_date.dateTime().toPython()
        end_date = self.item_end_date.dateTime().toPython()

        obj.data.title = self.item_main_title.text()
        obj.data.description = self.item_sub_title.toPlainText()
        obj.data.description = obj.data.description.replace('\n', '<br>\n')
        obj.data.location = self.item_location.text()
        obj.data.url = self.item_url.text()
        obj.data.chief_referee = self.item_refery.text()
        obj.data.secretary = self.item_secretary.text()
        obj.data.start_datetime = start_date
        obj.data.end_datetime = end_date

        t = RaceType.get_by_name(self.item_type.currentText())
        if t is not None:
            obj.data.race_type = t
        obj.data.relay_leg_count = self.item_relay_legs.value()

        obj.set_setting('system_zero_time',
                        (start_date.hour, start_date.minute, 0))

        ResultCalculation(race()).process_results()
        GlobalAccess().get_main_window().set_title()
Example #6
0
class PresetItemPool(PresetTab, Ui_PresetItemPool):
    _boxes_for_category: Dict[ItemCategory,
                              Tuple[QGroupBox, QGridLayout,
                                    Dict[MajorItem, ItemConfigurationWidget]]]
    _default_items: Dict[ItemCategory, QtWidgets.QComboBox]

    _ammo_maximum_spinboxes: Dict[int, List[QSpinBox]]
    _ammo_pickup_widgets: Dict[Ammo, AmmoPickupWidgets]
    _progressive_widgets: List[ProgressiveItemWidget]
    _split_ammo_widgets: List[SplitAmmoWidget]

    def __init__(self, editor: PresetEditor):
        super().__init__()
        self.setupUi(self)

        self._editor = editor
        size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        self.item_pool_layout.setAlignment(Qt.AlignTop)

        # Relevant Items
        self.game = editor.game
        self.game_description = default_database.game_description_for(
            self.game)
        item_database = default_database.item_database_for_game(self.game)

        self._energy_tank_item = item_database.major_items["Energy Tank"]

        self._register_random_starting_events()
        self._create_categories_boxes(item_database, size_policy)
        self._create_customizable_default_items(item_database)
        self._create_progressive_widgets(item_database)
        self._create_major_item_boxes(item_database,
                                      self.game_description.resource_database)
        self._create_energy_tank_box()
        self._create_split_ammo_widgets(item_database)
        self._create_ammo_pickup_boxes(size_policy, item_database)

    @property
    def uses_patches_tab(self) -> bool:
        return False

    def on_preset_changed(self, preset: Preset):
        # Item alternatives
        layout = preset.configuration
        major_configuration = layout.major_items_configuration

        for progressive_widget in self._progressive_widgets:
            progressive_widget.on_preset_changed(
                preset,
                self._boxes_for_category[
                    progressive_widget.progressive_item.item_category][2],
            )

        for split_ammo in self._split_ammo_widgets:
            split_ammo.on_preset_changed(preset, self._ammo_pickup_widgets)

        # Random Starting Items
        self.minimum_starting_spinbox.setValue(
            major_configuration.minimum_random_starting_items)
        self.maximum_starting_spinbox.setValue(
            major_configuration.maximum_random_starting_items)

        # Default Items
        for category, default_item in major_configuration.default_items.items(
        ):
            combo = self._default_items[category]
            combo.setCurrentIndex(combo.findData(default_item))

            for item, widget in self._boxes_for_category[category][2].items():
                widget.setEnabled(default_item != item)

        # Major Items
        for _, _, elements in self._boxes_for_category.values():
            for major_item, widget in elements.items():
                widget.state = major_configuration.items_state[major_item]

        # Energy Tank
        energy_tank_state = major_configuration.items_state[
            self._energy_tank_item]
        self.energy_tank_starting_spinbox.setValue(
            energy_tank_state.num_included_in_starting_items)
        self.energy_tank_shuffled_spinbox.setValue(
            energy_tank_state.num_shuffled_pickups)

        # Ammo
        ammo_provided = major_configuration.calculate_provided_ammo()
        ammo_configuration = layout.ammo_configuration

        for ammo_item, maximum in ammo_configuration.maximum_ammo.items():
            for spinbox in self._ammo_maximum_spinboxes[ammo_item]:
                spinbox.setValue(maximum)

        previous_pickup_for_item = {}
        resource_database = self.game_description.resource_database

        item_for_index: Dict[int, ItemResourceInfo] = {
            ammo_index: resource_database.get_item(ammo_index)
            for ammo_index in ammo_provided.keys()
        }

        for ammo, state in ammo_configuration.items_state.items():
            widgets = self._ammo_pickup_widgets[ammo]
            widgets.pickup_spinbox.setValue(state.pickup_count)

            if widgets.require_major_item_check is not None:
                widgets.require_major_item_check.setChecked(
                    state.requires_major_item)

            try:
                if state.pickup_count == 0:
                    widgets.expected_count.setText(
                        "No expansions will be created.")
                    continue

                ammo_per_pickup = items_for_ammo(
                    ammo, state, ammo_provided, previous_pickup_for_item,
                    ammo_configuration.maximum_ammo)

                totals = functools.reduce(
                    lambda a, b: [x + y for x, y in zip(a, b)],
                    ammo_per_pickup, [0 for _ in ammo.items])

                if {total % state.pickup_count for total in totals} == {0}:
                    count_text_template = _EXPECTED_COUNT_TEXT_TEMPLATE_EXACT
                else:
                    count_text_template = _EXPECTED_COUNT_TEXT_TEMPLATE

                widgets.expected_count.setText(
                    count_text_template.format(
                        per_expansion=" and ".join(
                            "{:.3g} {}".format(
                                total / state.pickup_count,
                                item_for_index[ammo_index].long_name)
                            for ammo_index, total in zip(ammo.items, totals)),
                        total=" and ".join(
                            "{} {}".format(
                                total, item_for_index[ammo_index].long_name)
                            for ammo_index, total in zip(ammo.items, totals)),
                        from_items=" and ".join("{} {}".format(
                            ammo_provided[ammo_index],
                            item_for_index[ammo_index].long_name)
                                                for ammo_index in ammo.items),
                    ))

            except InvalidConfiguration as invalid_config:
                widgets.expected_count.setText(str(invalid_config))

        # Item pool count
        try:
            pool_items, maximum_size = pool_creator.calculate_pool_item_count(
                layout)
            self.item_pool_count_label.setText("Items in pool: {}/{}".format(
                pool_items, maximum_size))
            common_qt_lib.set_error_border_stylesheet(
                self.item_pool_count_label, pool_items > maximum_size)

        except InvalidConfiguration as invalid_config:
            self.item_pool_count_label.setText(
                "Invalid Configuration: {}".format(invalid_config))
            common_qt_lib.set_error_border_stylesheet(
                self.item_pool_count_label, True)

    # Item Alternatives

    def _persist_bool_layout_field(self, field_name: str):
        def bound(value: int):
            with self._editor as options:
                options.set_configuration_field(field_name, bool(value))

        return bound

    def _persist_bool_major_configuration_field(self, field_name: str):
        def bound(value: int):
            with self._editor as options:
                kwargs = {field_name: bool(value)}
                options.major_items_configuration = dataclasses.replace(
                    options.major_items_configuration, **kwargs)

        return bound

    # Random Starting

    def _register_random_starting_events(self):
        self.minimum_starting_spinbox.valueChanged.connect(
            self._on_update_minimum_starting)
        self.maximum_starting_spinbox.valueChanged.connect(
            self._on_update_maximum_starting)

    def _on_update_minimum_starting(self, value: int):
        with self._editor as options:
            options.major_items_configuration = dataclasses.replace(
                options.major_items_configuration,
                minimum_random_starting_items=value)

    def _on_update_maximum_starting(self, value: int):
        with self._editor as options:
            options.major_items_configuration = dataclasses.replace(
                options.major_items_configuration,
                maximum_random_starting_items=value)

    # Major Items
    def _create_progressive_widgets(self, item_database: ItemDatabase):
        self._progressive_widgets = []

        all_progressive = []

        if self.game == RandovaniaGame.PRIME2:
            all_progressive.append((
                "Progressive Suit",
                ("Dark Suit", "Light Suit"),
            ))
            all_progressive.append((
                "Progressive Grapple",
                ("Grapple Beam", "Screw Attack"),
            ))
        elif self.game == RandovaniaGame.PRIME3:
            all_progressive.append((
                "Progressive Missile",
                ("Ice Missile", "Seeker Missile"),
            ))
            all_progressive.append((
                "Progressive Beam",
                ("Plasma Beam", "Nova Beam"),
            ))

        for (progressive_item_name, non_progressive_items) in all_progressive:
            progressive_item = item_database.major_items[progressive_item_name]
            parent, layout, _ = self._boxes_for_category[
                progressive_item.item_category]

            widget = ProgressiveItemWidget(
                parent,
                self._editor,
                progressive_item=progressive_item,
                non_progressive_items=[
                    item_database.major_items[it]
                    for it in non_progressive_items
                ],
            )
            widget.setText("Use progressive {}".format(
                " → ".join(non_progressive_items)))
            self._progressive_widgets.append(widget)
            layout.addWidget(widget)

    def _create_split_ammo_widgets(self, item_database: ItemDatabase):
        parent, layout, _ = self._boxes_for_category[ItemCategory.BEAM]

        self._split_ammo_widgets = []

        if self.game == RandovaniaGame.PRIME2:
            beam_ammo = SplitAmmoWidget(
                parent,
                self._editor,
                unified_ammo=item_database.ammo["Beam Ammo Expansion"],
                split_ammo=[
                    item_database.ammo["Dark Ammo Expansion"],
                    item_database.ammo["Light Ammo Expansion"],
                ],
            )
            beam_ammo.setText("Split Beam Ammo Expansions")
            self._split_ammo_widgets.append(beam_ammo)

        if self._split_ammo_widgets:
            line = QtWidgets.QFrame(parent)
            line.setFrameShape(QtWidgets.QFrame.HLine)
            line.setFrameShadow(QtWidgets.QFrame.Sunken)
            layout.addWidget(line, layout.rowCount(), 0, 1, -1)

        for widget in self._split_ammo_widgets:
            layout.addWidget(widget, layout.rowCount(), 0, 1, -1)

    def _create_categories_boxes(self, item_database: ItemDatabase,
                                 size_policy):
        self._boxes_for_category = {}

        categories = set()
        for major_item in item_database.major_items.values():
            if not major_item.required:
                categories.add(major_item.item_category)

        all_categories = list(iterate_enum(ItemCategory))
        for major_item_category in sorted(
                categories, key=lambda it: all_categories.index(it)):
            category_box = QGroupBox(self.scroll_area_contents)
            category_box.setTitle(major_item_category.long_name)
            category_box.setSizePolicy(size_policy)
            category_box.setObjectName(f"category_box {major_item_category}")

            category_layout = QGridLayout(category_box)
            category_layout.setObjectName(
                f"category_layout {major_item_category}")

            self.item_pool_layout.addWidget(category_box)
            self._boxes_for_category[
                major_item_category] = category_box, category_layout, {}

    def _create_customizable_default_items(self, item_database: ItemDatabase):
        self._default_items = {}

        for category, possibilities in item_database.default_items.items():
            parent, layout, _ = self._boxes_for_category[category]

            label = QtWidgets.QLabel(parent)
            label.setText(f"Default {category.long_name}")
            layout.addWidget(label, 0, 0)

            combo = QtWidgets.QComboBox(parent)
            for item in possibilities:
                combo.addItem(item.name, item)
            combo.currentIndexChanged.connect(
                partial(self._on_default_item_updated, category, combo))
            layout.addWidget(combo, 0, 1)

            self._default_items[category] = combo

    def _on_default_item_updated(self, category: ItemCategory,
                                 combo: QtWidgets.QComboBox, _):
        with self._editor as editor:
            new_config = editor.major_items_configuration
            new_config = new_config.replace_default_item(
                category, combo.currentData())
            new_config = new_config.replace_state_for_item(
                combo.currentData(),
                MajorItemState(num_included_in_starting_items=1))
            editor.major_items_configuration = new_config

    def _create_major_item_boxes(self, item_database: ItemDatabase,
                                 resource_database: ResourceDatabase):
        for major_item in item_database.major_items.values():
            if major_item.required or major_item.item_category == ItemCategory.ENERGY_TANK:
                continue

            category_box, category_layout, elements = self._boxes_for_category[
                major_item.item_category]
            widget = ItemConfigurationWidget(None, major_item,
                                             MajorItemState(),
                                             resource_database)
            widget.Changed.connect(partial(self._on_major_item_updated,
                                           widget))

            row = category_layout.rowCount()
            category_layout.addWidget(widget, row, 0, 1, -1)

            elements[major_item] = widget

    def _on_major_item_updated(self, item_widget: ItemConfigurationWidget):
        with self._editor as editor:
            editor.major_items_configuration = editor.major_items_configuration.replace_state_for_item(
                item_widget.item, item_widget.state)

    # Energy Tank

    def _create_energy_tank_box(self):
        category_box, category_layout, _ = self._boxes_for_category[
            ItemCategory.ENERGY_TANK]

        starting_label = QLabel(category_box)
        starting_label.setText("Starting Quantity")

        shuffled_label = QLabel(category_box)
        shuffled_label.setText("Shuffled Quantity")

        self.energy_tank_starting_spinbox = QSpinBox(category_box)
        self.energy_tank_starting_spinbox.setMaximum(ENERGY_TANK_MAXIMUM_COUNT)
        self.energy_tank_starting_spinbox.valueChanged.connect(
            self._on_update_starting_energy_tank)
        self.energy_tank_shuffled_spinbox = QSpinBox(category_box)
        self.energy_tank_shuffled_spinbox.setMaximum(
            DEFAULT_MAXIMUM_SHUFFLED[-1])
        self.energy_tank_shuffled_spinbox.valueChanged.connect(
            self._on_update_shuffled_energy_tank)

        category_layout.addWidget(starting_label, 0, 0)
        category_layout.addWidget(self.energy_tank_starting_spinbox, 0, 1)
        category_layout.addWidget(shuffled_label, 1, 0)
        category_layout.addWidget(self.energy_tank_shuffled_spinbox, 1, 1)

    def _on_update_starting_energy_tank(self, value: int):
        with self._editor as options:
            major_configuration = options.major_items_configuration
            options.major_items_configuration = major_configuration.replace_state_for_item(
                self._energy_tank_item,
                dataclasses.replace(
                    major_configuration.items_state[self._energy_tank_item],
                    num_included_in_starting_items=value))

    def _on_update_shuffled_energy_tank(self, value: int):
        with self._editor as options:
            major_configuration = options.major_items_configuration
            options.major_items_configuration = major_configuration.replace_state_for_item(
                self._energy_tank_item,
                dataclasses.replace(
                    major_configuration.items_state[self._energy_tank_item],
                    num_shuffled_pickups=value))

    # Ammo

    def _create_ammo_pickup_boxes(self, size_policy,
                                  item_database: ItemDatabase):
        """
        Creates the GroupBox with SpinBoxes for selecting the pickup count of all the ammo
        :param item_database:
        :return:
        """

        self._ammo_maximum_spinboxes = collections.defaultdict(list)
        self._ammo_pickup_widgets = {}

        resource_database = default_database.resource_database_for(self.game)
        broad_to_category = {
            ItemCategory.BEAM_RELATED: ItemCategory.BEAM,
            ItemCategory.MORPH_BALL_RELATED: ItemCategory.MORPH_BALL,
            ItemCategory.MISSILE_RELATED: ItemCategory.MISSILE,
        }

        for ammo in item_database.ammo.values():
            category_box, category_layout, _ = self._boxes_for_category[
                broad_to_category[ammo.broad_category]]

            pickup_box = QGroupBox(category_box)
            pickup_box.setSizePolicy(size_policy)
            pickup_box.setTitle(ammo.name + "s")
            layout = QGridLayout(pickup_box)
            layout.setObjectName(f"{ammo.name} Box Layout")
            current_row = 0

            for ammo_item in ammo.items:
                item = resource_database.get_by_type_and_index(
                    ResourceType.ITEM, ammo_item)

                target_count_label = QLabel(pickup_box)
                target_count_label.setText(f"{item.long_name} Target" if len(
                    ammo.items) > 1 else "Target count")

                maximum_spinbox = QSpinBox(pickup_box)
                maximum_spinbox.setMaximum(ammo.maximum)
                maximum_spinbox.valueChanged.connect(
                    partial(self._on_update_ammo_maximum_spinbox, ammo_item))
                self._ammo_maximum_spinboxes[ammo_item].append(maximum_spinbox)

                layout.addWidget(target_count_label, current_row, 0)
                layout.addWidget(maximum_spinbox, current_row, 1)
                current_row += 1

            count_label = QLabel(pickup_box)
            count_label.setText("Pickup Count")
            count_label.setToolTip(
                "How many instances of this expansion should be placed.")

            pickup_spinbox = QSpinBox(pickup_box)
            pickup_spinbox.setMaximum(AmmoState.maximum_pickup_count())
            pickup_spinbox.valueChanged.connect(
                partial(self._on_update_ammo_pickup_spinbox, ammo))

            layout.addWidget(count_label, current_row, 0)
            layout.addWidget(pickup_spinbox, current_row, 1)
            current_row += 1

            if ammo.temporaries:
                require_major_item_check = QCheckBox(pickup_box)
                require_major_item_check.setText(
                    "Requires the major item to work?")
                require_major_item_check.stateChanged.connect(
                    partial(self._on_update_ammo_require_major_item, ammo))
                layout.addWidget(require_major_item_check, current_row, 0, 1,
                                 2)
                current_row += 1
            else:
                require_major_item_check = None

            expected_count = QLabel(pickup_box)
            expected_count.setWordWrap(True)
            expected_count.setText(_EXPECTED_COUNT_TEXT_TEMPLATE)
            expected_count.setToolTip(
                "Some expansions may provide 1 extra, even with no variance, if the total count "
                "is not divisible by the pickup count.")
            layout.addWidget(expected_count, current_row, 0, 1, 2)
            current_row += 1

            self._ammo_pickup_widgets[ammo] = AmmoPickupWidgets(
                pickup_spinbox, expected_count, pickup_box,
                require_major_item_check)
            category_layout.addWidget(pickup_box)

    def _on_update_ammo_maximum_spinbox(self, ammo_int: int, value: int):
        with self._editor as options:
            options.ammo_configuration = options.ammo_configuration.replace_maximum_for_item(
                ammo_int, value)

    def _on_update_ammo_pickup_spinbox(self, ammo: Ammo, value: int):
        with self._editor as options:
            ammo_configuration = options.ammo_configuration
            options.ammo_configuration = ammo_configuration.replace_state_for_ammo(
                ammo,
                dataclasses.replace(ammo_configuration.items_state[ammo],
                                    pickup_count=value))

    def _on_update_ammo_require_major_item(self, ammo: Ammo, value: int):
        with self._editor as options:
            ammo_configuration = options.ammo_configuration
            options.ammo_configuration = ammo_configuration.replace_state_for_ammo(
                ammo,
                dataclasses.replace(ammo_configuration.items_state[ammo],
                                    requires_major_item=bool(value)))
class HyperparametersConfigWidgetGui(QWidget, HyperparametersConfigWidget):
    def __init__(self, parent: "QWidget" = None):
        HyperparametersConfigWidget.__init__(self)
        QWidget.__init__(self, parent)

        # Widgets
        self._epoch_spinbox = QSpinBox(parent=self)
        self._epoch_spinbox.setMinimum(1)
        self._epoch_spinbox.setValue(self.get_epochs())

        self._loss_function_combobox = QComboBox(parent=self)
        self._loss_function_combobox.addItems(self.get_available_loss_functions())
        self._loss_function_combobox.setCurrentText(self.get_loss_function())

        self._optimizer_combobox = QComboBox()
        self._optimizer_combobox.addItems(self.get_available_optimizers())
        self._optimizer_combobox.setCurrentText(self.get_optimizer())

        self._batch_size_spinbox = QSpinBox(parent=self)
        self._batch_size_spinbox.setValue(self.get_batch_size())
        self._batch_size_spinbox.setMinimum(1)
        self._batch_size_spinbox.setMaximum(999999)

        # Layouts
        self._main_layout = QFormLayout()
        self._main_layout.addRow("Epochs", self._epoch_spinbox)
        self._main_layout.addRow("Optimizer", self._optimizer_combobox)
        self._main_layout.addRow("Loss function", self._loss_function_combobox)
        self._main_layout.addRow("Batch size", self._batch_size_spinbox)
        self.setLayout(self._main_layout)

        # Hyperparameters dictionary
        self._epoch_spinbox.valueChanged.connect(self.set_epochs)
        self._loss_function_combobox.currentTextChanged.connect(self.set_loss_function)
        self._optimizer_combobox.currentTextChanged.connect(self.set_optimizer)
        self._batch_size_spinbox.valueChanged.connect(self.set_batch_size)

    def set_epochs(self, epochs: int):
        super().set_epochs(epochs)

        self._epoch_spinbox.setValue(epochs)

    def set_loss_function(self, loss_function: str):
        super().set_loss_function(loss_function)

        self._loss_function_combobox.setCurrentText(loss_function)

    def set_optimizer(self, optimizer: str):
        super().set_optimizer(optimizer)

        self._optimizer_combobox.setCurrentText(optimizer)

    def set_batch_size(self, batch_size: int):
        super().set_batch_size(batch_size)

        self._batch_size_spinbox.setValue(batch_size)

    def sizeHint(self) -> "QSize":
        return QSize(350, 200)

    def __getstate__(self):
        return {"hyperparameters": self.get_hyperparameters()}

    def __setstate__(self, new_state):
        self._hyperparameters = new_state["hyperparameters"]

        self.set_hyperparameters(new_state["hyperparameters"])

    def __reduce__(self):
        return (HyperparametersConfigWidgetGui, (), self.__getstate__())
Example #8
0
    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()
class QFlightCreator(QDialog):

    def __init__(self, game: Game, from_cp:ControlPoint, possible_aircraft_type:List[UnitType], flight_view=None):
        super(QFlightCreator, self).__init__()
        self.game = game
        self.from_cp = from_cp
        self.flight_view = flight_view
        self.planner = self.game.planners[from_cp.id]
        self.available = self.planner.get_available_aircraft()

        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.setModal(True)
        self.setWindowTitle("Create flight")
        self.setWindowIcon(EVENT_ICONS["strike"])

        self.select_type_aircraft = QComboBox()
        for aircraft_type in self.planner.get_available_aircraft().keys():
            print(aircraft_type)
            print(aircraft_type.name)
            self.select_type_aircraft.addItem(aircraft_type.id, userData=aircraft_type)
        self.select_type_aircraft.setCurrentIndex(0)

        self.select_flight_type = QComboBox()
        self.select_flight_type.addItem("CAP [Combat Air Patrol]", userData=FlightType.CAP)
        self.select_flight_type.addItem("BARCAP [Barrier Combat Air Patrol]", userData=FlightType.BARCAP)
        self.select_flight_type.addItem("TARCAP [Target Combat Air Patrol]", userData=FlightType.TARCAP)
        self.select_flight_type.addItem("INTERCEPT [Interception]", userData=FlightType.INTERCEPTION)
        self.select_flight_type.addItem("CAS [Close Air Support]", userData=FlightType.CAS)
        self.select_flight_type.addItem("BAI [Battlefield Interdiction]", userData=FlightType.BAI)
        self.select_flight_type.addItem("SEAD [Suppression of Enemy Air Defenses]", userData=FlightType.SEAD)
        self.select_flight_type.addItem("DEAD [Destruction of Enemy Air Defenses]", userData=FlightType.DEAD)
        self.select_flight_type.addItem("STRIKE [Strike]", userData=FlightType.STRIKE)
        self.select_flight_type.addItem("ANTISHIP [Antiship Attack]", userData=FlightType.ANTISHIP)
        self.select_flight_type.setCurrentIndex(0)

        self.select_count_of_aircraft = QSpinBox()
        self.select_count_of_aircraft.setMinimum(1)
        self.select_count_of_aircraft.setMaximum(4)
        self.select_count_of_aircraft.setValue(2)

        self.add_button = QPushButton("Add")
        self.add_button.clicked.connect(self.create_flight)

        self.init_ui()


    def init_ui(self):
        layout = QVBoxLayout()

        type_layout = QHBoxLayout()
        type_layout.addWidget(QLabel("Type of Aircraft : "))
        type_layout.addStretch()
        type_layout.addWidget(self.select_type_aircraft, alignment=Qt.AlignRight)

        count_layout = QHBoxLayout()
        count_layout.addWidget(QLabel("Count : "))
        count_layout.addStretch()
        count_layout.addWidget(self.select_count_of_aircraft, alignment=Qt.AlignRight)

        flight_type_layout = QHBoxLayout()
        flight_type_layout.addWidget(QLabel("Task : "))
        flight_type_layout.addStretch()
        flight_type_layout.addWidget(self.select_flight_type, alignment=Qt.AlignRight)

        layout.addLayout(type_layout)
        layout.addLayout(count_layout)
        layout.addLayout(flight_type_layout)
        layout.addStretch()
        layout.addWidget(self.add_button, alignment=Qt.AlignRight)

        self.setLayout(layout)

    def create_flight(self):
        aircraft_type = self.select_type_aircraft.currentData()
        count = self.select_count_of_aircraft.value()

        if self.available[aircraft_type] < count:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Information)
            msg.setText("Not enough aircraft of this type are available. Only " + str(self.available[aircraft_type]) + " available.")
            msg.setWindowTitle("Not enough aircraft")
            msg.setStandardButtons(QMessageBox.Ok)
            msg.setWindowFlags(Qt.WindowStaysOnTopHint)
            msg.exec_()
            return
        else:
            flight = Flight(aircraft_type, count, self.from_cp, self.select_flight_type.currentData())
            self.planner.flights.append(flight)
            self.planner.custom_flights.append(flight)
            if self.flight_view is not None:
                self.flight_view.set_flight_planner(self.planner, len(self.planner.flights)-1)
            self.close()
Example #10
0
class main(QWidget):
    def __init__(self, parent=None):
        super(main, self).__init__(parent)
        self.setup()  # connections, widgets, layouts, etc.

        self.blksize = 2**20  # 1 MB; must be divisible by 16
        self.ext = '.enc'  # extension is appended to encrypted files
        self.path = ''
        self.encrypted = []  # to highlight done files in list
        self.decrypted = []

        self.clipboard = QApplication.clipboard()
        self.timeout = None  # to clear message label, see setMessage

        # this program was just an excuse to play with QprogressBar
        if not hash(os.urandom(11)) % 11:
            QTimer().singleShot(50, self.windDown)

        # various random hints
        hints = [
            'Freshly encrypted files can be renamed in the table!',
            'Clipboard is always cleared on program close!',
            'Keys can contain emoji if you <em>really</em> want: \U0001f4e6',
            'Keys can contain emoji if you <em>really</em> want: \U0001F511',
            'This isn\'t a tip, I just wanted to say hello!',
            'Keys can be anywhere from 8 to 4096 characters long!',
            'This program was just an excuse to play with the progress bars!',
            'Select \'Party\' in the hash button for progress bar fun!',
            ('Did you know you can donate one or all of your vital organs to '
             'the Aperture Science Self-Esteem Fund for Girls? It\'s true!'),
            ('It\'s been {:,} days since Half-Life 2: Episode '
             'Two'.format(int((time.time() - 1191988800) / 86400))),
            'I\'m version {}!'.format(VERSION),
            'I\'m version {}.whatever!'.format(VERSION.split('.')[0]),
            ('Brought to you by me, I\'m <a href="https://orthallelous.word'
             'press.com/">Orthallelous!</a>'),
            #'Brought to you by me, I\'m Htom Sirveaux!',
            'I wonder if there\'s beer on the sun',
            'Raspberry World: For all your raspberry needs. Off the beltline',
            #'I\'ve plummented to my death and I can\'t get up',
            '<em>NOT</em> compatible with the older version!',
            ('Hello there, fellow space travellers! Until somebody gives me '
             'some new lines in KAS, that is all I can say. - Bentusi Exchange'
             )
        ]
        if not hash(os.urandom(9)) % 4:
            self.extraLabel.setText(random.choice(hints))

    def genKey(self):
        "generate a random key"
        n = self.keySizeSB.value()
        char = string.printable.rstrip()  #map(chr, range(256))
        while len(char) < n:
            char += char
        key = ''.join(random.sample(char, n))
        self.keyInput.setText(key)

    def showKey(self, state=None):
        "hide/show key characters"
        if state is None: state = bool(self.showKeyCB.checkState())
        else: state = bool(state)
        if state: self.keyInput.setEchoMode(QLineEdit.Normal)
        else: self.keyInput.setEchoMode(QLineEdit.PasswordEchoOnEdit)

    def getFolder(self):
        "open file dialog and fill file table"
        path = QFileDialog(directory=self.path).getExistingDirectory()
        if not path: return
        self.path = str(path)
        self.populateTable(self.path)
        self.encrypted, self.decrypted = [], []
        return

    def resizeEvent(self, event):
        self.showFolder(self.path)  # update how the folder is shown

    def splitterChanged(self, pos):
        self.showFolder(self.path)  # likewise

    def showFolder(self, path):
        "displays current path, truncating as needed"
        if not path: return

        ell, sl = '\u2026', os.path.sep  # ellipsis, slash chars
        lfg, rfg = Qt.ElideLeft, Qt.ElideRight
        lst, wdh = os.path.basename(path), self.folderLabel.width()

        path = path.replace(os.path.altsep or '\\', sl)
        self.folderLabel.setToolTip(path)

        # truncate folder location
        fnt = QFontMetrics(self.folderLabel.font())
        txt = str(fnt.elidedText(path, lfg, wdh))

        if len(txt) <= 1:  # label is way too short
            self.folderLabel.setText('\u22ee' if txt != sl else txt)
            return  # but when would this happen?

        # truncate some more (don't show part of a folder name)
        if len(txt) < len(path) and txt[1] != sl:
            txt = ell + sl + txt.split(sl, 1)[-1]

            # don't truncate remaining folder name from the left
            if txt[2:] != lst and len(txt[2:]) < len(lst) + 2:
                txt = str(fnt.elidedText(ell + sl + lst, rfg, wdh))
        # you'd think len(txt) < len(lst) would work, but no; you'd be wrong

        self.folderLabel.setText(txt)

    def populateTable(self, path):
        "fill file table with file names"
        self.showFolder(path)

        names = []
        for n in os.listdir(path):
            if os.path.isdir(os.path.join(path, n)): continue  # folder
            names.append(n)

        self.folderTable.clearContents()
        self.folderTable.setRowCount(len(names))
        self.folderTable.setColumnCount(1)

        if not names:  # no files in this folder, inform user
            self.setMessage('This folder has no files')
            return

        self.folderTable.blockSignals(True)
        selEnab = Qt.ItemIsSelectable | Qt.ItemIsEnabled
        for i, n in enumerate(names):
            item = QTableWidgetItem()
            item.setText(n)
            item.setToolTip(n)
            item.setFlags(selEnab)

            # color code encrypted/decrypted files
            if n in self.encrypted:
                item.setTextColor(QColor(211, 70, 0))
                # allowed encrypted filenames to be changed
                item.setFlags(selEnab | Qt.ItemIsEditable)
            if n in self.decrypted:
                item.setForeground(QColor(0, 170, 255))
            self.folderTable.setItem(i, 0, item)
        if len(names) > 5:
            self.setMessage('{:,} files'.format(len(names)), 7)
        self.folderTable.blockSignals(False)
        return

    def editFileName(self, item):
        "change file name"
        new, old = str(item.text()), str(item.toolTip())

        result = QMessageBox.question(
            self, 'Renaming?',
            ("<p align='center'>Do you wish to rename<br>" +
             '<span style="color:#d34600;">{}</span>'.format(old) +
             "<br>to<br>" +
             '<span style="color:#ef4b00;">{}</span>'.format(new) +
             '<br>?</p>'))

        self.folderTable.blockSignals(True)
        if any(i in new for i in '/?<>:*|"^'):
            self.setMessage('Invalid character in name', 7)
            item.setText(old)
        elif result == QMessageBox.Yes:
            oold = os.path.join(self.path, old)
            try:
                os.rename(oold, os.path.join(self.path, new))
                self.encrypted.remove(old)
                self.encrypted.append(new)
                item.setToolTip(new)
            except Exception as err:
                self.setMessage(str(err), 9)
                item.setText(old)
                item.setToolTip(old)
                self.encrypted.remove(new)
                self.encrypted.append(old)
        else:
            item.setText(old)
        self.folderTable.blockSignals(False)

    def setMessage(self, message, secs=4, col=None):
        "show a message for a few seconds - col must be rgb triplet tuple"
        if self.timeout:  # https://stackoverflow.com/a/21081371
            self.timeout.stop()
            self.timeout.deleteLater()

        if col is None: color = 'rgb(255, 170, 127)'
        else:
            try:
                color = 'rgb({}, {}, {})'.format(*col)
            except:
                color = 'rgb(255, 170, 127)'

        self.messageLabel.setStyleSheet('background-color: {};'.format(color))
        self.messageLabel.setText(message)
        self.messageLabel.setToolTip(message)

        self.timeout = QTimer()
        self.timeout.timeout.connect(self.clearMessage)
        self.timeout.setSingleShot(True)
        self.timeout.start(secs * 1000)

    def clearMessage(self):
        self.messageLabel.setStyleSheet('')
        self.messageLabel.setToolTip('')
        self.messageLabel.setText('')

    def getName(self):
        "return file name of selected"
        items = self.folderTable.selectedItems()
        names = [str(i.text()) for i in items]
        if names: return names[0]  # only the first selected file
        else: return ''

    def showKeyLen(self, string):
        "displays a tooltip showing length of key"
        s = len(string)
        note = '{:,} character{}'.format(s, '' if s == 1 else 's')
        tip = QToolTip
        pos = self.genKeyButton.mapToGlobal(QPoint(0, 0))

        if s < self.minKeyLen:
            note = '<span style="color:#c80000;">{}</span>'.format(note)
        else:
            note = '<span style="color:#258f22;">{}</span>'.format(note)
        tip.showText(pos, note)

    def lock(self, flag=True):
        "locks buttons if True"
        stuff = [
            self.openButton,
            self.encryptButton,
            self.decryptButton,
            self.genKeyButton,
            self.hashButton,
            self.showKeyCB,
            self.copyButton,
            self.keyInput,
            self.keySizeSB,
            self.folderTable,
        ]
        for i in stuff:
            i.blockSignals(flag)
            i.setEnabled(not flag)
        return

    def _lerp(self, v1, v2, numPts=10):
        "linearly interpolate from v1 to v2\nFrom Orthallelous"
        if len(v1) != len(v2): raise ValueError("different dimensions")
        D, V, n = [], [], abs(numPts)
        for i, u in enumerate(v1):
            D.append(v2[i] - u)
        for i in range(n + 1):
            vn = []
            for j, u in enumerate(v1):
                vn.append(u + D[j] / float(n + 2) * i)
            V.append(tuple(vn))
        return V

    def weeeeeee(self):
        "party time"
        self.lock()
        self.setMessage('Party time!', 2.5)
        a, b, c = self.encryptPbar, self.decryptPbar, self.hashPbar
        process, sleep = app.processEvents, time.sleep

        am, bm, cm = a.minimum(), b.minimum(), c.minimum()
        ax, bx, cx = a.maximum(), b.maximum(), c.maximum()
        a.reset()
        b.reset()
        c.reset()

        loops = self._lerp((am, bm, cm), (ax, bx, cx), 100)
        ivops = loops[::-1]

        # up and up!
        for i in range(3):
            for j, k, l in loops:
                a.setValue(int(j))
                b.setValue(int(k))
                c.setValue(int(l))
                process()
                sleep(0.01)

        a.setValue(ax)
        b.setValue(bx)
        c.setValue(cx)
        sleep(0.25)
        a.setValue(am)
        b.setValue(bm)
        c.setValue(cm)

        # snake!
        self.setMessage('Snake time!')
        self.messageLabel.setStyleSheet('background-color: rgb(127,170,255);')
        for i in range(2):
            for j, k, l in loops:
                a.setValue(int(j))
                process()
                sleep(0.002)
            process()
            a.setInvertedAppearance(True)
            process()
            for j, k, l in ivops:
                a.setValue(int(j))
                process()
                sleep(0.002)

            for j, k, l in loops:
                b.setValue(int(k))
                process()
                sleep(0.002)
            process()
            b.setInvertedAppearance(False)
            process()
            for j, k, l in ivops:
                b.setValue(int(k))
                process()
                sleep(0.002)

            for j, k, l in loops:
                c.setValue(int(l))
                process()
                sleep(0.002)
            process()
            c.setInvertedAppearance(True)
            process()
            for j, k, l in ivops:
                c.setValue(int(l))
                process()
                sleep(0.002)

            process()
            b.setInvertedAppearance(True)
            process()
            for j, k, l in loops:
                b.setValue(int(k))
                process()
                sleep(0.002)
            process()
            b.setInvertedAppearance(False)
            process()
            for j, k, l in ivops:
                b.setValue(int(k))
                process()
                sleep(0.002)
            process()

            a.setInvertedAppearance(False)
            b.setInvertedAppearance(True)
            c.setInvertedAppearance(False)
        for j, k, l in loops:
            a.setValue(int(j))
            process()
            sleep(0.002)
        process()
        a.setInvertedAppearance(True)
        process()
        for j, k, l in ivops:
            a.setValue(int(j))
            process()
            sleep(0.002)

        # bars
        sleep(0.5)
        self.setMessage('Bars!')
        process()
        self.messageLabel.setStyleSheet('background-color: rgb(127,255,170);')
        for i in range(2):
            a.setValue(ax)
            time.sleep(0.65)
            a.setValue(am)
            sleep(0.25)
            process()
            b.setValue(bx)
            time.sleep(0.65)
            b.setValue(bm)
            sleep(0.25)
            process()
            c.setValue(cx)
            time.sleep(0.65)
            c.setValue(cm)
            sleep(0.25)
            process()
            b.setValue(bx)
            time.sleep(0.65)
            b.setValue(bm)
            sleep(0.25)
            process()

        # okay, enough
        process()
        a.setValue(ax)
        b.setValue(bx)
        c.setValue(cx)
        #a.setValue(am); b.setValue(bm); c.setValue(cm)
        a.setInvertedAppearance(False)
        b.setInvertedAppearance(True)
        c.setInvertedAppearance(False)
        self.lock(False)
        return

    def windDown(self, note=None):
        "silly deload on load"
        if note is None: note = 'Loading...'
        self.lock()
        self.setMessage(note)
        self.messageLabel.setStyleSheet('background-color: rgb(9, 190, 130);')
        a, b, c = self.encryptPbar, self.decryptPbar, self.hashPbar
        am, bm, cm = a.minimum(), b.minimum(), c.minimum()
        ax, bx, cx = a.maximum(), b.maximum(), c.maximum()
        a.reset()
        b.reset()
        c.reset()
        loops = self._lerp((ax, bx, cx), (am, bm, cm), 100)
        for j, k, l in loops:
            a.setValue(int(j))
            b.setValue(int(k))
            c.setValue(int(l))
            app.processEvents()
            time.sleep(0.02)
        a.reset()
        b.reset()
        c.reset()
        self.lock(False)
        self.clearMessage()

    def genHash(self, action):
        "generate hash of selected file and display it"
        name, t0 = self.getName(), time.perf_counter()

        # mark what hash was used in the drop-down menu
        for i in self.hashButton.menu().actions():
            if i == action: i.setIconVisibleInMenu(True)
            else: i.setIconVisibleInMenu(False)

        if str(action.text()) == 'Party':
            self.weeeeeee()
            self.windDown('Winding down...')
            return
        if not name:
            self.setMessage('No file selected')
            return
        if not os.path.exists(os.path.join(self.path, name)):
            self.setMessage('File does not exist')
            return

        self.lock()
        hsh = self.hashFile(os.path.join(self.path, name),
                            getattr(hashlib, str(action.text())))
        self.lock(False)
        #hsh = str(action.text()) + ': ' + hsh
        self.hashLabel.setText(hsh)
        self.hashLabel.setToolTip(hsh)
        self.extraLabel.setText(
            str(action.text()) + ' hash took ' +
            self.secs_fmt(time.perf_counter() - t0))

    def setCancel(self):
        "cancel operation"
        self._requestStop = True

    def showCancelButton(self, state=False):
        "show/hide cancel button"
        self.cancelButton.blockSignals(not state)
        self.cancelButton.setEnabled(state)
        if state:
            self.cancelButton.show()
            self.keyInput.hide()
            self.genKeyButton.hide()
            self.keySizeSB.hide()
        else:
            self.cancelButton.hide()
            self.keyInput.show()
            self.genKeyButton.show()
            self.keySizeSB.show()

    def hashFile(self, fn, hasher):
        "returns the hash value of a file"
        hsh, blksize = hasher(), self.blksize
        fsz, csz = os.path.getsize(fn), 0.0

        self.hashPbar.reset()
        self.showCancelButton(True)
        prog, title = '(# {:.02%}) {}', self.windowTitle()
        with open(fn, 'rb') as f:
            while 1:
                blk = f.read(blksize)
                if not blk: break
                hsh.update(blk)

                csz += blksize
                self.hashPbar.setValue(int(round(csz * 100.0 / fsz)))
                app.processEvents()
                self.setWindowTitle(prog.format(csz / fsz, title))
                if self._requestStop: break

        self.hashPbar.setValue(self.hashPbar.maximum())
        self.setWindowTitle(title)
        self.showCancelButton(False)

        if self._requestStop:
            self.setMessage('Hashing canceled!')
            self.hashPbar.setValue(self.hashPbar.minimum())
            self._requestStop = False
            return
        return hsh.hexdigest()

    def hashKey(self, key, salt=b''):
        "hashes a key for encrypting/decrypting file"
        salt = salt.encode() if type(salt) != bytes else salt
        key = key.encode() if type(key) != bytes else key
        p = app.processEvents
        self.setMessage('Key Hashing...', col=(226, 182, 249))
        p()
        key = hashlib.pbkdf2_hmac('sha512', key, salt, 444401)
        p()
        self.clearMessage()
        p()
        return hashlib.sha3_256(key).digest()  # AES requires a 32 char key

    def encrypt(self):
        "encrypt selected file with key"
        name, t0 = self.getName(), time.perf_counter()
        if not name:
            self.setMessage('No file selected')
            return
        if not os.path.exists(os.path.join(self.path, name)):
            self.setMessage('File does not exist')
            return
        key = str(self.keyInput.text())
        if len(key) < self.minKeyLen:
            self.setMessage(('Key must be at least '
                             '{} characters long').format(self.minKeyLen))
            return

        self.lock()
        gn = self.encryptFile(key, os.path.join(self.path, name))
        if not gn:
            self.lock(False)
            return
        self.encrypted.append(os.path.basename(gn))
        self.lock(False)

        self.populateTable(self.path)  # repopulate folder list
        bn, tt = os.path.basename(gn), time.perf_counter() - t0
        self.setMessage('Encrypted, saved "{}"'.format(bn, 13))
        self.extraLabel.setText('Encrypting took ' + self.secs_fmt(tt))

    def encryptFile(self, key, fn):
        "encrypts a file using AES (MODE_GCM)"
        chars = ''.join(map(chr, range(256))).encode()
        chk = AES.block_size
        sample = random.sample
        iv = bytes(sample(chars, chk * 2))
        salt = bytes(sample(chars * 2, 256))

        vault = AES.new(self.hashKey(key, salt), AES.MODE_GCM, iv)
        fsz = os.path.getsize(fn)
        del key
        blksize = self.blksize
        gn = fn + self.ext

        fne = os.path.basename(fn).encode()
        fnz = len(fne)
        if len(fne) % chk: fne += bytes(sample(chars, chk - len(fne) % chk))

        csz = 0.0  # current processed value
        self.encryptPbar.reset()
        prog, title = '({:.02%}) {}', self.windowTitle()
        self.showCancelButton(True)

        with open(fn, 'rb') as src, open(gn, 'wb') as dst:
            dst.write(bytes([0] * 16))  # spacer for MAC written at end
            dst.write(iv)
            dst.write(salt)  # store iv, salt
            # is it safe to store MAC, iv, salt plain right in file?
            # can't really store them encrypted,
            # or elsewhere in this model of single file encryption?
            # can't have another file for the file to lug around

            # store file size, file name length
            dst.write(vault.encrypt(struct.pack('<2Q', fsz, fnz)))
            dst.write(vault.encrypt(fne))  # store filename

            while 1:
                dat = src.read(blksize)
                if not dat: break
                elif len(dat) % chk:  # add padding
                    fil = chk - len(dat) % chk
                    dat += bytes(sample(chars, fil))
                dst.write(vault.encrypt(dat))

                csz += blksize  # show progress
                self.encryptPbar.setValue(int(round(csz * 100.0 / fsz)))
                self.setWindowTitle(prog.format(csz / fsz, title))
                app.processEvents()

                if self._requestStop: break
            if not self._requestStop:
                stuf = random.randrange(23)  # pack in more stuffing
                fing = b''.join(bytes(sample(chars, 16)) for i in range(stuf))
                dst.write(vault.encrypt(fing))  # and for annoyance

                dst.seek(0)
                dst.write(vault.digest())  # write MAC
                self.hashLabel.setText('MAC: ' + vault.hexdigest())

        self.encryptPbar.setValue(self.encryptPbar.maximum())
        self.setWindowTitle(title)
        self.showCancelButton(False)

        if self._requestStop:
            self.setMessage('Encryption canceled!')
            self.encryptPbar.setValue(self.encryptPbar.minimum())
            self._requestStop = False
            os.remove(gn)
            return
        return gn

    def decrypt(self):
        "encrypt selected file with key"
        name, t0 = self.getName(), time.perf_counter()
        if not name:
            self.setMessage('No file selected')
            return
        if not os.path.exists(os.path.join(self.path, name)):
            self.setMessage('File does not exist')
            return
        key = str(self.keyInput.text())
        if len(key) < self.minKeyLen:
            self.setMessage(('Key must be at least '
                             '{} characters long').format(self.minKeyLen))
            return

        self.lock()
        gn = self.decryptFile(key, os.path.join(self.path, name))
        if not gn:
            self.lock(False)
            return
        self.decrypted.append(os.path.basename(gn))
        self.lock(False)

        self.populateTable(self.path)  # repopulate folder list
        bn, tt = os.path.basename(gn), time.perf_counter() - t0
        self.setMessage('Decrypted, saved "{}"'.format(bn, 13))
        self.extraLabel.setText('Decrypting took ' + self.secs_fmt(tt))

    def decryptFile(self, key, fn):
        "decrypts a file using AES (MODE_GCM)"
        blksize = self.blksize
        gn = hashlib.md5(os.path.basename(fn).encode()).hexdigest()
        gn = os.path.join(self.path, gn)  # temporary name
        if os.path.exists(gn):
            self.setMessage('file already exists')
            return

        self.decryptPbar.reset()
        csz = 0.0  # current processed value
        chk, fnsz = AES.block_size, os.path.getsize(fn)
        prog, title = '({:.02%}) {}', self.windowTitle()
        try:
            with open(fn, 'rb') as src, open(gn, 'wb') as dst:
                # extract iv, salt
                MAC = src.read(16)
                iv = src.read(AES.block_size * 2)
                salt = src.read(256)
                vault = AES.new(self.hashKey(key, salt), AES.MODE_GCM, iv)
                self.showCancelButton(True)

                # extract file size, file name length
                sizes = src.read(struct.calcsize('<2Q'))
                fsz, fnz = struct.unpack('<2Q', vault.decrypt(sizes))

                # extract filename; round up fnz to nearest chk
                rnz = fnz if not fnz % chk else fnz + chk - fnz % chk
                rfn = vault.decrypt(src.read(rnz))[:fnz].decode()
                self.setMessage('Found "{}"'.format(rfn), 13, (255, 211, 127))

                while 1:
                    dat = src.read(blksize)
                    if not dat: break
                    dst.write(vault.decrypt(dat))

                    csz += blksize  # show progress
                    self.decryptPbar.setValue(int(round(csz * 100.0 / fnsz)))
                    self.setWindowTitle(prog.format(1 - (csz / fnsz), title))
                    app.processEvents()
                    if self._requestStop: break

                if not self._requestStop: dst.truncate(fsz)  # remove padding
            if not self._requestStop:
                vault.verify(MAC)
                self.hashLabel.setText('')

        except (ValueError, KeyError) as err:
            os.remove(gn)
            self.setMessage('Invalid decryption!')
            self.setWindowTitle(title)
            self.showCancelButton(False)
            return
        except Exception as err:
            os.remove(gn)
            self.setMessage('Invalid key or file!')
            self.setWindowTitle(title)
            self.showCancelButton(False)
            return
        self.decryptPbar.setValue(self.decryptPbar.maximum())
        self.setWindowTitle(title)
        self.showCancelButton(False)

        if self._requestStop:
            self.setMessage('Decryption canceled!')
            self.decryptPbar.setValue(self.decryptPbar.minimum())
            self._requestStop = False
            os.remove(gn)
            return

        # restore original file name
        name, ext = os.path.splitext(rfn)
        count = 1
        fn = os.path.join(self.path, name + ext)
        while os.path.exists(fn):
            fn = os.path.join(self.path, name + '_{}'.format(count) + ext)
            count += 1
        os.rename(gn, fn)  # restore original name
        return fn  # saved name

    def copyKeyHash(self, action):
        "copies either the key or the hash to clipboard"
        act = str(action.text()).lower()

        if 'key' in act: txt = str(self.keyInput.text())
        elif 'hash' in act: txt = str(self.hashLabel.text())
        else:
            self.setMessage('Invalid copy selection')
            return

        if not txt:
            self.setMessage('Empty text; Nothing to copy')
            return

        if 'key' in act: self.setMessage('Key copied to clipboard')
        elif 'hash' in act: self.setMessage('Hash copied to clipboard')
        else:
            self.setMessage('Invalid copy selection')
            return

        self.clipboard.clear()
        self.clipboard.setText(txt)

    def secs_fmt(self, s):
        "6357 -> '1h 45m 57s'"
        Y, D, H, M = 31556952, 86400, 3600, 60
        y = int(s // Y)
        s -= y * Y
        d = int(s // D)
        s -= d * D
        h = int(s // H)
        s -= h * H
        m = int(s // M)
        s -= m * M

        r = (str(int(s)) if int(s) == s else str(round(s, 3))) + 's'

        if m: r = str(m) + 'm ' + r
        if h: r = str(h) + 'h ' + r
        if d: r = str(d) + 'd ' + r
        if y: r = str(y) + 'y ' + r
        return r.strip()

    def closeEvent(self, event):
        self.clipboard.clear()

    def setup(self):
        "constructs the gui"
        Fixed = QSizePolicy()
        MinimumExpanding = QSizePolicy(QSizePolicy.MinimumExpanding,
                                       QSizePolicy.MinimumExpanding)
        self.minKeyLen = 8
        self.maxKeyLen = 4096

        self.splitter = QSplitter(self)
        self.splitter.setOrientation(Qt.Horizontal)
        self.splitter.splitterMoved.connect(self.splitterChanged)

        # left column
        self.leftColumn = QWidget()
        self.vl01 = QVBoxLayout()

        # left column - first item (0; horizonal layout 0)
        self.hl00 = QHBoxLayout()
        self.hl00.setSpacing(5)

        self.openButton = QPushButton('&Open')
        self.openButton.setToolTip('Open folder')
        self.openButton.setMinimumSize(60, 20)
        self.openButton.setMaximumSize(60, 20)
        self.openButton.setSizePolicy(Fixed)
        self.openButton.clicked.connect(self.getFolder)
        #ico = self.style().standardIcon(QStyle.SP_DirIcon)
        #self.openButton.setIcon(ico)

        self.folderLabel = QLabel()
        self.folderLabel.setMinimumSize(135, 20)
        self.folderLabel.setMaximumSize(16777215, 20)
        self.folderLabel.setSizePolicy(MinimumExpanding)
        self.hl00.insertWidget(0, self.openButton)
        self.hl00.insertWidget(1, self.folderLabel)

        # left column - second item (1)
        self.folderTable = QTableWidget()
        self.folderTable.setMinimumSize(200, 32)
        self.folderTable.horizontalHeader().setVisible(False)
        self.folderTable.horizontalHeader().setStretchLastSection(True)
        self.folderTable.verticalHeader().setVisible(False)
        self.folderTable.verticalHeader().setDefaultSectionSize(15)
        self.folderTable.itemChanged.connect(self.editFileName)

        # left column - third item (2)
        self.extraLabel = QLabel()
        self.extraLabel.setMinimumSize(200, 20)
        self.extraLabel.setMaximumSize(16777215, 20)
        self.extraLabel.setSizePolicy(MinimumExpanding)
        self.extraLabel.setTextInteractionFlags(Qt.LinksAccessibleByMouse)

        # finalize left column
        self.vl01.insertLayout(0, self.hl00)
        self.vl01.insertWidget(1, self.folderTable)
        self.vl01.insertWidget(2, self.extraLabel)
        self.leftColumn.setLayout(self.vl01)

        # right column
        self.rightColumn = QWidget()
        self.vl02 = QVBoxLayout()

        # right column - first item (0)
        self.messageLabel = QLabel()
        self.messageLabel.setMinimumSize(290, 20)
        self.messageLabel.setMaximumSize(16777215, 20)
        self.messageLabel.setSizePolicy(MinimumExpanding)
        self.messageLabel.setAlignment(Qt.AlignCenter)

        # right column - second item (2; horizontal layout 1)
        self.hl01 = QHBoxLayout()
        self.hl01.setSpacing(5)

        self.encryptButton = QPushButton('&Encrypt')  #\U0001F512
        self.encryptButton.setToolTip('Encrypt selected file')
        self.encryptButton.setMinimumSize(60, 20)
        self.encryptButton.setMaximumSize(60, 20)
        self.encryptButton.setSizePolicy(Fixed)
        self.encryptButton.clicked.connect(self.encrypt)

        self.encryptPbar = QProgressBar()
        self.encryptPbar.setMinimumSize(225, 20)
        self.encryptPbar.setMaximumSize(16777215, 20)
        self.encryptPbar.setSizePolicy(MinimumExpanding)
        self.encryptPbar.setTextVisible(False)

        palette = self.encryptPbar.palette()  # color of progress bar
        color = QColor(211, 70, 0)
        palette.setColor(QPalette.Highlight, color)
        self.encryptPbar.setPalette(palette)

        self.hl01.insertWidget(0, self.encryptButton)
        self.hl01.insertWidget(1, self.encryptPbar)

        # right column - third item (3; horizontal layout 2)
        self.hl02 = QHBoxLayout()
        self.hl02.setSpacing(5)

        self.cancelButton = QPushButton('C&ANCEL')
        self.cancelButton.setToolTip('Cancels current operation')
        self.cancelButton.setMinimumSize(70, 24)
        self.cancelButton.setMaximumSize(70, 24)
        self.cancelButton.setSizePolicy(Fixed)
        self.cancelButton.clicked.connect(self.setCancel)
        font = self.cancelButton.font()
        font.setBold(True)
        self.cancelButton.setFont(font)
        self.cancelButton.blockSignals(True)
        self.cancelButton.setEnabled(False)
        self.cancelButton.hide()
        self._requestStop = False

        self.keyInput = QLineEdit()
        self.keyInput.setMinimumSize(225, 20)
        self.keyInput.setMaximumSize(16777215, 20)
        self.keyInput.setSizePolicy(MinimumExpanding)
        self.keyInput.setPlaceholderText('key')
        self.keyInput.setMaxLength(self.maxKeyLen)
        self.keyInput.setAlignment(Qt.AlignCenter)
        self.keyInput.textEdited.connect(self.showKeyLen)

        self.genKeyButton = QPushButton('&Gen Key')  #\U0001F511
        self.genKeyButton.setToolTip('Generate a random key')
        self.genKeyButton.setMinimumSize(60, 20)
        self.genKeyButton.setMaximumSize(60, 20)
        self.genKeyButton.setSizePolicy(Fixed)
        self.genKeyButton.clicked.connect(self.genKey)

        self.keySizeSB = QSpinBox()
        self.keySizeSB.setToolTip('Length of key to generate')
        self.keySizeSB.setRange(32, 1024)
        self.keySizeSB.setMinimumSize(40, 20)
        self.keySizeSB.setMaximumSize(40, 20)
        self.keySizeSB.setSizePolicy(Fixed)
        self.keySizeSB.setAlignment(Qt.AlignCenter)
        self.keySizeSB.setButtonSymbols(QSpinBox.NoButtons)
        self.keySizeSB.setWrapping(True)

        self.hl02.insertWidget(0, self.cancelButton)
        self.hl02.insertWidget(1, self.keyInput)
        self.hl02.insertWidget(2, self.genKeyButton)
        self.hl02.insertWidget(3, self.keySizeSB)

        # right column - fourth item (4; horizontal layout 3)
        self.hl03 = QHBoxLayout()
        self.hl03.setSpacing(5)

        self.decryptButton = QPushButton('&Decrypt')  #\U0001F513
        self.decryptButton.setToolTip('Decrypt selected file')
        self.decryptButton.setMinimumSize(60, 20)
        self.decryptButton.setMaximumSize(60, 20)
        self.decryptButton.setSizePolicy(Fixed)
        self.decryptButton.clicked.connect(self.decrypt)

        self.decryptPbar = QProgressBar()
        self.decryptPbar.setMinimumSize(225, 20)
        self.decryptPbar.setMaximumSize(16777215, 20)
        self.decryptPbar.setSizePolicy(MinimumExpanding)
        self.decryptPbar.setTextVisible(False)
        self.decryptPbar.setInvertedAppearance(True)

        palette = self.decryptPbar.palette()  # color of progress bar
        color = QColor(0, 170, 255)
        palette.setColor(QPalette.Highlight, color)
        self.decryptPbar.setPalette(palette)

        self.hl03.insertWidget(0, self.decryptButton)
        self.hl03.insertWidget(1, self.decryptPbar)

        # right column - fifth item (7; horizontal layout 4)
        self.hl04 = QHBoxLayout()
        self.hl04.setSpacing(5)

        self.showKeyCB = QCheckBox('&Show Key')
        self.showKeyCB.setToolTip('Show/Hide key value')
        self.showKeyCB.setMinimumSize(75, 20)
        self.showKeyCB.setMaximumSize(75, 20)
        self.showKeyCB.setSizePolicy(Fixed)
        self.showKeyCB.clicked.connect(self.showKey)
        self.showKeyCB.setChecked(True)

        self.hashPbar = QProgressBar()
        self.hashPbar.setMinimumSize(150, 20)
        self.hashPbar.setMaximumSize(16777215, 20)
        self.hashPbar.setSizePolicy(MinimumExpanding)
        self.hashPbar.setTextVisible(False)

        palette = self.hashPbar.palette()  # color of progress bar
        color = QColor(31, 120, 73)
        palette.setColor(QPalette.Highlight, color)
        self.hashPbar.setPalette(palette)

        self.hashButton = QPushButton('&Hash')
        self.hashButton.setToolTip('Determine file hash')
        self.hashButton.setMinimumSize(60, 20)
        self.hashButton.setMaximumSize(60, 20)
        self.hashButton.setSizePolicy(Fixed)

        menu = QMenu(self.hashButton)
        ico = self.style().standardIcon(QStyle.SP_DialogYesButton)
        for alg in sorted(
                filter(lambda x: 'shake' not in x,
                       hashlib.algorithms_guaranteed),
                key=lambda n:
            (len(n), sorted(hashlib.algorithms_guaranteed).index(n))):
            menu.addAction(
                ico, alg
            )  # drop shake algs as their .hexdigest requires an argument - the rest don't
        menu.addAction(ico, 'Party')
        for i in menu.actions():
            i.setIconVisibleInMenu(False)
        self.hashButton.setMenu(menu)
        menu.triggered.connect(self.genHash)

        self.hl04.insertWidget(0, self.showKeyCB)
        self.hl04.insertWidget(1, self.hashPbar)
        self.hl04.insertWidget(2, self.hashButton)

        # right column - sixth item (8; horizontal layout 5)
        self.hl05 = QHBoxLayout()
        self.hl05.setSpacing(5)

        self.copyButton = QPushButton('&Copy')  #\U0001F4CB
        self.copyButton.setToolTip('Copy key or hash to clipboard')
        self.copyButton.setMinimumSize(60, 20)
        self.copyButton.setMaximumSize(60, 20)
        self.copyButton.setSizePolicy(Fixed)

        menu2 = QMenu(self.copyButton)
        menu2.addAction('Copy Key')
        menu2.addAction('Copy Hash')
        self.copyButton.setMenu(menu2)
        menu2.triggered.connect(self.copyKeyHash)

        self.hashLabel = QLabel()
        self.hashLabel.setMinimumSize(225, 20)
        self.hashLabel.setMaximumSize(16777215, 20)
        self.hashLabel.setSizePolicy(MinimumExpanding)
        self.hashLabel.setTextFormat(Qt.PlainText)
        self.hashLabel.setAlignment(Qt.AlignCenter)
        self.hashLabel.setTextInteractionFlags(Qt.TextSelectableByMouse)

        self.hl05.insertWidget(0, self.copyButton)
        self.hl05.insertWidget(1, self.hashLabel)

        # finalize right column
        self.vl02.insertWidget(0, self.messageLabel)
        self.vl02.insertSpacerItem(1, QSpacerItem(0, 0))
        self.vl02.insertLayout(2, self.hl01)
        self.vl02.insertLayout(3, self.hl02)
        self.vl02.insertLayout(4, self.hl03)
        self.vl02.insertSpacerItem(5, QSpacerItem(0, 0))
        self.vl02.insertWidget(6, QFrame())
        self.vl02.insertLayout(7, self.hl04)
        self.vl02.insertLayout(8, self.hl05)
        self.rightColumn.setLayout(self.vl02)

        # finalize main window
        self.splitter.insertWidget(0, self.leftColumn)
        self.splitter.insertWidget(1, self.rightColumn)

        layout = QHBoxLayout(self)
        layout.addWidget(self.splitter)
        self.setLayout(layout)

        self.setWindowTitle('Simple File Encryptor/Decryptor')
        self.resize(self.sizeHint())
Example #11
0
    def __init__(self):
        super(Window, self).__init__()

        self.renderArea = RenderArea()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.setWindowTitle("Basic Drawing")
Example #12
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()

        self.renderArea = RenderArea()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.setWindowTitle("Basic Drawing")

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

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

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

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

        if style == Qt.LinearGradientPattern:
            linearGradient = QLinearGradient(0, 0, 100, 100)
            linearGradient.setColorAt(0.0, Qt.white)
            linearGradient.setColorAt(0.2, Qt.green)
            linearGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(linearGradient))
        elif style == Qt.RadialGradientPattern:
            radialGradient = QRadialGradient(50, 50, 50, 70, 70)
            radialGradient.setColorAt(0.0, Qt.white)
            radialGradient.setColorAt(0.2, Qt.green)
            radialGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(radialGradient))
        elif style == Qt.ConicalGradientPattern:
            conicalGradient = QConicalGradient(50, 50, 150)
            conicalGradient.setColorAt(0.0, Qt.white)
            conicalGradient.setColorAt(0.2, Qt.green)
            conicalGradient.setColorAt(1.0, Qt.black)
            self.renderArea.setBrush(QBrush(conicalGradient))
        elif style == Qt.TexturePattern:
            self.renderArea.setBrush(QBrush(QPixmap(':/images/brick.png')))
        else:
            self.renderArea.setBrush(QBrush(Qt.green, style))
        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)
 def setUp(self):
     super(SpinBoxPySlot, self).setUp()
     self.spin = QSpinBox()
Example #15
0
class EditView:
    widget = QWidget()
    layout = QVBoxLayout()
    grid_widget = QWidget()
    grid_layout = QGridLayout()
    buttons_widget = QWidget()
    buttons_layout = QHBoxLayout()

    lbl_timestamp = QLabel("Timestamp")
    cal_timestamp = QDateTimeEdit()
    lbl_duration = QLabel("Duration")
    lbl_hour = QLabel("Hours")
    spn_hour = QSpinBox()
    lbl_min = QLabel("Minutes")
    spn_min = QSpinBox()
    lbl_sec = QLabel("Seconds")
    spn_sec = QSpinBox()
    lbl_activity = QLabel("Activity")
    txt_activity = QLineEdit()

    btn_done = QPushButton(QIcon.fromTheme('cancel'), "Done")
    btn_revert = QPushButton(QIcon.fromTheme('edit-undo'), "Revert")
    btn_save = QPushButton(QIcon.fromTheme('document-save'), "Save")

    index = None
    entry = None

    done_callback = None

    @classmethod
    def build(cls):
        """Build the interface."""

        cls.lbl_timestamp.setWhatsThis("The timestamp for the entry.")
        cls.cal_timestamp.setWhatsThis("The timestamp for the entry.")
        cls.cal_timestamp.setDisplayFormat("yyyy MMM dd hh:mm:ss")
        cls.cal_timestamp.dateTimeChanged.connect(cls.edited)

        cls.lbl_hour.setWhatsThis("The hour part of the entry duration.")
        cls.spn_hour.setWhatsThis("The hour part of the entry duration.")
        cls.spn_hour.valueChanged.connect(cls.edited)

        cls.lbl_min.setWhatsThis("The minute part of the entry duration.")
        cls.spn_min.setWhatsThis("The minute part of the entry duration.")
        cls.spn_min.valueChanged.connect(cls.edited)

        cls.lbl_sec.setWhatsThis("The second part of the entry duration.")
        cls.spn_sec.setWhatsThis("The second part of the entry duration.")
        cls.spn_sec.valueChanged.connect(cls.edited)

        cls.lbl_activity.setWhatsThis("The activity notes for the entry.")
        cls.txt_activity.setWhatsThis("The activity notes for the entry.")
        cls.txt_activity.textChanged.connect(cls.edited)

        cls.grid_layout.addWidget(cls.lbl_timestamp, 0, 0, 1, 1)
        cls.grid_layout.addWidget(cls.cal_timestamp, 0, 1, 1, 1)

        cls.grid_layout.addWidget(cls.lbl_duration, 2, 0, 1, 2)
        cls.grid_layout.addWidget(cls.lbl_hour, 3, 0, 1, 1)
        cls.grid_layout.addWidget(cls.spn_hour, 3, 1, 1, 1)
        cls.grid_layout.addWidget(cls.lbl_min, 4, 0, 1, 1)
        cls.grid_layout.addWidget(cls.spn_min, 4, 1, 1, 1)
        cls.grid_layout.addWidget(cls.lbl_sec, 5, 0, 1, 1)
        cls.grid_layout.addWidget(cls.spn_sec, 5, 1, 1, 1)

        cls.grid_layout.addWidget(cls.lbl_activity, 6, 0, 1, 1)
        cls.grid_layout.addWidget(cls.txt_activity, 6, 1, 1, 1)

        cls.grid_widget.setLayout(cls.grid_layout)

        cls.btn_done.clicked.connect(cls.done)
        cls.btn_done.setWhatsThis("Return to time log.")
        cls.buttons_layout.addWidget(cls.btn_done)
        cls.buttons_layout.addWidget(cls.btn_revert)
        cls.buttons_layout.addWidget(cls.btn_save)
        cls.btn_save.clicked.connect(cls.save)
        cls.btn_save.setWhatsThis("Save the settings.")
        cls.btn_revert.clicked.connect(cls.refresh)
        cls.btn_revert.setWhatsThis("Discard changes to settings.")

        cls.buttons_widget.setLayout(cls.buttons_layout)
        cls.layout.addWidget(cls.grid_widget)
        cls.layout.addWidget(cls.buttons_widget)
        cls.widget.setLayout(cls.layout)

        cls.refresh()
        return cls.widget

    @classmethod
    def connect(cls, done=None):
        if done:
            cls.done_callback = done

    @classmethod
    def done(cls):
        if cls.done_callback:
            cls.done_callback()

    @classmethod
    def load_item(cls, timestamp):
        cls.entry = TimeLog.retrieve_from_log(timestamp)
        cls.refresh()

    @classmethod
    def edited(cls):
        cls.btn_done.setEnabled(False)
        cls.btn_revert.setEnabled(True)
        cls.btn_save.setEnabled(True)

    @classmethod
    def not_edited(cls):
        cls.btn_done.setEnabled(True)
        cls.btn_revert.setEnabled(False)
        cls.btn_save.setEnabled(False)

    @classmethod
    def refresh(cls):
        if cls.entry is None:
            return
        timestamp = cls.entry.timestamp
        datetime = QDateTime()
        datetime.setDate(QDate(timestamp.year, timestamp.month, timestamp.day))
        datetime.setTime(
            QTime(timestamp.hour, timestamp.minute, timestamp.second))
        cls.cal_timestamp.setDateTime(datetime)

        hours, minutes, seconds = cls.entry.duration
        cls.spn_hour.setValue(hours)
        cls.spn_min.setValue(minutes)
        cls.spn_sec.setValue(seconds)

        cls.txt_activity.setText(cls.entry.notes)

        cls.not_edited()

    @classmethod
    def save(cls):
        TimeLog.remove_from_log(cls.entry.timestamp)
        timestamp = datetime(cls.cal_timestamp.date().year(),
                             cls.cal_timestamp.date().month(),
                             cls.cal_timestamp.date().day(),
                             cls.cal_timestamp.time().hour(),
                             cls.cal_timestamp.time().minute(),
                             cls.cal_timestamp.time().second())
        new_timestamp = TimeLog.add_to_log(timestamp, cls.spn_hour.value(),
                                           cls.spn_min.value(),
                                           cls.spn_sec.value(),
                                           cls.txt_activity.text())
        cls.not_edited()

        cls.entry = TimeLog.retrieve_from_log(new_timestamp)
        # Display the revised data.
        cls.refresh()
    def initUI(self):

        QToolTip.setFont(QFont('SansSerif', 12))
        
        Title = QLabel('Выберите параметры обучения нейросети')
        Title.setToolTip('Для корректной работы функций обучения и оптимизации \n'
                         'в каталоге с программой должны находится подкаталоги \n'
                         'train, val, test. В каждом из этих каталогов должно \n'
                         'быть столько подкаталогов с изображениями, сколько \n'
                         'необходимо распознавать классов')
        Title1 = QLabel('Выберите параметры исследования изображения')
        Title1.setToolTip('Для корректной работы функции классификации и локализации \n'
                          'изображения для исследования и модель нейросети должны \n'
                          'находиться в одном каталоге с программой, формат изображения \n'
                          '.jpg, формат модели нейросети .h5, указывать формат в полях не нужно')
        TitleEp = QLabel('Эпохи:')
        TitleEp.setToolTip('Эпоха — один «проход» данных через нейросеть. \n'
                           'Изменение этого параметра позволяет избежать \n'
                           'недообученности или переобученности нейросети')
        TitleBa = QLabel('Размер мини-выборки:')
        TitleBa.setToolTip('Количество изображений загружаемых в нейросеть '
                           'за раз')
        TitleTr = QLabel('Количество изображений для обучения:')
        TitleTr.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога train')
        TitleVa = QLabel('Количество изображений для проверки:')
        TitleVa.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога val')
        TitleTe = QLabel('Количество изображений для тестирования:')
        TitleTe.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога test')
        TitleSc = QLabel('Масштабирование пирамиды изображений:')
        TitleSc.setToolTip('Коэффициент масштабирования изображения')
        TitleSs = QLabel('Шаг скользящего окна:')
        TitleSs.setToolTip('Расстояние в пикселях, на которое смещается \n'
                           'окно классификатора по изображению за одну итерацию')
        TitleNi = QLabel('Имя изображения для исследования:')
        TitleNi.setToolTip('Наименование изображения без расширения. \n'
                           'Изображение должно иметь формат jpg и \n'
                           'находится в одном каталоге с программой, иначе \n'
                           'необходимо указывать полный путь до изображения')
        TitleNm = QLabel('Имя модели нейросети:')
        TitleNm.setToolTip('Наименование модели нейросети без расширения. \n'
                           'Модель должна иметь формат h5 и находится \n'
                           'в одном каталоге с программой, иначе необходимо \n'
                           'указывать полный путь до модели нейросети')
        TitleCl = QLabel('Количество классов:')
        
        self.InputEpochs = QSpinBox(self)
        self.InputEpochs.setRange(5,50)
        self.InputEpochs.setValue(10)

        self.InputBatch = QSpinBox(self)
        self.InputBatch.setRange(5,100)
        self.InputBatch.setValue(15)

        self.InputTrain = QSpinBox(self)
        self.InputTrain.setRange(100,100000)
        self.InputTrain.setValue(1050)

        self.InputValidation = QSpinBox(self)
        self.InputValidation.setRange(100,100000)
        self.InputValidation.setValue(225)

        self.InputTest = QSpinBox(self)
        self.InputTest.setRange(100,100000)
        self.InputTest.setValue(225)

        self.InputScale = QDoubleSpinBox(self)
        self.InputScale.setRange(1.1,5)
        self.InputScale.setValue(1.5)

        self.InputStep = QSpinBox(self)
        self.InputStep.setRange(1,150)
        self.InputStep.setValue(30)

        self.InputClass = QSpinBox(self)
        self.InputClass.setRange(3,20)
        self.InputClass.setValue(3)
        
        self.ImageName = QLineEdit("ImageName", self)
        self.ImageName.setMaxLength(20)

        self.ModelName = QLineEdit("TestModel", self)
        self.ModelName.setMaxLength(20)
        
        btn = QPushButton('Обучить нейросеть', self)
        btn.setToolTip('В результате обучения модель нейросети '
                       'будет сохранена в каталоге с программой')
        btn.resize(btn.sizeHint())
        btn.clicked.connect(self.buttonClicked)
        
        btn1 = QPushButton('Оптимизировать нейросеть', self)
        btn1.setToolTip('В результате оптимизации 3 лучшие модели '
                        'будут сохранены в каталоге с программой')
        btn1.resize(btn1.sizeHint())
        btn1.clicked.connect(self.buttonClicked1)
        
        btn2 = QPushButton('Поиск и распознавание', self)
        btn2.resize(btn2.sizeHint())
        btn2.clicked.connect(self.buttonClicked2)

        grid = QGridLayout(self)

        grid.setSpacing(10)

        grid.addWidget(Title, 1, 0, 1, 4)
        grid.addWidget(TitleEp, 2, 0)
        grid.addWidget(TitleBa, 3, 0)
        grid.addWidget(TitleCl, 4, 0)
        grid.addWidget(self.InputEpochs, 2, 1)
        grid.addWidget(self.InputBatch, 3, 1)
        grid.addWidget(self.InputClass, 4, 1)
        grid.addWidget(TitleTr, 2, 2)
        grid.addWidget(TitleVa, 3, 2)
        grid.addWidget(TitleTe, 4, 2)
        grid.addWidget(self.InputTrain, 2, 3)
        grid.addWidget(self.InputValidation, 3, 3)
        grid.addWidget(self.InputTest, 4, 3)
        grid.addWidget(btn, 5, 0, 1, 2)
        grid.addWidget(btn1, 5, 2, 1, 2)
        
        grid.addWidget(Title1, 6, 0, 1, 4)
        grid.addWidget(TitleSc, 7, 0)
        grid.addWidget(self.InputScale, 7, 1)
        grid.addWidget(TitleSs, 7, 2)
        grid.addWidget(self.InputStep, 7, 3)
        grid.addWidget(TitleNi, 8, 0)
        grid.addWidget(self.ImageName, 8, 1)
        grid.addWidget(TitleNm, 8, 2)
        grid.addWidget(self.ModelName, 8, 3)
        grid.addWidget(btn2, 9, 1, 1, 2)
        
        self.setLayout(grid)
        
        self.setWindowTitle('Система поиска и распознавания сорных растений')
        self.setWindowIcon(QIcon('icon.png'))
        self.show()
Example #17
0
 def __init__(self, parent=None):
     QSpinBox.__init__(self, parent)
Example #18
0
class PlanesWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(PlanesWidget, self).__init__(parent)

        self.chan_combo = QComboBox()
        self.chan_combo.addItems(
            [self.tr('Luminance'), self.tr('Red'), self.tr('Green'), self.tr('Blue'), self.tr('RGB Norm')])
        self.plane_spin = QSpinBox()
        self.plane_spin.setPrefix(self.tr('Bit '))
        self.plane_spin.setRange(0, 7)
        self.filter_combo = QComboBox()
        self.filter_combo.addItems([self.tr('Disabled'), self.tr('Median'), self.tr('Gaussian')])

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.planes = None
        self.preprocess()

        self.chan_combo.currentIndexChanged.connect(self.preprocess)
        self.plane_spin.valueChanged.connect(self.process)
        self.filter_combo.currentIndexChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Channel:')))
        top_layout.addWidget(self.chan_combo)
        top_layout.addWidget(QLabel(self.tr('Plane:')))
        top_layout.addWidget(self.plane_spin)
        top_layout.addWidget(QLabel(self.tr('Filter:')))
        top_layout.addWidget(self.filter_combo)
        top_layout.addStretch()

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

    def preprocess(self):
        channel = self.chan_combo.currentIndex()
        if channel == 0:
            img = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        elif channel == 4:
            b, g, r = cv.split(self.image.astype(np.float64))
            img = cv.sqrt(cv.pow(b, 2) + cv.pow(g, 2) + cv.pow(r, 2)).astype(np.uint8)
        else:
            img = self.image[:, :, 3 - channel]

        self.planes = [normalize_mat(cv.bitwise_and(np.full_like(img, 2**b), img), to_bgr=True) for b in range(8)]

        # rows, cols = img.shape
        # bits = 8
        # data = [np.binary_repr(img[i][j], width=bits) for i in range(rows) for j in range(cols)]
        # self.planes = [
        #     (np.array([int(i[b]) for i in data], dtype=np.uint8) * 2 ** (bits - b - 1)).reshape(
        #         (rows, cols)) for b in range(bits)]

        self.process()

    def process(self):
        plane = self.planes[self.plane_spin.value()]
        if self.filter_combo.currentIndex() == 1:
            plane = cv.medianBlur(plane, 3)
        elif self.filter_combo.currentIndex() == 2:
            plane = cv.GaussianBlur(plane, (3, 3), 0)
        self.viewer.update_processed(plane)
Example #19
0
 def validate(self,text,pos):
     return QSpinBox.validate(self,text,pos)
Example #20
0
    def setupUi(self, parent):
        """Setup the interfaces for the clock."""

        if not self.objectName():
            self.setObjectName(u"Clock")

        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(parent.sizePolicy().hasHeightForWidth())
        parent.setSizePolicy(sizePolicy)
        parent.setAutoFillBackground(True)

        parent.setWindowFlag(Qt.Widget, True)
        if os.uname().sysname == "Linux" or self.frameless:
            parent.setWindowFlag(Qt.FramelessWindowHint, True)
    
        self.tabWidget = QTabWidget(parent)
        self.tabWidget.setObjectName(u"tabWidget")
        self.tabWidget.setGeometry(QRect(0, 0, 800, 460))
        # This works for Mac, but seems to not work with Linux/Arm/RPi
        # tabbar = self.tabWidget.tabBar()
        # tabbar.setMinimumSize(50, 24)
        # tabfont = QFont()
        # tabfont.setBold(True)
        # tabfont.setItalic(True)
        # tabfont.setPointSize(32)
        # tabbar.setFont(tabfont)

        # Setup the TABS
        self.clock = QWidget()
        self.clock.setObjectName(u"clock")
        self.tabWidget.addTab(self.clock, "")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.clock), "Clock")

        self.weather = QWeather(parent=None, debug=self.debug)
        self.tabWidget.addTab(self.weather, "")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.weather), "Weather")

        self.settings = QWidget()
        self.settings.setObjectName(u"settings")
        self.tabWidget.addTab(self.settings, "")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.settings), "Settings")

        self.tabWidget.setCurrentIndex(0)

        #################################################################################################
        # Setup Clock Page
        #################################################################################################

        self.analog = AnalogClock(self.clock)

        # DIGITAL clock in "clock" tab
        self.Digital = QLabel(self.clock)
        self.Digital.setObjectName(u"Digital")
        self.Digital.setGeometry(QRect(0, 5, 765, 71))
        self.Digital.setAutoFillBackground(False)
        self.Digital.setStyleSheet(u"")
        self.Digital.setText(u"Current Time - Date + time")

        # Weather Icon
        self.weathericon = QWeatherIcon((480, 5), self.weather, parent=self.clock)
        self.weather.weather_updated.connect(self.weathericon.update)

        # Weather info on the Clock page.
        self.minipanel = QTempMiniPanel((475, 105), self.weather, parent=self.clock)
        self.weather.temp_updated.connect(self.minipanel.update)

        self.hilo = QHiLoTide((580, 5), parent=self.clock, debug=self.debug)


        # Moon phase
        self.moon = QMoon(pos=(450, 210), parent=self.clock, size=216, web=self.web)

        # Push buttons in "clock tab.
        push_button_width = 111
        push_button_height = 40
        push_button_x = 670
        push_button_y = 220

        self.ledball_off = QPushButton(self.clock)
        self.ledball_off.setObjectName(u"ledball_off")
        self.ledball_off.setText(u"LED off")
        self.ledball_off.setGeometry(QRect(push_button_x, push_button_y, push_button_width, push_button_height))

        self.ledball_on = QPushButton(self.clock)
        self.ledball_on.setObjectName(u"ledball_on")
        self.ledball_on.setText(u"LED on ")
        self.ledball_on.setGeometry(QRect(push_button_x, push_button_y+push_button_height, push_button_width, push_button_height))

        self.ledball_on2 = QPushButton(self.clock)
        self.ledball_on2.setObjectName(u"ledball_on2")
        self.ledball_on2.setText(u"LED on 2")
        self.ledball_on2.setGeometry(QRect(push_button_x, push_button_y+push_button_height*2, push_button_width, push_button_height))

        self.sleep = QPushButton(self.clock)
        self.sleep.setObjectName(u"sleep")
        self.sleep.setText(u"Sleep")
        self.sleep.setGeometry(QRect(push_button_x, push_button_y+push_button_height*3+10, push_button_width, push_button_height))

        #################################################################################################
        # Setup Weather Page
        #################################################################################################

        #################################################################################################
        # Setup Setting Page
        #################################################################################################
        self.timeEdit = QTimeEdit(self.settings)
        self.timeEdit.setObjectName(u"timeEdit")
        self.timeEdit.setDisplayFormat(u"h:mm AP")
        self.timeEdit.setGeometry(QRect(200, 30, 191, 41))
        font8 = QFont()
        font8.setFamily(u"Gill Sans")
        font8.setPointSize(16)
        font8.setBold(False)
        font8.setItalic(False)
        font8.setWeight(50)
        self.timeEdit.setFont(font8)
        self.timeEdit.setAutoFillBackground(True)
        self.timeEdit.setTime(self.bedtime)
        self.bedtime_label = QLabel(self.settings)
        self.bedtime_label.setObjectName(u"bedtime_label")
        self.bedtime_label.setText(u"Set Bedtime:")
        self.bedtime_label.setGeometry(QRect(200, 0, 151, 31))
        self.bedtime_label.setFont(font8)
        self.bedtime_label.setAutoFillBackground(True)
        self.Brightness_Value = QLCDNumber(self.settings)
        self.Brightness_Value.setObjectName(u"Brightness_Value")
        self.Brightness_Value.setGeometry(QRect(20, 120, 61, 31))
        self.Brightness_Value.setStyleSheet(u"color: \"White\";\n"
                                            "margin:0px;\n"
                                            "border:0px;background:\"transparent\";")
        self.Brightness_Value.setDigitCount(3)
        self.Brightness_Value.setProperty("value", 180.000000000000000)
        self.Brightness = QSlider(self.settings)
        self.Brightness.setObjectName(u"Brightness")
        self.Brightness.setGeometry(QRect(30, 160, 51, 261))
        self.Brightness.setAutoFillBackground(False)
        self.Brightness.setMaximum(255)
        self.Brightness.setValue(self.LCD_brightness)
        self.Brightness.setOrientation(Qt.Vertical)
        self.Brightness_label = QLabel(self.settings)
        self.Brightness_label.setObjectName(u"Brightness_label")
        self.Brightness_label.setText(u"Brightness")
        self.Brightness_label.setGeometry(QRect(20, 70, 101, 41))
        font10 = QFont()
        font10.setFamily(u"Arial Black")
        font10.setPointSize(12)
        font10.setBold(True)
        font10.setWeight(75)
        self.Brightness_label.setFont(font10)
        self.temp_test = QLabel(self.settings)
        self.temp_test.setObjectName(u"temp_test")
        self.temp_test.setText(u"T20.5 C")
        self.temp_test.setFont(font8)
        self.temp_test.setGeometry(QRect(630, 60, 141, 51))
        # self.temp_test.setFont(font_bold_20)
        self.temp_test_slide = QSlider(self.settings)
        self.temp_test_slide.setObjectName(u"temp_test_slide")
        self.temp_test_slide.setGeometry(QRect(660, 150, 51, 271))
        self.temp_test_slide.setAutoFillBackground(False)
        self.temp_test_slide.setMinimum(-250)
        self.temp_test_slide.setMaximum(450)
        self.temp_test_slide.setSingleStep(5)
        self.temp_test_slide.setPageStep(25)
        self.temp_test_slide.setValue(38)
        self.temp_test_slide.setOrientation(Qt.Vertical)
        self.temp_check_outside = QCheckBox(self.settings)
        self.temp_check_outside.setObjectName(u"temp_check_outside")
        self.temp_check_outside.setText(u"Outside")
        self.temp_check_outside.setGeometry(QRect(640, 110, 86, 20))
        self.grace_period = QSpinBox(self.settings)
        self.grace_period.setObjectName(u"grace_period")
        self.grace_period.setGeometry(QRect(411, 31, 111, 41))
        self.grace_period.setFont(font8)
        self.grace_period.setMinimum(1)
        self.grace_period.setMaximum(60)
        self.grace_period.setValue(self.bedtime_grace_period)
        self.grace_period.setDisplayIntegerBase(10)
        self.grace_period_label = QLabel(self.settings)
        self.grace_period_label.setObjectName(u"grace_period_label")
        self.grace_period_label.setText(u"Grace period:")
        self.grace_period_label.setGeometry(QRect(410, 10, 111, 16))
        self.grace_period_label.setFont(font8)

        #################################################################################################
        # SET ALL LABEL TEXTS
        #################################################################################################

        # if QT_CONFIG(tooltip)
        self.sleep.setToolTip(u"Put display to sleep")
        self.ledball_on2.setToolTip(u"Turn on the LED Ball, mode 2")
        self.ledball_on.setToolTip(u"Turn on the LED Ball.")
        self.ledball_off.setToolTip(u"Turn off the LED Ball.")
        # endif // QT_CONFIG(tooltip)

        #################################################################################################
        # Make the Connections.
        #################################################################################################

        self.temp_test_slide.valueChanged.connect(self.test_temp_update)
        self.temp_check_outside.clicked.connect(self.test_temp_update)

        self.ledball_off.clicked.connect(self.set_ledball_off)
        self.ledball_on.clicked.connect(self.set_ledball_on)
        self.ledball_on2.clicked.connect(self.set_ledball_on2)
        self.sleep.clicked.connect(self.set_sleep)

        self.timeEdit.timeChanged.connect(self.set_bedtime)
        self.grace_period.valueChanged.connect(self.set_grace_period)
        self.Brightness.valueChanged.connect(self.set_screen_brightness)
        self.Brightness.valueChanged.connect(self.Brightness_Value.display)
Example #21
0
    def init_ui(self):
        self.main_layout = QGridLayout(self)
        self.chart = HierarchicalChart(toolbar=True)
        self.main_layout.addWidget(self.chart, 0, 0, 1, 4)

        self.load_dataset_button = QPushButton(qta.icon("fa5s.database"),
                                               self.tr("Load Dataset"))
        self.load_dataset_button.clicked.connect(
            lambda: self.load_dataset_dialog.show())
        self.main_layout.addWidget(self.load_dataset_button, 1, 0, 1, 2)

        self.n_samples_label = QLabel(self.tr("N<sub>components</sub>"))
        self.n_samples_label.setToolTip(
            self.tr("The Number of samples in the loaded dataset."))
        self.n_samples_display = QLabel(self.tr("Unknown"))
        self.main_layout.addWidget(self.n_samples_label, 1, 2)
        self.main_layout.addWidget(self.n_samples_display, 1, 3)

        self.supported_methods = [
            "single", "complete", "average", "weighted", "centroid", "median",
            "ward"
        ]
        self.supported_distances = [
            "braycurtis", "canberra", "chebyshev", "cityblock", "correlation",
            "cosine", "dice", "euclidean", "hamming", "jaccard",
            "jensenshannon", "kulsinski", "mahalanobis", "matching",
            "minkowski", "rogerstanimoto", "russellrao", "seuclidean",
            "sokalmichener", "sokalsneath", "sqeuclidean", "yule"
        ]

        self.linkage_method_label = QLabel(self.tr("Linkage Method"))
        self.linkage_method_label.setToolTip(
            self.
            tr("The linkage method for calculating the distance between the newly formed cluster and each observation vector."
               ))
        self.linkage_method_combo_box = QComboBox()
        self.linkage_method_combo_box.addItems(self.supported_methods)
        self.linkage_method_combo_box.setCurrentText("ward")
        self.distance_label = QLabel(self.tr("Distance"))
        self.distance_label.setToolTip(
            self.
            tr("The distance metric to use in the case that y is a collection of observation vectors."
               ))
        self.distance_combo_box = QComboBox()
        self.distance_combo_box.addItems(self.supported_distances)
        self.distance_combo_box.setCurrentText("euclidean")
        self.main_layout.addWidget(self.linkage_method_label, 2, 0)
        self.main_layout.addWidget(self.linkage_method_combo_box, 2, 1)
        self.main_layout.addWidget(self.distance_label, 2, 2)
        self.main_layout.addWidget(self.distance_combo_box, 2, 3)

        self.p_label = QLabel(self.tr("p"))
        self.p_label.setToolTip(
            self.
            tr("Controls the number of leaves at the bottom level of the figure."
               ))
        self.p_input = QSpinBox()
        self.p_input.setMinimum(1)
        self.main_layout.addWidget(self.p_label, 3, 0)
        self.main_layout.addWidget(self.p_input, 3, 1)
        self.n_clusers_label = QLabel(self.tr("N<sub>clusters</sub>"))
        self.n_clusers_label.setToolTip(
            self.tr(
                "Controls the number of clusters of this clustering algorithm."
            ))
        self.n_clusers_input = QSpinBox()
        self.n_clusers_input.setMinimum(2)
        self.main_layout.addWidget(self.n_clusers_label, 3, 2)
        self.main_layout.addWidget(self.n_clusers_input, 3, 3)

        self.perform_button = QPushButton(qta.icon("ei.ok-sign"),
                                          self.tr("Perform"))
        self.perform_button.setEnabled(False)
        self.perform_button.clicked.connect(self.on_perform_clicked)
        self.show_typical_button = QPushButton(qta.icon("fa.area-chart"),
                                               self.tr("Show Typical"))
        self.show_typical_button.clicked.connect(self.on_show_typical_clicked)
        self.show_typical_button.setEnabled(False)
        self.save_button = QPushButton(qta.icon("fa5s.save"), self.tr("Save"))
        self.save_button.setEnabled(False)
        self.show_all_button = QPushButton(qta.icon("mdi.view-grid-outline"),
                                           self.tr("Show All"))
        self.show_all_button.setEnabled(False)
        self.show_all_button.clicked.connect(self.on_show_all_clicked)
        self.save_button.clicked.connect(self.on_save_clicked)
        self.main_layout.addWidget(self.perform_button, 4, 0, 1, 2)
        self.main_layout.addWidget(self.show_typical_button, 4, 2, 1, 2)
        self.main_layout.addWidget(self.save_button, 5, 0, 1, 2)
        self.main_layout.addWidget(self.show_all_button, 5, 2, 1, 2)
Example #22
0
class NGL_HKLViewer(QWidget):
    def __init__(self, parent=None):
        super(NGL_HKLViewer, self).__init__(parent)

        self.verbose = 0
        self.UseOSbrowser = False
        self.jscriptfname = ""
        self.devmode = False
        for e in sys.argv:
            if "verbose" in e:
                self.verbose = e.split("verbose=")[1]
            if "UseOSbrowser" in e:
                self.UseOSbrowser = e.split("UseOSbrowser=")[1]
            if "jscriptfname" in e:
                self.jscriptfname = e.split("jscriptfname=")[1]
            if "devmode" in e:
                self.devmode = True

        self.zmq_context = None
        self.bufsize = 20000

        self.originalPalette = QApplication.palette()

        self.openFileNameButton = QPushButton("Load reflection file")
        self.openFileNameButton.setDefault(True)
        self.openFileNameButton.clicked.connect(self.OpenReflectionsFile)

        self.debugbutton = QPushButton("Debug")
        self.debugbutton.clicked.connect(self.DebugInteractively)

        self.settingsbtn = QPushButton("Settings")
        self.settingsbtn.clicked.connect(self.SettingsDialog)

        self.mousemoveslider = QSlider(Qt.Horizontal)
        self.mousemoveslider.setMinimum(0)
        self.mousemoveslider.setMaximum(300)
        self.mousemoveslider.setValue(0)
        self.mousemoveslider.sliderReleased.connect(
            self.onFinalMouseSensitivity)
        self.mousemoveslider.valueChanged.connect(self.onMouseSensitivity)
        self.mousesensitxtbox = QLineEdit('')
        self.mousesensitxtbox.setReadOnly(True)
        self.fontspinBox = QDoubleSpinBox()
        self.fontspinBox.setSingleStep(1)
        self.fontspinBox.setRange(4, 50)
        self.font = QFont()
        self.font.setFamily(self.font.defaultFamily())
        self.fontspinBox.setValue(self.font.pointSize())
        #self.fontspinBox.setValue(self.font.pixelSize())
        self.fontspinBox.valueChanged.connect(self.onFontsizeChanged)
        self.Fontsize_labeltxt = QLabel()
        self.Fontsize_labeltxt.setText("Font size:")

        self.cameraPerspectCheckBox = QCheckBox()
        self.cameraPerspectCheckBox.setText("Perspective camera")
        self.cameraPerspectCheckBox.clicked.connect(self.onCameraPerspect)
        self.cameraPerspectCheckBox.setCheckState(Qt.Unchecked)

        self.settingsform = SettingsForm(self)

        self.MillerComboBox = QComboBox()
        self.MillerComboBox.activated.connect(self.onMillerComboSelchange)
        #self.MillerComboBox.setSizeAdjustPolicy(QComboBox.AdjustToContents)

        self.MillerLabel = QLabel()
        self.MillerLabel.setText("Selected HKL Scene")

        self.HKLnameedit = QLineEdit('')
        self.HKLnameedit.setReadOnly(True)
        self.textInfo = QTextEdit()
        self.textInfo.setLineWrapMode(QTextEdit.NoWrap)
        self.textInfo.setReadOnly(True)

        labels = [
            "Label", "Type", "no. of HKLs", "Span of HKLs", "Min Max data",
            "Min Max sigmas", "d_min, d_max", "Symmetry unique", "Anomalous"
        ]
        self.millertable = QTableWidget(0, len(labels))
        self.millertable.setHorizontalHeaderLabels(labels)
        self.millertable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        # don't allow editing this table
        self.millertable.setEditTriggers(QTableWidget.NoEditTriggers)

        self.createExpansionBox()
        self.createFileInfoBox()
        self.CreateSliceTabs()
        self.createRadiiScaleGroupBox()
        self.createBinsBox()
        self.CreateFunctionTabs()

        mainLayout = QGridLayout()
        mainLayout.addWidget(self.FileInfoBox, 0, 0)
        mainLayout.addWidget(self.MillerLabel, 1, 0)
        mainLayout.addWidget(self.MillerComboBox, 2, 0)
        mainLayout.addWidget(self.functionTabWidget, 3, 0)
        mainLayout.addWidget(self.settingsbtn, 4, 0, 1, 1)

        #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) )
        if self.UseOSbrowser == False:
            self.BrowserBox = QWebEngineView()
            mainLayout.addWidget(self.BrowserBox, 0, 1, 5, 3)
            self.BrowserBox.setUrl("https://cctbx.github.io/")
            #self.BrowserBox.setUrl("https://webglreport.com/")
            #self.BrowserBox.loadFinished.connect(self.onLoadFinished)
            mainLayout.setColumnStretch(2, 1)

        mainLayout.setRowStretch(0, 1)
        mainLayout.setRowStretch(1, 0)
        mainLayout.setRowStretch(2, 1)
        mainLayout.setRowStretch(3, 1)
        mainLayout.setColumnStretch(4, 0)
        self.setLayout(mainLayout)

        self.setWindowTitle("HKL-Viewer")
        self.cctbxproc = None
        self.LaunchCCTBXPython()
        self.out = None
        self.err = None
        self.comboviewwidth = 0
        self.hklscenes_arrays = []
        self.array_infotpls = []
        self.matching_arrays = []
        self.bin_infotpls = None
        self.bin_opacities = None
        self.html_url = ""
        self.spacegroups = []
        self.info = []
        self.infostr = ""
        self.fileisvalid = False
        self.NewFileLoaded = False
        self.NewHKLscenes = False
        self.updatingNbins = False
        self.binstableitemchanges = False

        self.show()

    def SettingsDialog(self):
        self.settingsform.show()

    def update(self):
        if self.cctbxproc:
            if self.cctbxproc.stdout:
                print(self.cctbxproc.stdout.read().decode("utf-8"))
            if self.cctbxproc.stderr:
                print(self.cctbxproc.stderr.read().decode("utf-8"))
        if self.out:
            print(self.out.decode("utf-8"))
        if self.err:
            print(self.err.decode("utf-8"))
        if self.zmq_context:
            try:
                msg = self.socket.recv(
                    flags=zmq.NOBLOCK
                )  #To empty the socket from previous messages
                msgstr = msg.decode()
                self.infodict = eval(msgstr)
                #print("received from cctbx: " + str(self.infodict))
                if self.infodict:

                    if self.infodict.get("hklscenes_arrays"):
                        self.hklscenes_arrays = self.infodict.get(
                            "hklscenes_arrays", [])

                    if self.infodict.get("array_infotpls"):
                        self.array_infotpls = self.infodict.get(
                            "array_infotpls", [])

                    if self.infodict.get("bin_data_label"):
                        self.BinDataComboBox.setCurrentText(
                            self.infodict["bin_data_label"])

                    if self.infodict.get("bin_infotpls"):
                        self.bin_infotpls = self.infodict["bin_infotpls"]

                        self.nbins = len(self.bin_infotpls)
                        self.updatingNbins = True
                        self.Nbins_spinBox.setValue(self.nbins)
                        self.updatingNbins = False
                        self.binstable.clearContents()
                        self.binstable.setRowCount(self.nbins)
                        for row, bin_infotpl in enumerate(self.bin_infotpls):
                            for col, elm in enumerate(bin_infotpl):
                                # only allow changing the last column with opacity values
                                if col != 3:
                                    item = QTableWidgetItem(str(elm))
                                else:
                                    item = QTableWidgetItem()
                                    item.setFlags(Qt.ItemIsUserCheckable
                                                  | Qt.ItemIsEnabled)
                                    item.setCheckState(Qt.Checked)
                                item.setFlags(item.flags() ^ Qt.ItemIsEditable)
                                self.binstable.setItem(row, col, item)
                        if self.bin_opacities:
                            self.update_table_opacities()

                    if self.infodict.get("bin_opacities"):
                        self.bin_opacities = self.infodict["bin_opacities"]
                        if self.binstable.rowCount() > 0:
                            self.update_table_opacities()

                    if self.infodict.get("html_url"):
                        self.html_url = self.infodict["html_url"]
                        if self.UseOSbrowser == False:
                            self.BrowserBox.setUrl(self.html_url)
                            # workaround for background colour bug in chromium
                            # https://bugreports.qt.io/browse/QTBUG-41960
                            self.BrowserBox.page().setBackgroundColor(
                                QColor(100, 100, 100, 1.0))

                    if self.infodict.get("spacegroups"):
                        self.spacegroups = self.infodict.get("spacegroups", [])
                        self.SpaceGroupComboBox.clear()
                        self.SpaceGroupComboBox.addItems(self.spacegroups)

                    if self.infodict.get("merge_data"):
                        self.mergedata = self.infodict["merge_data"]

                    currentinfostr = ""
                    if self.infodict.get("info"):
                        currentinfostr = self.infodict.get("info", [])

                    if self.infodict.get("NewFileLoaded"):
                        self.NewFileLoaded = self.infodict.get(
                            "NewFileLoaded", False)

                    if self.infodict.get("NewHKLscenes"):
                        self.NewHKLscenes = self.infodict.get(
                            "NewHKLscenes", False)

                    self.fileisvalid = True
                    #print("ngl_hkl_infodict: " + str(ngl_hkl_infodict))

                    if currentinfostr:
                        #print(currentinfostr)
                        self.infostr += currentinfostr + "\n"
                        # display no more than self.bufsize bytes of text
                        self.infostr = self.infostr[-self.bufsize:]
                        self.textInfo.setPlainText(self.infostr)
                        self.textInfo.verticalScrollBar().setValue(
                            self.textInfo.verticalScrollBar().maximum())

                    if self.NewFileLoaded and self.NewHKLscenes:
                        #if self.mergedata == True : val = Qt.CheckState.Checked
                        #if self.mergedata == None : val = Qt.CheckState.PartiallyChecked
                        #if self.mergedata == False : val = Qt.CheckState.Unchecked
                        #self.mergecheckbox.setCheckState(val )
                        #print("got hklscenes: " + str(self.hklscenes_arrays))

                        self.MillerComboBox.clear()
                        self.MillerComboBox.addItems(
                            [e[3] for e in self.hklscenes_arrays])
                        self.MillerComboBox.setCurrentIndex(
                            -1)  # unselect the first item in the list
                        self.comboviewwidth = 0
                        for e in self.hklscenes_arrays:
                            self.comboviewwidth = max(
                                self.comboviewwidth,
                                self.MillerComboBox.fontMetrics().width(e[3]))
                        self.MillerComboBox.view().setMinimumWidth(
                            self.comboviewwidth)

                        self.millertable.clearContents()
                        self.millertable.setRowCount(len(
                            self.hklscenes_arrays))
                        for n, millarr in enumerate(self.array_infotpls):
                            for m, elm in enumerate(millarr):
                                self.millertable.setItem(
                                    n, m, QTableWidgetItem(str(elm)))
                        self.functionTabWidget.setDisabled(True)
                        self.NewFileLoaded = False

                    if self.NewHKLscenes:
                        self.BinDataComboBox.clear()
                        self.BinDataComboBox.addItems(
                            ["Resolution"] +
                            [e[3] for e in self.hklscenes_arrays])
                        self.BinDataComboBox.view().setMinimumWidth(
                            self.comboviewwidth)
                        #self.BinDataComboBox.setCurrentIndex(-1) # unselect the first item in the list
                        self.NewHKLscenes = False

            except Exception as e:
                errmsg = str(e)
                if "Resource temporarily unavailable" not in errmsg:
                    print(errmsg + traceback.format_exc(limit=10))
                pass

    def onFinalMouseSensitivity(self):
        val = self.mousemoveslider.value() / 100.0
        self.NGL_HKL_command(
            'NGL_HKLviewer.viewer.NGL.mouse_sensitivity = %f' % val)

    def onMouseSensitivity(self):
        val = self.mousemoveslider.value() / 100.0
        self.mousesensitxtbox.setText("%2.2f" % val)

    def onFontsizeChanged(self, val):
        font = app.font()
        font.setPointSize(val)
        app.setFont(font)
        self.settingsform.setFixedSize(self.settingsform.sizeHint())

    def onCameraPerspect(self, val):
        if self.cameraPerspectCheckBox.isChecked():
            self.NGL_HKL_command("NGL_HKLviewer.camera_type = perspective")
        else:
            self.NGL_HKL_command("NGL_HKLviewer.camera_type = orthographic")

    def MergeData(self):
        if self.mergecheckbox.checkState() == Qt.CheckState.Checked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = True')
        if self.mergecheckbox.checkState() == Qt.CheckState.PartiallyChecked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = None')
        if self.mergecheckbox.checkState() == Qt.CheckState.Unchecked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = False')

    def ExpandToP1(self):
        if self.expandP1checkbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = True')
        else:
            self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = False')

    def ExpandAnomalous(self):
        if self.expandAnomalouscheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.expand_anomalous = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.expand_anomalous = False')

    def showSysAbsent(self):
        if self.sysabsentcheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_systematic_absences = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_systematic_absences = False')

    def showMissing(self):
        if self.missingcheckbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = True')
        else:
            self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = False')

    def showOnlyMissing(self):
        if self.onlymissingcheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_only_missing = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_only_missing = False')

    def showSlice(self):
        if self.showslicecheckbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.slice_mode = True')
            if self.expandP1checkbox.isChecked():
                self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                       expand_to_p1 = True
                                                       inbrowser = False
                                                    }
                             """)
            if self.expandAnomalouscheckbox.isChecked():
                self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                       expand_anomalous = True
                                                       inbrowser = False
                                                     }
                             """)
        else:
            self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                      slice_mode = False
                                                      inbrowser = True
                                                    }
                            """)

    def onSliceComboSelchange(self, i):
        rmin = self.array_infotpls[self.MillerComboBox.currentIndex()][3][0][i]
        rmax = self.array_infotpls[self.MillerComboBox.currentIndex()][3][1][i]
        self.sliceindexspinBox.setRange(rmin, rmax)
        self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_axis = %s" %
                             self.sliceaxis[i])

    def onSliceIndexChanged(self, val):
        self.sliceindex = val
        self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_index = %d" %
                             self.sliceindex)

    def onBindataComboSelchange(self, i):
        if self.BinDataComboBox.currentText():
            if self.BinDataComboBox.currentIndex() > 0:
                bin_scene_label = str(self.BinDataComboBox.currentIndex() - 1)
            else:
                bin_scene_label = "Resolution"
            self.NGL_HKL_command("NGL_HKLviewer.bin_scene_label = %s" %
                                 bin_scene_label)

    def update_table_opacities(self, allalpha=None):
        bin_opacitieslst = eval(self.bin_opacities)
        self.binstable_isready = False
        for binopacity in bin_opacitieslst:
            if not allalpha:
                alpha = float(binopacity.split(",")[0])
            else:
                alpha = allalpha
            bin = int(binopacity.split(",")[1])
            item = QTableWidgetItem()
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            if alpha < 0.5:
                item.setCheckState(Qt.Unchecked)
            else:
                item.setCheckState(Qt.Checked)
            item.setFlags(item.flags() ^ Qt.ItemIsEditable)
            self.binstable.setItem(bin, 3, item)
        self.binstable_isready = True

    def SetOpaqueAll(self):
        if self.binstableitemchanges:
            return
        bin_opacitieslst = eval(self.bin_opacities)
        nbins = len(bin_opacitieslst)
        sum = 0
        for binopacity in bin_opacitieslst:
            sum += float(binopacity.split(",")[0])
        if sum >= nbins:
            self.OpaqueAllCheckbox.setCheckState(Qt.Checked)
        if sum == 0:
            self.OpaqueAllCheckbox.setCheckState(Qt.Unchecked)
        if sum > 0.0 and sum < nbins:
            self.OpaqueAllCheckbox.setCheckState(Qt.PartiallyChecked)

    def onBinsTableItemChanged(self, item):
        row = item.row()
        column = item.column()
        try:
            if item.checkState() == Qt.Unchecked:
                newval = 0
            else:
                newval = 1.0
            if column == 3 and self.binstable_isready:  # changing opacity
                assert (newval <= 1.0 and newval >= 0.0)
                bin_opacitieslst = eval(self.bin_opacities)
                bin_opacitieslst[row] = str(newval) + ', ' + str(row)
                self.bin_opacities = str(bin_opacitieslst)
                self.SetOpaqueAll()
                self.NGL_HKL_command(
                    'NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' %
                    self.bin_opacities)
        except Exception as e:
            print(str(e))
            #self.binstable.currentItem().setText( self.currentSelectedBinsTableVal)

    def onBinsTableItemSelectionChanged(self):
        row = self.binstable.currentItem().row()
        column = self.binstable.currentItem().column()
        self.currentSelectedBinsTableVal = self.binstable.currentItem().text()
        #print( "in itemSelectionChanged " + self.currentSelectedBinsTableVal)

    def onOpaqueAll(self):
        self.binstableitemchanges = True
        bin_opacitieslst = eval(self.bin_opacities)
        nbins = len(bin_opacitieslst)
        bin_opacitieslst = []
        self.binstable_isready = False
        if self.OpaqueAllCheckbox.isChecked():
            for i in range(nbins):
                bin_opacitieslst.append("1.0, %d" % i)
        else:
            for i in range(nbins):
                bin_opacitieslst.append("0.0, %d" % i)
        self.bin_opacities = str(bin_opacitieslst)
        self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' %
                             self.bin_opacities)
        self.binstableitemchanges = False
        self.binstable_isready = True

    """
  def onLoadFinished(self, val):
    pass
    #print("web page finished loading now")


  def onBinsTableitemActivated(self, item):
    row = item.row()
    column = item.column()
    currentval = item.text()
    #print( "in itemActivated " + currentval)


  def onBinsTableCellentered(self, row, col):
    pass
    #print( "in Cellentered " + self.binstable.currentItem().text() )


  def onBinsTableCellPressed(self, row, col):
    pass
    #print( "in CellPressed " + self.binstable.currentItem().text() )
  """

    def onNbinsChanged(self, val):
        self.nbins = val
        if not self.updatingNbins:  # avoid possible endless loop to cctbx
            self.NGL_HKL_command("NGL_HKLviewer.nbins = %d" % self.nbins)

    def onRadiiScaleChanged(self, val):
        self.radii_scale = val
        self.NGL_HKL_command("""
      NGL_HKLviewer.viewer {
        nth_power_scale_radii = %f
        scale = %f
      }
      """ % (self.nth_power_scale, self.radii_scale))

    def onPowerScaleChanged(self, val):
        self.nth_power_scale = val
        self.NGL_HKL_command("""
      NGL_HKLviewer.viewer {
        nth_power_scale_radii = %f
        scale = %f
      }
      """ % (self.nth_power_scale, self.radii_scale))

    def onManualPowerScale(self):
        if self.ManualPowerScalecheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.nth_power_scale_radii = %f' %
                self.nth_power_scale)
            self.power_scale_spinBox.setEnabled(True)
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.nth_power_scale_radii = -1.0')
            self.power_scale_spinBox.setEnabled(False)
            self.nth_power_scale = -1.0

    def OpenReflectionsFile(self):
        options = QFileDialog.Options()
        fileName, filtr = QFileDialog.getOpenFileName(
            self, "Load reflections file", "",
            "All Files (*);;MTZ Files (*.mtz);;CIF (*.cif)", "", options)
        if fileName:
            self.HKLnameedit.setText(fileName)
            #self.infostr = ""
            self.textInfo.setPlainText("")
            self.fileisvalid = False
            self.NGL_HKL_command('NGL_HKLviewer.filename = "%s"' % fileName)
            self.MillerComboBox.clear()
            self.BinDataComboBox.clear()

    def createExpansionBox(self):
        self.SpaceGroupComboBox = QComboBox()
        self.SpaceGroupComboBox.activated.connect(self.SpacegroupSelchange)

        self.SpacegroupLabel = QLabel()
        self.SpacegroupLabel.setText("Space Subgroups")

        self.mergecheckbox = QCheckBox()
        self.mergecheckbox.setText("Merge data")
        #self.mergecheckbox.setTristate (True)
        self.mergecheckbox.clicked.connect(self.MergeData)

        self.expandP1checkbox = QCheckBox()
        self.expandP1checkbox.setText("Expand to P1")
        self.expandP1checkbox.clicked.connect(self.ExpandToP1)

        self.expandAnomalouscheckbox = QCheckBox()
        self.expandAnomalouscheckbox.setText("Show Friedel pairs")
        self.expandAnomalouscheckbox.clicked.connect(self.ExpandAnomalous)

        self.sysabsentcheckbox = QCheckBox()
        self.sysabsentcheckbox.setText("Show Systematic Absences")
        self.sysabsentcheckbox.clicked.connect(self.showSysAbsent)

        self.missingcheckbox = QCheckBox()
        self.missingcheckbox.setText("Show Missing")
        self.missingcheckbox.clicked.connect(self.showMissing)

        self.onlymissingcheckbox = QCheckBox()
        self.onlymissingcheckbox.setText("Only Show Missing")
        self.onlymissingcheckbox.clicked.connect(self.showOnlyMissing)

        self.ExpansionBox = QGroupBox("Expansions")
        layout = QGridLayout()
        layout.addWidget(self.SpacegroupLabel, 0, 0)
        layout.addWidget(self.SpaceGroupComboBox, 0, 1)
        #layout.addWidget(self.mergecheckbox,             1, 0)
        layout.addWidget(self.expandP1checkbox, 1, 0)
        layout.addWidget(self.expandAnomalouscheckbox, 1, 1)
        layout.addWidget(self.sysabsentcheckbox, 2, 0)
        layout.addWidget(self.missingcheckbox, 3, 0)
        layout.addWidget(self.onlymissingcheckbox, 3, 1)
        layout.setRowStretch(0, 0)
        layout.setRowStretch(1, 0)
        layout.setRowStretch(2, 0)
        layout.setRowStretch(3, 1)
        self.ExpansionBox.setLayout(layout)

    def CreateSliceTabs(self):
        self.showslicecheckbox = QCheckBox()
        self.showslicecheckbox.setText("Show Slice")
        self.showslicecheckbox.clicked.connect(self.showSlice)

        self.sliceindexspinBox = QDoubleSpinBox()
        self.sliceindex = 0
        self.sliceindexspinBox.setValue(self.sliceindex)
        self.sliceindexspinBox.setDecimals(0)
        self.sliceindexspinBox.setSingleStep(1)
        self.sliceindexspinBox.setRange(0, 20)
        self.sliceindexspinBox.valueChanged.connect(self.onSliceIndexChanged)

        self.SliceLabelComboBox = QComboBox()
        self.SliceLabelComboBox.activated.connect(self.onSliceComboSelchange)
        self.sliceaxis = ["h", "k", "l"]
        self.SliceLabelComboBox.addItems(self.sliceaxis)

        self.sliceTabWidget = QTabWidget()
        tab1 = QWidget()
        layout1 = QGridLayout()
        layout1.addWidget(self.showslicecheckbox, 0, 0, 1, 1)
        layout1.addWidget(self.SliceLabelComboBox, 0, 1, 1, 1)
        layout1.addWidget(self.sliceindexspinBox, 0, 2, 1, 1)
        tab1.setLayout(layout1)

        tab2 = QWidget()
        layout2 = QGridLayout()

        self.hvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hvecval = 2.0
        self.hvec_spinBox.setValue(self.hvecval)
        self.hvec_spinBox.setDecimals(2)
        self.hvec_spinBox.setSingleStep(0.5)
        self.hvec_spinBox.setRange(-100.0, 10.0)
        self.hvec_spinBox.valueChanged.connect(self.onHvecChanged)
        self.hvec_Label = QLabel()
        self.hvec_Label.setText("H")
        layout2.addWidget(self.hvec_Label, 0, 0, 1, 1)
        layout2.addWidget(self.hvec_spinBox, 0, 1, 1, 1)

        self.kvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.kvecval = 0.0
        self.kvec_spinBox.setValue(self.kvecval)
        self.kvec_spinBox.setDecimals(2)
        self.kvec_spinBox.setSingleStep(0.5)
        self.kvec_spinBox.setRange(-100.0, 100.0)
        self.kvec_spinBox.valueChanged.connect(self.onKvecChanged)
        self.kvec_Label = QLabel()
        self.kvec_Label.setText("K")
        layout2.addWidget(self.kvec_Label, 1, 0, 1, 1)
        layout2.addWidget(self.kvec_spinBox, 1, 1, 1, 1)

        self.lvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.lvecval = 0.0
        self.lvec_spinBox.setValue(self.lvecval)
        self.lvec_spinBox.setDecimals(2)
        self.lvec_spinBox.setSingleStep(0.5)
        self.lvec_spinBox.setRange(-100.0, 100.0)
        self.lvec_spinBox.valueChanged.connect(self.onLvecChanged)
        self.lvec_Label = QLabel()
        self.lvec_Label.setText("L")
        layout2.addWidget(self.lvec_Label, 2, 0, 1, 1)
        layout2.addWidget(self.lvec_spinBox, 2, 1, 1, 1)

        self.hkldist_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hkldistval = 0.0
        self.hkldist_spinBox.setValue(self.hkldistval)
        self.hkldist_spinBox.setDecimals(2)
        self.hkldist_spinBox.setSingleStep(0.5)
        self.hkldist_spinBox.setRange(-100.0, 100.0)
        self.hkldist_spinBox.valueChanged.connect(self.onHKLdistChanged)
        self.hkldist_Label = QLabel()
        self.hkldist_Label.setText("Distance from Origin")
        layout2.addWidget(self.hkldist_Label, 3, 0, 1, 1)
        layout2.addWidget(self.hkldist_spinBox, 3, 1, 1, 1)

        self.clipwidth_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.clipwidthval = 0.5
        self.clipwidth_spinBox.setValue(self.clipwidthval)
        self.clipwidth_spinBox.setDecimals(2)
        self.clipwidth_spinBox.setSingleStep(0.05)
        self.clipwidth_spinBox.setRange(0.0, 100.0)
        self.clipwidth_spinBox.valueChanged.connect(self.onClipwidthChanged)
        self.clipwidth_Label = QLabel()
        self.clipwidth_Label.setText("Clip Plane Width")
        layout2.addWidget(self.clipwidth_Label, 4, 0, 1, 1)
        layout2.addWidget(self.clipwidth_spinBox, 4, 1, 1, 1)

        self.ClipBox = QGroupBox("Normal Vector to Clip Plane")
        self.ClipBox.setLayout(layout2)

        layout3 = QGridLayout()
        self.ClipPlaneChkBox = QCheckBox(self.sliceTabWidget)
        self.ClipPlaneChkBox.setText(
            "Use clip plane normal to HKL vector pointing out")
        self.ClipPlaneChkBox.clicked.connect(self.onClipPlaneChkBox)

        layout3.addWidget(self.ClipPlaneChkBox, 0, 0)
        layout3.addWidget(self.ClipBox, 1, 0)
        tab2.setLayout(layout3)
        self.sliceTabWidget.addTab(tab1, "Explicit Slicing")
        self.sliceTabWidget.addTab(tab2, "Clip Plane Slicing")
        self.ClipBox.setDisabled(True)

    def onClipPlaneChkBox(self):
        if self.ClipPlaneChkBox.isChecked():
            self.ClipBox.setDisabled(False)
            philstr = """NGL_HKLviewer.normal_clip_plane {
  h = %s
  k = %s
  l = %s
  hkldist = %s
  clipwidth = %s
}
  NGL_HKLviewer.viewer.NGL.fixorientation = %s

      """ %(self.hvecval, self.kvecval, self.lvecval, self.hkldistval, self.clipwidthval, \
                                    str(self.fixedorientcheckbox.isChecked()) )
            self.NGL_HKL_command(philstr)
        else:
            self.ClipBox.setDisabled(True)
            self.NGL_HKL_command(
                "NGL_HKLviewer.normal_clip_plane.clipwidth = None")

    def onClipwidthChanged(self, val):
        self.clipwidthval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.clipwidth = %f" %
                             self.clipwidthval)

    def onHKLdistChanged(self, val):
        self.hkldistval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.hkldist = %f" %
                             self.hkldistval)

    def onHvecChanged(self, val):
        self.hvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.h = %f" %
                             self.hvecval)

    def onKvecChanged(self, val):
        self.kvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.k = %f" %
                             self.kvecval)

    def onLvecChanged(self, val):
        self.lvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.l = %f" %
                             self.lvecval)

    def onFixedorient(self):
        self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.fixorientation = %s' \
                                        %str(self.fixedorientcheckbox.isChecked()))

    def onMillerComboSelchange(self, i):
        self.NGL_HKL_command("NGL_HKLviewer.scene_id = %d" % i)
        #self.MillerComboBox.setCurrentIndex(i)
        if self.MillerComboBox.currentText():
            self.functionTabWidget.setEnabled(True)
            self.expandAnomalouscheckbox.setEnabled(True)
            # don' allow anomalous expansion for data that's already anomalous
            for arrayinfo in self.array_infotpls:
                isanomalous = arrayinfo[-1]
                label = arrayinfo[0]
                if isanomalous and label == self.MillerComboBox.currentText(
                )[:len(label)]:
                    self.expandAnomalouscheckbox.setDisabled(True)
        else:
            self.functionTabWidget.setDisabled(True)

        self.SpaceGroupComboBox.clear()
        self.SpaceGroupComboBox.addItems(self.spacegroups)
        # need to supply issymunique flag in infotuple
        #if self.hklscenes_arrays[ i ][6] == 0:
        #  self.mergecheckbox.setEnabled(True)
        #else:
        #  self.mergecheckbox.setEnabled(False)

    def createFileInfoBox(self):
        self.FileInfoBox = QGroupBox("Reflection File Information")
        layout = QGridLayout()
        layout.addWidget(self.openFileNameButton, 0, 0, 1, 2)
        if self.devmode:
            layout.addWidget(self.debugbutton, 0, 2, 1, 1)
        layout.addWidget(self.HKLnameedit, 1, 0, 1, 3)
        layout.addWidget(self.millertable, 2, 0, 1, 3)
        layout.addWidget(self.textInfo, 3, 0, 1, 3)
        #layout.setColumnStretch(1, 2)
        self.FileInfoBox.setLayout(layout)

    def createRadiiScaleGroupBox(self):
        self.RadiiScaleGroupBox = QGroupBox("Radii Size of HKL Spheres")

        self.ManualPowerScalecheckbox = QCheckBox()
        self.ManualPowerScalecheckbox.setText(
            "Manual Power Scaling of Sphere Radii")
        self.ManualPowerScalecheckbox.clicked.connect(self.onManualPowerScale)

        self.power_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox)
        self.nth_power_scale = 0.5
        self.power_scale_spinBox.setValue(self.nth_power_scale)
        self.power_scale_spinBox.setDecimals(2)
        self.power_scale_spinBox.setSingleStep(0.05)
        self.power_scale_spinBox.setRange(0.0, 1.0)
        self.power_scale_spinBox.valueChanged.connect(self.onPowerScaleChanged)
        self.power_scale_spinBox.setEnabled(False)
        self.powerscaleLabel = QLabel()
        self.powerscaleLabel.setText("Power scale Factor")

        self.radii_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox)
        self.radii_scale = 1.0
        self.radii_scale_spinBox.setValue(self.radii_scale)
        self.radii_scale_spinBox.setDecimals(1)
        self.radii_scale_spinBox.setSingleStep(0.1)
        self.radii_scale_spinBox.setRange(0.2, 2.0)
        self.radii_scale_spinBox.valueChanged.connect(self.onRadiiScaleChanged)
        self.radiiscaleLabel = QLabel()
        self.radiiscaleLabel.setText("Linear Scale Factor")

        layout = QGridLayout()
        layout.addWidget(self.ManualPowerScalecheckbox, 1, 0, 1, 2)
        layout.addWidget(self.powerscaleLabel, 2, 0, 1, 2)
        layout.addWidget(self.power_scale_spinBox, 2, 1, 1, 2)
        layout.addWidget(self.radiiscaleLabel, 3, 0, 1, 2)
        layout.addWidget(self.radii_scale_spinBox, 3, 1, 1, 2)
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 0)
        self.RadiiScaleGroupBox.setLayout(layout)

    def createBinsBox(self):
        self.binstable = QTableWidget(0, 4)
        self.binstable_isready = False
        labels = [
            "no. of HKLs", "lower bin value", "upper bin value", "opacity"
        ]
        self.binstable.setHorizontalHeaderLabels(labels)
        self.binstable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        self.bindata_labeltxt = QLabel()
        self.bindata_labeltxt.setText("Data binned:")
        self.Nbins_spinBox = QSpinBox()
        self.Nbins_spinBox.setSingleStep(1)
        self.Nbins_spinBox.setRange(1, 40)
        self.Nbins_spinBox.valueChanged.connect(self.onNbinsChanged)
        self.Nbins_labeltxt = QLabel()
        self.Nbins_labeltxt.setText("Number of bins:")

        self.OpaqueAllCheckbox = QCheckBox()
        #self.OpaqueAllCheckbox.setTristate()
        self.OpaqueAllCheckbox.setText("Show all data in bins")
        self.OpaqueAllCheckbox.clicked.connect(self.onOpaqueAll)

        self.binstable.itemChanged.connect(self.onBinsTableItemChanged)
        self.binstable.itemSelectionChanged.connect(
            self.onBinsTableItemSelectionChanged)
        self.BinDataComboBox = QComboBox()
        self.BinDataComboBox.activated.connect(self.onBindataComboSelchange)
        self.BinsGroupBox = QGroupBox("Bins")
        layout = QGridLayout()
        layout.addWidget(self.bindata_labeltxt, 0, 0)
        layout.addWidget(self.BinDataComboBox, 0, 1)
        layout.addWidget(self.Nbins_labeltxt, 0, 2)
        layout.addWidget(self.Nbins_spinBox, 0, 3)
        layout.addWidget(self.OpaqueAllCheckbox, 1, 2)
        layout.addWidget(self.binstable, 2, 0, 1, 4)
        layout.setColumnStretch(0, 0)
        layout.setColumnStretch(1, 2)
        layout.setColumnStretch(3, 1)
        self.BinsGroupBox.setLayout(layout)

    def DebugInteractively(self):
        import code, traceback
        code.interact(local=locals(),
                      banner="".join(traceback.format_stack(limit=10)))

    def CreateFunctionTabs(self):
        self.functionTabWidget = QTabWidget()
        tab1 = QWidget()
        layout1 = QGridLayout()
        layout1.addWidget(self.ExpansionBox, 0, 0)
        layout1.setRowStretch(0, 0)
        tab1.setLayout(layout1)

        tab2 = QWidget()
        layout2 = QGridLayout()

        self.fixedorientcheckbox = QCheckBox(self.sliceTabWidget)
        self.fixedorientcheckbox.setText(
            "Fix orientation but allow zoom and translation")
        self.fixedorientcheckbox.clicked.connect(self.onFixedorient)
        layout2.addWidget(self.fixedorientcheckbox, 0, 0)

        layout2.addWidget(self.sliceTabWidget, 1, 0)
        tab2.setLayout(layout2)

        tab3 = QWidget()
        layout3 = QGridLayout()
        layout3.addWidget(self.RadiiScaleGroupBox, 0, 0)
        tab3.setLayout(layout3)

        tab4 = QWidget()
        layout4 = QGridLayout()
        layout4.addWidget(self.BinsGroupBox, 0, 0)
        tab4.setLayout(layout4)

        self.functionTabWidget.addTab(tab1, "Expand")
        self.functionTabWidget.addTab(tab2, "Slice")
        self.functionTabWidget.addTab(tab3, "Size")
        self.functionTabWidget.addTab(tab4, "Bins")
        self.functionTabWidget.setDisabled(True)

    def SpacegroupSelchange(self, i):
        self.NGL_HKL_command("NGL_HKLviewer.spacegroup_choice = %d" % i)

    def find_free_port(self):
        import socket
        s = socket.socket()
        s.bind(('', 0))  # Bind to a free port provided by the host.
        port = s.getsockname()[1]
        s.close()
        return port

    def LaunchCCTBXPython(self):
        self.sockport = self.find_free_port()
        self.zmq_context = zmq.Context()
        self.socket = self.zmq_context.socket(zmq.PAIR)
        self.socket.bind("tcp://127.0.0.1:%s" % self.sockport)
        try:
            msg = self.socket.recv(
                flags=zmq.NOBLOCK)  #To empty the socket from previous messages
        except Exception as e:
            pass
        cmdargs = 'cctbx.python.bat -i -c "from crys3d.hklview import cmdlineframes;' \
         + ' myHKLview = cmdlineframes.HKLViewFrame(useGuiSocket=%s, high_quality=True,' %self.sockport \
         + ' jscriptfname = \'%s\', ' %self.jscriptfname \
         + ' verbose=%s, UseOSBrowser= %s )"\n' %(self.verbose, str(self.UseOSbrowser))
        self.cctbxproc = subprocess.Popen(cmdargs,
                                          shell=True,
                                          stdin=subprocess.PIPE,
                                          stdout=sys.stdout,
                                          stderr=sys.stderr)
        #time.sleep(1)

    def NGL_HKL_command(self, cmdstr):
        #print("sending:\n" + cmdstr)
        self.socket.send(bytes(cmdstr, "utf-8"))
Example #23
0
    def onFunctionTecTree(self, item, column, function_ui, data,
                          hidden_columns):
        group_box = function_ui.findChild(QGroupBox, "parameter_box")
        display_name_box = function_ui.findChild(QLineEdit, "display_name")
        labels = group_box.findChildren(QLabel)
        spin_boxs = group_box.findChildren(QSpinBox)
        for label in labels:
            label.close()
        for spin_box in spin_boxs:
            spin_box.close()
        text = item.text(column)

        if text in talib.get_function_groups().keys():
            return
        indicator = abstract.Function(text.lower())
        info = indicator.info
        display_name = info.get("display_name", "")
        display_name_box.setText(display_name)

        params_dict = indicator.get_parameters()
        keys = list(params_dict.keys())
        keys.insert(0, u"Column")
        locator = 20
        num = 0
        paras_locators = [locator + i * 30 for i in range(len(keys))]
        for key in keys:
            p = paras_locators[num]
            label = QLabel(group_box)
            label.setText(key)
            label.setGeometry(10, p, 100, 20)
            if key == "Column":
                combo_box = QComboBox(group_box)
                combo_box.setGeometry(100, p, 100, 20)
                combo_box.setObjectName(key)
                combo_box.setWhatsThis(key)
                columns = [
                    i for i in list(data.columns) if i not in hidden_columns
                ]
                combo_box.addItems(columns)
                if "close" in columns:
                    combo_box.setCurrentText("close")
                combo_box.show()
            else:
                spin_box = QSpinBox(group_box)
                spin_box.setGeometry(100, p, 50, 20)
                spin_box.setObjectName(text)
                spin_box.setWhatsThis(key)
                value = params_dict[key]
                spin_box.setValue(value)
                spin_box.show()
            label.show()

            num += 1
Example #24
0
class MixedDistributionChart(QDialog):
    def __init__(self, parent=None, show_mode=True, toolbar=False, use_animation=False):
        flags = Qt.Window | Qt.WindowTitleHint | Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint
        super().__init__(parent=parent, f=flags)
        self.setWindowTitle(self.tr("Mixed Distribution Chart"))
        self.figure = plt.figure(figsize=(4, 3))
        self.axes = self.figure.subplots()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.main_layout = QGridLayout(self)
        self.main_layout.addWidget(self.toolbar, 0, 0, 1, 2)
        self.main_layout.addWidget(self.canvas, 1, 0, 1, 2)
        if not toolbar:
            self.toolbar.hide()
        self.supported_scales = [("log-linear", self.tr("Log-linear")),
                                 ("log", self.tr("Log")),
                                 ("phi", self.tr("φ")),
                                 ("linear", self.tr("Linear"))]

        self.scale_label = QLabel(self.tr("Scale"))
        self.scale_combo_box = QComboBox()
        self.scale_combo_box.addItems([name for key, name in self.supported_scales])
        self.scale_combo_box.currentIndexChanged.connect(self.update_chart)
        self.main_layout.addWidget(self.scale_label, 2, 0)
        self.main_layout.addWidget(self.scale_combo_box, 2, 1)
        self.interval_label = QLabel(self.tr("Interval [ms]"))
        self.interval_input = QSpinBox()
        self.interval_input.setRange(0, 10000)
        self.interval_input.setValue(30)
        self.interval_input.valueChanged.connect(self.update_animation)
        self.main_layout.addWidget(self.interval_label, 3, 0)
        self.main_layout.addWidget(self.interval_input, 3, 1)
        self.repeat_check_box = QCheckBox(self.tr("Repeat"))
        self.repeat_check_box.setChecked(False)
        self.repeat_check_box.stateChanged.connect(self.update_animation)
        self.save_button = QPushButton(self.tr("Save"))
        self.save_button.clicked.connect(self.save_animation)
        self.main_layout.addWidget(self.repeat_check_box, 4, 0)
        self.main_layout.addWidget(self.save_button, 4, 1)
        self.show_mode = show_mode
        self.animation = None
        self.last_model = None
        self.last_result = None

        if not use_animation:
            self.interval_label.setVisible(False)
            self.interval_input.setVisible(False)
            self.repeat_check_box.setVisible(False)
            self.save_button.setVisible(False)

        self.normal_msg = QMessageBox(parent=self)
        self.file_dialog = QFileDialog(parent=self)

    @property
    def scale(self) -> str:
        index = self.scale_combo_box.currentIndex()
        key, name = self.supported_scales[index]
        return key

    @property
    def transfer(self) -> typing.Callable:
        if self.scale == "log-linear":
            return lambda classes_φ: convert_φ_to_μm(classes_φ)
        elif self.scale == "log":
            return lambda classes_φ: np.log(convert_φ_to_μm(classes_φ))
        elif self.scale == "phi":
            return lambda classes_φ: classes_φ
        elif self.scale == "linear":
            return lambda classes_φ: convert_φ_to_μm(classes_φ)

    @property
    def xlabel(self) -> str:
        if self.scale == "log-linear":
            return self.tr("Grain-size [μm]")
        elif self.scale == "log":
            return self.tr("Ln(grain-size in μm)")
        elif self.scale == "phi":
            return self.tr("Grain-size [φ]")
        elif self.scale == "linear":
            return self.tr("Grain-size [μm]")

    @property
    def ylabel(self) -> str:
        return self.tr("Frequency")

    @property
    def xlog(self) -> bool:
        if self.scale == "log-linear":
            return True
        else:
            return False

    @property
    def interval(self) -> float:
        return self.interval_input.value()

    @property
    def repeat(self) -> bool:
        return self.repeat_check_box.isChecked()

    def show_demo(self):
        demo_model = get_demo_view_model()
        self.show_model(demo_model)

    def update_chart(self):
        if self.last_model is not None:
            self.show_model(self.last_model)
        elif self.last_result is not None:
            self.show_result(self.last_result)

    def update_animation(self):
        if self.last_result is not None:
            self.show_result(self.last_result)

    def show_model(self, model: SSUViewModel, quick=False):
        if self.animation is not None:
            self.animation._stop()
            self.animation = None
        if not quick:
            self.last_result = None

            self.last_model = model
            self.interval_label.setEnabled(False)
            self.interval_input.setEnabled(False)
            self.repeat_check_box.setEnabled(False)
            self.save_button.setEnabled(False)

            self.axes.clear()
            x = self.transfer(model.classes_φ)
            if self.xlog:
                self.axes.set_xscale("log")
            self.axes.set_title(model.title)
            self.axes.set_xlabel(self.xlabel)
            self.axes.set_ylabel(self.ylabel)
            self.target = self.axes.plot(x, model.target, c="#ffffff00", marker=".", ms=8, mfc="black", mew=0.0, label=self.tr("Target"))[0]
            # scatter can not be modified from the tool bar
            # self.target = self.axes.scatter(x, model.target, c="black", s=1)
            self.axes.set_xlim(x[0], x[-1])
            self.axes.set_ylim(0.0, round(np.max(model.target)*1.2, 2))
            self.mixed = self.axes.plot(x, model.mixed, c="black", label=self.tr("Mixed"))[0]
            self.components = [self.axes.plot(x, distribution*fraction, c=plt.get_cmap()(i), label=model.component_prefix+str(i+1))[0] for i, (distribution, fraction) in enumerate(zip(model.distributions, model.fractions))]
            if self.show_mode:
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                colors = [plt.get_cmap()(i) for i in range(model.n_components)]
                self.vlines = self.axes.vlines(modes, 0.0, round(np.max(model.target)*1.2, 2), colors=colors)
            if model.n_components < 6:
                self.axes.legend(loc="upper left")
            self.figure.tight_layout()
            self.canvas.draw()
        else:
            self.mixed.set_ydata(model.mixed)
            for comp, distribution, fraction in zip(self.components, model.distributions, model.fractions):
                comp.set_ydata(distribution*fraction)
            if self.show_mode:
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                self.vlines.set_offsets(modes)
            self.canvas.draw()

    def show_result(self, result: SSUResult):
        if self.animation is not None:
            self.animation._stop()
            self.animation = None
        self.last_model = None
        self.last_result = result
        self.interval_label.setEnabled(True)
        self.interval_input.setEnabled(True)
        self.repeat_check_box.setEnabled(True)
        self.save_button.setEnabled(True)

        models = iter(result.view_models)
        first = next(models)
        x = self.transfer(first.classes_φ)
        self.axes.cla()
        if self.xlog:
            self.axes.set_xscale("log")
        self.axes.set_title(first.title)
        self.axes.set_xlabel(self.xlabel)
        self.axes.set_ylabel(self.ylabel)
        self.target = self.axes.plot(x, first.target, c="#ffffff00", marker=".", ms=8, mfc="black", mew=0.0)[0]
        self.axes.set_xlim(x[0], x[-1])
        self.axes.set_ylim(0.0, round(np.max(first.target)*1.2, 2))
        self.figure.tight_layout()
        # self.canvas.draw()
        colors = [plt.get_cmap()(i) for i in range(first.n_components)]
        def init():
            model = first
            self.mixed = self.axes.plot(x, model.mixed, c="black")[0]
            self.components = [self.axes.plot(x, distribution*fraction, c=plt.get_cmap()(i))[0] for i, (distribution, fraction) in enumerate(zip(model.distributions, model.fractions))]
            if self.show_mode:
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                self.vlines = self.axes.vlines(modes, 0.0, round(np.max(model.target)*1.2, 2), colors=colors)
            return self.mixed, self.vlines, *self.components
        def animate(current):
            model = current
            self.mixed.set_ydata(current.mixed)
            for line, distribution, fraction in zip(self.components, model.distributions, model.fractions):
                line.set_ydata(distribution*fraction)
            if self.show_mode:
                self.vlines.remove()
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                self.vlines = self.axes.vlines(modes, 0.0, round(np.max(model.target)*1.2, 2), colors=colors)
            return self.mixed, self.vlines, *self.components
        self.animation = FuncAnimation(self.figure, animate, frames=models, init_func=init,
                                       interval=self.interval, blit=True,
                                       repeat=self.repeat, repeat_delay=3.0, save_count=result.n_iterations)

    def save_animation(self):
        if self.last_result is not None:
            filename, format_str = self.file_dialog.getSaveFileName(self, self.tr("Save the animation of this SSU result"), None, self.tr("MPEG-4 Video File (*.mp4);;Graphics Interchange Format (*.gif)"))
            if filename is None or filename == "":
                return
            progress = QProgressDialog(self)
            progress.setRange(0, 100)
            progress.setLabelText(self.tr("Saving Animation [{0} Frames]").format(self.last_result.n_iterations))
            canceled = False
            def save_callback(i, n):
                if progress.wasCanceled():
                    nonlocal canceled
                    canceled = True
                    raise StopIteration()
                progress.setValue((i+1)/n*100)
                QCoreApplication.processEvents()
            self.show_result(self.last_result)
            # plt.rcParams["savefig.dpi"] = 120.0
            if "*.gif" in format_str:
                if not ImageMagickWriter.isAvailable():
                    self.normal_msg.setWindowTitle(self.tr("Error"))
                    self.normal_msg.setText(self.tr("ImageMagick is not installed, please download and install it from its offical website (https://imagemagick.org/index.php)."))
                    self.normal_msg.exec_()
                else:
                    self.animation.save(filename, writer="imagemagick", fps=30, progress_callback=save_callback)
            elif "*.mp4" in format_str:
                if not FFMpegWriter.isAvailable():
                    self.normal_msg.setWindowTitle(self.tr("Error"))
                    self.normal_msg.setText(self.tr("FFMpeg is not installed, please download and install it from its offical website (https://ffmpeg.org/)."))
                    self.normal_msg.exec_()
                else:
                    self.animation.save(filename, writer="ffmpeg", fps=30, progress_callback=save_callback)
            # plt.rcParams["savefig.dpi"] = 300.0
            if not canceled:
                progress.setValue(100)
Example #25
0
class StreamFieldsWidget(QDialog):
    """
    A stream widget containing schema-specific properties.
    """
    def __init__(self, parent, show_only_f142_stream: bool = False):
        super().__init__()
        self.setParent(parent)
        self.setLayout(QGridLayout())
        self.setWindowModality(Qt.WindowModal)
        self.setModal(True)

        self._show_only_f142_stream = show_only_f142_stream
        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 = DropDownList()
        self.schema_validator = SchemaSelectionValidator()
        self.schema_combo.setValidator(self.schema_validator)
        self.schema_validator.is_valid.connect(
            partial(validate_general_widget, self.schema_combo))

        self.topic_label = QLabel("Topic: ")
        self.topic_line_edit = QLineEdit()
        self.topic_validator = NoEmptyStringValidator()
        self.topic_line_edit.setValidator(self.topic_validator)
        self.topic_validator.is_valid.connect(
            partial(
                validate_line_edit,
                self.topic_line_edit,
                tooltip_on_reject="Topic name can not be empty.",
            ))
        validate_line_edit(self.topic_line_edit, False)

        self.source_label = QLabel("Source: ")
        self.source_line_edit = QLineEdit()
        self.source_validator = NoEmptyStringValidator()
        self.source_line_edit.setValidator(self.source_validator)
        self.source_validator.is_valid.connect(
            partial(
                validate_line_edit,
                self.source_line_edit,
                tooltip_on_reject="Source name can not be empty.",
            ))
        validate_line_edit(self.source_line_edit, False)

        self.array_size_label = QLabel("Array size: ")
        self.array_size_spinbox = QSpinBox()
        self.array_size_spinbox.setMaximum(np.iinfo(np.int32).max)

        self.array_size_table = QTableWidget(1, 3)
        self.array_size_table.setHorizontalHeaderLabels(["x", "y", "z"])
        self.array_size_table.setVerticalHeaderLabels([""])
        table_height = self.array_size_table.sizeHintForRow(
            0) + self.array_size_table.sizeHintForRow(1)
        self.array_size_table.setMaximumHeight(table_height)
        self.array_size_table.setFrameStyle(QFrame.NoFrame)
        self.array_size_table.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.array_size_table.resizeColumnsToContents()
        self.array_size_table.resizeRowsToContents()
        self.array_size_table.setItemDelegate(
            ValueDelegate(int, self.array_size_table))

        self.type_label = QLabel("Type: ")
        self.type_combo = QComboBox()
        self.type_combo.addItems(F142_TYPES)
        self.type_combo.setCurrentText("double")

        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)
        if self._show_only_f142_stream:
            self.schema_combo.addItems([StreamModules.F142.value])
        else:
            self.schema_combo.addItems([e.value for e in StreamModules])

        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.array_size_table, 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())
        self.parent().parent().field_name_edit.setVisible(False)

    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_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.ev42_chunk_size_spinner = (
            self.create_label_and_spinbox_for_advanced_option(
                CHUNK_SIZE, self.ev42_advanced_group_box))
        self.ev42_cue_interval_spinner = (
            self.create_label_and_spinbox_for_advanced_option(
                CUE_INTERVAL, self.ev42_advanced_group_box))

    def create_label_and_spinbox_for_advanced_option(self, nexus_string: str,
                                                     group_box: QGroupBox):
        """
        Creates a SpinBox with a label and adds them to GroupBox then returns the SpinBox.
        :param nexus_string: The nexus string label for the SpinBox.
        :param group_box: The GroupBox that the label and SpinBox should be added to.
        :return: The newly created SpinBox.
        """
        label = QLabel(nexus_string)
        spinner = QSpinBox()
        spinner.setRange(self.minimum_spinbox_value,
                         self.maximum_spinbox_value)
        group_box.layout().addRow(label, spinner)

        return 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_chunk_size_spinner = (
            self.create_label_and_spinbox_for_advanced_option(
                CHUNK_SIZE, self.f142_advanced_group_box))
        self.f142_cue_interval_spinner = (
            self.create_label_and_spinbox_for_advanced_option(
                CUE_INTERVAL, self.f142_advanced_group_box))

    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)
        self.array_size_table.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.ADAR.value:
            self._set_edits_visible(True, False)
            self._show_array_size_table(True)
        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 _show_array_size_table(self, show: bool):
        self.array_size_label.setVisible(show)
        self.array_size_table.setVisible(show)

    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_module(self, parent) -> StreamModule:
        """
        Create the stream module
        :return: The created stream module
        """

        source = self.source_line_edit.text()
        topic = self.topic_line_edit.text()
        stream: StreamModule = None
        type = self.type_combo.currentText()
        current_schema = self.schema_combo.currentText()
        if current_schema == WriterModules.F142.value:
            value_units = self.value_units_edit.text()
            array_size = self.array_size_spinbox.value()
            stream = F142Stream(
                parent_node=parent,
                source=source,
                topic=topic,
                type=type,
                value_units=value_units,
                array_size=array_size,
            )
            if array_size:
                stream.array_size = array_size
            if self.advanced_options_enabled:
                self.record_advanced_f142_values(stream)
        elif current_schema == WriterModules.ADAR.value:
            array_size = []
            for i in range(self.array_size_table.columnCount()):
                table_value = self.array_size_table.item(0, i)
                if table_value:
                    array_size.append(int(table_value.text()))
            stream = ADARStream(parent_node=parent, source=source, topic=topic)
            stream.array_size = array_size
        elif current_schema == WriterModules.EV42.value:
            stream = EV42Stream(parent_node=parent, source=source, topic=topic)
            if self.advanced_options_enabled:
                self.record_advanced_ev42_values(stream)
        elif current_schema == WriterModules.NS10.value:
            stream = NS10Stream(parent_node=parent, source=source, topic=topic)
        elif current_schema == WriterModules.SENV.value:
            stream = SENVStream(parent_node=parent, source=source, topic=topic)
        elif current_schema == WriterModules.HS00.value:
            stream = HS00Stream(  # type: ignore
                parent=parent,
                source=source,
                topic=topic,
                data_type=NotImplemented,
                edge_type=NotImplemented,
                error_type=NotImplemented,
                shape=[],
            )
        elif current_schema == WriterModules.TDCTIME.value:
            stream = TDCTStream(parent_node=parent, source=source, topic=topic)

        return stream

    def record_advanced_f142_values(self, stream: F142Stream):
        """
        Save the advanced f142 properties to the stream data object.
        :param stream: The stream data object to be modified.
        """
        stream.chunk_size = self.f142_chunk_size_spinner.value()
        stream.cue_interval = self.f142_cue_interval_spinner.value()

    def record_advanced_ev42_values(self, stream: EV42Stream):
        """
        Save the advanced ev42 properties to the stream data object.
        :param stream: The stream data object to be modified.
        """
        stream.adc_pulse_debug = self.ev42_adc_pulse_debug_checkbox.isChecked()
        stream.chunk_size = self.ev42_chunk_size_spinner.value()
        stream.cue_interval = self.ev42_cue_interval_spinner.value()

    def fill_in_existing_ev42_fields(self, field: EV42Stream):
        """
        Fill in specific existing ev42 fields into the new UI field.
        :param field: The stream group
        """
        if check_if_advanced_options_should_be_enabled(
            [field.adc_pulse_debug, field.chunk_size, field.cue_interval]):
            self._show_advanced_options(True)
            self._fill_existing_advanced_ev42_fields(field)

    def _fill_existing_advanced_ev42_fields(self, field: EV42Stream):
        """
        Fill the fields in the interface with the existing ev42 stream data.
        :param field: The ev42 stream data object.
        """
        self.ev42_adc_pulse_debug_checkbox.setChecked(field.adc_pulse_debug)
        self.ev42_chunk_size_spinner.setValue(field.chunk_size)
        self.ev42_cue_interval_spinner.setValue(field.cue_interval)

    def fill_in_existing_f142_fields(self, field: F142Stream):
        """
        Fill in specific existing f142 fields into the new UI field.
        :param field: The stream group
        """
        self.type_combo.setCurrentText(field.type)
        if field.array_size is not None:
            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 field.value_units is not None:
            self.value_units_edit.setText(field.value_units)

        if check_if_advanced_options_should_be_enabled(
            [field.chunk_size, field.cue_interval]):
            self._show_advanced_options(True)
            self._fill_existing_advanced_f142_fields(field)

    def _fill_existing_advanced_f142_fields(self, field: F142Stream):
        """
        Fill the advanced fields in the interface with the existing f142 stream data.
        :param field: The f412 stream data object.
        """
        self.f142_chunk_size_spinner.setValue(field.chunk_size)
        self.f142_cue_interval_spinner.setValue(field.cue_interval)

    def update_existing_stream_info(self, field):
        """
        Fill in stream fields and properties into the new UI field.
        :param field: The stream group
        """
        if isinstance(field, Group):
            field = field.children[0]
        if hasattr(field, "parent_node") and isinstance(
                field.parent_node, Group):
            self.schema_validator.set_group(field.parent_node)
        else:
            self.schema_validator.set_group(None)
        schema = field.writer_module
        self.schema_combo.setCurrentText(schema)
        self.schema_validator.validate(schema, 0)
        self.topic_line_edit.setText(field.topic)
        self.topic_validator.validate(field.topic, 0)
        self.source_line_edit.setText(field.source)
        self.source_validator.validate(field.source, 0)
        if schema == WriterModules.F142.value:
            self.fill_in_existing_f142_fields(field)
        elif schema == WriterModules.EV42.value:
            self.fill_in_existing_ev42_fields(field)
        elif schema == WriterModules.ADAR.value:
            for i, val in enumerate(field.array_size):
                self.array_size_table.setItem(0, i, QTableWidgetItem(str(val)))
Example #26
0
    def _create_ammo_pickup_boxes(self, size_policy,
                                  item_database: ItemDatabase):
        """
        Creates the GroupBox with SpinBoxes for selecting the pickup count of all the ammo
        :param item_database:
        :return:
        """

        self._ammo_maximum_spinboxes = collections.defaultdict(list)
        self._ammo_pickup_widgets = {}

        resource_database = default_database.resource_database_for(self.game)
        broad_to_category = {
            ItemCategory.BEAM_RELATED: ItemCategory.BEAM,
            ItemCategory.MORPH_BALL_RELATED: ItemCategory.MORPH_BALL,
            ItemCategory.MISSILE_RELATED: ItemCategory.MISSILE,
        }

        for ammo in item_database.ammo.values():
            category_box, category_layout, _ = self._boxes_for_category[
                broad_to_category[ammo.broad_category]]

            pickup_box = QGroupBox(category_box)
            pickup_box.setSizePolicy(size_policy)
            pickup_box.setTitle(ammo.name + "s")
            layout = QGridLayout(pickup_box)
            layout.setObjectName(f"{ammo.name} Box Layout")
            current_row = 0

            for ammo_item in ammo.items:
                item = resource_database.get_by_type_and_index(
                    ResourceType.ITEM, ammo_item)

                target_count_label = QLabel(pickup_box)
                target_count_label.setText(f"{item.long_name} Target" if len(
                    ammo.items) > 1 else "Target count")

                maximum_spinbox = QSpinBox(pickup_box)
                maximum_spinbox.setMaximum(ammo.maximum)
                maximum_spinbox.valueChanged.connect(
                    partial(self._on_update_ammo_maximum_spinbox, ammo_item))
                self._ammo_maximum_spinboxes[ammo_item].append(maximum_spinbox)

                layout.addWidget(target_count_label, current_row, 0)
                layout.addWidget(maximum_spinbox, current_row, 1)
                current_row += 1

            count_label = QLabel(pickup_box)
            count_label.setText("Pickup Count")
            count_label.setToolTip(
                "How many instances of this expansion should be placed.")

            pickup_spinbox = QSpinBox(pickup_box)
            pickup_spinbox.setMaximum(AmmoState.maximum_pickup_count())
            pickup_spinbox.valueChanged.connect(
                partial(self._on_update_ammo_pickup_spinbox, ammo))

            layout.addWidget(count_label, current_row, 0)
            layout.addWidget(pickup_spinbox, current_row, 1)
            current_row += 1

            if ammo.temporaries:
                require_major_item_check = QCheckBox(pickup_box)
                require_major_item_check.setText(
                    "Requires the major item to work?")
                require_major_item_check.stateChanged.connect(
                    partial(self._on_update_ammo_require_major_item, ammo))
                layout.addWidget(require_major_item_check, current_row, 0, 1,
                                 2)
                current_row += 1
            else:
                require_major_item_check = None

            expected_count = QLabel(pickup_box)
            expected_count.setWordWrap(True)
            expected_count.setText(_EXPECTED_COUNT_TEXT_TEMPLATE)
            expected_count.setToolTip(
                "Some expansions may provide 1 extra, even with no variance, if the total count "
                "is not divisible by the pickup count.")
            layout.addWidget(expected_count, current_row, 0, 1, 2)
            current_row += 1

            self._ammo_pickup_widgets[ammo] = AmmoPickupWidgets(
                pickup_spinbox, expected_count, pickup_box,
                require_major_item_check)
            category_layout.addWidget(pickup_box)
Example #27
0
    def __init__(self, parent, show_only_f142_stream: bool = False):
        super().__init__()
        self.setParent(parent)
        self.setLayout(QGridLayout())
        self.setWindowModality(Qt.WindowModal)
        self.setModal(True)

        self._show_only_f142_stream = show_only_f142_stream
        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 = DropDownList()
        self.schema_validator = SchemaSelectionValidator()
        self.schema_combo.setValidator(self.schema_validator)
        self.schema_validator.is_valid.connect(
            partial(validate_general_widget, self.schema_combo))

        self.topic_label = QLabel("Topic: ")
        self.topic_line_edit = QLineEdit()
        self.topic_validator = NoEmptyStringValidator()
        self.topic_line_edit.setValidator(self.topic_validator)
        self.topic_validator.is_valid.connect(
            partial(
                validate_line_edit,
                self.topic_line_edit,
                tooltip_on_reject="Topic name can not be empty.",
            ))
        validate_line_edit(self.topic_line_edit, False)

        self.source_label = QLabel("Source: ")
        self.source_line_edit = QLineEdit()
        self.source_validator = NoEmptyStringValidator()
        self.source_line_edit.setValidator(self.source_validator)
        self.source_validator.is_valid.connect(
            partial(
                validate_line_edit,
                self.source_line_edit,
                tooltip_on_reject="Source name can not be empty.",
            ))
        validate_line_edit(self.source_line_edit, False)

        self.array_size_label = QLabel("Array size: ")
        self.array_size_spinbox = QSpinBox()
        self.array_size_spinbox.setMaximum(np.iinfo(np.int32).max)

        self.array_size_table = QTableWidget(1, 3)
        self.array_size_table.setHorizontalHeaderLabels(["x", "y", "z"])
        self.array_size_table.setVerticalHeaderLabels([""])
        table_height = self.array_size_table.sizeHintForRow(
            0) + self.array_size_table.sizeHintForRow(1)
        self.array_size_table.setMaximumHeight(table_height)
        self.array_size_table.setFrameStyle(QFrame.NoFrame)
        self.array_size_table.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.array_size_table.resizeColumnsToContents()
        self.array_size_table.resizeRowsToContents()
        self.array_size_table.setItemDelegate(
            ValueDelegate(int, self.array_size_table))

        self.type_label = QLabel("Type: ")
        self.type_combo = QComboBox()
        self.type_combo.addItems(F142_TYPES)
        self.type_combo.setCurrentText("double")

        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)
        if self._show_only_f142_stream:
            self.schema_combo.addItems([StreamModules.F142.value])
        else:
            self.schema_combo.addItems([e.value for e in StreamModules])

        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.array_size_table, 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())
        self.parent().parent().field_name_edit.setVisible(False)
Example #28
0
    def init_ui(self):
        self.setFixedWidth(500)
        self.setWindowTitle(_('Event properties'))
        self.setWindowIcon(QIcon(config.ICON))
        self.setSizeGripEnabled(False)
        self.setModal(True)

        self.layout = QFormLayout(self)

        self.label_main_title = QLabel(_('Main title'))
        self.item_main_title = QLineEdit()
        self.layout.addRow(self.label_main_title, self.item_main_title)

        self.label_sub_title = QLabel(_('Sub title'))
        self.item_sub_title = QTextEdit()
        self.item_sub_title.setMaximumHeight(100)
        self.layout.addRow(self.label_sub_title, self.item_sub_title)

        self.label_start_date = QLabel(_('Start date'))
        self.item_start_date = QDateTimeEdit()
        self.item_start_date.setDisplayFormat('yyyy.MM.dd HH:mm:ss')
        self.layout.addRow(self.label_start_date, self.item_start_date)

        self.label_end_date = QLabel(_('End date'))
        # self.item_end_date = QCalendarWidget()
        self.item_end_date = QDateTimeEdit()
        self.item_end_date.setDisplayFormat('yyyy.MM.dd HH:mm:ss')
        self.layout.addRow(self.label_end_date, self.item_end_date)

        self.label_location = QLabel(_('Location'))
        self.item_location = QLineEdit()
        self.layout.addRow(self.label_location, self.item_location)

        self.label_type = QLabel(_('Event type'))
        self.item_type = AdvComboBox()
        self.item_type.addItems(RaceType.get_titles())
        self.layout.addRow(self.label_type, self.item_type)

        self.label_relay_legs = QLabel(_('Relay legs'))
        self.item_relay_legs = QSpinBox()
        self.item_relay_legs.setMinimum(1)
        self.item_relay_legs.setMaximum(20)
        self.item_relay_legs.setValue(3)
        self.layout.addRow(self.label_relay_legs, self.item_relay_legs)

        self.item_type.currentTextChanged.connect(self.change_type)

        self.label_refery = QLabel(_('Chief referee'))
        self.item_refery = QLineEdit()
        self.layout.addRow(self.label_refery, self.item_refery)

        self.label_secretary = QLabel(_('Secretary'))
        self.item_secretary = QLineEdit()
        self.layout.addRow(self.label_secretary, self.item_secretary)

        self.label_url = QLabel(_('URL'))
        self.item_url = QLineEdit()
        self.layout.addRow(self.label_url, self.item_url)

        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.set_values_from_model()

        self.show()
Example #29
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        parameters = {
            'Gain Scheduling': {
                'GS': 'Gain scheduling',
                'AS': 'Active Set',
                'B12': 'Boundary 1/2',
                'B23': 'Boundary 2/3'
            },
            'Set 1': {
                'P1': 'Proportional 1',
                'I1': 'Integral 1',
                'D1': 'Derivative 1'
            },
            'Set 2': {
                'P2': 'Proportional 2',
                'I2': 'Integral 2',
                'D2': 'Derivative 2'
            },
            'Set 3': {
                'P3': 'Proportional 3',
                'I3': 'Integral 3',
                'D3': 'Derivative 3'
            }
        }

        self.units = {
            'I1': ' s',
            'I2': ' s',
            'I3': ' s',
            'D1': ' s',
            'D2': ' s',
            'D3': ' s'
        }
        self.entries = {
            key: QComboBox() if key == 'GS' else
            QSpinBox(minimum=1, maximum=3) if key == 'AS' else QDoubleSpinBox(
                decimals=0, singleStep=10, minimum=0, maximum=100000)
            for subset in parameters for key in parameters[subset]
        }
        self.entries['GS'].addItems(
            ['None', 'Set', 'Process Variable', 'Setpoint', 'Output'])

        for entry, suffix in self.units.items():
            self.entries[entry].setSuffix(suffix)

        vbox = QVBoxLayout()
        vbox.setSpacing(0)
        vbox.setContentsMargins(10, 10, 10, 10)
        for subset in parameters:
            label = QLabel(text=subset, objectName='Header')
            vbox.addWidget(label)
            vbox.addSpacing(10)
            form = QFormLayout()
            form.setSpacing(5)
            form.setHorizontalSpacing(20)
            form.setContentsMargins(0, 0, 0, 0)
            for key in parameters[subset]:
                form.addRow(parameters[subset][key], self.entries[key])
            vbox.addLayout(form)
            vbox.addSpacing(20)

        refresh_button = QPushButton(text='Refresh', objectName='Refresh')
        refresh_button.clicked.connect(
            lambda: pubsub.pub.sendMessage('gui.request.pid_parameters'))
        vbox.addWidget(refresh_button)

        vbox.addStretch()
        self.setLayout(vbox)

        for key, entry in self.entries.items():
            if key == 'GS':
                entry.currentTextChanged.connect(
                    functools.partial(self.set_pid_parameter, control=key))
            else:
                entry.setKeyboardTracking(False)
                entry.valueChanged.connect(
                    functools.partial(self.set_pid_parameter, control=key))

        pubsub.pub.subscribe(self.update_pid_parameters,
                             'engine.answer.pid_parameters')
Example #30
0
 def setUp(self):
     super(SpinBoxPySignal, self).setUp()
     self.obj = Dummy()
     self.spin = QSpinBox()
     self.spin.setValue(0)
Example #31
0
class AcquistoForm(QDialog):
    '''
    Widget per l'inserimento di un acquisto immediato.
    '''
    def __init__(self, conn):
        '''
        Parameters:
            conn : connection
                Connection to the database.
        '''
        super().__init__()
        self.setWindowTitle('Aggiungi Acquisto')
        self.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, False)

        self.conn = conn
        self.cursor = conn.cursor()

        self.books = dict()
        self.books_qt = dict()

        self.gen_layout = QVBoxLayout()

        self.form_layout = QFormLayout()
        self.form_layout.setRowWrapPolicy(QFormLayout.WrapLongRows)

        # Widgets
        self.client_field = QLineEdit()
        self.form_layout.addRow('Numero Cliente (facoltativo): ',
                                self.client_field)

        self.dip_field = QLineEdit()
        self.form_layout.addRow('Dipendente (CF): ', self.dip_field)

        self.date_picker = QDateEdit(QDate.currentDate())
        self.date_picker.setDisplayFormat("MM/dd/yyyy")
        self.date_picker.setCalendarPopup(True)
        self.form_layout.addRow('Data (mm/gg/aaaa): ', self.date_picker)

        self.importo_field = QDoubleSpinBox()
        self.importo_field.setMaximum(999999999.99)
        self.form_layout.addRow('Importo: ', self.importo_field)

        self.ins_layout = QHBoxLayout()
        self.libro_field = QLineEdit()
        self.quantita_field = QSpinBox()
        self.quantita_field.setMinimum(1)
        self.libro_button = QPushButton('Aggiungi')
        self.libro_button.clicked.connect(self.aggiungi_libro)
        self.ins_layout.addWidget(QLabel('Libro (ISBN): '))
        self.ins_layout.addWidget(self.libro_field)
        self.ins_layout.addWidget(QLabel('Quantità: '))
        self.ins_layout.addWidget(self.quantita_field)
        self.ins_layout.addWidget(self.libro_button)

        self.labels = ['ISBN', 'Quantità', '']
        self.table = QTableWidget(0, 3)
        self.table.setHorizontalHeaderLabels(self.labels)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self.confirm_button = QPushButton('Conferma')
        self.confirm_button.clicked.connect(self.post_acquisto)

        self.gen_layout.addLayout(self.form_layout)
        self.gen_layout.addLayout(self.ins_layout)
        self.gen_layout.addWidget(self.table)
        self.gen_layout.addWidget(self.confirm_button)
        self.setLayout(self.gen_layout)

    def aggiungi_libro(self):
        self.books[self.libro_field.text()] = self.quantita_field.value()
        self.update_table()

    def remove_libro(self, book):
        self.books.pop(book, None)
        self.update_table()

    def update_table(self):
        self.table.clearContents()
        while self.table.rowCount() > 0:
            self.table.removeRow(0)
        for book in self.books.keys():
            row = self.table.rowCount()
            button = QPushButton('Rimuovi')
            button.clicked.connect(lambda: self.remove_libro(book))
            self.table.insertRow(row)
            self.table.setItem(row, 0, QTableWidgetItem(book))
            self.table.setItem(row, 1, QTableWidgetItem(str(self.books[book])))
            self.table.setCellWidget(row, 2, button)

    def verif_qty(self):
        '''
        Shows error messages based on the validity of inserted books, and
        returns False, or returns True if all the books are ok to sell right now.
        '''
        if len(self.books.items()) == 0:
            self._show_error('Non ci sono libri nell\'acquisto')
            return 1
        for book, qty in self.books.items():
            self.cursor.execute(FIND_QUANTITA, (book, ))
            result = self.cursor.fetchall()
            if not result:
                self._show_error('\'{}\' non è un libro valido.'.format(book))
                return 2
            stored = result[0][0]
            if stored < qty:
                return self.__show_are_you_sure(
                    'L\'acquisto richiede {} libri {}, ma ne sono presenti solo {}.\nNon sarà possibile sottrarre i libri acquistati.\nVuoi proseguire ugualmente?'
                    .format(qty, book, stored))
        return 0

    def verif_client_dip(self):
        '''
        Returns false and displays and error message if cliente and dipendente are
        not valid tuples in the database, returns true if they are ok
        '''
        cliente = self.client_field.text()
        if cliente:
            if not cliente.isdigit():
                self._show_error('Il codice del Cliente deve essere numerico.')
                return 1
            self.cursor.execute(FIND_CLIENTE, (cliente, ))
            result = self.cursor.fetchall()
            if not result or not result[0][0]:
                self._show_error('Cliente {} non esiste.'.format(cliente))
                return 2

        dipendente = self.dip_field.text()
        if not dipendente:
            self._show_error('Il Dipendente non può essere vuoto.')
            return 3
        self.cursor.execute(FIND_DIPENDENTE, (dipendente, ))
        result = self.cursor.fetchall()
        if not result or not result[0][0]:
            self._show_error('Dipendente {} non esiste.'.format(dipendente))
            return 4
        return 0

    def post_acquisto(self):
        if self.verif_client_dip():
            return
        should_show = self.verif_qty()
        if should_show > 0:
            return
        cliente = self.client_field.text().strip() if self.client_field.text(
        ).strip() else None
        importo = self.importo_field.value()
        self.cursor.execute(
            INSERT_ACQUISTO,
            (self.date_picker.date().toString('MM/dd/yyyy'),
             self.importo_field.value(), self.dip_field.text()))
        new_id = self.cursor.fetchall()[0][0]
        self.cursor.execute(INSERT_IMMEDIATO, (new_id, cliente))
        for book in self.books.keys():
            self.cursor.execute(INSERT_COMPRENDE,
                                (new_id, book, self.books[book]))
        self.conn.commit()
        if should_show == 0: self._show_confirm()
        self.accept()

    def __show_are_you_sure(self, msg=''):
        dialog = _AreYouSureDialog(msg)
        dialog.setWindowTitle('ATTENZIONE')
        result = dialog.exec_()
        return -1 if result == QDialog.Accepted else 3

    def _show_confirm(self):
        dialog = _ScalaAcquistiDialog(self.books, self.conn)
        dialog.setWindowTitle('Rimozione libri')
        dialog.exec_()

    def _show_error(self, msg=''):
        dialog = QMessageBox()
        dialog.setWindowTitle('ERRORE')
        dialog.setText(msg)
        dialog.exec_()
class Example(QWidget):

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

    def initUI(self):

        QToolTip.setFont(QFont('SansSerif', 12))
        
        Title = QLabel('Выберите параметры обучения нейросети')
        Title.setToolTip('Для корректной работы функций обучения и оптимизации \n'
                         'в каталоге с программой должны находится подкаталоги \n'
                         'train, val, test. В каждом из этих каталогов должно \n'
                         'быть столько подкаталогов с изображениями, сколько \n'
                         'необходимо распознавать классов')
        Title1 = QLabel('Выберите параметры исследования изображения')
        Title1.setToolTip('Для корректной работы функции классификации и локализации \n'
                          'изображения для исследования и модель нейросети должны \n'
                          'находиться в одном каталоге с программой, формат изображения \n'
                          '.jpg, формат модели нейросети .h5, указывать формат в полях не нужно')
        TitleEp = QLabel('Эпохи:')
        TitleEp.setToolTip('Эпоха — один «проход» данных через нейросеть. \n'
                           'Изменение этого параметра позволяет избежать \n'
                           'недообученности или переобученности нейросети')
        TitleBa = QLabel('Размер мини-выборки:')
        TitleBa.setToolTip('Количество изображений загружаемых в нейросеть '
                           'за раз')
        TitleTr = QLabel('Количество изображений для обучения:')
        TitleTr.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога train')
        TitleVa = QLabel('Количество изображений для проверки:')
        TitleVa.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога val')
        TitleTe = QLabel('Количество изображений для тестирования:')
        TitleTe.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога test')
        TitleSc = QLabel('Масштабирование пирамиды изображений:')
        TitleSc.setToolTip('Коэффициент масштабирования изображения')
        TitleSs = QLabel('Шаг скользящего окна:')
        TitleSs.setToolTip('Расстояние в пикселях, на которое смещается \n'
                           'окно классификатора по изображению за одну итерацию')
        TitleNi = QLabel('Имя изображения для исследования:')
        TitleNi.setToolTip('Наименование изображения без расширения. \n'
                           'Изображение должно иметь формат jpg и \n'
                           'находится в одном каталоге с программой, иначе \n'
                           'необходимо указывать полный путь до изображения')
        TitleNm = QLabel('Имя модели нейросети:')
        TitleNm.setToolTip('Наименование модели нейросети без расширения. \n'
                           'Модель должна иметь формат h5 и находится \n'
                           'в одном каталоге с программой, иначе необходимо \n'
                           'указывать полный путь до модели нейросети')
        TitleCl = QLabel('Количество классов:')
        
        self.InputEpochs = QSpinBox(self)
        self.InputEpochs.setRange(5,50)
        self.InputEpochs.setValue(10)

        self.InputBatch = QSpinBox(self)
        self.InputBatch.setRange(5,100)
        self.InputBatch.setValue(15)

        self.InputTrain = QSpinBox(self)
        self.InputTrain.setRange(100,100000)
        self.InputTrain.setValue(1050)

        self.InputValidation = QSpinBox(self)
        self.InputValidation.setRange(100,100000)
        self.InputValidation.setValue(225)

        self.InputTest = QSpinBox(self)
        self.InputTest.setRange(100,100000)
        self.InputTest.setValue(225)

        self.InputScale = QDoubleSpinBox(self)
        self.InputScale.setRange(1.1,5)
        self.InputScale.setValue(1.5)

        self.InputStep = QSpinBox(self)
        self.InputStep.setRange(1,150)
        self.InputStep.setValue(30)

        self.InputClass = QSpinBox(self)
        self.InputClass.setRange(3,20)
        self.InputClass.setValue(3)
        
        self.ImageName = QLineEdit("ImageName", self)
        self.ImageName.setMaxLength(20)

        self.ModelName = QLineEdit("TestModel", self)
        self.ModelName.setMaxLength(20)
        
        btn = QPushButton('Обучить нейросеть', self)
        btn.setToolTip('В результате обучения модель нейросети '
                       'будет сохранена в каталоге с программой')
        btn.resize(btn.sizeHint())
        btn.clicked.connect(self.buttonClicked)
        
        btn1 = QPushButton('Оптимизировать нейросеть', self)
        btn1.setToolTip('В результате оптимизации 3 лучшие модели '
                        'будут сохранены в каталоге с программой')
        btn1.resize(btn1.sizeHint())
        btn1.clicked.connect(self.buttonClicked1)
        
        btn2 = QPushButton('Поиск и распознавание', self)
        btn2.resize(btn2.sizeHint())
        btn2.clicked.connect(self.buttonClicked2)

        grid = QGridLayout(self)

        grid.setSpacing(10)

        grid.addWidget(Title, 1, 0, 1, 4)
        grid.addWidget(TitleEp, 2, 0)
        grid.addWidget(TitleBa, 3, 0)
        grid.addWidget(TitleCl, 4, 0)
        grid.addWidget(self.InputEpochs, 2, 1)
        grid.addWidget(self.InputBatch, 3, 1)
        grid.addWidget(self.InputClass, 4, 1)
        grid.addWidget(TitleTr, 2, 2)
        grid.addWidget(TitleVa, 3, 2)
        grid.addWidget(TitleTe, 4, 2)
        grid.addWidget(self.InputTrain, 2, 3)
        grid.addWidget(self.InputValidation, 3, 3)
        grid.addWidget(self.InputTest, 4, 3)
        grid.addWidget(btn, 5, 0, 1, 2)
        grid.addWidget(btn1, 5, 2, 1, 2)
        
        grid.addWidget(Title1, 6, 0, 1, 4)
        grid.addWidget(TitleSc, 7, 0)
        grid.addWidget(self.InputScale, 7, 1)
        grid.addWidget(TitleSs, 7, 2)
        grid.addWidget(self.InputStep, 7, 3)
        grid.addWidget(TitleNi, 8, 0)
        grid.addWidget(self.ImageName, 8, 1)
        grid.addWidget(TitleNm, 8, 2)
        grid.addWidget(self.ModelName, 8, 3)
        grid.addWidget(btn2, 9, 1, 1, 2)
        
        self.setLayout(grid)
        
        self.setWindowTitle('Система поиска и распознавания сорных растений')
        self.setWindowIcon(QIcon('icon.png'))
        self.show()
    
    def buttonClicked(self):

        train_dir = 'train' # Каталог с данными для обучения
        val_dir = 'val' # Каталог с данными для проверки
        test_dir = 'test' # Каталог с данными для тестирования
        img_width, img_height = 150, 150 # Размеры изображения
        input_shape = (img_width, img_height, 3) # Размерность тензора на основе изображения для входных данных в нейронную сеть
        
        epochs = self.InputEpochs.value()
        Nclasses = self.InputClass.value()
        batch_size = self.InputBatch.value()
        nb_train_samples = self.InputTrain.value()
        nb_validation_samples = self.InputValidation.value()
        nb_test_samples = self.InputTest.value()
        
        model = Sequential()
        model.add(Conv2D(32, (3, 3), input_shape=input_shape))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))

        model.add(Conv2D(64, (3, 3)))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))

        model.add(Conv2D(64, (3, 3)))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))

        model.add(Conv2D(128, (3, 3)))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))

        model.add(Flatten())
        model.add(Dense(768))
        model.add(Activation('selu'))
        model.add(Dropout(0.5))
        model.add(Dense(Nclasses))
        model.add(Activation('softmax'))

        model.compile(loss='categorical_crossentropy',
            optimizer='adam',
            metrics=['accuracy'])

        datagen = ImageDataGenerator(rescale=1. / 255)

        train_generator = datagen.flow_from_directory(
            train_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        val_generator = datagen.flow_from_directory(
            val_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        test_generator = datagen.flow_from_directory(
            test_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        model.fit_generator(
            train_generator,
            steps_per_epoch=nb_train_samples // batch_size,
            epochs=epochs,
            validation_data=val_generator,
            validation_steps=nb_validation_samples // batch_size)

        scores = model.evaluate_generator(test_generator, nb_test_samples // batch_size)

        print("Аккуратность на тестовых данных: %.2f%%" % (scores[1]*100))

        model.save('TestModel.h5')

    def buttonClicked1(self):

        train_dir = 'train'
        val_dir = 'val'
        test_dir = 'test'
        img_width, img_height = 150, 150
        input_shape = (img_width, img_height, 3)

        epochs = self.InputEpochs.value()
        Nclasses = self.InputClass.value()
        batch_size = self.InputBatch.value()
        nb_train_samples = self.InputTrain.value()
        nb_validation_samples = self.InputValidation.value()
        nb_test_samples = self.InputTest.value()

        l=0

        def build_model(hp):  
            model = Sequential()

            num_hidden_layers = hp.Int('num_hidden_layers', 1, 3, default=1)
            num_conv_layers = hp.Int('num_conv_layers', 2, 6, default=2)

            model.add(Conv2D(32, (3, 3), input_shape=input_shape))
            model.add(Activation('relu'))
            model.add(MaxPooling2D(pool_size=(2, 2)))

            for i in range(num_conv_layers):
                filters = hp.Int('filters'+str(i), 32, 64, step=16)
                model.add(Conv2D(filters,(3, 3)))
                model.add(Activation('relu'))
            model.add(MaxPooling2D(pool_size=(2, 2)))

            model.add(Conv2D(128, (3, 3)))
            model.add(Activation('relu'))
            model.add(MaxPooling2D(pool_size=(2, 2)))

            model.add(Flatten())
    
            for j in range(num_hidden_layers):
                model.add(Dense(units=hp.Int('units_hiddenNeurons_'+str(j),
                                             min_value=128,
                                             max_value=1024,
                                             step=64),
                                activation=hp.Choice('activation'+str(j),values=['relu','tanh','elu','selu'])))

            model.add(Dropout(0.5))
            model.add(Dense(Nclasses))
            model.add(Activation('softmax'))
            model.compile(
                loss='categorical_crossentropy',
                optimizer=hp.Choice('optimizer', values=['adam','rmsprop','SGD'],default='adam'),
                metrics=['accuracy'])
            return model

        tuner = RandomSearch(
            build_model,
            objective='val_accuracy',
            max_trials=15,
            directory='test_directory')

        tuner.search_space_summary()

        datagen = ImageDataGenerator(rescale=1. / 255)

        train_generator = datagen.flow_from_directory(
            train_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        val_generator = datagen.flow_from_directory(
            val_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        test_generator = datagen.flow_from_directory(
            test_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        tuner.search(
            train_generator,
            steps_per_epoch=nb_train_samples // batch_size,
            epochs=epochs,
            validation_data=val_generator,
            validation_steps=nb_validation_samples // batch_size)

        tuner.results_summary()

        models = tuner.get_best_models(num_models=3)

        for model in models:
            model.summary()
            l=l+1
            scores = model.evaluate_generator(test_generator, nb_test_samples // batch_size)
            model.save('bestmodel_'+str(l)+'.h5')
            print("Аккуратность на тестовых данных: %.2f%%" % (scores[1]*100))


    def buttonClicked2(self):

        def pyramid(image, scale, minSize=(150, 150)):
            yield image
            while True:
                w = int(image.shape[1] / scale)
                image = imutils.resize(image, width=w)
                if image.shape[0] < minSize[1] or image.shape[1] < minSize[0]:
                    break
                yield image

        def sliding_window(image, stepSize, windowSize):
            # сдвиг окна по изображению
            for y in range(0, image.shape[0], stepSize):
                for x in range(0, image.shape[1], stepSize):
                    yield (x, y, image[y:y + windowSize[1], x:x + windowSize[0]])


        # расстояние между точками
        def dist(x,y):
            return np.sqrt(np.sum(np.square(np.array(center(x))-np.array(center(y)))))

        # вычисляем точку-центр рамки
        def center(frame):
            (x, y, x2, y2, _ , _ , _ ) = frame
            return [ x+((x2-x)//2), y2+((y-y2)//2) ]

        # очистка списка найденных рамок
        def clean(X, i=0, max_dist=150):
            # выбираем основной элемент X[i]
            j = i+1 # и, следующий за ним, элемент X[j]
            if i <= len(X) and i > 0:
                max_dist *= X[i][6]
            while(j<len(X)): # для всех элементов j (!= i)
                d = dist( X[i], X[j] ) # считаем расстояние между точками i,j
                if ( d < max_dist ): # i,j в одном кластере
                    if ( X[i][4] >= X[j][4] ): # сравниваем рейтинг
                        del X[j]  # удаляем элемент j
                    else:
                        del X[i] # удаляем основной элемент i
                    X = clean(X, i=i, max_dist=max_dist) # рекурсивно повторяем уже без элемента i
                    break
                else:
                    j+=1
            if ( i<(len(X)-1) ): # если есть ещё точки в других, относительно X[i], кластерах
                X = clean(X, i=i+1, max_dist=max_dist) # то выполняем проверку
            return X

        if __name__ == "__main__":

            k = 1
            path = os.getcwd()
            classes = os.listdir(path + "/train")
            boxes = []
            scale = self.InputScale.value()
            stepSize = self.InputStep.value()
            imagename = self.ImageName.text()
            modelname = self.ModelName.text()
            font = cv2.FONT_HERSHEY_SIMPLEX
	
            model = load_model(modelname+'.h5')
            img = cv2.imread(imagename+'.jpg')
            width1, height1, channels1 = img.shape
            if (width1 > 1000) or (height1 > 1000):
                img = cv2.resize(img, (0, 0), fx = 0.5, fy = 0.5)
            (winW, winH) = (150, 150)
            clone = img.copy()

            for resized in pyramid(img, scale):
                for (x, y, window) in sliding_window(resized, stepSize, windowSize=(winW, winH)):
                    # если окно не соответствует нашему желаемому размеру окна, игнорируем его
                    if window.shape[0] != winH or window.shape[1] != winW:
                        continue
        		
                    img_tensor = image.img_to_array(window)                 # (height, width, channels)
                    img_tensor = np.expand_dims(img_tensor, axis=0)         # (1, height, width, channels), добавим измерение, потому что модель ожидает эту форму: (batch_size, height, width, channels)
                    img_tensor /= 255.                                      # imshow ожидает значений в диапазоне [0, 1]
		
                    pred = model.predict(img_tensor)
                    nclass = np.argmax(pred)
                    pred = np.amax(pred)
                    if pred >= 0.9:
                        boxes.append([x*k, y*k, (x + winW)*k, (y + winH)*k, pred, classes[nclass], k])

                k *= scale
	

            boxes = clean(boxes)
	
            for (x, y, x2, y2, score, classname, scales) in boxes:
                    cv2.rectangle(clone, (int(x),int(y)),(int(x2), int(y2)),(0, 255, 0), 2)
                    cv2.putText(clone, classname + " %.3f" % score, (int(x),int(y2)), font, 0.7, (0, 255, 0), thickness=2)
            cv2.imshow("Result", clone)
            cv2.waitKey(1)

    def closeEvent(self, event):

        reply = QMessageBox.question(self, 'Выход',
            "Вы уверены что хотите закрыть программу?", QMessageBox.Yes |
            QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
Example #33
0
    def __init__(self, conn):
        '''
        Parameters:
            conn : connection
                Connection to the database.
        '''
        super().__init__()
        self.setWindowTitle('Aggiungi Acquisto')
        self.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, False)

        self.conn = conn
        self.cursor = conn.cursor()

        self.books = dict()
        self.books_qt = dict()

        self.gen_layout = QVBoxLayout()

        self.form_layout = QFormLayout()
        self.form_layout.setRowWrapPolicy(QFormLayout.WrapLongRows)

        # Widgets
        self.client_field = QLineEdit()
        self.form_layout.addRow('Numero Cliente (facoltativo): ',
                                self.client_field)

        self.dip_field = QLineEdit()
        self.form_layout.addRow('Dipendente (CF): ', self.dip_field)

        self.date_picker = QDateEdit(QDate.currentDate())
        self.date_picker.setDisplayFormat("MM/dd/yyyy")
        self.date_picker.setCalendarPopup(True)
        self.form_layout.addRow('Data (mm/gg/aaaa): ', self.date_picker)

        self.importo_field = QDoubleSpinBox()
        self.importo_field.setMaximum(999999999.99)
        self.form_layout.addRow('Importo: ', self.importo_field)

        self.ins_layout = QHBoxLayout()
        self.libro_field = QLineEdit()
        self.quantita_field = QSpinBox()
        self.quantita_field.setMinimum(1)
        self.libro_button = QPushButton('Aggiungi')
        self.libro_button.clicked.connect(self.aggiungi_libro)
        self.ins_layout.addWidget(QLabel('Libro (ISBN): '))
        self.ins_layout.addWidget(self.libro_field)
        self.ins_layout.addWidget(QLabel('Quantità: '))
        self.ins_layout.addWidget(self.quantita_field)
        self.ins_layout.addWidget(self.libro_button)

        self.labels = ['ISBN', 'Quantità', '']
        self.table = QTableWidget(0, 3)
        self.table.setHorizontalHeaderLabels(self.labels)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self.confirm_button = QPushButton('Conferma')
        self.confirm_button.clicked.connect(self.post_acquisto)

        self.gen_layout.addLayout(self.form_layout)
        self.gen_layout.addLayout(self.ins_layout)
        self.gen_layout.addWidget(self.table)
        self.gen_layout.addWidget(self.confirm_button)
        self.setLayout(self.gen_layout)
Example #34
0
 def setUp(self):
     super(SpinBoxPySignal, self).setUp()
     self.obj = Dummy()
     self.spin = QSpinBox()
     self.spin.setValue(0)
Example #35
0
class TrainingPanel(Panel):

    def __init__(self, datasets, testing_panel, threads):
        super().__init__()
        if isinstance(testing_panel, TestingPanel):
            self.testing_panel = testing_panel
        else:
            raise TypeError('"testing_panel" must be the instance of '
                            '"TestingPanel"')
        self.datasets = datasets
        self.threads = threads

        self.__set_execution_ui()
        self.__set_options_ui()
        self.__set_outputs_ui()
        self.__set_graphic_ui()

    def __set_execution_ui(self):
        group_box = QGroupBox('Training Execution')
        inner_layout = QHBoxLayout()
        group_box.setLayout(inner_layout)

        self.data_selector = QComboBox()
        self.data_selector.addItems(list(self.datasets.keys()))
        self.data_selector.setStatusTip('Select the training dataset.')

        self.start_btn = QPushButton('Train')
        self.start_btn.setStatusTip('Start training.')
        self.start_btn.clicked.connect(self.__run)

        self.stop_btn = QPushButton('Stop')
        self.stop_btn.setStatusTip('Force the training stop running.')
        self.stop_btn.setDisabled(True)

        self.multicore_cb = QCheckBox('Multicore')
        self.multicore_cb.setStatusTip('Use multiprocessing in calculating '
                                       'fitting for populations.')
        self.multicore_cb.setChecked(True)

        inner_layout.addWidget(self.data_selector, 1)
        inner_layout.addWidget(self.start_btn)
        inner_layout.addWidget(self.stop_btn)
        inner_layout.addWidget(self.multicore_cb)

        self._layout.addWidget(group_box)

    def __set_options_ui(self):
        group_box = QGroupBox('Training Options')
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.iter_times = QSpinBox()
        self.iter_times.setRange(1, 1000000)
        self.iter_times.setValue(200)
        self.iter_times.setStatusTip('The total iterating times for training.')

        self.population_size = QSpinBox()
        self.population_size.setRange(1, 100000)
        self.population_size.setValue(100)
        self.population_size.setStatusTip('The population size for the PSO.')

        self.inertia_weight = QDoubleSpinBox()
        self.inertia_weight.setRange(0, 50)
        self.inertia_weight.setValue(1)
        self.inertia_weight.setSingleStep(0.1)
        self.inertia_weight.setStatusTip('The inertia weight of the velocity '
                                         ' for each individual.')

        self.cognitive_const_rand_upper = QDoubleSpinBox()
        self.cognitive_const_rand_upper.setRange(0, 50)
        self.cognitive_const_rand_upper.setValue(2)
        self.cognitive_const_rand_upper.setSingleStep(0.1)
        self.cognitive_const_rand_upper.setStatusTip(
            'The random upper bound for cognitive accelerate constant.')

        self.social_const_rand_upper = QDoubleSpinBox()
        self.social_const_rand_upper.setRange(0, 50)
        self.social_const_rand_upper.setValue(3)
        self.social_const_rand_upper.setSingleStep(0.1)
        self.social_const_rand_upper.setStatusTip(
            'The random upper bound for social accelerate constant.')

        self.v_max = QDoubleSpinBox()
        self.v_max.setRange(0.5, 100)
        self.v_max.setValue(5)
        self.v_max.setSingleStep(1)
        self.v_max.setStatusTip('The maximum of velocity for each individual.')

        self.nneuron = QSpinBox()
        self.nneuron.setRange(1, 100)
        self.nneuron.setValue(6)
        self.nneuron.setStatusTip('The number of RBFN neuron.')

        self.sd_max = QDoubleSpinBox()
        self.sd_max.setRange(0.01, 20)
        self.sd_max.setValue(10)
        self.sd_max.setSingleStep(0.1)
        self.sd_max.setStatusTip('The random range maximum of standard '
                                 'deviation of each neuron in RBFN (only for '
                                 'initialization).')

        inner_layout.addRow('Iterating Times:', self.iter_times)
        inner_layout.addRow('Population Size:', self.population_size)
        inner_layout.addRow('Inertia Weight:', self.inertia_weight)
        inner_layout.addRow('Cognitive Const Upper:',
                            self.cognitive_const_rand_upper)
        inner_layout.addRow('Social Const Upper:',
                            self.social_const_rand_upper)
        inner_layout.addRow('Maximum of Velocity:', self.v_max)
        inner_layout.addRow('Number of Neuron:', self.nneuron)
        inner_layout.addRow('Maximum of SD:', self.sd_max)

        self._layout.addWidget(group_box)

    def __set_outputs_ui(self):
        group_box = QGroupBox('Training Details')
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.current_iter_time = QLabel('--')
        self.current_error = QLabel('--')
        self.avg_error = QLabel('--')
        self.global_best_error = QLabel('--')
        self.total_best_error = QLabel('--')
        self.progressbar = QProgressBar()

        self.current_iter_time.setAlignment(Qt.AlignCenter)
        self.current_error.setAlignment(Qt.AlignCenter)
        self.avg_error.setAlignment(Qt.AlignCenter)
        self.global_best_error.setAlignment(Qt.AlignCenter)
        self.total_best_error.setAlignment(Qt.AlignCenter)

        self.current_iter_time.setStatusTip('The current iterating time of '
                                            'the PSO.')
        self.current_error.setStatusTip('The current error from the fitting '
                                        'function. ("( )": normalized error)')
        self.avg_error.setStatusTip('The average error from the fitting '
                                    'function in current iteration.  ("( )": '
                                    'normalized error)')
        self.global_best_error.setStatusTip(
            'The error of global best individual from the fitting function in '
            'current iteration.  ("( )": normalized error)')
        self.total_best_error.setStatusTip(
            'The error of total best individual from the fitting function in '
            'training.  ("( )": normalized error)')

        inner_layout.addRow('Current Iterating Time:', self.current_iter_time)
        inner_layout.addRow('Current Error:', self.current_error)
        inner_layout.addRow('Average Error:', self.avg_error)
        inner_layout.addRow('Global Best Error:', self.global_best_error)
        inner_layout.addRow('Total Best Error:', self.total_best_error)
        inner_layout.addRow(self.progressbar)

        self._layout.addWidget(group_box)

    def __set_graphic_ui(self):
        group_box = QGroupBox('Error Line Charts:')
        inner_layout = QVBoxLayout()
        group_box.setLayout(inner_layout)

        self.err_chart = ErrorLineChart(1)
        self.err_chart.setStatusTip('The history of error from the fitting '
                                    'of the PSO for each data.')
        self.__err_x = 1

        self.iter_err_chart = ErrorLineChart(
            3, ('Avg', 'Global Best', 'Total Best'))
        self.iter_err_chart.setStatusTip('The history of average and least '
                                         'error from the fitting of the PSO '
                                         'for each iteration.')
        self.iter_err_chart.setMinimumHeight(150)

        inner_layout.addWidget(QLabel('Current Error'))
        inner_layout.addWidget(self.err_chart)
        inner_layout.addWidget(QLabel('Average Error'))
        inner_layout.addWidget(self.iter_err_chart)
        self._layout.addWidget(group_box)

    @Slot()
    def __init_widgets(self):
        self.start_btn.setDisabled(True)
        self.stop_btn.setEnabled(True)
        self.multicore_cb.setDisabled(True)
        self.data_selector.setDisabled(True)
        self.iter_times.setDisabled(True)
        self.population_size.setDisabled(True)
        self.inertia_weight.setDisabled(True)
        self.cognitive_const_rand_upper.setDisabled(True)
        self.social_const_rand_upper.setDisabled(True)
        self.v_max.setDisabled(True)
        self.nneuron.setDisabled(True)
        self.sd_max.setDisabled(True)
        self.err_chart.clear()
        self.iter_err_chart.clear()
        self.__err_x = 1

    @Slot()
    def __reset_widgets(self):
        self.start_btn.setEnabled(True)
        self.stop_btn.setDisabled(True)
        self.multicore_cb.setEnabled(True)
        self.data_selector.setEnabled(True)
        self.iter_times.setEnabled(True)
        self.population_size.setEnabled(True)
        self.inertia_weight.setEnabled(True)
        self.cognitive_const_rand_upper.setEnabled(True)
        self.social_const_rand_upper.setEnabled(True)
        self.v_max.setEnabled(True)
        self.nneuron.setEnabled(True)
        self.sd_max.setEnabled(True)
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(100)

    @Slot()
    def __indicate_busy(self):
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(0)

    @Slot(int)
    def __show_current_iter_time(self, value):
        self.current_iter_time.setText(str(value + 1))
        self.progressbar.setValue(value + 1)

    @Slot(float)
    def __show_current_error(self, value):
        self.current_error.setText('{:.5f} ({:.5f})'.format(value, value / 40))
        self.err_chart.append_point(self.__err_x, value)
        self.__err_x += 1

    @Slot(float, float, float)
    def __show_iter_error(self, avg, glob, total):
        self.avg_error.setText('{:.5f} ({:.5f})'.format(avg, avg / 40))
        self.global_best_error.setText(
            '{:.5f} ({:.5f})'.format(glob, glob / 40))
        self.total_best_error.setText(
            '{:.5f} ({:.5f})'.format(total, total / 40))
        self.iter_err_chart.append_point(
            int(self.current_iter_time.text()), total, 2)
        self.iter_err_chart.append_point(
            int(self.current_iter_time.text()), glob, 1)
        self.iter_err_chart.append_point(
            int(self.current_iter_time.text()), avg, 0)

    def __run(self):
        self.progressbar.setMaximum(self.iter_times.value())

        self.__current_dataset = self.datasets[
            self.data_selector.currentText()]

        self.__pso = PSO(self.iter_times.value(), self.population_size.value(),
                         self.inertia_weight.value(),
                         self.cognitive_const_rand_upper.value(),
                         self.social_const_rand_upper.value(),
                         self.v_max.value(), self.nneuron.value(),
                         self.__current_dataset, self.sd_max.value(),
                         is_multicore=self.multicore_cb.isChecked())
        self.threads.append(self.__pso)
        self.stop_btn.clicked.connect(self.__pso.stop)
        self.__pso.started.connect(self.__init_widgets)
        self.__pso.finished.connect(self.__reset_widgets)
        self.__pso.sig_current_iter_time.connect(self.__show_current_iter_time)
        self.__pso.sig_current_error.connect(self.__show_current_error)
        self.__pso.sig_iter_error.connect(self.__show_iter_error)
        self.__pso.sig_indicate_busy.connect(self.__indicate_busy)
        self.__pso.sig_console.connect(self.testing_panel.print_console)
        self.__pso.sig_rbfn.connect(self.testing_panel.load_rbfn)
        self.__pso.start()
Example #36
0
    def setup(self):
        "constructs the gui"
        Fixed = QSizePolicy()
        MinimumExpanding = QSizePolicy(QSizePolicy.MinimumExpanding,
                                       QSizePolicy.MinimumExpanding)
        self.minKeyLen = 8
        self.maxKeyLen = 4096

        self.splitter = QSplitter(self)
        self.splitter.setOrientation(Qt.Horizontal)
        self.splitter.splitterMoved.connect(self.splitterChanged)

        # left column
        self.leftColumn = QWidget()
        self.vl01 = QVBoxLayout()

        # left column - first item (0; horizonal layout 0)
        self.hl00 = QHBoxLayout()
        self.hl00.setSpacing(5)

        self.openButton = QPushButton('&Open')
        self.openButton.setToolTip('Open folder')
        self.openButton.setMinimumSize(60, 20)
        self.openButton.setMaximumSize(60, 20)
        self.openButton.setSizePolicy(Fixed)
        self.openButton.clicked.connect(self.getFolder)
        #ico = self.style().standardIcon(QStyle.SP_DirIcon)
        #self.openButton.setIcon(ico)

        self.folderLabel = QLabel()
        self.folderLabel.setMinimumSize(135, 20)
        self.folderLabel.setMaximumSize(16777215, 20)
        self.folderLabel.setSizePolicy(MinimumExpanding)
        self.hl00.insertWidget(0, self.openButton)
        self.hl00.insertWidget(1, self.folderLabel)

        # left column - second item (1)
        self.folderTable = QTableWidget()
        self.folderTable.setMinimumSize(200, 32)
        self.folderTable.horizontalHeader().setVisible(False)
        self.folderTable.horizontalHeader().setStretchLastSection(True)
        self.folderTable.verticalHeader().setVisible(False)
        self.folderTable.verticalHeader().setDefaultSectionSize(15)
        self.folderTable.itemChanged.connect(self.editFileName)

        # left column - third item (2)
        self.extraLabel = QLabel()
        self.extraLabel.setMinimumSize(200, 20)
        self.extraLabel.setMaximumSize(16777215, 20)
        self.extraLabel.setSizePolicy(MinimumExpanding)
        self.extraLabel.setTextInteractionFlags(Qt.LinksAccessibleByMouse)

        # finalize left column
        self.vl01.insertLayout(0, self.hl00)
        self.vl01.insertWidget(1, self.folderTable)
        self.vl01.insertWidget(2, self.extraLabel)
        self.leftColumn.setLayout(self.vl01)

        # right column
        self.rightColumn = QWidget()
        self.vl02 = QVBoxLayout()

        # right column - first item (0)
        self.messageLabel = QLabel()
        self.messageLabel.setMinimumSize(290, 20)
        self.messageLabel.setMaximumSize(16777215, 20)
        self.messageLabel.setSizePolicy(MinimumExpanding)
        self.messageLabel.setAlignment(Qt.AlignCenter)

        # right column - second item (2; horizontal layout 1)
        self.hl01 = QHBoxLayout()
        self.hl01.setSpacing(5)

        self.encryptButton = QPushButton('&Encrypt')  #\U0001F512
        self.encryptButton.setToolTip('Encrypt selected file')
        self.encryptButton.setMinimumSize(60, 20)
        self.encryptButton.setMaximumSize(60, 20)
        self.encryptButton.setSizePolicy(Fixed)
        self.encryptButton.clicked.connect(self.encrypt)

        self.encryptPbar = QProgressBar()
        self.encryptPbar.setMinimumSize(225, 20)
        self.encryptPbar.setMaximumSize(16777215, 20)
        self.encryptPbar.setSizePolicy(MinimumExpanding)
        self.encryptPbar.setTextVisible(False)

        palette = self.encryptPbar.palette()  # color of progress bar
        color = QColor(211, 70, 0)
        palette.setColor(QPalette.Highlight, color)
        self.encryptPbar.setPalette(palette)

        self.hl01.insertWidget(0, self.encryptButton)
        self.hl01.insertWidget(1, self.encryptPbar)

        # right column - third item (3; horizontal layout 2)
        self.hl02 = QHBoxLayout()
        self.hl02.setSpacing(5)

        self.cancelButton = QPushButton('C&ANCEL')
        self.cancelButton.setToolTip('Cancels current operation')
        self.cancelButton.setMinimumSize(70, 24)
        self.cancelButton.setMaximumSize(70, 24)
        self.cancelButton.setSizePolicy(Fixed)
        self.cancelButton.clicked.connect(self.setCancel)
        font = self.cancelButton.font()
        font.setBold(True)
        self.cancelButton.setFont(font)
        self.cancelButton.blockSignals(True)
        self.cancelButton.setEnabled(False)
        self.cancelButton.hide()
        self._requestStop = False

        self.keyInput = QLineEdit()
        self.keyInput.setMinimumSize(225, 20)
        self.keyInput.setMaximumSize(16777215, 20)
        self.keyInput.setSizePolicy(MinimumExpanding)
        self.keyInput.setPlaceholderText('key')
        self.keyInput.setMaxLength(self.maxKeyLen)
        self.keyInput.setAlignment(Qt.AlignCenter)
        self.keyInput.textEdited.connect(self.showKeyLen)

        self.genKeyButton = QPushButton('&Gen Key')  #\U0001F511
        self.genKeyButton.setToolTip('Generate a random key')
        self.genKeyButton.setMinimumSize(60, 20)
        self.genKeyButton.setMaximumSize(60, 20)
        self.genKeyButton.setSizePolicy(Fixed)
        self.genKeyButton.clicked.connect(self.genKey)

        self.keySizeSB = QSpinBox()
        self.keySizeSB.setToolTip('Length of key to generate')
        self.keySizeSB.setRange(32, 1024)
        self.keySizeSB.setMinimumSize(40, 20)
        self.keySizeSB.setMaximumSize(40, 20)
        self.keySizeSB.setSizePolicy(Fixed)
        self.keySizeSB.setAlignment(Qt.AlignCenter)
        self.keySizeSB.setButtonSymbols(QSpinBox.NoButtons)
        self.keySizeSB.setWrapping(True)

        self.hl02.insertWidget(0, self.cancelButton)
        self.hl02.insertWidget(1, self.keyInput)
        self.hl02.insertWidget(2, self.genKeyButton)
        self.hl02.insertWidget(3, self.keySizeSB)

        # right column - fourth item (4; horizontal layout 3)
        self.hl03 = QHBoxLayout()
        self.hl03.setSpacing(5)

        self.decryptButton = QPushButton('&Decrypt')  #\U0001F513
        self.decryptButton.setToolTip('Decrypt selected file')
        self.decryptButton.setMinimumSize(60, 20)
        self.decryptButton.setMaximumSize(60, 20)
        self.decryptButton.setSizePolicy(Fixed)
        self.decryptButton.clicked.connect(self.decrypt)

        self.decryptPbar = QProgressBar()
        self.decryptPbar.setMinimumSize(225, 20)
        self.decryptPbar.setMaximumSize(16777215, 20)
        self.decryptPbar.setSizePolicy(MinimumExpanding)
        self.decryptPbar.setTextVisible(False)
        self.decryptPbar.setInvertedAppearance(True)

        palette = self.decryptPbar.palette()  # color of progress bar
        color = QColor(0, 170, 255)
        palette.setColor(QPalette.Highlight, color)
        self.decryptPbar.setPalette(palette)

        self.hl03.insertWidget(0, self.decryptButton)
        self.hl03.insertWidget(1, self.decryptPbar)

        # right column - fifth item (7; horizontal layout 4)
        self.hl04 = QHBoxLayout()
        self.hl04.setSpacing(5)

        self.showKeyCB = QCheckBox('&Show Key')
        self.showKeyCB.setToolTip('Show/Hide key value')
        self.showKeyCB.setMinimumSize(75, 20)
        self.showKeyCB.setMaximumSize(75, 20)
        self.showKeyCB.setSizePolicy(Fixed)
        self.showKeyCB.clicked.connect(self.showKey)
        self.showKeyCB.setChecked(True)

        self.hashPbar = QProgressBar()
        self.hashPbar.setMinimumSize(150, 20)
        self.hashPbar.setMaximumSize(16777215, 20)
        self.hashPbar.setSizePolicy(MinimumExpanding)
        self.hashPbar.setTextVisible(False)

        palette = self.hashPbar.palette()  # color of progress bar
        color = QColor(31, 120, 73)
        palette.setColor(QPalette.Highlight, color)
        self.hashPbar.setPalette(palette)

        self.hashButton = QPushButton('&Hash')
        self.hashButton.setToolTip('Determine file hash')
        self.hashButton.setMinimumSize(60, 20)
        self.hashButton.setMaximumSize(60, 20)
        self.hashButton.setSizePolicy(Fixed)

        menu = QMenu(self.hashButton)
        ico = self.style().standardIcon(QStyle.SP_DialogYesButton)
        for alg in sorted(
                filter(lambda x: 'shake' not in x,
                       hashlib.algorithms_guaranteed),
                key=lambda n:
            (len(n), sorted(hashlib.algorithms_guaranteed).index(n))):
            menu.addAction(
                ico, alg
            )  # drop shake algs as their .hexdigest requires an argument - the rest don't
        menu.addAction(ico, 'Party')
        for i in menu.actions():
            i.setIconVisibleInMenu(False)
        self.hashButton.setMenu(menu)
        menu.triggered.connect(self.genHash)

        self.hl04.insertWidget(0, self.showKeyCB)
        self.hl04.insertWidget(1, self.hashPbar)
        self.hl04.insertWidget(2, self.hashButton)

        # right column - sixth item (8; horizontal layout 5)
        self.hl05 = QHBoxLayout()
        self.hl05.setSpacing(5)

        self.copyButton = QPushButton('&Copy')  #\U0001F4CB
        self.copyButton.setToolTip('Copy key or hash to clipboard')
        self.copyButton.setMinimumSize(60, 20)
        self.copyButton.setMaximumSize(60, 20)
        self.copyButton.setSizePolicy(Fixed)

        menu2 = QMenu(self.copyButton)
        menu2.addAction('Copy Key')
        menu2.addAction('Copy Hash')
        self.copyButton.setMenu(menu2)
        menu2.triggered.connect(self.copyKeyHash)

        self.hashLabel = QLabel()
        self.hashLabel.setMinimumSize(225, 20)
        self.hashLabel.setMaximumSize(16777215, 20)
        self.hashLabel.setSizePolicy(MinimumExpanding)
        self.hashLabel.setTextFormat(Qt.PlainText)
        self.hashLabel.setAlignment(Qt.AlignCenter)
        self.hashLabel.setTextInteractionFlags(Qt.TextSelectableByMouse)

        self.hl05.insertWidget(0, self.copyButton)
        self.hl05.insertWidget(1, self.hashLabel)

        # finalize right column
        self.vl02.insertWidget(0, self.messageLabel)
        self.vl02.insertSpacerItem(1, QSpacerItem(0, 0))
        self.vl02.insertLayout(2, self.hl01)
        self.vl02.insertLayout(3, self.hl02)
        self.vl02.insertLayout(4, self.hl03)
        self.vl02.insertSpacerItem(5, QSpacerItem(0, 0))
        self.vl02.insertWidget(6, QFrame())
        self.vl02.insertLayout(7, self.hl04)
        self.vl02.insertLayout(8, self.hl05)
        self.rightColumn.setLayout(self.vl02)

        # finalize main window
        self.splitter.insertWidget(0, self.leftColumn)
        self.splitter.insertWidget(1, self.rightColumn)

        layout = QHBoxLayout(self)
        layout.addWidget(self.splitter)
        self.setLayout(layout)

        self.setWindowTitle('Simple File Encryptor/Decryptor')
        self.resize(self.sizeHint())
Example #37
0
    def __set_options_ui(self):
        group_box = QGroupBox('Training Options')
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.iter_times = QSpinBox()
        self.iter_times.setRange(1, 1000000)
        self.iter_times.setValue(200)
        self.iter_times.setStatusTip('The total iterating times for training.')

        self.population_size = QSpinBox()
        self.population_size.setRange(1, 100000)
        self.population_size.setValue(100)
        self.population_size.setStatusTip('The population size for the PSO.')

        self.inertia_weight = QDoubleSpinBox()
        self.inertia_weight.setRange(0, 50)
        self.inertia_weight.setValue(1)
        self.inertia_weight.setSingleStep(0.1)
        self.inertia_weight.setStatusTip('The inertia weight of the velocity '
                                         ' for each individual.')

        self.cognitive_const_rand_upper = QDoubleSpinBox()
        self.cognitive_const_rand_upper.setRange(0, 50)
        self.cognitive_const_rand_upper.setValue(2)
        self.cognitive_const_rand_upper.setSingleStep(0.1)
        self.cognitive_const_rand_upper.setStatusTip(
            'The random upper bound for cognitive accelerate constant.')

        self.social_const_rand_upper = QDoubleSpinBox()
        self.social_const_rand_upper.setRange(0, 50)
        self.social_const_rand_upper.setValue(3)
        self.social_const_rand_upper.setSingleStep(0.1)
        self.social_const_rand_upper.setStatusTip(
            'The random upper bound for social accelerate constant.')

        self.v_max = QDoubleSpinBox()
        self.v_max.setRange(0.5, 100)
        self.v_max.setValue(5)
        self.v_max.setSingleStep(1)
        self.v_max.setStatusTip('The maximum of velocity for each individual.')

        self.nneuron = QSpinBox()
        self.nneuron.setRange(1, 100)
        self.nneuron.setValue(6)
        self.nneuron.setStatusTip('The number of RBFN neuron.')

        self.sd_max = QDoubleSpinBox()
        self.sd_max.setRange(0.01, 20)
        self.sd_max.setValue(10)
        self.sd_max.setSingleStep(0.1)
        self.sd_max.setStatusTip('The random range maximum of standard '
                                 'deviation of each neuron in RBFN (only for '
                                 'initialization).')

        inner_layout.addRow('Iterating Times:', self.iter_times)
        inner_layout.addRow('Population Size:', self.population_size)
        inner_layout.addRow('Inertia Weight:', self.inertia_weight)
        inner_layout.addRow('Cognitive Const Upper:',
                            self.cognitive_const_rand_upper)
        inner_layout.addRow('Social Const Upper:',
                            self.social_const_rand_upper)
        inner_layout.addRow('Maximum of Velocity:', self.v_max)
        inner_layout.addRow('Number of Neuron:', self.nneuron)
        inner_layout.addRow('Maximum of SD:', self.sd_max)

        self._layout.addWidget(group_box)
Example #38
0
class DataBrowserMain(QWidget):
    sliceUpdated = Signal(int, int, int, int)

    def __init__(self, parent):
        super(DataBrowserMain, self).__init__(parent)

        # data import
        self.brkraw_obj = self.parent().brkraw_obj
        self.selectedScan = None
        self.selectedScanTR = None

        self.set_viewer_frame()
        self.set_controller_frame()
        self.set_gridlayouts()
        self.set_font()
        # self.set_palette()  # TODO
        self.set_size()
        self.set_objectnames()
        self.set_texts()
        self.ratio_container = []
        self.init_connection()
        self.inactivate_widgets()  # Inactivate during startup

    def init_connection(self):
        self.parent().dataSelected.connect(
            self.selectScanEvent)  # run selectScanEvent when data selected
        self.event_timer = QTimer()
        self.event_timer.timeout.connect(self.sliceUpdateEvent)  #
        self.sliceUpdated.connect(self.updateImage)

        self.xaxis_slider.valueChanged.connect(self.xaxis_spinbox.setValue)
        self.xaxis_spinbox.valueChanged.connect(self.xaxis_slider.setValue)
        self.yaxis_slider.valueChanged.connect(self.yaxis_spinbox.setValue)
        self.yaxis_spinbox.valueChanged.connect(self.yaxis_slider.setValue)
        self.zaxis_slider.valueChanged.connect(self.zaxis_spinbox.setValue)
        self.zaxis_spinbox.valueChanged.connect(self.zaxis_slider.setValue)
        self.frame_slider.valueChanged.connect(self.frame_spinbox.setValue)
        self.frame_spinbox.valueChanged.connect(self.frame_slider.setValue)

        self.axial_view.pointed.connect(self.axialview_pointing_event)
        self.sagittal_view.pointed.connect(self.sagittalview_pointing_event)
        self.coronal_view.pointed.connect(self.coronalview_pointing_event)

        self.connect_sliders_to_update()

    def sagittalview_pointing_event(self, pos_x, pos_y, meta):
        max_x = self.yaxis_slider.maximum()
        max_y = self.zaxis_slider.maximum()

        # print(pos_x, pos_y, max_x, max_y)
        self.yaxis_slider.setValue(int(max_x * pos_x))
        self.zaxis_slider.setValue(max_y - int(max_y * pos_y))
        # print(int(max_x * pos_x), int(max_y * pos_y))

    def axialview_pointing_event(self, pos_x, pos_y, meta):
        max_x = self.yaxis_slider.maximum()
        max_y = self.xaxis_slider.maximum()

        # print(pos_x, pos_y, max_x, max_y)
        self.yaxis_slider.setValue(int(max_x * pos_x))
        self.xaxis_slider.setValue(int(max_y * pos_y))
        # print(int(max_x * pos_x), int(max_y * pos_y))

    def coronalview_pointing_event(self, pos_x, pos_y, meta):
        max_x = self.xaxis_slider.maximum()
        max_y = self.zaxis_slider.maximum()

        # print(pos_x, pos_y, max_x, max_y)
        self.xaxis_slider.setValue(int(max_x * pos_x))
        self.zaxis_slider.setValue(max_y - int(max_y * pos_y))
        # print(int(max_x * pos_x), int(max_y * pos_y))

    def sliderChangeEvent(self):
        self.event_timer.start(10)

    def sliceUpdateEvent(self):
        # This will executed only when timer timeout
        x = self.xaxis_slider.value()
        y = self.yaxis_slider.value()
        z = self.zaxis_slider.value()
        t = self.frame_slider.value()
        self.sliceUpdated.emit(x, y, z, t)
        self.event_timer.stop()

    @staticmethod
    def slice_data(dataobj, slice_orient, slice_num):
        if slice_orient == 'axial':
            sliced_data = dataobj[:, :, slice_num]
        elif slice_orient == 'sagittal':
            sliced_data = dataobj[:, slice_num, ::-1]
        elif slice_orient == 'coronal':
            sliced_data = dataobj[slice_num, :, ::-1]
        else:
            popup_error_dialog(UnexpectedError.message)
            return None
        return sliced_data

    def updateImage(self, x, y, z, frame):
        if len(self.selectedScan.shape) == 4:
            dataobj = self.selectedScan[:, :, :, frame]
        else:
            dataobj = self.selectedScan[...]

        data_xy = self.slice_data(dataobj, 'axial', z)
        data_yz = self.slice_data(dataobj, 'sagittal', x)
        data_xz = self.slice_data(dataobj, 'coronal', y)
        ratio_xy, ratio_yz, ratio_xz = self.ratio_container
        # ratio_xy, ratio_yz, ratio_xz = 1, 1, 1

        qm_xy = convert_arr2qpixmap(data_xy, ratio_xy)
        qm_yz = convert_arr2qpixmap(data_yz, ratio_yz)
        qm_xz = convert_arr2qpixmap(data_xz, ratio_xz)

        self.axial_view.setPixmap(qm_xy)
        self.sagittal_view.setPixmap(qm_yz)
        self.coronal_view.setPixmap(qm_xz)

    def selectScanEvent(self, delivery_package: list):
        """ this event is occurring when a scan selected on scanlist """
        self.axial_view.setEnabled(True)
        self.sagittal_view.setEnabled(True)
        self.coronal_view.setEnabled(True)
        self.selectedScan, affine, resol, self.selectedScanTR, is_localizer = delivery_package
        self.selectedScanTR /= 1000

        from slfmri.imgman import reorient_to_ras, determine_slice_plane
        slice_plane_ref = dict(sagittal=0, coronal=1, axial=2)

        if is_localizer:
            img_container = dict()
            for i, aff in enumerate(affine):
                size = config.get('ImageViewer', 'size')
                data = self.selectedScan[..., i]
                slice_plane = determine_slice_plane(2, aff, resol)
                ras_data, ras_resol = reorient_to_ras(data[:, :, np.newaxis],
                                                      aff, resol)
                slice_axis = slice_plane_ref[slice_plane]
                ras_data = ras_data.mean(slice_axis)
                ras_resol = np.delete(ras_resol, slice_axis)
                qpixmap = convert_arr2qpixmap(ras_data, ras_resol, size)
                img_container[slice_plane] = qpixmap

            self.update_axisview(img_container)
        else:
            # other than localizer
            self.init_data(self.selectedScan)
            matrix_size = np.asarray(self.selectedScan.shape)
            resol = np.asarray(resol)
            fov = matrix_size[:3] * resol
            self.ratio_container = [
                fov[0] / fov[1], fov[1] / fov[2], fov[0] / fov[2]
            ]
            # reset value
            init_x, init_y, init_z = (np.asarray(self.selectedScan.shape[:3]) /
                                      2.0).astype(int)
            init_f = 0

            self.disconnect_sliders_to_update()
            self.xaxis_slider.setValue(init_x)
            self.yaxis_slider.setValue(init_y)
            self.zaxis_slider.setValue(init_z)
            self.frame_slider.setValue(init_f)
            self.connect_sliders_to_update()
            self.updateImage(init_x, init_y, init_z, init_f)

    def connect_sliders_to_update(self):
        # connect to check slice update
        self.xaxis_slider.valueChanged.connect(self.sliderChangeEvent)
        self.yaxis_slider.valueChanged.connect(self.sliderChangeEvent)
        self.zaxis_slider.valueChanged.connect(self.sliderChangeEvent)
        self.frame_slider.valueChanged.connect(self.sliderChangeEvent)

    def disconnect_sliders_to_update(self):
        # disconnect to check slice update
        self.xaxis_slider.valueChanged.disconnect(self.sliderChangeEvent)
        self.yaxis_slider.valueChanged.disconnect(self.sliderChangeEvent)
        self.zaxis_slider.valueChanged.disconnect(self.sliderChangeEvent)
        self.frame_slider.valueChanged.disconnect(self.sliderChangeEvent)

    def init_data(self, dataobj):
        self.slicecontrol_pane.setEnabled(True)
        dim = len(dataobj.shape)
        if dim == 3:
            size_x, size_y, size_z = dataobj.shape
            size_frame = None
        elif dim == 4:
            size_x, size_y, size_z, size_frame = dataobj.shape
        else:
            popup_error_dialog(UnexpectedError.message)
            return None

        # init sliders and spinboxes
        self.xaxis_slider.setRange(0, size_x - 1)
        self.yaxis_slider.setRange(0, size_y - 1)
        self.zaxis_slider.setRange(0, size_z - 1)

        self.xaxis_spinbox.setRange(0, size_x - 1)
        self.yaxis_spinbox.setRange(0, size_y - 1)
        self.zaxis_spinbox.setRange(0, size_z - 1)

        if dim == 3:
            self.frame_label.setDisabled(True)
            self.frame_slider.setDisabled(True)
            self.frame_spinbox.setDisabled(True)
        else:
            self.frame_label.setEnabled(True)
            self.frame_slider.setEnabled(True)
            self.frame_spinbox.setEnabled(True)
            self.frame_slider.setRange(0, size_frame - 1)
            self.frame_spinbox.setRange(0, size_frame - 1)

    def update_axisview(self, img_container: dict):
        for view_plane, pixmap in img_container.items():
            if view_plane == 'axial':
                self.axial_view.setPixmap(pixmap)
            elif view_plane == 'sagittal':
                self.sagittal_view.setPixmap(pixmap)
            else:
                self.coronal_view.setPixmap(pixmap)

    def inactivate_widgets(self):
        self.slicecontrol_pane.setDisabled(True)
        self.graph_frame.setDisabled(True)

    def set_navigationmode(self):
        # mouse click will navigate slice.
        pass

    def set_drawingmode(self):
        # roi drawing function
        pass

    def mask_data_handler(self):
        # mask later handler
        pass

    def slider_event_related(self):
        # slider for slicing.
        pass

    def set_viewer_frame(self):
        self.imageframe = QFrame(self)
        self.axial_view = SliceViewer(self.imageframe)
        self.axial_view.setDisabled(True)
        self.sagittal_view = SliceViewer(self.imageframe)
        self.sagittal_view.setDisabled(True)
        self.coronal_view = SliceViewer(self.imageframe)
        self.coronal_view.setDisabled(True)

        # TODO: Will reactivate these on later version
        # self.axial_title = QLabel(self.imageframe)
        # self.coronal_title = QLabel(self.imageframe)
        # self.sagittal_title = QLabel(self.imageframe)
        #
        # self.axialL_label = QLabel(self.imageframe)
        # self.axialA_label = QLabel(self.imageframe)
        # self.axialR_label = QLabel(self.imageframe)
        # self.axialP_label = QLabel(self.imageframe)
        #
        # self.sagittalS_label = QLabel(self.imageframe)
        # self.sagittalA_label = QLabel(self.imageframe)
        # self.sagittalI_label = QLabel(self.imageframe)
        # self.sagittalP_label = QLabel(self.imageframe)
        #
        # self.coronalL_label = QLabel(self.imageframe)
        # self.coronalS_label = QLabel(self.imageframe)
        # self.coronalR_label = QLabel(self.imageframe)
        # self.coronalI_label = QLabel(self.imageframe)
        #
        # self.axial_title.setTextFormat(Qt.MarkdownText)
        # self.axialL_label.setTextFormat(Qt.MarkdownText)
        # self.axialA_label.setTextFormat(Qt.MarkdownText)
        # self.axialR_label.setTextFormat(Qt.MarkdownText)
        # self.axialP_label.setTextFormat(Qt.MarkdownText)
        #
        # self.sagittal_title.setTextFormat(Qt.MarkdownText)
        # self.sagittalS_label.setTextFormat(Qt.MarkdownText)
        # self.sagittalA_label.setTextFormat(Qt.MarkdownText)
        # self.sagittalI_label.setTextFormat(Qt.MarkdownText)
        # self.sagittalP_label.setTextFormat(Qt.MarkdownText)
        #
        # self.coronal_title.setTextFormat(Qt.MarkdownText)
        # self.coronalL_label.setTextFormat(Qt.MarkdownText)
        # self.coronalS_label.setTextFormat(Qt.MarkdownText)
        # self.coronalR_label.setTextFormat(Qt.MarkdownText)
        # self.coronalI_label.setTextFormat(Qt.MarkdownText)
        #
        # self.axial_title.setAlignment(Qt.AlignCenter)
        # self.axialL_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter)
        # self.axialA_label.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
        # self.axialR_label.setAlignment(Qt.AlignLeading | Qt.AlignLeft | Qt.AlignVCenter)
        # self.axialP_label.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
        #
        # self.sagittal_title.setAlignment(Qt.AlignCenter)
        # self.sagittalS_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter)
        # self.sagittalA_label.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
        # self.sagittalI_label.setAlignment(Qt.AlignLeading | Qt.AlignLeft | Qt.AlignVCenter)
        # self.sagittalP_label.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
        #
        # self.coronal_title.setAlignment(Qt.AlignCenter)
        # self.coronalL_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter)
        # self.coronalS_label.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
        # self.coronalR_label.setAlignment(Qt.AlignLeading | Qt.AlignLeft | Qt.AlignVCenter)
        # self.coronalI_label.setAlignment(Qt.AlignHCenter | Qt.AlignTop)

    def set_controller_frame(self):
        self.controller_frame = QFrame(self)
        self.slicecontrol_pane = QGroupBox(self.controller_frame)
        self.frame_spinbox = QSpinBox(self.slicecontrol_pane)

        self.xaxis_label = QLabel(self.slicecontrol_pane)
        self.yaxis_label = QLabel(self.slicecontrol_pane)
        self.zaxis_label = QLabel(self.slicecontrol_pane)
        self.frame_label = QLabel(self.slicecontrol_pane)

        self.xaxis_slider = QSlider(self.slicecontrol_pane)
        self.yaxis_slider = QSlider(self.slicecontrol_pane)
        self.zaxis_slider = QSlider(self.slicecontrol_pane)
        self.frame_slider = QSlider(self.slicecontrol_pane)

        self.xaxis_spinbox = QSpinBox(self.slicecontrol_pane)
        self.yaxis_spinbox = QSpinBox(self.slicecontrol_pane)
        self.zaxis_spinbox = QSpinBox(self.slicecontrol_pane)

        self.graph_frame = QFrame(self)
        self.graph_view = pg.PlotWidget(self.graph_frame)
        self.graph_view.setBackground('w')

        # TODO: Will reactivate these on later version
        # self.graph_view = QGraphicsView(self.graph_frame)
        # self.graphcontrol_pane = QGroupBox(self.graph_frame)
        # self.addmask_button = QPushButton(self.graphcontrol_pane)
        # self.removemask_button = QPushButton(self.graphcontrol_pane)
        # self.mask_listview = QListView(self.graphcontrol_pane)
        # self.savepng_button = QPushButton(self.graphcontrol_pane)
        # self.savecsv_button = QPushButton(self.graphcontrol_pane)

        self.axial_view.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.sagittal_view.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.coronal_view.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

        self.xaxis_slider.setOrientation(Qt.Horizontal)
        self.yaxis_slider.setOrientation(Qt.Horizontal)
        self.zaxis_slider.setOrientation(Qt.Horizontal)
        self.frame_slider.setOrientation(Qt.Horizontal)

        self.slicecontrol_pane.setAlignment(Qt.AlignCenter)
        self.xaxis_label.setAlignment(Qt.AlignCenter)
        self.yaxis_label.setAlignment(Qt.AlignCenter)
        self.zaxis_label.setAlignment(Qt.AlignCenter)
        self.frame_label.setAlignment(Qt.AlignCenter)
        # TODO: Will reactivate these on later version
        # self.graphcontrol_pane.setAlignment(Qt.AlignCenter)

    def set_size(self):
        size = int(config.get('ImageViewer', 'size'))
        self.imageframe.setLineWidth(0)
        self.axial_view.setMinimumSize(QSize(size, size))
        self.axial_view.setMaximumSize(QSize(size, size))
        self.axial_view.setLineWidth(0)
        self.sagittal_view.setMinimumSize(QSize(size, size))
        self.sagittal_view.setMaximumSize(QSize(size, size))
        self.sagittal_view.setLineWidth(0)
        self.coronal_view.setMinimumSize(QSize(size, size))
        self.coronal_view.setMaximumSize(QSize(size, size))
        self.coronal_view.setLineWidth(0)

        # TODO: Will reactivate these on later version
        # self.axialL_label.setMinimumSize(QSize(20, 0))
        # self.axialA_label.setMinimumSize(QSize(0, 20))
        # self.axialR_label.setMinimumSize(QSize(20, 0))
        # self.axialP_label.setMinimumSize(QSize(0, 20))
        # self.sagittalS_label.setMinimumSize(QSize(20, 0))
        # self.sagittalA_label.setMinimumSize(QSize(0, 20))
        # self.sagittalI_label.setMinimumSize(QSize(20, 0))
        # self.sagittalP_label.setMinimumSize(QSize(0, 20))
        # self.coronalL_label.setMinimumSize(QSize(20, 0))
        # self.coronalS_label.setMinimumSize(QSize(0, 20))
        # self.coronalR_label.setMinimumSize(QSize(20, 0))
        # self.coronalI_label.setMinimumSize(QSize(0, 20))

        self.controller_frame.setMinimumSize(QSize(300, 300))
        self.controller_frame.setMaximumSize(QSize(400, 300))
        self.graph_frame.setMinimumSize(QSize(0, 300))
        self.graph_frame.setMaximumSize(QSize(4000, 4000))
        self.graph_view.setMaximumSize(QSize(4000, 600))

        # TODO: Will reactivate these on later version
        # self.graphcontrol_pane.setMinimumSize(QSize(300, 0))
        # self.graphcontrol_pane.setMaximumSize(QSize(300, 4000))
        # self.addmask_button.setMinimumSize(QSize(30, 0))
        # self.addmask_button.setMaximumSize(QSize(30, 4000))
        # self.removemask_button.setMinimumSize(QSize(30, 0))
        # self.removemask_button.setMaximumSize(QSize(30, 4000))

    def set_font(self):
        self.arial_8 = QFont()
        self.arial_8.setFamily(u"Arial")
        self.arial_8.setPointSize(8)
        self.setFont(self.arial_8)
        # TODO: Will reactivate these on later version
        # self.axial_title.setFont(self.arial_8)
        # self.coronal_title.setFont(self.arial_8)
        # self.sagittal_title.setFont(self.arial_8)
        # self.axialL_label.setFont(self.arial_8)
        # self.axialA_label.setFont(self.arial_8)
        # self.axialR_label.setFont(self.arial_8)
        # self.axialP_label.setFont(self.arial_8)
        # self.sagittalS_label.setFont(self.arial_8)
        # self.sagittalA_label.setFont(self.arial_8)
        # self.sagittalI_label.setFont(self.arial_8)
        # self.sagittalP_label.setFont(self.arial_8)
        # self.coronalL_label.setFont(self.arial_8)
        # self.coronalS_label.setFont(self.arial_8)
        # self.coronalR_label.setFont(self.arial_8)
        # self.coronalI_label.setFont(self.arial_8)
        self.slicecontrol_pane.setFont(self.arial_8)

        # TODO: Will reactivate these on later version
        # self.xaxis_label.setFont(self.arial_8)
        # self.yaxis_label.setFont(self.arial_8)
        # self.zaxis_label.setFont(self.arial_8)
        # self.frame_label.setFont(self.arial_8)
        # self.graphcontrol_pane.setFont(self.arial_8)
        # self.addmask_button.setFont(self.arial_8)
        # self.removemask_button.setFont(self.arial_8)
        # self.savepng_button.setFont(self.arial_8)
        # self.savecsv_button.setFont(self.arial_8)

    def set_palette(self):
        # Brush
        gray_text = QBrush(QColor(171, 171, 171, 255))
        gray_text.setStyle(Qt.SolidPattern)
        black_background = QBrush(QColor(0, 0, 0, 255))
        black_background.setStyle(Qt.SolidPattern)

        self.orientation_label_palette = QPalette()
        self.orientation_label_palette.setBrush(QPalette.Active,
                                                QPalette.WindowText, gray_text)
        self.orientation_label_palette.setBrush(QPalette.Inactive,
                                                QPalette.WindowText, gray_text)
        self.orientation_label_palette.setBrush(QPalette.Disabled,
                                                QPalette.WindowText, gray_text)
        self.ortho_viewer_palette = QPalette()
        self.ortho_viewer_palette.setBrush(QPalette.Active, QPalette.Base,
                                           black_background)
        self.ortho_viewer_palette.setBrush(QPalette.Inactive, QPalette.Base,
                                           black_background)
        self.ortho_viewer_palette.setBrush(QPalette.Disabled, QPalette.Base,
                                           black_background)

        self.axialA_label.setPalette(self.orientation_label_palette)
        self.axialL_label.setPalette(self.orientation_label_palette)
        self.axialR_label.setPalette(self.orientation_label_palette)
        self.axialP_label.setPalette(self.orientation_label_palette)
        self.axial_view.setPalette(self.ortho_viewer_palette)
        self.sagittalS_label.setPalette(self.orientation_label_palette)
        self.sagittalA_label.setPalette(self.orientation_label_palette)
        self.sagittalI_label.setPalette(self.orientation_label_palette)
        self.sagittalP_label.setPalette(self.orientation_label_palette)
        self.sagittal_view.setPalette(self.ortho_viewer_palette)
        self.coronalL_label.setPalette(self.orientation_label_palette)
        self.coronalS_label.setPalette(self.orientation_label_palette)
        self.coronalR_label.setPalette(self.orientation_label_palette)
        self.coronalI_label.setPalette(self.orientation_label_palette)
        self.coronal_view.setPalette(self.ortho_viewer_palette)

    def set_gridlayouts(self):
        self.axial_gridLayout = QGridLayout()
        self.coronal_gridLayout = QGridLayout()
        self.sagittal_gridLayout = QGridLayout()
        self.imagecont_gridLayout = QGridLayout(self.slicecontrol_pane)
        self.imageframe_gridLayout = QGridLayout(self.imageframe)
        # self.graphcontrol_gridLayout = QGridLayout(self.graphcontrol_pane)
        self.verticalLayout = QVBoxLayout(self.controller_frame)
        self.horizontalLayout = QHBoxLayout(self.graph_frame)
        self.main_gridLayout = QGridLayout(self)
        # TODO: Will reactivate these on later version
        # self.imageframe_gridLayout.addWidget(self.axial_title, 0, 1, 1, 1)
        # self.imageframe_gridLayout.addWidget(self.coronal_title, 0, 2, 1, 1)
        # self.imageframe_gridLayout.addWidget(self.sagittal_title, 0, 0, 1, 1)
        # self.axial_gridLayout.addWidget(self.axialL_label, 1, 0, 1, 1)
        # self.axial_gridLayout.addWidget(self.axialA_label, 0, 1, 1, 1)
        # self.axial_gridLayout.addWidget(self.axialR_label, 1, 2, 1, 1)
        # self.axial_gridLayout.addWidget(self.axialP_label, 2, 1, 1, 1)
        self.axial_gridLayout.addWidget(self.axial_view, 1, 1, 1, 1)
        # self.sagittal_gridLayout.addWidget(self.sagittalS_label, 1, 0, 1, 1)
        # self.sagittal_gridLayout.addWidget(self.sagittalA_label, 0, 1, 1, 1)
        # self.sagittal_gridLayout.addWidget(self.sagittalI_label, 1, 2, 1, 1)
        # self.sagittal_gridLayout.addWidget(self.sagittalP_label, 2, 1, 1, 1)
        self.sagittal_gridLayout.addWidget(self.sagittal_view, 1, 1, 1, 1)
        # self.coronal_gridLayout.addWidget(self.coronalL_label, 1, 0, 1, 1)
        # self.coronal_gridLayout.addWidget(self.coronalS_label, 0, 1, 1, 1)
        # self.coronal_gridLayout.addWidget(self.coronalR_label, 1, 2, 1, 1)
        # self.coronal_gridLayout.addWidget(self.coronalI_label, 2, 1, 1, 1)
        self.coronal_gridLayout.addWidget(self.coronal_view, 1, 1, 1, 1)
        self.imagecont_gridLayout.addWidget(self.xaxis_label, 0, 0, 1, 1)
        self.imagecont_gridLayout.addWidget(self.xaxis_slider, 0, 1, 1, 1)
        self.imagecont_gridLayout.addWidget(self.xaxis_spinbox, 0, 2, 1, 1)
        self.imagecont_gridLayout.addWidget(self.yaxis_label, 1, 0, 1, 1)
        self.imagecont_gridLayout.addWidget(self.yaxis_slider, 1, 1, 1, 1)
        self.imagecont_gridLayout.addWidget(self.yaxis_spinbox, 1, 2, 1, 1)
        self.imagecont_gridLayout.addWidget(self.zaxis_label, 2, 0, 1, 1)
        self.imagecont_gridLayout.addWidget(self.zaxis_slider, 2, 1, 1, 1)
        self.imagecont_gridLayout.addWidget(self.zaxis_spinbox, 2, 2, 1, 1)
        self.imagecont_gridLayout.addWidget(self.frame_label, 3, 0, 1, 1)
        self.imagecont_gridLayout.addWidget(self.frame_slider, 3, 1, 1, 1)
        self.imagecont_gridLayout.addWidget(self.frame_spinbox, 3, 2, 1, 1)
        self.imageframe_gridLayout.addLayout(self.axial_gridLayout, 1, 1, 1, 1)
        self.imageframe_gridLayout.addLayout(self.coronal_gridLayout, 1, 2, 1,
                                             1)
        self.imageframe_gridLayout.addLayout(self.sagittal_gridLayout, 1, 0, 1,
                                             1)
        # self.graphcontrol_gridLayout.addWidget(self.addmask_button, 3, 0, 1, 1)
        # self.graphcontrol_gridLayout.addWidget(self.removemask_button, 3, 1, 1, 1)
        # self.graphcontrol_gridLayout.addWidget(self.mask_listview, 0, 0, 1, 5)
        # self.graphcontrol_gridLayout.addWidget(self.savepng_button, 3, 4, 1, 1)
        # self.graphcontrol_gridLayout.addWidget(self.savecsv_button, 3, 3, 1, 1)
        self.verticalLayout.addWidget(self.slicecontrol_pane)
        self.horizontalLayout.addWidget(self.graph_view)
        # self.horizontalLayout.addWidget(self.graphcontrol_pane)
        self.main_gridLayout.addWidget(self.imageframe, 0, 0, 1, 2)
        self.main_gridLayout.addWidget(self.controller_frame, 1, 0, 1, 1)
        self.main_gridLayout.addWidget(self.graph_frame, 1, 1, 1, 1)

    def set_objectnames(self):
        self.setObjectName(u"data_browser")
        self.imageframe.setObjectName(u"image_frame")
        self.axial_gridLayout.setObjectName(u"axial_gridLayout")
        self.coronal_gridLayout.setObjectName(u"coronal_gridLayout")
        self.sagittal_gridLayout.setObjectName(u"sagittal_gridLayout")
        # TODO: Will reactivate these on later version
        # self.axial_title.setObjectName(u"axial_label")
        # self.coronal_title.setObjectName(u"coronal_label")
        # self.sagittal_title.setObjectName(u"sagittal_label")
        self.axial_view.setObjectName(u"axial_view")
        self.sagittal_view.setObjectName(u"sagittal_view")
        self.coronal_view.setObjectName(u"coronal_view")
        # self.axialL_label.setObjectName(u"axialL_label")
        # self.axialR_label.setObjectName(u"axialR_label")
        # self.axialA_label.setObjectName(u"axialA_label")
        # self.axialP_label.setObjectName(u"axialP_label")
        # self.sagittalS_label.setObjectName(u"sagittalS_label")
        # self.sagittalA_label.setObjectName(u"sagittalA_label")
        # self.sagittalI_label.setObjectName(u"sagittalI_label")
        # self.sagittalP_label.setObjectName(u"sagittalP_label")
        # self.coronalL_label.setObjectName(u"coronalL_label")
        # self.coronalS_label.setObjectName(u"coronalS_label")
        # self.coronalR_label.setObjectName(u"coronalR_label")
        # self.coronalI_label.setObjectName(u"coronalI_label")
        self.controller_frame.setObjectName(u"controller_frame")
        self.slicecontrol_pane.setObjectName(u"slicecontrol_pane")
        self.xaxis_label.setObjectName(u"xaxis_label")
        self.xaxis_slider.setObjectName(u"xaxis_slider")
        self.xaxis_spinbox.setObjectName(u"xaxis_spinbox")
        self.yaxis_label.setObjectName(u"yaxis_label")
        self.yaxis_slider.setObjectName(u"yaxis_slider")
        self.yaxis_spinbox.setObjectName(u"yaxis_spinbox")
        self.zaxis_label.setObjectName(u"zaxis_label")
        self.zaxis_slider.setObjectName(u"zaxis_slider")
        self.zaxis_spinbox.setObjectName(u"zaxis_spinbox")
        self.frame_label.setObjectName(u"frame_label")
        self.frame_slider.setObjectName(u"frame_slider")
        self.frame_spinbox.setObjectName(u"frame_spinbox")
        self.graph_frame.setObjectName(u"graph_frame")
        self.graph_view.setObjectName(u"graph_view")
        # TODO: Will reactivate these on later version
        # self.graphcontrol_pane.setObjectName(u"graphcontrol_pane")
        # self.addmask_button.setObjectName(u"addmask_button")
        # self.removemask_button.setObjectName(u"removemask_button")
        # self.mask_listview.setObjectName(u"mask_listview")
        # self.savepng_button.setObjectName(u"savepng_button")
        # self.savecsv_button.setObjectName(u"savecsv_button")
        self.imagecont_gridLayout.setObjectName(u"imagecont_gridLayout")
        self.imageframe_gridLayout.setObjectName(u"imageframe_gridLayout")
        # self.graphcontrol_gridLayout.setObjectName(u"graphcontrol_gridLayout")
        self.verticalLayout.setObjectName(u"verticalLayout")
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.main_gridLayout.setObjectName(u"main_gridLayout")
        QMetaObject.connectSlotsByName(self)

    def set_texts(self):
        self.setWindowTitle(u"Data Browser")
        # TODO: Will reactivate these on later version
        # self.axial_title.setText(u"**Axial**")
        # self.coronal_title.setText(u"**Coronal**")
        # self.sagittal_title.setText(u"**Sagittal**")
        # self.sagittalS_label.setText(u"**S**")
        # self.sagittalA_label.setText(u"**A**")
        # self.sagittalI_label.setText(u"**I**")
        # self.sagittalP_label.setText(u"**P**")
        # self.axialL_label.setText(u"**L**")
        # self.axialA_label.setText(u"**A**")
        # self.axialR_label.setText(u"**R**")
        # self.axialP_label.setText( u"**P**")
        # self.coronalL_label.setText(u"**L**")
        # self.coronalS_label.setText(u"**S**")
        # self.coronalR_label.setText(u"**R**")
        # self.coronalI_label.setText(u"**I**")
        self.slicecontrol_pane.setTitle(u"Slice Control Pane")
        self.xaxis_label.setText(u"x")
        self.yaxis_label.setText(u"y")
        self.zaxis_label.setText(u"z")
        self.frame_label.setText(u"Frame")
        # TODO: Will reactivate these on later version
        # self.graphcontrol_pane.setTitle(u"Graph Control Pane")
        # self.addmask_button.setText(u"+")
        # self.removemask_button.setText(u"-")
        # self.savepng_button.setText(u"toPNG")
        # self.savecsv_button.setText(u"toCSV")

    def plot_timecourse(self, x, y):
        self.graph_frame.setEnabled(True)
        self.graph_view.clear()
        pen = pg.mkPen(color=(255, 0, 0))
        if x is None:
            x = [0]
            y = [y]
            self.graph_view.plot(x, y, pen=pen, symbol='o')
        else:
            self.graph_view.plot(x, y, pen=pen)

    def get_coord(self):
        x = self.xaxis_slider.value()
        y = self.yaxis_slider.value()
        z = self.zaxis_slider.value()
        return (x, y, z)
Example #39
0
    def editor(self):
        w = QWidget()
        l = QFormLayout(w)

        width = QSpinBox()
        width.setMinimum(1)
        width.setMaximum(MAX_WIDTH)
        width.setValue(self.desc.width)

        def _set_width(value):
            self.desc.width = value

        width.valueChanged.connect(_set_width)
        l.addRow('Width', width)

        num_inputs = QSpinBox()
        num_inputs.setMinimum(2)
        num_inputs.setValue(self.desc.num_inputs)
        num_inputs.valueChanged.connect(self._set_num_inputs)
        l.addRow('Number of inputs', num_inputs)

        return w
Example #40
0
class Clock_widget(QMainWindow):

    def __init__(self, frameless=False, web=False, debug=0):
        super(Clock_widget, self).__init__()

        self.debug = debug
        self.frameless = frameless
        self.web = web
        self.analog = None
        self.bedtime = QTime(20, 15, 00)
        self.bedtime_grace_period = 10
        self.LEDBall_state = 0
        self.temp_update_interval = 10
        self.n_updates = 0

        self.temp_data = ['i', 0, 0, 0, 'o', 0, 0, 0, 'c', 0, 0]
        self.LCD_brightness = 150

        self.resize(800, 460)
        self.setupUi(self)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update)
        self.timer.start(1000)

    def setupUi(self, parent):
        """Setup the interfaces for the clock."""

        if not self.objectName():
            self.setObjectName(u"Clock")

        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(parent.sizePolicy().hasHeightForWidth())
        parent.setSizePolicy(sizePolicy)
        parent.setAutoFillBackground(True)

        parent.setWindowFlag(Qt.Widget, True)
        if os.uname().sysname == "Linux" or self.frameless:
            parent.setWindowFlag(Qt.FramelessWindowHint, True)
    
        self.tabWidget = QTabWidget(parent)
        self.tabWidget.setObjectName(u"tabWidget")
        self.tabWidget.setGeometry(QRect(0, 0, 800, 460))
        # This works for Mac, but seems to not work with Linux/Arm/RPi
        # tabbar = self.tabWidget.tabBar()
        # tabbar.setMinimumSize(50, 24)
        # tabfont = QFont()
        # tabfont.setBold(True)
        # tabfont.setItalic(True)
        # tabfont.setPointSize(32)
        # tabbar.setFont(tabfont)

        # Setup the TABS
        self.clock = QWidget()
        self.clock.setObjectName(u"clock")
        self.tabWidget.addTab(self.clock, "")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.clock), "Clock")

        self.weather = QWeather(parent=None, debug=self.debug)
        self.tabWidget.addTab(self.weather, "")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.weather), "Weather")

        self.settings = QWidget()
        self.settings.setObjectName(u"settings")
        self.tabWidget.addTab(self.settings, "")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.settings), "Settings")

        self.tabWidget.setCurrentIndex(0)

        #################################################################################################
        # Setup Clock Page
        #################################################################################################

        self.analog = AnalogClock(self.clock)

        # DIGITAL clock in "clock" tab
        self.Digital = QLabel(self.clock)
        self.Digital.setObjectName(u"Digital")
        self.Digital.setGeometry(QRect(0, 5, 765, 71))
        self.Digital.setAutoFillBackground(False)
        self.Digital.setStyleSheet(u"")
        self.Digital.setText(u"Current Time - Date + time")

        # Weather Icon
        self.weathericon = QWeatherIcon((480, 5), self.weather, parent=self.clock)
        self.weather.weather_updated.connect(self.weathericon.update)

        # Weather info on the Clock page.
        self.minipanel = QTempMiniPanel((475, 105), self.weather, parent=self.clock)
        self.weather.temp_updated.connect(self.minipanel.update)

        self.hilo = QHiLoTide((580, 5), parent=self.clock, debug=self.debug)


        # Moon phase
        self.moon = QMoon(pos=(450, 210), parent=self.clock, size=216, web=self.web)

        # Push buttons in "clock tab.
        push_button_width = 111
        push_button_height = 40
        push_button_x = 670
        push_button_y = 220

        self.ledball_off = QPushButton(self.clock)
        self.ledball_off.setObjectName(u"ledball_off")
        self.ledball_off.setText(u"LED off")
        self.ledball_off.setGeometry(QRect(push_button_x, push_button_y, push_button_width, push_button_height))

        self.ledball_on = QPushButton(self.clock)
        self.ledball_on.setObjectName(u"ledball_on")
        self.ledball_on.setText(u"LED on ")
        self.ledball_on.setGeometry(QRect(push_button_x, push_button_y+push_button_height, push_button_width, push_button_height))

        self.ledball_on2 = QPushButton(self.clock)
        self.ledball_on2.setObjectName(u"ledball_on2")
        self.ledball_on2.setText(u"LED on 2")
        self.ledball_on2.setGeometry(QRect(push_button_x, push_button_y+push_button_height*2, push_button_width, push_button_height))

        self.sleep = QPushButton(self.clock)
        self.sleep.setObjectName(u"sleep")
        self.sleep.setText(u"Sleep")
        self.sleep.setGeometry(QRect(push_button_x, push_button_y+push_button_height*3+10, push_button_width, push_button_height))

        #################################################################################################
        # Setup Weather Page
        #################################################################################################

        #################################################################################################
        # Setup Setting Page
        #################################################################################################
        self.timeEdit = QTimeEdit(self.settings)
        self.timeEdit.setObjectName(u"timeEdit")
        self.timeEdit.setDisplayFormat(u"h:mm AP")
        self.timeEdit.setGeometry(QRect(200, 30, 191, 41))
        font8 = QFont()
        font8.setFamily(u"Gill Sans")
        font8.setPointSize(16)
        font8.setBold(False)
        font8.setItalic(False)
        font8.setWeight(50)
        self.timeEdit.setFont(font8)
        self.timeEdit.setAutoFillBackground(True)
        self.timeEdit.setTime(self.bedtime)
        self.bedtime_label = QLabel(self.settings)
        self.bedtime_label.setObjectName(u"bedtime_label")
        self.bedtime_label.setText(u"Set Bedtime:")
        self.bedtime_label.setGeometry(QRect(200, 0, 151, 31))
        self.bedtime_label.setFont(font8)
        self.bedtime_label.setAutoFillBackground(True)
        self.Brightness_Value = QLCDNumber(self.settings)
        self.Brightness_Value.setObjectName(u"Brightness_Value")
        self.Brightness_Value.setGeometry(QRect(20, 120, 61, 31))
        self.Brightness_Value.setStyleSheet(u"color: \"White\";\n"
                                            "margin:0px;\n"
                                            "border:0px;background:\"transparent\";")
        self.Brightness_Value.setDigitCount(3)
        self.Brightness_Value.setProperty("value", 180.000000000000000)
        self.Brightness = QSlider(self.settings)
        self.Brightness.setObjectName(u"Brightness")
        self.Brightness.setGeometry(QRect(30, 160, 51, 261))
        self.Brightness.setAutoFillBackground(False)
        self.Brightness.setMaximum(255)
        self.Brightness.setValue(self.LCD_brightness)
        self.Brightness.setOrientation(Qt.Vertical)
        self.Brightness_label = QLabel(self.settings)
        self.Brightness_label.setObjectName(u"Brightness_label")
        self.Brightness_label.setText(u"Brightness")
        self.Brightness_label.setGeometry(QRect(20, 70, 101, 41))
        font10 = QFont()
        font10.setFamily(u"Arial Black")
        font10.setPointSize(12)
        font10.setBold(True)
        font10.setWeight(75)
        self.Brightness_label.setFont(font10)
        self.temp_test = QLabel(self.settings)
        self.temp_test.setObjectName(u"temp_test")
        self.temp_test.setText(u"T20.5 C")
        self.temp_test.setFont(font8)
        self.temp_test.setGeometry(QRect(630, 60, 141, 51))
        # self.temp_test.setFont(font_bold_20)
        self.temp_test_slide = QSlider(self.settings)
        self.temp_test_slide.setObjectName(u"temp_test_slide")
        self.temp_test_slide.setGeometry(QRect(660, 150, 51, 271))
        self.temp_test_slide.setAutoFillBackground(False)
        self.temp_test_slide.setMinimum(-250)
        self.temp_test_slide.setMaximum(450)
        self.temp_test_slide.setSingleStep(5)
        self.temp_test_slide.setPageStep(25)
        self.temp_test_slide.setValue(38)
        self.temp_test_slide.setOrientation(Qt.Vertical)
        self.temp_check_outside = QCheckBox(self.settings)
        self.temp_check_outside.setObjectName(u"temp_check_outside")
        self.temp_check_outside.setText(u"Outside")
        self.temp_check_outside.setGeometry(QRect(640, 110, 86, 20))
        self.grace_period = QSpinBox(self.settings)
        self.grace_period.setObjectName(u"grace_period")
        self.grace_period.setGeometry(QRect(411, 31, 111, 41))
        self.grace_period.setFont(font8)
        self.grace_period.setMinimum(1)
        self.grace_period.setMaximum(60)
        self.grace_period.setValue(self.bedtime_grace_period)
        self.grace_period.setDisplayIntegerBase(10)
        self.grace_period_label = QLabel(self.settings)
        self.grace_period_label.setObjectName(u"grace_period_label")
        self.grace_period_label.setText(u"Grace period:")
        self.grace_period_label.setGeometry(QRect(410, 10, 111, 16))
        self.grace_period_label.setFont(font8)

        #################################################################################################
        # SET ALL LABEL TEXTS
        #################################################################################################

        # if QT_CONFIG(tooltip)
        self.sleep.setToolTip(u"Put display to sleep")
        self.ledball_on2.setToolTip(u"Turn on the LED Ball, mode 2")
        self.ledball_on.setToolTip(u"Turn on the LED Ball.")
        self.ledball_off.setToolTip(u"Turn off the LED Ball.")
        # endif // QT_CONFIG(tooltip)

        #################################################################################################
        # Make the Connections.
        #################################################################################################

        self.temp_test_slide.valueChanged.connect(self.test_temp_update)
        self.temp_check_outside.clicked.connect(self.test_temp_update)

        self.ledball_off.clicked.connect(self.set_ledball_off)
        self.ledball_on.clicked.connect(self.set_ledball_on)
        self.ledball_on2.clicked.connect(self.set_ledball_on2)
        self.sleep.clicked.connect(self.set_sleep)

        self.timeEdit.timeChanged.connect(self.set_bedtime)
        self.grace_period.valueChanged.connect(self.set_grace_period)
        self.Brightness.valueChanged.connect(self.set_screen_brightness)
        self.Brightness.valueChanged.connect(self.Brightness_Value.display)

    def setup_from_json(self, json):
        """Set settings from the json dictionary passed."""

        if "BedTime" in json:
            new_bedtime = QTime.fromString(json["BedTime"], "hh:mm:ss")
            if not new_bedtime.isValid():
                new_bedtime = QTime.fromString(json["BedTime"], "hh:mm")

            if new_bedtime.isValid():
                self.bedtime = new_bedtime
                self.timeEdit.setTime(self.bedtime)
            else:
                print("Could not set bedtime to {}".format(str(new_bedtime)))

        if "GracePeriod" in json:
            self.bedtime_grace_period = int(json["GracePeriod"])
            self.grace_period.setValue(self.bedtime_grace_period)

        if "Brightness" in json:
            self.LCD_brightness = int(json["Brightness"])
            self.Brightness.setValue(self.LCD_brightness)

    @Slot()
    def update(self):
        """This is called every second to perform the clock functions."""
        AnalogClock.update(self)

        dtime = QDateTime.currentDateTime()
        text = dtime.toString("ddd MMM dd hh:mm:ss")
        self.Digital.setText(text)

        time = dtime.time()
        if self.bedtime < time < self.bedtime.addSecs(self.bedtime_grace_period * 60):
            self.Digital.setStyleSheet("color: rgba(200,100,0,200)")
            self.Digital.setText(text + " Bedtime")

        if self.bedtime < time < self.bedtime.addSecs(1) and self.LEDBall_state > 0:
            self.set_ledball_ready_for_bed()

        if self.bedtime.addSecs(self.bedtime_grace_period*60) < time < \
                self.bedtime.addSecs(self.bedtime_grace_period*60 + 1):
            self.Digital.setStyleSheet("")
            self.set_ledball_off()
            self.turn_off_lcd()


    @Slot()
    def set_ledball_off(self):
        """Turn off the LED ball."""
        if self.debug > 0:
            print("Set LED ball off.")

        os.system("ssh bbb1 \"./LEDBall_off.py\" >/dev/null")
        self.LEDBall_state = 0

    @Slot()
    def set_ledball_ready_for_bed(self):
        """Set LED ball to very red."""
        if self.LEDBall_state != 3:
            if self.debug > 0:
                print("Set LED ball to ready for bed.")
            os.system("ssh bbb1 \"./LEDBall_off.py && ./matrix.py 200 5.\" >/dev/null ")
            self.LEDBall_state = 3

    @Slot()
    def set_ledball_on(self):
        """Turn LED ball to normal on"""
        if self.debug > 0:
            print("Set LED ball on.")

        os.system("(ssh bbb1 \"./LEDBall_off.py && ./matrix.py 200\" >/dev/null)")
        self.LEDBall_state = 1

    @Slot()
    def set_ledball_on2(self):
        """Turn LED ball to alternate on"""
        if self.debug > 0:
            print("Set LED ball alternate on.")

        os.system("(ssh bbb1 \"./LEDBall_off.py && ./matrix.py 300 3. 50\" >/dev/null)");
        self.LEDBall_state = 2

    @Slot()
    def set_sleep(self):
        self.set_ledball_off()
        self.turn_off_lcd()

    def turn_off_lcd(self):
        """Turn the LCD off with the DPMS."""
        if os.uname().sysname == "Linux":
            os.system("/usr/bin/xset dpms force off");

    def set_pressure_color(selfs, obj, press, valid = True):
        """Set the color of obj according to the pressure. """
        pressures = (900., 950., 1000., 1020., 1040.)
        colors = (0, 60, 120, 240, 300)
        if valid:
            if press < pressures[0]:
                press = pressures[0] + 0.0001
            if press > pressures[-1]:
                press = pressures[-1] - 0.0001

            i=0
            while press > pressures[i]:
                i += 1
            hue = int(((press - pressures[i-1])/(pressures[i] - pressures[i-1]))*(colors[i]-colors[i-1]) +
                      colors[i-1])
            color = QColor.fromHsv(hue, 255, 120, 255)
            obj.setStyleSheet("color: rgba({},{},{},255)".format(color.red(), color.green(), color.blue()))


    def set_temp_color(self, obj, temp, inside=True, invalid=False):
        """Set the color of obj depending on the temperature displayed by obj."""
        temps = (-15., 16., 28., 40.)
        colors = (270, 145, 60, 0)

        if inside:
            temps = (12., 20., 25., 32.)

        if invalid:
            obj.setStyleSheet("color: rgba(100,100,100,100)")
        else:
            if temp < temps[0]:
                temp = temps[0] + 0.0001
            if temp > temps[-1]:
                temp = temps[-1] - 0.0001

            i = 0
            while temp > temps[i]:
                i += 1
            hue = int(((temp - temps[i-1])/(temps[i] - temps[i-1]))*(colors[i] - colors[i-1]) + colors[i-1])
            color = QColor.fromHsv(hue, 255, 150, 255)

            obj.setStyleSheet("color: rgba({},{},{},255)".format(color.red(), color.green(), color.blue()))

    @Slot()
    def test_temp_update(self, val=None):
        """Update the temperature on the test slider."""

        if val is None or type(val) is bool:
            val = self.temp_test_slide.value()

        temp = val*0.1
        text = "{:6.2f} C".format(temp)
        self.temp_test.setText(text)
        self.set_temp_color(self.temp_test, temp, not self.temp_check_outside.isChecked(), False)

    @Slot()
    def set_bedtime(self, ntime):
        """Set the bedtime to a new time"""
        self.bedtime = ntime

    @Slot()
    def set_grace_period(self, grace):
        """Set the grace period to a new delta time"""
        self.bedtime_grace_period = grace

    @Slot()
    def set_screen_brightness(self, value):
        """Set the brightness of the screen on Raspberry Pi"""
        self.LCD_brightness = value

        if os.uname().sysname == "Linux":
            try:
                f = open("/sys/class/backlight/rpi_backlight/brightness", "w")
                f.write(str(value))
                f.close()
            except Exception as e:
                print("Issue with opening brightness file \n",e)
Example #41
0
class MagnifierWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(MagnifierWidget, self).__init__(parent)

        self.equalize_radio = QRadioButton(self.tr('Equalization'))
        self.contrast_radio = QRadioButton(self.tr('Auto Contrast'))
        self.retinex_radio = QRadioButton(self.tr('Human Retina'))
        self.centile_spin = QSpinBox()
        self.centile_spin.setRange(0, 100)
        self.centile_spin.setValue(20)
        self.centile_spin.setSuffix(self.tr(' %'))
        self.channel_check = QCheckBox(self.tr('By channel'))
        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.view_changed.connect(self.process)
        self.equalize_radio.toggled.connect(self.change)
        self.contrast_radio.toggled.connect(self.change)
        self.centile_spin.valueChanged.connect(self.change)
        self.channel_check.stateChanged.connect(self.change)
        self.retinex_radio.toggled.connect(self.change)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Enhancement:')))
        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.addWidget(self.retinex_radio)
        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():
            roi = cv.merge([cv.equalizeHist(c) for c in cv.split(roi)])
            self.last_radio = self.equalize_radio
        elif self.contrast_radio.isChecked():
            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
        elif self.retinex_radio.isChecked():
            self.last_radio = self.retinex_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())
Example #42
0
class FirstAlgorithm(QDialog):

    executed = Signal(dict, list)

    defaultParameters = {
        'offset filter': True,
        'supply filter': True,
        'LPF highcut': 3,
        'BPF lowcut': 8,
        'BPF highcut': 30,
        'art thres': 100,
        'window': 25,
        'prev sec': 5,
        'hmt larger': 3,
        'hmt larger mean': 2,
    }

    def __init__(self,
                 dataManager,
                 chartManager,
                 parent=None,
                 inputList=None,
                 initParam=None):
        QDialog.__init__(self, parent)

        self.dataManager = dataManager
        self.fs = self.dataManager.getFs()
        self.chartManager = chartManager
        self.setWindowTitle('Algorithms')
        self.inputList = inputList
        if initParam:
            self.parameters = initParam
            print('initParam')
        else:
            self.parameters = self.defaultParameters
            print('defaultParameters')

        #Setup Layouts
        self.mainLayout = QVBoxLayout(self)
        self.setupInLayout()

        self.setupSettings()

        self.setupBtnBoxLayout()

    def setupInLayout(self):
        inGroup = QGroupBox('Input to process')
        inLayout = QFormLayout(inGroup)

        self.inTree = DataSelector(self.dataManager, inputList=self.inputList)

        inLayout.addWidget(QLabel('Select Input'))
        inLayout.addWidget(self.inTree)

        self.mainLayout.addWidget(inGroup)

    def setupSettings(self):

        spinBoxLayout = QFormLayout()

        self.removeOffset = QCheckBox('Remove DC offset')
        self.removeOffset.setChecked(self.parameters['offset filter'])
        spinBoxLayout.addRow(self.removeOffset)

        self.removeSupply = QCheckBox('Remove 50Hz')
        self.removeSupply.setChecked(self.parameters['supply filter'])
        spinBoxLayout.addRow(self.removeSupply)

        ##        self.lpfHighcut = QSpinBox()
        ##        self.lpfHighcut.setMaximum(10000)
        ##        self.lpfHighcut.setValue(self.parameters['LPF highcut'])
        ##        spinBoxLayout.addRow('LPF highcut frequency:', self.lpfHighcut)

        self.bpfLowcut = QSpinBox()
        self.bpfLowcut.setMaximum(10000)
        self.bpfLowcut.setValue(self.parameters['BPF lowcut'])
        spinBoxLayout.addRow('BPF lowcut frequency:', self.bpfLowcut)

        self.bpfHighcut = QSpinBox()
        self.bpfHighcut.setMaximum(10000)
        self.bpfHighcut.setValue(self.parameters['BPF highcut'])
        spinBoxLayout.addRow('BPF highcut frequency:', self.bpfHighcut)

        ##        self.ArtefactsThreshold = QSpinBox()
        ##        self.ArtefactsThreshold.setMaximum(10000)
        ##        self.ArtefactsThreshold.setValue(self.parameters['art thres'])
        ##        spinBoxLayout.addRow('Artefacts Threshold:', self.ArtefactsThreshold)

        self.algWindowSize = QSpinBox()
        self.algWindowSize.setMaximum(10000)
        self.algWindowSize.setValue(self.parameters['window'])
        spinBoxLayout.addRow('Window (samples):', self.algWindowSize)

        self.hmtLargerMean = QDoubleSpinBox()
        self.hmtLargerMean.setMinimum(0.1)
        self.hmtLargerMean.setMaximum(10000)
        self.hmtLargerMean.setValue(self.parameters['hmt larger mean'])
        spinBoxLayout.addRow('How many times larger than mean:',
                             self.hmtLargerMean)

        self.prevSeconds = QDoubleSpinBox()
        self.prevSeconds.setMinimum(0.1)
        self.prevSeconds.setMaximum(10000)
        self.prevSeconds.setValue(self.parameters['prev sec'])
        spinBoxLayout.addRow('Number of previous seconds:', self.prevSeconds)

        self.hmtLarger = QDoubleSpinBox()
        self.hmtLarger.setMinimum(0.1)
        self.hmtLarger.setMaximum(10000)
        self.hmtLarger.setValue(self.parameters['hmt larger'])
        spinBoxLayout.addRow('How many times larger than previous:',
                             self.hmtLarger)

        gBox = QGroupBox('Settings')
        gBox.setLayout(spinBoxLayout)
        self.mainLayout.addWidget(gBox)

    def setupBtnBoxLayout(self):
        bottomLayout = QHBoxLayout()
        self.progBar = QProgressBar()
        self.progBar.setVisible(False)
        bottomLayout.addWidget(self.progBar)
        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Close)
        buttonBox.accepted.connect(self.okBtnBox)
        buttonBox.rejected.connect(self.close)
        bottomLayout.addWidget(buttonBox)
        self.mainLayout.addLayout(bottomLayout)

    def okBtnBox(self):
        inStruct = self.inTree.getSelectedStruct()
        inDataStruct = self.dataManager.getData(inStruct, inv=True)

        self.progBar.setVisible(True)
        self.progBar.setValue(0)
        nProgres = 5
        progStep = 100.0 / nProgres
        progress = 0

        wName = list(inDataStruct.keys())[0]
        gName = list(inDataStruct[wName].keys())[0]

        ## Input
        inData = np.copy(inDataStruct[wName][gName])

        ## Noises
        if self.removeOffset.isChecked():
            inData = [signal.detrend(data, type='constant') for data in inData]

        if self.removeSupply.isChecked():
            b, a = filterCalc(order=5,
                              bandarr=[48, 52],
                              fs=self.fs,
                              btype='bandstop',
                              ftype='butter')
            inData = [signal.lfilter(b, a, data) for data in inData]

        winLen = self.algWindowSize.value()

        ##        ## Artefacts
        ##        lpfHighcut = self.lpfHighcut.value()
        ##        order=5
        ##
        ##        b, a = filterCalc(order, [lpfHighcut], self.fs, 'low', 'butter')
        ##        lpfData = []
        ##        for data in inData:
        ##            newData = signal.lfilter(b, a, data)
        ##            lpfData.append(newData)
        ##
        ##
        ##
        ##        segNmbr = int(np.shape(lpfData)[1]/winLen)
        ##        artefactsThreshold = self.ArtefactsThreshold.value()
        ##
        ##        lpfWinData = np.copy(lpfData)
        ##        lpfWinData = [np.array_split(ch, segNmbr) for ch in lpfWinData]
        ##
        ##        for ch in lpfWinData:
        ##            for seg in ch:
        ##                seg.fill(max(seg)- min(seg))
        ##
        progress += progStep
        self.progBar.setValue(progress)
        ##
        ####        thresLpfData = np.copy(lpfWinData)
        ##        thresLpfData = deepcopy(lpfWinData)
        ##
        ##        for x in thresLpfData:
        ##            for y in x:
        ##                if y[0] >= artefactsThreshold:
        ##                    y.fill(1)
        ##                else:
        ##                    y.fill(0)
        ##
        ##        lpfWinData = [np.concatenate(ch) for ch in lpfWinData]
        ##        thresLpfData = [np.concatenate(ch) for ch in thresLpfData]
        ##
        progress += progStep
        self.progBar.setValue(progress)

        ## Spikes
        bpfLowcut = self.bpfLowcut.value()
        bpfHighcut = self.bpfHighcut.value()
        order = 4
        b, a = filterCalc(order, [bpfLowcut, bpfHighcut], self.fs, 'band',
                          'butter')
        bpfData = []
        for data in inData:
            newData = signal.lfilter(b, a, data)
            bpfData.append(newData)

        segNmbr = int(np.shape(bpfData)[1] / winLen)

        prevSeconds = self.prevSeconds.value()
        prevWindows = int(prevSeconds * self.fs / winLen)

        progress += progStep
        self.progBar.setValue(progress)

        bpfWinData = np.copy(bpfData)
        bpfWinData = [np.array_split(ch, segNmbr) for ch in bpfWinData]
        chi = 0
        for ch in bpfWinData:
            for seg in ch:
                seg.fill(max(seg) - min(seg))

        progress += progStep
        self.progBar.setValue(progress)

        hmtLarger = self.hmtLarger.value()
        hmtLargerMean = self.hmtLargerMean.value()
        ##        thresBpfData = np.copy(bpfWinData)
        thresBpfData = deepcopy(bpfWinData)

        for ch in range(len(bpfWinData)):
            channelMean = self.hmtLargerMean.value() * np.mean(inData[ch])
            for i in range(prevWindows, len(bpfWinData[ch])):
                if bpfWinData[ch][i][0] > channelMean:
                    prev = [
                        bpfWinData[ch][j][0]
                        for j in range(i - prevWindows, i)
                    ]
                    if bpfWinData[ch][i][0] > hmtLarger * np.mean(prev):
                        thresBpfData[ch][i].fill(1)
                    else:
                        thresBpfData[ch][i].fill(0)
                else:
                    thresBpfData[ch][i].fill(0)

        progress += progStep
        self.progBar.setValue(progress)

        for ch in thresBpfData:
            for i in range(prevWindows):
                ch[i].fill(0)

        bpfWinData = [np.concatenate(ch) for ch in bpfWinData]
        thresBpfData = [np.concatenate(ch) for ch in thresBpfData]

        spikeMap = [np.sum(x) / winLen for x in thresBpfData]
        nazwaPliku = str(winLen) + '_' + str(prevSeconds) + '_' + str(
            hmtLarger) + '.csv'
        with open(nazwaPliku, 'w', encoding='utf-8') as csvfile:
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(spikeMap)


##        for ch in spikeMap
##            csvwriter.writerow(spikeMap)

## Add data or replace existing
        swsName = 'Algorithm output'
        chNames = inStruct[wName][gName]
        if swsName not in self.dataManager.getDataGroups():
            self.dataManager.createDataGroup(swsName, 'Algorithm')
            self.dataManager.addChannels(swsName, chNames)

            self.dataManager.addSignal(swsName, 'Input Signal', inData,
                                       chNames)
            ##            self.dataManager.addSignal(swsName, 'LPF', lpfData, chNames)
            ##            self.dataManager.addSignal(swsName, 'LPF+Window+Peak-to-peak', lpfWinData, chNames)
            ##            self.dataManager.addSignal(swsName, 'LPF+Threshold - Artefacts', thresLpfData, chNames)
            self.dataManager.addSignal(swsName, 'BPF', bpfData, chNames)
            self.dataManager.addSignal(swsName, 'BPF+Window+Peak-to-peak',
                                       bpfWinData, chNames)
            self.dataManager.addSignal(swsName, 'BPF+Threshold - Spikes',
                                       thresBpfData, chNames)
        else:
            self.dataManager.silentChangeSignal(swsName, 'Input Signal',
                                                inData, chNames)
            ##            self.dataManager.silentChangeSignal(swsName, 'LPF', lpfData, chNames)
            ##            self.dataManager.silentChangeSignal(swsName, 'LPF+Window+P2P', lpfWinData, chNames)
            ##            self.dataManager.silentChangeSignal(swsName, 'LPF+Threshold - Artefacts', thresLpfData, chNames)
            self.dataManager.silentChangeSignal(swsName, 'BPF', bpfData,
                                                chNames)
            self.dataManager.silentChangeSignal(swsName,
                                                'BPF+Window+Peak-to-peak',
                                                bpfWinData, chNames)
            self.dataManager.silentChangeSignal(swsName,
                                                'BPF+Threshold - Spikes',
                                                thresBpfData, chNames)

        self.chartManager.setMask('Algorithm output', 'BPF+Threshold - Spikes')
        self.chartManager.setMap(spikeMap)
        self.parameters = {
            'offset filter': self.removeOffset.isChecked(),
            'supply filter': self.removeSupply.isChecked(),
            ##                           'LPF highcut'   : lpfHighcut,
            'BPF lowcut': bpfLowcut,
            'BPF highcut': bpfHighcut,
            ##                           'art thres'     : artefactsThreshold,
            'window': winLen,
            'prev sec': prevSeconds,
            'hmt larger': hmtLarger,
            'hmt larger mean': hmtLargerMean,
        }
        self.executed.emit(self.parameters, self.inputList)
Example #43
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)