コード例 #1
0
class SFeaturesViewer(QWidget):
    """Widget to display a the tracks features table

    Parameters
    ----------
    napari_viewer: QWidget
        The napari viewer

    """
    def __init__(self, napari_viewer):
        super().__init__()
        self.viewer = napari_viewer
        self.layer_name = ''

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        self.tableWidget = QTableWidget()
        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        layout.addWidget(self.tableWidget)
        self.setLayout(layout)

    def reload(self):
        """Reload the tracks features from the layers to the table widget"""
        particles = self.viewer.layers[self.layer_name].data
        features = self.viewer.layers[self.layer_name].metadata
        headers = ['track_id']
        for key in features:
            if isinstance(features[key], dict):
                headers.append(key)
        self.tableWidget.setColumnCount(len(headers))
        self.tableWidget.setHorizontalHeaderLabels(headers)
        self.tableWidget.setRowCount(len(np.unique(particles[:, 0])))

        features_dict = dict()
        tracks_ids = np.unique(particles[:, 0])
        for id_ in tracks_ids:
            features_dict[id_] = list()

        for key in features:
            if isinstance(features[key], dict):
                feature_dict = features[key]
                for f_key in feature_dict:
                    if f_key in features_dict:
                        features_dict[f_key].append(str(feature_dict[f_key]))

        line = -1
        for key in features_dict:
            line += 1
            # track_id = key
            self.tableWidget.setItem(line, 0, QTableWidgetItem(str(key)))
            # add each feature per column
            col = 0
            for feature in features_dict[key]:
                col += 1
                self.tableWidget.setItem(line, col, QTableWidgetItem(feature))
コード例 #2
0
 def create_page_game(self):
     widget = QTableWidget()
     widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
     widget.setSortingEnabled(True)
     widget.setRowCount(1000)
     widget.setColumnCount(len(GAME_LIST))
     widget.setHorizontalHeaderLabels(GAME_LIST)
     header = widget.horizontalHeader()
     for i in range(len(GAME_LIST)):
         header.setSectionResizeMode(i, QHeaderView.ResizeToContents)
     return widget
コード例 #3
0
 def create_page_rank(self):
     widget = QTableWidget()
     widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
     widget.setSortingEnabled(True)
     widget.setRowCount(20)
     widget.setColumnCount(len(RANK_LIST))
     widget.setHorizontalHeaderLabels(RANK_LIST)
     header = widget.horizontalHeader()
     for i in range(len(RANK_LIST)):
         header.setSectionResizeMode(i, QHeaderView.ResizeToContents)
     widget.horizontalHeader().sortIndicatorChanged.connect(
         self.update_chart)
     return widget
コード例 #4
0
ファイル: view.py プロジェクト: ethoeng/mantid
    def _make_table_widget(self):
        """
        Make a table showing the matplotlib figure number of the
        plots, the name with close and edit buttons, and a hidden
        column for sorting with the last actuve order
        :return: A QTableWidget object which will contain plot widgets
        """
        table_widget = QTableWidget(0, 3, self)
        table_widget.setHorizontalHeaderLabels(
            ['No.', 'Plot Name', 'Last Active Order (hidden)'])

        table_widget.verticalHeader().setVisible(False)

        # Fix the size of 'No.' and let 'Plot Name' fill the space
        top_header = table_widget.horizontalHeader()

        table_widget.horizontalHeaderItem(Column.Number).setToolTip(
            'This is the matplotlib figure number.\n\nFrom a '
            'script use plt.figure(N), where N is this figure '
            'number, to get a handle to the plot.')

        table_widget.horizontalHeaderItem(Column.Name).setToolTip(
            'The plot name, also used  as the file name when '
            'saving multiple plots.')

        table_widget.setSelectionBehavior(QAbstractItemView.SelectRows)
        table_widget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        table_widget.sortItems(Column.Number, Qt.AscendingOrder)
        table_widget.setSortingEnabled(True)

        table_widget.horizontalHeader().sectionClicked.connect(
            self.update_sort_menu_selection)

        if not DEBUG_MODE:
            table_widget.setColumnHidden(Column.LastActive, True)

        top_header.resizeSection(Column.Number,
                                 top_header.sectionSizeHint(Column.Number))
        top_header.setSectionResizeMode(Column.Name, QHeaderView.Stretch)

        return table_widget
コード例 #5
0
ファイル: view.py プロジェクト: mantidproject/mantid
    def _make_table_widget(self):
        """
        Make a table showing the matplotlib figure number of the
        plots, the name with close and edit buttons, and a hidden
        column for sorting with the last actuve order
        :return: A QTableWidget object which will contain plot widgets
        """
        table_widget = QTableWidget(0, 3, self)
        table_widget.setHorizontalHeaderLabels(['No.', 'Plot Name', 'Last Active Order (hidden)'])

        table_widget.verticalHeader().setVisible(False)

        # Fix the size of 'No.' and let 'Plot Name' fill the space
        top_header = table_widget.horizontalHeader()

        table_widget.horizontalHeaderItem(Column.Number).setToolTip('This is the matplotlib figure number.\n\nFrom a '
                                                                    'script use plt.figure(N), where N is this figure '
                                                                    'number, to get a handle to the plot.')

        table_widget.horizontalHeaderItem(Column.Name).setToolTip('The plot name, also used  as the file name when '
                                                                  'saving multiple plots.')

        table_widget.setSelectionBehavior(QAbstractItemView.SelectRows)
        table_widget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        table_widget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        table_widget.sortItems(Column.Number, Qt.AscendingOrder)
        table_widget.setSortingEnabled(True)

        table_widget.horizontalHeader().sectionClicked.connect(self.update_sort_menu_selection)

        if not DEBUG_MODE:
            table_widget.setColumnHidden(Column.LastActive, True)

        top_header.resizeSection(Column.Number, top_header.sectionSizeHint(Column.Number))
        top_header.setSectionResizeMode(Column.Name, QHeaderView.Stretch)

        return table_widget
コード例 #6
0
class SPropertiesViewer(QWidget):
    """Widget to display a the particles properties table

    Parameters
    ----------
    napari_viewer: QWidget
        The napari viewer

    """
    def __init__(self, napari_viewer):
        super().__init__()
        self.viewer = napari_viewer
        self.layer_name = ''

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        self.setLayout(layout)
        self.tableWidget = QTableWidget()
        self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
        layout.addWidget(self.tableWidget)
        self.setLayout(layout)

    def reload(self):
        """Reload the particles properties from the layers to the table widget"""
        particles = self.viewer.layers[self.layer_name].data
        print(particles)
        properties = self.viewer.layers[self.layer_name].properties
        headers = []
        if particles.shape[1] == 3:
            headers = ['T', 'Y', 'X']
        elif particles.shape[1] == 4:
            headers = ['T', 'Z', 'Y', 'X']

        for key in properties:
            headers.append(key)
        self.tableWidget.setColumnCount(len(headers))
        self.tableWidget.setHorizontalHeaderLabels(headers)
        self.tableWidget.setRowCount(particles.shape[0])

        col = 0
        for line in range(particles.shape[0]):
            col = -1

            # T
            if particles.shape[1] == 4:
                col += 1
                self.tableWidget.setItem(line, col,
                                         QTableWidgetItem(
                                             str(particles[line, col])))
            # T or Z
            if particles.shape[1] >= 3:
                col += 1
                self.tableWidget.setItem(line, col,
                                         QTableWidgetItem(
                                             str(particles[line, col])))
            # Y
            col += 1
            self.tableWidget.setItem(line, col,
                                     QTableWidgetItem(
                                         str(particles[line, col])))
            # X
            col += 1
            self.tableWidget.setItem(line, col,
                                     QTableWidgetItem(
                                         str(particles[line, col])))
        # properties
        for key in properties:
            col += 1
            prop = properties[key]
            for line in range(len(prop)):
                self.tableWidget.setItem(line, col,
                                         QTableWidgetItem(str(prop[line])))
コード例 #7
0
ファイル: logger.py プロジェクト: locolucco209/MongoScraper
class LogViewerDialog(DialogBase):
    """Logger widget."""

    def __init__(
        self,
        parent=None,
        log_folder=LOG_FOLDER,
        log_filename=LOG_FILENAME,
    ):
        """
        Logger widget.

        Parameters
        ----------
        log_folder: str
            Folder where logs are located
        log_filename: str
            Basic name for the rotating log files.
        """
        super(LogViewerDialog, self).__init__(parent=parent)

        self._data = None
        self._columns = ['level', 'time', 'module', 'method', 'message']
        self._headers = [c.capitalize() for c in self._columns]
        self._log_filename = log_filename
        self._log_folder = log_folder

        # Widgets
        self.label = QLabel('Select log file:')
        self.combobox = ComboBoxBase()
        self.table_logs = QTableWidget(self)
        self.button_copy = ButtonPrimary('Copy')
        self.text_search = LineEditSearch()

        # Widget setup
        self.table_logs.setAttribute(Qt.WA_LayoutUsesWidgetRect, True)
        horizontal_header = self.table_logs.horizontalHeader()
        vertical_header = self.table_logs.verticalHeader()
        horizontal_header.setStretchLastSection(True)
        horizontal_header.setSectionResizeMode(QHeaderView.Fixed)
        vertical_header.setSectionResizeMode(QHeaderView.Fixed)

        self.table_logs.setSelectionBehavior(QTableWidget.SelectRows)
        self.table_logs.setEditTriggers(QTableWidget.NoEditTriggers)

        self.setWindowTitle('Log Viewer')
        self.setMinimumWidth(800)
        self.setMinimumHeight(500)
        self.text_search.setPlaceholderText("Search...")

        # Layouts
        top_layout = QHBoxLayout()
        top_layout.addWidget(self.label)
        top_layout.addWidget(SpacerHorizontal())
        top_layout.addWidget(self.combobox)
        top_layout.addStretch()
        top_layout.addWidget(SpacerHorizontal())
        top_layout.addWidget(self.text_search)
        top_layout.addWidget(SpacerHorizontal())
        top_layout.addWidget(self.button_copy)
        layout = QVBoxLayout()
        layout.addLayout(top_layout)
        layout.addWidget(SpacerVertical())
        layout.addWidget(self.table_logs)
        self.setLayout(layout)

        # Signals
        self.combobox.currentIndexChanged.connect(self.update_text)
        self.button_copy.clicked.connect(self.copy_item)
        self.text_search.textChanged.connect(self.filter_text)

        # Setup()
        self.setup()
        self.update_style_sheet()

    def update_style_sheet(self, style_sheet=None):
        """Update custom CSS stylesheet."""
        if style_sheet is None:
            style_sheet = load_style_sheet()
        self.setStyleSheet(style_sheet)

    def setup(self):
        """Setup widget content."""
        self.combobox.clear()
        paths = log_files(
            log_folder=self._log_folder,
            log_filename=self._log_filename,
        )
        files = [os.path.basename(p) for p in paths]
        self.combobox.addItems(files)

    def filter_text(self):
        """Search for text in the selected log file."""
        search = self.text_search.text().lower()
        for i, data in enumerate(self._data):
            if any(search in str(d).lower() for d in data.values()):
                self.table_logs.showRow(i)
            else:
                self.table_logs.hideRow(i)

    def row_data(self, row):
        """Give the current row data concatenated with spaces."""
        data = {}
        if self._data:
            length = len(self._data)
            if 0 >= row < length:
                data = self._data[row]
        return data

    def update_text(self, index):
        """Update logs based on combobox selection."""
        path = os.path.join(self._log_folder, self.combobox.currentText())
        self._data = load_log(path)

        self.table_logs.clear()
        self.table_logs.setSortingEnabled(False)
        self.table_logs.setRowCount(len(self._data))
        self.table_logs.setColumnCount(len(self._columns))
        self.table_logs.setHorizontalHeaderLabels(self._headers)

        for row, data in enumerate(self._data):
            for col, col_key in enumerate(self._columns):
                item = QTableWidgetItem(data.get(col_key, ''))
                self.table_logs.setItem(row, col, item)

        for c in [0, 2, 3]:
            self.table_logs.resizeColumnToContents(c)

        self.table_logs.resizeRowsToContents()
        self.table_logs.setSortingEnabled(True)
        self.table_logs.scrollToBottom()
        self.table_logs.scrollToTop()
        self.table_logs.sortByColumn(1, Qt.AscendingOrder)

        # Make sure there is always a selected row
        self.table_logs.setCurrentCell(0, 0)

    def copy_item(self):
        """Copy selected item to clipboard in markdown format."""
        app = QApplication.instance()
        items = self.table_logs.selectedIndexes()
        if items:
            rows = set(sorted(i.row() for i in items))
            if self._data:
                all_data = [self._data[row] for row in rows]
                dump = json.dumps(all_data, sort_keys=True, indent=4)
                app.clipboard().setText('```json\n' + dump + '\n```')
コード例 #8
0
class MeasurementWidget(QWidget):
    """
    :type settings: Settings
    :type segment: Segment
    """
    def __init__(self, settings: PartSettings, segment=None):
        super().__init__()
        self.settings = settings
        self.segment = segment
        self.measurements_storage = MeasurementsStorage()
        self.recalculate_button = QPushButton(
            "Recalculate and\n replace measurement", self)
        self.recalculate_button.clicked.connect(
            self.replace_measurement_result)
        self.recalculate_append_button = QPushButton(
            "Recalculate and\n append measurement", self)
        self.recalculate_append_button.clicked.connect(
            self.append_measurement_result)
        self.copy_button = QPushButton("Copy to clipboard", self)
        self.copy_button.setToolTip(
            "You cacn copy also with 'Ctrl+C'. To get raw copy copy with 'Ctrl+Shit+C'"
        )
        self.horizontal_measurement_present = QCheckBox(
            "Horizontal view", self)
        self.no_header = QCheckBox("No header", self)
        self.no_units = QCheckBox("No units", self)
        self.no_units.setChecked(True)
        self.no_units.clicked.connect(self.refresh_view)
        self.expand_mode = QCheckBox("Expand", self)
        self.expand_mode.setToolTip(
            "Shows results for each component in separate entry")
        self.file_names = EnumComboBox(FileNamesEnum)
        self.file_names_label = QLabel("Add file name:")
        self.file_names.currentIndexChanged.connect(self.refresh_view)
        self.horizontal_measurement_present.stateChanged.connect(
            self.refresh_view)
        self.expand_mode.stateChanged.connect(self.refresh_view)
        self.copy_button.clicked.connect(self.copy_to_clipboard)
        self.measurement_type = SearchCombBox(self)
        # noinspection PyUnresolvedReferences
        self.measurement_type.currentIndexChanged.connect(
            self.measurement_profile_selection_changed)
        self.measurement_type.addItem("<none>")
        self.measurement_type.addItems(
            list(sorted(self.settings.measurement_profiles.keys())))
        self.measurement_type.setToolTip(
            'You can create new measurement profile in advanced window, in tab "Measurement settings"'
        )
        self.channels_chose = ChannelComboBox()
        self.units_choose = EnumComboBox(Units)
        self.units_choose.set_value(self.settings.get("units_value", Units.nm))
        self.info_field = QTableWidget(self)
        self.info_field.setColumnCount(3)
        self.info_field.setHorizontalHeaderLabels(["Name", "Value", "Units"])
        self.measurement_add_shift = 0
        layout = QVBoxLayout()
        # layout.addWidget(self.recalculate_button)
        v_butt_layout = QVBoxLayout()
        v_butt_layout.setSpacing(1)
        self.up_butt_layout = QHBoxLayout()
        self.up_butt_layout.addWidget(self.recalculate_button)
        self.up_butt_layout.addWidget(self.recalculate_append_button)
        self.butt_layout = QHBoxLayout()
        # self.butt_layout.setMargin(0)
        # self.butt_layout.setSpacing(10)
        self.butt_layout.addWidget(self.horizontal_measurement_present, 1)
        self.butt_layout.addWidget(self.no_header, 1)
        self.butt_layout.addWidget(self.no_units, 1)
        self.butt_layout.addWidget(self.expand_mode, 1)
        self.butt_layout.addWidget(self.file_names_label)
        self.butt_layout.addWidget(self.file_names, 1)
        self.butt_layout.addWidget(self.copy_button, 2)
        self.butt_layout2 = QHBoxLayout()
        self.butt_layout3 = QHBoxLayout()
        self.butt_layout3.addWidget(QLabel("Channel:"))
        self.butt_layout3.addWidget(self.channels_chose)
        self.butt_layout3.addWidget(QLabel("Units:"))
        self.butt_layout3.addWidget(self.units_choose)
        # self.butt_layout3.addWidget(QLabel("Noise removal:"))
        # self.butt_layout3.addWidget(self.noise_removal_method)
        self.butt_layout3.addWidget(QLabel("Measurement set:"))
        self.butt_layout3.addWidget(self.measurement_type, 2)
        v_butt_layout.addLayout(self.up_butt_layout)
        v_butt_layout.addLayout(self.butt_layout)
        v_butt_layout.addLayout(self.butt_layout2)
        v_butt_layout.addLayout(self.butt_layout3)
        layout.addLayout(v_butt_layout)
        # layout.addLayout(self.butt_layout)
        layout.addWidget(self.info_field)
        self.setLayout(layout)
        # noinspection PyArgumentList
        self.clip = QApplication.clipboard()
        self.settings.image_changed[int].connect(self.image_changed)
        self.previous_profile = None

    def check_if_measurement_can_be_calculated(self, name):
        if name == "<none>":
            return "<none>"
        profile: MeasurementProfile = self.settings.measurement_profiles.get(
            name)
        if profile.is_any_mask_measurement() and self.settings.mask is None:
            QMessageBox.information(
                self, "Need mask",
                "To use this measurement set please use data with mask loaded",
                QMessageBox.Ok)
            self.measurement_type.setCurrentIndex(0)
            return "<none>"
        if self.settings.roi is None:
            QMessageBox.information(
                self,
                "Need segmentation",
                'Before calculating please create segmentation ("Execute" button)',
                QMessageBox.Ok,
            )
            self.measurement_type.setCurrentIndex(0)
            return "<none>"
        return name

    def image_changed(self, channels_num):
        self.channels_chose.change_channels_num(channels_num)

    def measurement_profile_selection_changed(self, index):
        text = self.measurement_type.itemText(index)
        text = self.check_if_measurement_can_be_calculated(text)
        try:
            stat = self.settings.measurement_profiles[text]
            is_mask = stat.is_any_mask_measurement()
            disable = is_mask and (self.settings.mask is None)
        except KeyError:
            disable = True
        self.recalculate_button.setDisabled(disable)
        self.recalculate_append_button.setDisabled(disable)
        if disable:
            self.recalculate_button.setToolTip(
                "Measurement profile contains mask measurements when mask is not loaded"
            )
            self.recalculate_append_button.setToolTip(
                "Measurement profile contains mask measurements when mask is not loaded"
            )
        else:
            self.recalculate_button.setToolTip("")
            self.recalculate_append_button.setToolTip("")

    def copy_to_clipboard(self):
        s = ""
        for r in range(self.info_field.rowCount()):
            for c in range(self.info_field.columnCount()):
                try:
                    s += str(self.info_field.item(r, c).text()) + "\t"
                except AttributeError:
                    s += "\t"
            s = s[:-1] + "\n"  # eliminate last '\t'
        self.clip.setText(s)

    def replace_measurement_result(self):
        self.measurements_storage.clear()
        self.previous_profile = ""
        self.append_measurement_result()

    def refresh_view(self):
        self.measurements_storage.set_expand(self.expand_mode.isChecked())
        self.measurements_storage.set_show_units(not self.no_units.isChecked())
        self.info_field.clear()
        save_orientation = self.horizontal_measurement_present.isChecked()
        columns, rows = self.measurements_storage.get_size(save_orientation)
        self.info_field.setColumnCount(columns)
        self.info_field.setRowCount(rows)
        self.info_field.setHorizontalHeaderLabels(
            self.measurements_storage.get_header(save_orientation))
        self.info_field.setVerticalHeaderLabels(
            self.measurements_storage.get_rows(save_orientation))
        for x in range(rows):
            for y in range(columns):
                self.info_field.setItem(
                    x, y,
                    QTableWidgetItem(
                        self.measurements_storage.get_val_as_str(
                            x, y, save_orientation)))
        if self.file_names.get_value() == FileNamesEnum.No:
            if save_orientation:
                self.info_field.removeColumn(0)
            else:
                self.info_field.removeRow(0)
        elif self.file_names.get_value() == FileNamesEnum.Short:
            if save_orientation:
                columns = 1
            else:
                rows = 1
            for x in range(rows):
                for y in range(columns):
                    item = self.info_field.item(x, y)
                    item.setText(os.path.basename(item.text()))

        self.info_field.setEditTriggers(QAbstractItemView.NoEditTriggers)

    def append_measurement_result(self):
        try:
            compute_class = self.settings.measurement_profiles[
                self.measurement_type.currentText()]
        except KeyError:
            QMessageBox.warning(
                self,
                "Measurement profile not found",
                f"Measurement profile '{self.measurement_type.currentText()}' not found'",
            )
            return

        if self.settings.roi is None:
            return
        units = self.units_choose.get_value()

        # FIXME find which errors should be displayed as warning
        # def exception_hook(exception):
        #    QMessageBox.warning(self, "Calculation error", f"Error during calculation: {exception}")

        for num in compute_class.get_channels_num():
            if num >= self.settings.image.channels:
                QMessageBox.warning(
                    self,
                    "Measurement error",
                    "Cannot calculate this measurement because "
                    f"image do not have channel {num+1}",
                )
                return

        thread = ExecuteFunctionThread(
            compute_class.calculate,
            [
                self.settings.image,
                self.channels_chose.currentIndex(), self.settings.roi_info,
                units
            ],
        )
        dial = WaitingDialog(
            thread,
            "Measurement calculation")  # , exception_hook=exception_hook)
        dial.exec()
        stat: MeasurementResult = thread.result
        if stat is None:
            return
        stat.set_filename(self.settings.image_path)
        self.measurements_storage.add_measurements(stat)
        self.previous_profile = compute_class.name
        self.refresh_view()

    def keyPressEvent(self, e: QKeyEvent):
        if e.modifiers() & Qt.ControlModifier:
            selected = self.info_field.selectedRanges()

            if e.key() == Qt.Key_C:  # copy
                s = ""

                for r in range(selected[0].topRow(),
                               selected[0].bottomRow() + 1):
                    for c in range(selected[0].leftColumn(),
                                   selected[0].rightColumn() + 1):
                        try:
                            s += str(self.info_field.item(r, c).text()) + "\t"
                        except AttributeError:
                            s += "\t"
                    s = s[:-1] + "\n"  # eliminate last '\t'
                self.clip.setText(s)

    def update_measurement_list(self):
        self.measurement_type.blockSignals(True)
        available = list(sorted(self.settings.measurement_profiles.keys()))
        text = self.measurement_type.currentText()
        try:
            index = available.index(text) + 1
        except ValueError:
            index = 0
        self.measurement_type.clear()
        self.measurement_type.addItem("<none>")
        self.measurement_type.addItems(available)
        self.measurement_type.setCurrentIndex(index)
        self.measurement_type.blockSignals(False)

    def showEvent(self, _):
        self.update_measurement_list()

    def event(self, event: QEvent):
        if event.type() == QEvent.WindowActivate:
            self.update_measurement_list()
        return super().event(event)

    @staticmethod
    def _move_widgets(widgets_list: List[Tuple[QWidget, int]],
                      layout1: QBoxLayout, layout2: QBoxLayout):
        for el in widgets_list:
            layout1.removeWidget(el[0])
            layout2.addWidget(el[0], el[1])

    def resizeEvent(self, _event: QResizeEvent) -> None:
        if self.width() < 800 and self.butt_layout2.count() == 0:
            self._move_widgets(
                [(self.file_names_label, 1), (self.file_names, 1),
                 (self.copy_button, 2)],
                self.butt_layout,
                self.butt_layout2,
            )
        elif self.width() > 800 and self.butt_layout2.count() != 0:
            self._move_widgets(
                [(self.file_names_label, 1), (self.file_names, 1),
                 (self.copy_button, 2)],
                self.butt_layout2,
                self.butt_layout,
            )
コード例 #9
0
class LevelsPresetDialog(QDialog):
    # name of the current preset; whether to set this preset as default; dict of Levels
    levels_changed = Signal(str, bool, dict)

    def __init__(self, parent, preset_name, levels):
        super().__init__(parent)

        self.preset_name = preset_name
        self.levels = deepcopy(levels)

        self.setupUi()
        self.update_output()

    def setupUi(self):
        self.resize(480, 340)
        self.vbox = QVBoxLayout(self)
        self.presetLabel = QLabel(self)
        self.table = QTableWidget(0, 4, self)
        self.setAsDefaultCheckbox = QCheckBox("Set as default preset", self)
        self.vbox.addWidget(self.presetLabel)
        self.vbox.addWidget(self.table)
        self.vbox.addWidget(self.setAsDefaultCheckbox)

        self.table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.table.setSelectionBehavior(QTableWidget.SelectRows)
        self.table.setHorizontalHeaderLabels(
            ["Show", "Level name", "Preview", "Preview (dark)"])
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionsClickable(False)
        self.table.horizontalHeader().setSectionsMovable(False)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.table.verticalHeader().setVisible(False)
        self.table.doubleClicked.connect(self.open_level_edit_dialog)

        self.table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table.customContextMenuRequested.connect(self.open_menu)

        buttons = QDialogButtonBox.Reset | QDialogButtonBox.Save | QDialogButtonBox.Cancel
        self.buttonBox = QDialogButtonBox(buttons, self)
        self.vbox.addWidget(self.buttonBox)

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.resetButton = self.buttonBox.button(QDialogButtonBox.Reset)
        self.resetButton.clicked.connect(self.reset)

    def update_output(self):
        self.presetLabel.setText("Preset: {}".format(self.preset_name))
        self.setAsDefaultCheckbox.setChecked(
            CONFIG['default_levels_preset'] == self.preset_name)
        self.table.clearContents()
        self.table.setRowCount(len(self.levels))

        for i, levelname in enumerate(self.levels):
            level = self.levels[levelname]
            checkbox = self.get_level_show_checkbox(level)
            nameItem = QTableWidgetItem(level.levelname)
            preview, previewDark = self.get_preview_items(level)

            self.table.setCellWidget(i, 0, checkbox)
            self.table.setItem(i, 1, nameItem)
            self.table.setItem(i, 2, preview)
            self.table.setItem(i, 3, previewDark)

    def get_level_show_checkbox(self, level):
        checkbox_widget = QWidget(self.table)
        checkbox_widget.setStyleSheet("QWidget { background-color:none;}")

        checkbox = QCheckBox()
        checkbox.setStyleSheet(
            "QCheckBox::indicator { width: 15px; height: 15px;}")
        checkbox.setChecked(level.enabled)

        checkbox_layout = QHBoxLayout()
        checkbox_layout.setAlignment(Qt.AlignCenter)
        checkbox_layout.setContentsMargins(0, 0, 0, 0)
        checkbox_layout.addWidget(checkbox)
        checkbox_widget.setLayout(checkbox_layout)
        return checkbox_widget

    def get_preview_items(self, level):
        previewItem = QTableWidgetItem("Log message")
        previewItem.setBackground(QBrush(level.bg, Qt.SolidPattern))
        previewItem.setForeground(QBrush(level.fg, Qt.SolidPattern))
        previewItemDark = QTableWidgetItem("Log message")
        previewItemDark.setBackground(QBrush(level.bgDark, Qt.SolidPattern))
        previewItemDark.setForeground(QBrush(level.fgDark, Qt.SolidPattern))
        font = QFont(CONFIG.logger_table_font, CONFIG.logger_table_font_size)
        fontDark = QFont(font)
        if 'bold' in level.styles:
            font.setBold(True)
        if 'italic' in level.styles:
            font.setItalic(True)
        if 'underline' in level.styles:
            font.setUnderline(True)
        if 'bold' in level.stylesDark:
            fontDark.setBold(True)
        if 'italic' in level.stylesDark:
            fontDark.setItalic(True)
        if 'underline' in level.stylesDark:
            fontDark.setUnderline(True)
        previewItem.setFont(font)
        previewItemDark.setFont(fontDark)
        return previewItem, previewItemDark

    def open_level_edit_dialog(self, index):
        levelname = self.table.item(index.row(), 1).data(Qt.DisplayRole)
        level = self.levels[levelname]
        d = LevelEditDialog(self, level)
        d.setWindowModality(Qt.NonModal)
        d.setWindowTitle('Level editor')
        d.level_changed.connect(self.update_output)
        d.open()

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

        preset_menu = menu.addMenu('Presets')
        preset_menu.addAction('New preset', self.new_preset_dialog)
        preset_menu.addSeparator()

        preset_names = CONFIG.get_levels_presets()

        if len(preset_names) == 0:
            action = preset_menu.addAction('No presets')
            action.setEnabled(False)
        else:
            delete_menu = menu.addMenu('Delete preset')
            for name in preset_names:
                preset_menu.addAction(name, partial(self.load_preset, name))
                delete_menu.addAction(name, partial(self.delete_preset, name))

        menu.addSeparator()
        menu.addAction('New level...', self.create_new_level_dialog)

        if len(self.table.selectedIndexes()) > 0:
            menu.addAction('Delete selected', self.delete_selected)

        menu.popup(self.table.viewport().mapToGlobal(position))

    def load_preset(self, name):
        new_levels = CONFIG.load_levels_preset(name)
        if not new_levels:
            return

        self.levels = new_levels
        self.preset_name = name
        self.update_output()

    def delete_preset(self, name):
        CONFIG.delete_levels_preset(name)
        if name == self.preset_name:
            self.reset()

    def delete_selected(self):
        selected = self.table.selectionModel().selectedRows()
        for index in selected:
            item = self.table.item(index.row(), 1)
            del self.levels[item.text()]
        self.update_output()

    def new_preset_dialog(self):
        d = QInputDialog(self)
        d.setLabelText('Enter the new name for the new preset:')
        d.setWindowTitle('Create new preset')
        d.textValueSelected.connect(self.create_new_preset)
        d.open()

    def create_new_preset(self, name):
        if name in CONFIG.get_levels_presets():
            show_warning_dialog(
                self, "Preset creation error",
                'Preset named "{}" already exists.'.format(name))
            return
        if len(name.strip()) == 0:
            show_warning_dialog(
                self, "Preset creation error",
                'This preset name is not allowed.'.format(name))
            return

        self.preset_name = name
        self.update_output()
        CONFIG.save_levels_preset(name, self.levels)

    def create_new_level_dialog(self):
        d = LevelEditDialog(self,
                            creating_new_level=True,
                            level_names=self.levels.keys())
        d.setWindowModality(Qt.NonModal)
        d.setWindowTitle('Level editor')
        d.level_changed.connect(self.level_changed)
        d.open()

    def level_changed(self, level):
        if level.levelname in self.levels:
            self.levels.copy_from(level)
        else:
            self.levels[level.levelname] = level
        self.update_output()

    def accept(self):
        for i, _ in enumerate(self.levels):
            checkbox = self.table.cellWidget(i, 0).children()[1]
            levelname = self.table.item(i, 1).text()
            self.levels[levelname].enabled = checkbox.isChecked()
        self.levels_changed.emit(self.preset_name,
                                 self.setAsDefaultCheckbox.isChecked(),
                                 self.levels)
        self.done(0)

    def reject(self):
        self.done(0)

    def reset(self):
        for levelname, level in self.levels.items():
            level.copy_from(get_default_level(levelname))
        self.update_output()
コード例 #10
0
ファイル: auxiliary_dialogs.py プロジェクト: lnls-sirius/hla
class OpticsAdjustSettings(SiriusDialog):
    """Auxiliar window to optics adjust settings."""

    updateSettings = Signal(str, str)

    def __init__(self, tuneconfig_currname, chromconfig_currname, parent=None):
        """Initialize object."""
        super().__init__(parent)
        self.setWindowTitle('Optics Adjust Settings')
        self.setObjectName('BOApp')
        self.tuneconfig_currname = tuneconfig_currname
        self.chromconfig_currname = chromconfig_currname
        self.conn_tuneparams = _ConfigDBClient(
            config_type='bo_tunecorr_params')
        self.conn_chromparams = _ConfigDBClient(
            config_type='bo_chromcorr_params')
        self._setupUi()

    def _setupUi(self):
        self.tune_settings = QWidget(self)
        self.tune_settings.setLayout(self._setupTuneSettings())
        self.le_tuneconfig.setText(self.tuneconfig_currname)
        self.chrom_settings = QWidget(self)
        self.chrom_settings.setLayout(self._setupChromSettings())
        self.le_chromconfig.setText(self.chromconfig_currname)
        self.bt_apply = QPushButton('Apply Settings', self)
        self.bt_apply.setStyleSheet("""min-width:8em; max-width:8em;""")
        self.bt_apply.clicked.connect(self._emitSettings)
        self.bt_apply.setAutoDefault(False)
        self.bt_apply.setDefault(False)
        hlay_apply = QHBoxLayout()
        hlay_apply.addItem(
            QSpacerItem(20, 60, QSzPlcy.Expanding, QSzPlcy.Ignored))
        hlay_apply.addWidget(self.bt_apply)

        tabs = QTabWidget(self)
        tabs.addTab(self.tune_settings, 'Tune')
        tabs.addTab(self.chrom_settings, 'Chromaticity')

        lay = QVBoxLayout()
        lay.addWidget(tabs)
        lay.addLayout(hlay_apply)
        self.setLayout(lay)

    def _setupTuneSettings(self):
        l_tuneconfig = QLabel('<h3>Tune Variation Config</h3>', self)
        l_tuneconfig.setAlignment(Qt.AlignCenter)
        self.le_tuneconfig = _ConfigLineEdit(parent=self,
                                             config_type='bo_tunecorr_params')
        self.le_tuneconfig.textChanged.connect(self._showTuneConfigData)

        label_tunemat = QLabel('<h4>Matrix</h4>', self)
        label_tunemat.setAlignment(Qt.AlignCenter)
        self.table_tunemat = QTableWidget(self)
        self.table_tunemat.setObjectName('tunemat')
        self.table_tunemat.setStyleSheet("""
            #tunemat{
                background-color: #efebe7;
                min-width: 22.14em;
                min-height: 6em; max-height: 6em;}""")
        self.table_tunemat.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table_tunemat.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_tunemat.setRowCount(2)
        self.table_tunemat.setColumnCount(2)
        self.table_tunemat.setVerticalHeaderLabels(['  X', '  Y'])
        self.table_tunemat.setHorizontalHeaderLabels(['QF', 'QD'])
        self.table_tunemat.horizontalHeader().setStyleSheet("""
            min-height:1.55em; max-height:1.55em;""")
        self.table_tunemat.verticalHeader().setStyleSheet("""
            min-width:1.55em; max-width:1.55em;""")
        self.table_tunemat.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.table_tunemat.verticalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.table_tunemat.setSizePolicy(QSzPlcy.MinimumExpanding,
                                         QSzPlcy.Preferred)

        label_nomKL = QLabel('<h4>Nominal KL</h4>')
        label_nomKL.setAlignment(Qt.AlignCenter)
        self.table_nomKL = QTableWidget(self)
        self.table_nomKL.setObjectName('nomKL')
        self.table_nomKL.setStyleSheet("""
            #nomKL{
                background-color: #efebe7;
                min-width: 22.14em;
                min-height: 4em; max-height: 4em;}""")
        self.table_nomKL.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table_nomKL.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_nomKL.setRowCount(1)
        self.table_nomKL.setColumnCount(2)
        self.table_nomKL.setVerticalHeaderLabels(['KL'])
        self.table_nomKL.setHorizontalHeaderLabels(['QF', 'QD'])
        self.table_nomKL.horizontalHeader().setStyleSheet("""
            min-height:1.55em; max-height:1.55em;""")
        self.table_nomKL.verticalHeader().setStyleSheet("""
            min-width:1.55em; max-width:1.55em;""")
        self.table_nomKL.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.table_nomKL.verticalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.table_nomKL.setSizePolicy(QSzPlcy.MinimumExpanding,
                                       QSzPlcy.Preferred)

        lay = QVBoxLayout()
        lay.addWidget(l_tuneconfig)
        lay.addWidget(self.le_tuneconfig)
        lay.addItem(QSpacerItem(20, 10, QSzPlcy.Ignored, QSzPlcy.Expanding))
        lay.addWidget(label_tunemat)
        lay.addWidget(self.table_tunemat)
        lay.addItem(QSpacerItem(20, 10, QSzPlcy.Ignored, QSzPlcy.Expanding))
        lay.addWidget(label_nomKL)
        lay.addWidget(self.table_nomKL)
        lay.addItem(QSpacerItem(20, 10, QSzPlcy.Ignored, QSzPlcy.Expanding))

        return lay

    def _setupChromSettings(self):
        l_chromconfig = QLabel('<h3>Chromaticity Variation Config</h3>', self)
        l_chromconfig.setAlignment(Qt.AlignCenter)
        self.le_chromconfig = _ConfigLineEdit(
            parent=self, config_type='bo_chromcorr_params')
        self.le_chromconfig.textChanged.connect(self._showChromConfigData)

        l_chrommat = QLabel('<h4>Matrix</h4>', self)
        l_chrommat.setAlignment(Qt.AlignCenter)
        self.table_chrommat = QTableWidget(self)
        self.table_chrommat.setObjectName('chrommat')
        self.table_chrommat.setStyleSheet("""
            #chrommat{
                background-color: #efebe7;
                min-width: 22.14em;
                min-height: 6em; max-height: 6em;}""")
        self.table_chrommat.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table_chrommat.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_chrommat.setRowCount(2)
        self.table_chrommat.setColumnCount(2)
        self.table_chrommat.setVerticalHeaderLabels(['  X', '  Y'])
        self.table_chrommat.setHorizontalHeaderLabels(['SF', 'SD'])
        self.table_chrommat.horizontalHeader().setStyleSheet("""
            min-height:1.55em; max-height:1.55em;""")
        self.table_chrommat.verticalHeader().setStyleSheet("""
            min-width:1.55em; max-width:1.55em;""")
        self.table_chrommat.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.table_chrommat.verticalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.table_chrommat.setSizePolicy(QSzPlcy.MinimumExpanding,
                                          QSzPlcy.Preferred)

        l_nomSL = QLabel('<h4>Nominal SL</h4>')
        l_nomSL.setAlignment(Qt.AlignCenter)
        self.table_nomSL = QTableWidget(self)
        self.table_nomSL.setObjectName('nomSL')
        self.table_nomSL.setStyleSheet("""
            #nomSL{
                background-color: #efebe7;
                min-width: 22.14em;
                min-height: 4em; max-height: 4em;}""")
        self.table_nomSL.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.table_nomSL.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.table_nomSL.setRowCount(1)
        self.table_nomSL.setColumnCount(2)
        self.table_nomSL.setVerticalHeaderLabels(['SL'])
        self.table_nomSL.setHorizontalHeaderLabels(['SF', 'SD'])
        self.table_nomSL.horizontalHeader().setStyleSheet("""
            min-height:1.55em; max-height:1.55em;""")
        self.table_nomSL.verticalHeader().setStyleSheet("""
            min-width:1.55em; max-width:1.55em;""")
        self.table_nomSL.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.table_nomSL.verticalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.table_nomSL.setSizePolicy(QSzPlcy.MinimumExpanding,
                                       QSzPlcy.Preferred)

        l_nomchrom = QLabel('<h4>Nominal Chrom</h4>')
        l_nomchrom.setAlignment(Qt.AlignCenter)
        self.label_nomchrom = QLabel()
        self.label_nomchrom.setAlignment(Qt.AlignCenter)

        lay = QVBoxLayout()
        lay.addWidget(l_chromconfig)
        lay.addWidget(self.le_chromconfig)
        lay.addItem(QSpacerItem(20, 10, QSzPlcy.Expanding, QSzPlcy.Expanding))
        lay.addWidget(l_chrommat)
        lay.addWidget(self.table_chrommat)
        lay.addItem(QSpacerItem(20, 10, QSzPlcy.Expanding, QSzPlcy.Expanding))
        lay.addWidget(l_nomSL)
        lay.addWidget(self.table_nomSL)
        lay.addItem(QSpacerItem(20, 10, QSzPlcy.Expanding, QSzPlcy.Expanding))
        lay.addWidget(l_nomchrom)
        lay.addWidget(self.label_nomchrom)

        return lay

    def _showTuneConfigData(self):
        try:
            name = self.le_tuneconfig.text()
            config = self.conn_tuneparams.get_config_value(name=name)
            mat = config['matrix']
            nomKL = config['nominal KLs']
        except _ConfigDBException as err:
            QMessageBox.critical(self, 'Error', str(err), QMessageBox.Ok)
        else:
            self.tuneconfig_currname = name
            self.table_tunemat.setItem(0, 0, QTableWidgetItem(str(mat[0][0])))
            self.table_tunemat.setItem(0, 1, QTableWidgetItem(str(mat[0][1])))
            self.table_tunemat.setItem(1, 0, QTableWidgetItem(str(mat[1][0])))
            self.table_tunemat.setItem(1, 1, QTableWidgetItem(str(mat[1][1])))
            self.table_tunemat.item(0, 0).setFlags(Qt.ItemIsEnabled)
            self.table_tunemat.item(0, 1).setFlags(Qt.ItemIsEnabled)
            self.table_tunemat.item(1, 0).setFlags(Qt.ItemIsEnabled)
            self.table_tunemat.item(1, 1).setFlags(Qt.ItemIsEnabled)
            self.table_nomKL.setItem(0, 0, QTableWidgetItem(str(nomKL[0])))
            self.table_nomKL.setItem(0, 1, QTableWidgetItem(str(nomKL[1])))
            self.table_nomKL.item(0, 0).setFlags(Qt.ItemIsEnabled)
            self.table_nomKL.item(0, 1).setFlags(Qt.ItemIsEnabled)

    def _showChromConfigData(self):
        try:
            name = self.le_chromconfig.text()
            config = self.conn_chromparams.get_config_value(name=name)
            mat = config['matrix']
            nomSL = config['nominal SLs']
            nomChrom = config['nominal chrom']
        except _ConfigDBException as err:
            QMessageBox.critical(self, 'Error', str(err), QMessageBox.Ok)
        else:
            self.chromconfig_currname = name
            self.table_chrommat.setItem(0, 0, QTableWidgetItem(str(mat[0][0])))
            self.table_chrommat.setItem(0, 1, QTableWidgetItem(str(mat[0][1])))
            self.table_chrommat.setItem(1, 0, QTableWidgetItem(str(mat[1][0])))
            self.table_chrommat.setItem(1, 1, QTableWidgetItem(str(mat[1][1])))
            self.table_chrommat.item(0, 0).setFlags(Qt.ItemIsEnabled)
            self.table_chrommat.item(0, 1).setFlags(Qt.ItemIsEnabled)
            self.table_chrommat.item(1, 0).setFlags(Qt.ItemIsEnabled)
            self.table_chrommat.item(1, 1).setFlags(Qt.ItemIsEnabled)
            self.table_nomSL.setItem(0, 0, QTableWidgetItem(str(nomSL[0])))
            self.table_nomSL.setItem(0, 1, QTableWidgetItem(str(nomSL[1])))
            self.table_nomSL.item(0, 0).setFlags(Qt.ItemIsEnabled)
            self.table_nomSL.item(0, 1).setFlags(Qt.ItemIsEnabled)
            self.label_nomchrom.setText(str(nomChrom))

    def _emitSettings(self):
        tuneconfig_name = self.le_tuneconfig.text()
        chromconfig_name = self.le_chromconfig.text()
        self.updateSettings.emit(tuneconfig_name, chromconfig_name)
        self.close()