class MeasuredDataModel(QObject):
    def __init__(self, calculator, parent=None):
        super().__init__(parent)
        self._project_dict = calculator.asDict()
        self._headers_model = QStandardItemModel()
        self._data_model = QStandardItemModel()
        self._setModelsFromProjectDict()

    def _setModelsFromProjectDict(self):
        """Create the model needed for GUI calculated data table and chart."""
        self._data_model.setColumnCount(0)  # faster than clear()
        self._headers_model.setRowCount(0)  # faster than clear()
        for experiment_id, experiment_dict in self._project_dict[
                'experiments'].items():
            headers = []
            for data_id, data_list in experiment_dict['measured'].items(
            ):  # or measured_pattern as calculated_pattern in another class?
                item = QStandardItem()
                item.setData(data_id, Qt.DisplayRole)
                headers.append(item)
                column = []
                for value in data_list:
                    item = QStandardItem()
                    item.setData(value, Qt.DisplayRole)
                    column.append(item)
                self._data_model.appendColumn(column)
            self._headers_model.appendRow(headers)

    def asHeadersModel(self):
        """Return headers model."""
        return self._headers_model

    def asDataModel(self):
        """Return data model."""
        return self._data_model
예제 #2
0
class CalculatedDataModel(QObject):
    def __init__(self, calculator, parent=None):
        super().__init__(parent)
        calculator.projectDictChanged.connect(self.onProjectChanged)
        self._project_dict = calculator.asDict()
        self._headers_model = QStandardItemModel()
        self._data_model = QStandardItemModel()
        self._setModelsFromProjectDict()

    def _setModelsFromProjectDict(self):
        """Create the model needed for GUI calculated data table and chart."""
        self._data_model.setColumnCount(0) # faster than clear()
        self._headers_model.setRowCount(0) # faster than clear()
        for experiment_id, experiment_dict in self._project_dict['calculations'].items():
            headers_row = []
            logging.info("setData start") # profiling
            for data_id, data_list in experiment_dict['calculated_pattern'].items():
                item = QStandardItem()
                item.setData(data_id, Qt.DisplayRole)
                headers_row.append(item)
                data_column = []
                for value in data_list:
                    item = QStandardItem()
                    item.setData(value, Qt.DisplayRole)
                    data_column.append(item)
                self._data_model.appendColumn(data_column)
            self._headers_model.appendRow(headers_row)
            logging.info("setData end") # profiling

    modelChanged = Signal()

    def onProjectChanged(self):
        """Set headers and data models from project dictionary"""
        self._setModelsFromProjectDict()
        self.modelChanged.emit()

    def asHeadersModel(self):
        """Return headers model."""
        return self._headers_model

    def asDataModel(self):
        """Return data model."""
        return self._data_model
예제 #3
0
class StatusModel(BaseModel):
    def __init__(self, parent=None):
        super().__init__(parent)

        self._calculator = None

        # Create the status items
        chi_item = StatusItem('chiSq',
                              title='Current \u03c7\u00b2',
                              additionalData=1)
        chi_item.setReturn(True)
        chi_item.title = 'Previous \u03c7\u00b2'
        chi_item.setReturn(False)
        self._interestedList = StatusList([
            chi_item,
            StatusItem('numPars', title='Fit parameters', additionalData=1),
            StatusItem('numData', title='Experiments', additionalData=0),
            StatusItem('numPhases', title='Phases', additionalData=0)
        ])

        # minor properties
        self._first_role = Qt.UserRole + 1

        self._statusBarModel = QStandardItemModel()
        self._chartDisplayModel = QStandardItemModel()
        # set role names
        self._role_names_list = ['label', 'value']
        self._roles_list = []
        self._roles_dict = {'status': {}, 'plot': {}}
        self._setRolesListAndDict()
        self._statusBarModel.setItemRoleNames(self._roles_dict['status'])
        self._chartDisplayModel.setItemRoleNames(self._roles_dict['plot'])

        self._log = logger.getLogger(self.__class__.__module__)

    def _setRolesListAndDict(self):
        """..."""
        offset = 100
        for i, role_name in enumerate(self._role_names_list):
            display_role = self._first_role + i
            self._roles_dict['status'][display_role] = role_name.encode()
            self._roles_list.append(display_role)
            self._roles_dict['plot'][self._first_role + i +
                                     offset] = role_name.encode()

    def _setModelsFromProjectDict(self):
        """Create the initial data list with structure for GUI fitables table."""
        _ = self._statusBarModel.removeColumns(
            0, self._statusBarModel.columnCount())
        _ = self._chartDisplayModel.removeColumns(
            0, self._chartDisplayModel.columnCount())

        column_status_bar = []
        column_chart_display = []

        self._updateStatusList()

        for interest in self._interestedList:
            # Add the status bar item
            column_status_bar.append(
                self._makeItem(interest, self._roles_dict['status'].items()))
            # Does this need to added to the plot?
            if interest.additionalData == 1:
                column_chart_display.append(
                    self._makeItem(interest, self._roles_dict['plot'].items()))

            # Does this item also have previous values which need to be shown?
            if interest.hasPrevious:
                interest.setReturn(True)
                if interest.value is not None:
                    column_status_bar.append(
                        self._makeItem(interest,
                                       self._roles_dict['status'].items()))
                interest.setReturn(False)

        # Set the models
        self._statusBarModel.appendColumn(column_status_bar)
        self._chartDisplayModel.appendColumn(column_chart_display)

        self._statusBarModel.dataChanged.emit(
            self._statusBarModel.index(0, 0),
            self._statusBarModel.index(self._statusBarModel.rowCount() - 1,
                                       self._statusBarModel.columnCount() - 1),
            self._roles_list)

    def _updateStatusList(self):
        """Update the values of the Item List"""
        project_dict = self._project_dict

        # Set chi squared
        try:
            self._interestedList.setItemValue(
                'chiSq',
                round(float(project_dict['info']['chi_squared'].value), 2))
        except KeyError:
            self._interestedList.setItemValue('chiSq', 0)

        # Get number of parameters
        num_pars = get_num_refine_pars(project_dict.asDict())

        # Set the other parameters.
        self._interestedList.setItemValue('numPars', num_pars)
        self._interestedList.setItemValue('numPhases',
                                          len(project_dict['phases']))
        self._interestedList.setItemValue('numData',
                                          len(project_dict['experiments']))

    def returnStatusBarModel(self):
        """Return the status bar model."""
        return self._statusBarModel

    def onRefinementDone(self):
        """Define what to do when the refinement done is triggered"""
        self._setModelsFromProjectDict()
        self._chartDisplayModel.layoutChanged.emit()

    def returnChartModel(self):
        """Return the chart model"""
        return self._chartDisplayModel

    @staticmethod
    def _makeItem(this_interest, these_items):
        """Make an item. This can be a plot or status bar"""
        item = QStandardItem()
        for role, role_name_bytes in these_items:
            role_name = role_name_bytes.decode()
            if role_name == 'label':
                value = this_interest.title
            elif role_name == 'value':
                value = this_interest.value
            else:
                continue
            item.setData(value, role)
        return item
예제 #4
0
class DesktopTimelogDialog(
        QtWidgets.QWidget,
        ui_sg_desktop_timelog_dialog.Ui_ShotgunDesktopTimelogDialog):
    def __init__(self, project_name, user_name, parent=None):
        super(DesktopTimelogDialog, self).__init__(parent)
        self.setupUi(self)
        self.timer = QtCore.QTimer()
        self.treeViewAsset.expanded.connect(self.asset_expanded)
        self.treeViewShot.expanded.connect(self.shot_expanded)
        self.treeViewSequence.expanded.connect(self.sequence_expanded)
        self.treeViewAsset.clicked.connect(self.treeview_single_clicked)
        self.treeViewShot.clicked.connect(self.treeview_single_clicked)
        self.treeViewSequence.clicked.connect(self.treeview_single_clicked)
        self.treeViewMyTask.clicked.connect(self.treeview_single_clicked)
        self.timer.timeout.connect(self.disable_double_clicked)
        self.tabWidgetList.currentChanged.connect(self.tab_widget_list_index)
        self.tabWidgetList.setCurrentIndex(0)

        self.tableWidgetTimelog.setColumnWidth(0, 90)
        self.tableWidgetTimelog.setColumnWidth(1, 100)
        self.tableWidgetTimelog.setColumnWidth(2, 70)
        self.tableWidgetTimelog.setColumnWidth(3, 300)
        self.tableWidgetTimelog.setColumnWidth(4, 30)
        self.tableWidgetTimelog.setSelectionBehavior(
            QtWidgets.QAbstractItemView.SelectRows)
        self.tableWidgetTimelog.setSelectionMode(
            QtWidgets.QAbstractItemView.SingleSelection)
        self.tableWidgetTimelog.setCornerButtonEnabled(True)
        self.tableWidgetTimelog.horizontalHeader().setSectionsClickable(False)
        self.tableWidgetTimelog.verticalHeader().setVisible(False)
        self.tableWidgetTimelog.horizontalHeader().setVisible(True)
        self.tableWidgetTimelog.setFrameShape(QtWidgets.QFrame.StyledPanel)

        self.tableWidgetTimelog.setContextMenuPolicy(
            QtCore.Qt.CustomContextMenu)
        self.tableWidgetTimelog.customContextMenuRequested[
            QtCore.QPoint].connect(self.right_context_menu)

        self.pushButtonSubmit.setEnabled(False)
        self.dateEditDate.setDate(QtCore.QDate.currentDate())

        validator = QDoubleValidator(0, 999, 1, self)
        validator.setNotation(QDoubleValidator.StandardNotation)
        self.lineEditDuration.setValidator(validator)

        self.project_name = project_name
        self.user_name = user_name
        self.sg = sg_publish.ShotgunPublish()
        self.project_entity = self.sg.get_project(self.project_name)

        # init source model
        self.source_asset_model = QStandardItemModel(self.treeViewAsset)
        self.source_shot_model = QStandardItemModel(self.treeViewShot)
        self.source_sequence_model = QStandardItemModel(self.treeViewSequence)
        self.source_mytask_model = QStandardItemModel(self.treeViewMyTask)

        # init treeview ui data
        self.tab_asset_ui()
        self.tab_shot_ui()
        self.tab_sequence_ui()
        self.tab_mytask_ui()

        self._project_level_info = []
        self._tab_index = self.tabWidgetList.currentIndex()

    @QtCore.Slot(int)
    def tab_widget_list_index(self, index):
        '''
        tabWidget changed slot
        :param index: tabWidget index
        :return:
        '''
        self._tab_index = index

    @QtCore.Slot()
    def search_asset_slot(self):
        '''
        search asset slot function
        :return:
        '''
        search_text = self.lineEditAssetSearch.text()
        if not search_text:
            self.tab_asset_init()
        else:
            self.tab_asset_search_init()
            self.search_asset(self.source_asset_model, search_text)

    @QtCore.Slot()
    def search_shot_slot(self):
        '''
        search shot slot function
        :return:
        '''
        search_text = self.lineEditShotSearch.text()
        if not search_text:
            self.tab_shot_init()
        else:
            self.tab_shot_search_init()
            self.search_shot(self.source_shot_model, search_text)

    @QtCore.Slot()
    def search_sequence_slot(self):
        '''
        search sequence slot function
        :return:
        '''
        search_text = self.lineEditSequenceSearch.text()
        if not search_text:
            self.tab_sequence_init()
        else:
            self.tab_sequence_search_init()
            self.search_sequence(self.source_sequence_model, search_text)

    @QtCore.Slot()
    def search_mytask_slot(self):
        '''
        search mytask slot function
        :return:
        '''
        search_text = self.lineEditMyTaskSearch.text()
        if not search_text:
            self.tab_mytask_init()
        else:
            self.tab_mytask_init()
            self.search_mytask(self.source_mytask_model, search_text)

    def search_mytask(self, source_model, search_text):
        '''
        search mytask
        :param source_model: source model
        :param search_text: text
        :return:
        '''
        mytask_type_item_temp_list = []
        for mytask_type_index in range(source_model.rowCount()):
            mytask_type_item = source_model.item(mytask_type_index, 0)
            mytask_type_item_temp = QStandardItem(mytask_type_item.text())
            mytask_type_item_temp.setEditable(False)
            for mytask_name_index in range(mytask_type_item.rowCount()):
                mytask_name_item = mytask_type_item.child(mytask_name_index, 0)
                mytask_name = mytask_name_item.text()
                if search_text in mytask_name:
                    mytask_name_item_temp = mytask_name_item.clone()
                    if mytask_name_item.hasChildren():
                        for mytask_name_index in range(
                                mytask_name_item.rowCount()):
                            mytask_step_item = mytask_name_item.child(
                                mytask_name_index, 0)
                            mytask_step_item_temp = mytask_step_item.clone()
                            if mytask_step_item.hasChildren():
                                for mytask_step_index in range(
                                        mytask_step_item.rowCount()):
                                    mytask_step_task_item = mytask_step_item.child(
                                        mytask_step_index, 0)
                                    mytask_step_task_item_temp = mytask_step_task_item.clone(
                                    )
                                    mytask_step_item_temp.appendRow(
                                        mytask_step_task_item_temp)
                            mytask_name_item_temp.appendRow(
                                mytask_step_item_temp)
                    mytask_name_item_temp.setEditable(False)
                    mytask_type_item_temp.appendRow(mytask_name_item_temp)
            if mytask_type_item_temp.hasChildren():
                mytask_type_item_temp_list.append(mytask_type_item_temp)
        source_model.clear()
        for item in mytask_type_item_temp_list:
            source_model.appendRow(item)

    def search_sequence(self, source_model, search_text):
        '''
        search sequence
        :param source_model: source model
        :param search_text: text
        :return:
        '''
        sequence_item_temp_list = []
        for sequence_index in range(source_model.rowCount()):
            sequence_item = source_model.item(sequence_index, 0)
            sequence_name = sequence_item.text()
            if search_text in sequence_name:
                sequence_name_item_temp = QStandardItem(sequence_name)
                retrieving = QStandardItem("Retrieving Tasks...")
                retrieving.setEditable(False)
                sequence_name_item_temp.appendRow(retrieving)
                sequence_name_item_temp.setEditable(False)
                sequence_item_temp_list.append(sequence_name_item_temp)
        source_model.clear()
        for item in sequence_item_temp_list:
            source_model.appendRow(item)

    def search_shot(self, source_model, search_text):
        '''
        search shot
        :param source_model: source model
        :param search_text: text
        :return:
        '''
        sequence_item_temp_list = []
        for sequence_index in range(source_model.rowCount()):
            sequence_item = source_model.item(sequence_index, 0)
            sequence_item_temp = QStandardItem(sequence_item.text())
            sequence_item_temp.setEditable(False)
            for shot_name_index in range(sequence_item.rowCount()):
                shot_name_item = sequence_item.child(shot_name_index, 0)
                shot_name = shot_name_item.text()
                if search_text in shot_name:
                    shot_name_item_temp = shot_name_item.clone()
                    retrieving = QStandardItem("Retrieving Tasks...")
                    retrieving.setEditable(False)
                    shot_name_item_temp.appendRow(retrieving)
                    shot_name_item_temp.setEditable(False)
                    sequence_item_temp.appendRow(shot_name_item_temp)
            if sequence_item_temp.hasChildren():
                sequence_item_temp_list.append(sequence_item_temp)
        source_model.clear()
        for item in sequence_item_temp_list:
            source_model.appendRow(item)

    def search_asset(self, source_model, search_text):
        '''
        search asset
        :param source_model: source model
        :param search_text: text
        :return:
        '''
        asset_type_item_temp_list = []
        for asset_type_index in range(source_model.rowCount()):
            asset_type_item = source_model.item(asset_type_index, 0)
            asset_type_item_temp = QStandardItem(asset_type_item.text())
            asset_type_item_temp.setEditable(False)
            for asset_name_index in range(asset_type_item.rowCount()):
                asset_name_item = asset_type_item.child(asset_name_index, 0)
                asset_name = asset_name_item.text()
                if search_text in asset_name:
                    asset_name_item_temp = asset_name_item.clone()
                    retrieving = QStandardItem("Retrieving Tasks...")
                    retrieving.setEditable(False)
                    asset_name_item_temp.appendRow(retrieving)
                    asset_name_item_temp.setEditable(False)
                    asset_type_item_temp.appendRow(asset_name_item_temp)
            if asset_type_item_temp.hasChildren():
                asset_type_item_temp_list.append(asset_type_item_temp)
        source_model.clear()
        for item in asset_type_item_temp_list:
            source_model.appendRow(item)

    def tab_asset_ui(self):
        '''
        tab asset ui
        :return:
        '''
        self.tab_asset_init()
        self.treeViewAsset.setModel(self.source_asset_model)
        self.treeViewAsset.setHeaderHidden(True)

    def tab_shot_ui(self):
        '''
        tab shot ui
        :return:
        '''
        self.tab_shot_init()
        self.treeViewShot.setModel(self.source_shot_model)
        self.treeViewShot.setHeaderHidden(True)

    def tab_sequence_ui(self):
        '''
        tab sequence ui
        :return:
        '''
        self.tab_sequence_init()
        self.treeViewSequence.setModel(self.source_sequence_model)
        self.treeViewSequence.setHeaderHidden(True)

    def tab_mytask_ui(self):
        '''
        tab mytask ui
        :return:
        '''
        self.tab_mytask_init()
        self.treeViewMyTask.setModel(self.source_mytask_model)
        self.treeViewMyTask.setHeaderHidden(True)

    def tab_asset_init(self):
        '''
        init asset list in treeView
        :return:
        '''
        self.source_asset_model.clear()

        asset_type_list = [
            'Chr', 'Env', 'Prp', 'Flg', 'Crd', 'Scn', 'Uif', 'Asb'
        ]

        for asset_type in asset_type_list:
            asset_type_item = QStandardItem(asset_type)
            asset_type_item.setEditable(False)
            # append the next level item
            retrieving = QStandardItem("Retrieving Tasks...")
            retrieving.setEditable(False)
            asset_type_item.appendRow(retrieving)

            self.source_asset_model.appendRow(asset_type_item)

    def tab_shot_init(self):
        '''
        init shot list in treeView
        :return:
        '''
        self.source_shot_model.clear()
        sequence_entity_list = self.sg.get_sequence_list(self.project_name)
        if sequence_entity_list:
            for sequence_entity in sequence_entity_list:
                sequence_name = sequence_entity['code']
                sequence_name_item = QStandardItem(sequence_name)
                sequence_name_item.setEditable(False)

                retrieving = QStandardItem("Retrieving Tasks...")
                retrieving.setEditable(False)
                sequence_name_item.appendRow(retrieving)

                self.source_shot_model.appendRow(sequence_name_item)

    def tab_sequence_init(self):
        '''
        init sequence list in treeView
        :return:
        '''
        self.source_sequence_model.clear()
        sequence_entity_list = self.sg.get_sequence_list(self.project_name)
        if sequence_entity_list:
            for sequence_entity in sequence_entity_list:
                sequence_name = sequence_entity['code']
                sequence_name_item = QStandardItem(sequence_name)
                sequence_name_item.setEditable(False)
                # append the next level item
                retrieving = QStandardItem("Retrieving Tasks...")
                retrieving.setEditable(False)
                sequence_name_item.appendRow(retrieving)
                self.source_sequence_model.appendRow(sequence_name_item)

    def tab_mytask_init(self):
        '''
        init mytask list in treeView
        :return:
        '''
        self.source_mytask_model.clear()
        mytask_entity_list = self.sg.get_mytask_list(self.project_name,
                                                     self.user_name)
        mytask_type_sequence_item = QStandardItem("Sequence")
        mytask_type_asset_item = QStandardItem("Asset")
        mytask_type_shot_item = QStandardItem("Shot")
        mytask_type_sequence_item.setEditable(False)
        mytask_type_asset_item.setEditable(False)
        mytask_type_shot_item.setEditable(False)

        mytask_link_type_list_item = [
            mytask_type_sequence_item, mytask_type_asset_item,
            mytask_type_shot_item
        ]

        mytask_link_name_set = set()
        if mytask_entity_list:
            # My God! It's really too complicated!!!!!!!!
            self.source_mytask_model.appendColumn(mytask_link_type_list_item)
            for mytask_entity in mytask_entity_list:
                mytask_name = mytask_entity['content']
                mytask_link_name = mytask_entity['entity']['name']
                mytask_link_type = mytask_entity['entity']['type']
                mytask_step_name = mytask_entity['step']['name']

                if mytask_link_name in mytask_link_name_set:
                    for mytask_index in range(
                            self.source_mytask_model.rowCount()):
                        mytask_link_type_item = self.source_mytask_model.item(
                            mytask_index, 0)
                        if mytask_link_type == mytask_link_type_item.text():
                            for mytask_link_type_index in range(
                                    mytask_link_type_item.rowCount()):
                                mytask_link_name_item = mytask_link_type_item.child(
                                    mytask_link_type_index, 0)
                                if mytask_link_name == mytask_link_name_item.text(
                                ):
                                    found = False
                                    for mytask_link_name_index in range(
                                            mytask_link_name_item.rowCount()):
                                        mytask_step_name_item = mytask_link_name_item.child(
                                            mytask_link_name_index, 0)
                                        if mytask_step_name.decode(
                                                'utf-8'
                                        ) == mytask_step_name_item.text():
                                            found = True
                                            mytask_name_item = QStandardItem(
                                                mytask_name)
                                            mytask_name_item.setEditable(False)
                                            mytask_step_name_item.appendRow(
                                                mytask_name_item)
                                    if not found:
                                        mytask_name_item = QStandardItem(
                                            mytask_name)
                                        mytask_name_item.setEditable(False)
                                        mytask_step_name_item = QStandardItem(
                                            mytask_step_name)
                                        mytask_step_name_item.setEditable(
                                            False)
                                        mytask_step_name_item.appendRow(
                                            mytask_name_item)
                                        mytask_link_name_item.appendRow(
                                            mytask_step_name_item)
                else:
                    mytask_name_item = QStandardItem(mytask_name)
                    mytask_name_item.setEditable(False)
                    mytask_step_name_item = QStandardItem(mytask_step_name)
                    mytask_step_name_item.setEditable(False)
                    mytask_step_name_item.appendRow(mytask_name_item)
                    mytask_link_name_item = QStandardItem(mytask_link_name)
                    mytask_link_name_item.setEditable(False)
                    mytask_link_name_item.appendRow(mytask_step_name_item)
                    for mytask_link_type_item in mytask_link_type_list_item:
                        if mytask_link_type_item.text() == mytask_link_type:
                            mytask_link_type_item.appendRow(
                                mytask_link_name_item)

                mytask_link_name_set.add(mytask_link_name)

    def tab_asset_search_init(self):
        '''
        init asset list in treeView(Only for search!)
        :return:
        '''
        self.source_asset_model.clear()

        asset_type_list = [
            'Chr', 'Env', 'Prp', 'Flg', 'Crd', 'Scn', 'Uif', 'Asb'
        ]

        for asset_type in asset_type_list:
            asset_type_item = QStandardItem(asset_type)
            asset_type_item.setEditable(False)

            asset_entity_list = self.sg.get_asset_list(self.project_name,
                                                       asset_type)
            if asset_entity_list:
                for asset_entity in asset_entity_list:
                    asset_name = asset_entity['code']
                    asset_name_chinesename = asset_entity['sg_chinesename']
                    if asset_name_chinesename:
                        asset_name = asset_name + "|" + asset_name_chinesename
                    asset_name_item = QStandardItem(asset_name)
                    asset_name_item.setEditable(False)

                    # append the next level item
                    retrieving = QStandardItem("Retrieving Tasks...")
                    retrieving.setEditable(False)
                    asset_name_item.appendRow(retrieving)

                    asset_type_item.appendRow(asset_name_item)

            self.source_asset_model.appendRow(asset_type_item)

    def tab_shot_search_init(self):
        '''
        init shot list in treeView(Only for search!)
        :return:
        '''
        self.source_shot_model.clear()
        sequence_entity_list = self.sg.get_sequence_list(self.project_name)
        if sequence_entity_list:
            for sequence_entity in sequence_entity_list:
                sequence_name = sequence_entity['code']
                sequence_name_item = QStandardItem(sequence_name)
                sequence_name_item.setEditable(False)

                # find the shot below sequence
                shot_entity_list = self.sg.get_sequence_shot_list(
                    self.project_name, sequence_name)
                if shot_entity_list:
                    for shot_entity in shot_entity_list:
                        shot_name = shot_entity['code']
                        shot_name_item = QStandardItem(shot_name)
                        shot_name_item.setEditable(False)

                        # append the next level item
                        retrieving = QStandardItem("Retrieving Tasks...")
                        retrieving.setEditable(False)
                        shot_name_item.appendRow(retrieving)

                        sequence_name_item.appendRow(shot_name_item)

                self.source_shot_model.appendRow(sequence_name_item)

    def tab_sequence_search_init(self):
        '''
        init sequence list in treeView(Only for search!)
        :return:
        '''
        self.source_sequence_model.clear()
        sequence_entity_list = self.sg.get_sequence_list(self.project_name)
        if sequence_entity_list:
            for sequence_entity in sequence_entity_list:
                sequence_name = sequence_entity['code']
                sequence_name_item = QStandardItem(sequence_name)
                sequence_name_item.setEditable(False)
                self.source_sequence_model.appendRow(sequence_name_item)

    @QtCore.Slot(int)
    def asset_expanded(self, index):
        '''
        asset treeView expanded
        :param index: index of the model
        :return:
        '''
        item = self.source_asset_model.itemFromIndex(index)
        asset_level_struct_item = []
        self.get_upper_level_item(self.source_asset_model,
                                  asset_level_struct_item, index)

        item_level = len(asset_level_struct_item)

        if item_level == 1:
            search_text = self.lineEditAssetSearch.text()
            if search_text:
                return
            item.removeRows(0, item.rowCount())
            # this is the top level
            _asset_type = asset_level_struct_item[0]
            asset_entity_list = self.sg.get_asset_list(self.project_name,
                                                       _asset_type)
            if asset_entity_list:
                for asset_entity in asset_entity_list:
                    asset_name = asset_entity['code']
                    asset_name_chinesename = asset_entity['sg_chinesename']
                    if asset_name_chinesename:
                        asset_name = asset_name + "|" + asset_name_chinesename
                    asset_name_item = QStandardItem(asset_name)
                    asset_name_item.setEditable(False)

                    # append the next level item
                    retrieving = QStandardItem("Retrieving Tasks...")
                    retrieving.setEditable(False)
                    asset_name_item.appendRow(retrieving)

                    item.appendRow(asset_name_item)
            else:
                # if this level not item then show Retrieving Task...
                retrieving = QStandardItem("Retrieving Tasks...")
                retrieving.setEditable(False)
                item.appendRow(retrieving)

        elif item_level == 2:
            item.removeRows(0, item.rowCount())
            asset_name = asset_level_struct_item[1]
            asset_task_list = self.sg.get_asset_task_list(
                self.project_name, asset_name)
            asset_step_name_set = set()
            if asset_task_list:
                for asset_task in asset_task_list:
                    asset_task_step = asset_task['step']
                    if asset_task_step:
                        asset_task_step_name = asset_task_step['name']
                        # remove all duplicate name in step by using set()
                        asset_step_name_set.add(asset_task_step_name)
                for step_name in asset_step_name_set:
                    asset_task_step_name_item = QStandardItem(step_name)
                    asset_task_step_name_item.setEditable(False)

                    # append the next level item
                    retrieving = QStandardItem("Retrieving Tasks...")
                    retrieving.setEditable(False)
                    asset_task_step_name_item.appendRow(retrieving)

                    item.appendRow(asset_task_step_name_item)
                    asset_level_struct_item.append(step_name)

        elif item_level == 3:
            item.removeRows(0, item.rowCount())
            asset_name = asset_level_struct_item[1]
            asset_step_name = asset_level_struct_item[2]
            asset_task_list = self.sg.get_asset_task_list(
                self.project_name, asset_name, asset_step_name)
            if asset_task_list:
                for asset_task in asset_task_list:
                    asset_task_name = asset_task['content']
                    asset_task_name_item = QStandardItem(asset_task_name)
                    asset_task_name_item.setEditable(False)

                    item.appendRow(asset_task_name_item)

    @QtCore.Slot(int)
    def shot_expanded(self, index):
        '''
        shot treeView expanded
        :param index: index of the model
        :return:
        '''
        # dynamic load data from shotgun server database
        item = self.source_shot_model.itemFromIndex(index)
        shot_level_struct_item = []
        self.get_upper_level_item(self.source_shot_model,
                                  shot_level_struct_item, index)
        item_level = len(shot_level_struct_item)
        # search item from shotgun server
        if item_level == 1:
            search_text = self.lineEditShotSearch.text()
            if search_text:
                return
            item.removeRows(0, item.rowCount())
            # this is the top level
            sequence_name = shot_level_struct_item[0]
            # find the shot below sequence
            shot_entity_list = self.sg.get_sequence_shot_list(
                self.project_name, sequence_name)
            if shot_entity_list:
                for shot_entity in shot_entity_list:
                    shot_name = shot_entity['code']
                    shot_name_item = QStandardItem(shot_name)
                    shot_name_item.setEditable(False)

                    # append the next level item
                    retrieving = QStandardItem("Retrieving Tasks...")
                    retrieving.setEditable(False)
                    shot_name_item.appendRow(retrieving)

                    item.appendRow(shot_name_item)
            else:
                # if this level not item then show Retrieving Task...
                retrieving = QStandardItem("Retrieving Tasks...")
                retrieving.setEditable(False)
                item.appendRow(retrieving)

        elif item_level == 2:
            item.removeRows(0, item.rowCount())
            sequence_name = shot_level_struct_item[0]
            shot_name = shot_level_struct_item[1]
            shot_task_list = self.sg.get_sequence_shot_task_list(
                self.project_name, sequence_name, shot_name)
            shot_step_name_set = set()
            if shot_task_list:
                for shot_task in shot_task_list:
                    shot_task_step = shot_task['step']
                    if shot_task_step:
                        shot_task_step_name = shot_task_step['name']
                        # remove all duplicate name in step by using set()
                        shot_step_name_set.add(shot_task_step_name)
                for step_name in shot_step_name_set:
                    shot_task_step_name_item = QStandardItem(step_name)
                    shot_task_step_name_item.setEditable(False)

                    # append the next level item
                    retrieving = QStandardItem("Retrieving Tasks...")
                    retrieving.setEditable(False)
                    shot_task_step_name_item.appendRow(retrieving)

                    item.appendRow(shot_task_step_name_item)
                    shot_level_struct_item.append(step_name)

        elif item_level == 3:
            item.removeRows(0, item.rowCount())
            sequence_name = shot_level_struct_item[0]
            shot_name = shot_level_struct_item[1]
            shot_step_name = shot_level_struct_item[2]
            shot_task_list = self.sg.get_sequence_shot_task_list(
                self.project_name, sequence_name, shot_name, shot_step_name)
            if shot_task_list:
                for shot_task in shot_task_list:
                    shot_task_name = shot_task['content']
                    shot_task_name_item = QStandardItem(shot_task_name)
                    shot_task_name_item.setEditable(False)

                    item.appendRow(shot_task_name_item)

    @QtCore.Slot(int)
    def sequence_expanded(self, index):
        '''
        sequence treeView expanded
        :param index: index of the model
        :return:
        '''
        # dynamic load data from shotgun server database
        item = self.source_sequence_model.itemFromIndex(index)
        item.removeRows(0, item.rowCount())
        sequence_level_struct_item = []
        self.get_upper_level_item(self.source_sequence_model,
                                  sequence_level_struct_item, index)
        item_level = len(sequence_level_struct_item)
        # search item from shotgun server
        if item_level == 1:
            # this is the top level
            sequence_name = sequence_level_struct_item[0]
            # find the step below sequence
            sequence_task_list = self.sg.get_sequence_task_list(
                self.project_name, sequence_name)
            sequence_step_name_set = set()
            if sequence_task_list:
                for sequence_task in sequence_task_list:
                    sequence_task_step = sequence_task['step']
                    if sequence_task_step:
                        sequence_task_step_name = sequence_task_step['name']
                        # remove all duplicate name in step by using set()
                        sequence_step_name_set.add(sequence_task_step_name)
                for step_name in sequence_step_name_set:
                    sequence_task_step_name_item = QStandardItem(step_name)
                    sequence_task_step_name_item.setEditable(False)

                    # append the next level item
                    retrieving = QStandardItem("Retrieving Tasks...")
                    retrieving.setEditable(False)
                    sequence_task_step_name_item.appendRow(retrieving)

                    item.appendRow(sequence_task_step_name_item)
                    sequence_level_struct_item.append(step_name)

        elif item_level == 2:
            sequence_name = sequence_level_struct_item[0]
            sequence_step_name = sequence_level_struct_item[1]
            sequence_task_list = self.sg.get_sequence_task_list(
                self.project_name, sequence_name, sequence_step_name)
            if sequence_task_list:
                for sequence_task in sequence_task_list:
                    sequence_task_name = sequence_task['content']
                    sequence_task_name_item = QStandardItem(sequence_task_name)
                    sequence_task_name_item.setEditable(False)

                    item.appendRow(sequence_task_name_item)

    def treeview_single_clicked(self, index):
        '''
        treeView single clicked
        :param index: index of model
        :return:
        '''
        if not self.timer.isActive():
            self.timer.start(500)
            self.listwidget_show_item_info(index)

    @QtCore.Slot()
    def disable_double_clicked(self):
        '''
        disable double clicked
        :return:
        '''
        self.timer.stop()

    @QtCore.Slot()
    def listwidget_show_item_info(self, index):
        '''
        this function process the published file to show in listWidget
        :param index: index of model
        :return:
        '''
        tab_index = self._tab_index
        project_level_info = []
        timelog_list = []
        self._project_level_info = []
        if tab_index == 0:
            # mytask table
            project_level_info, timelog_list = self.get_mytask_timelog_list(
                self.source_mytask_model, index)

        elif tab_index == 1:
            # asset table
            project_level_info, timelog_list = self.get_asset_timelog_list(
                self.source_asset_model, index)

        elif tab_index == 2:
            # shot table
            project_level_info, timelog_list = self.get_shot_timelog_list(
                self.source_shot_model, index)

        elif tab_index == 3:
            # sequence table
            project_level_info, timelog_list = self.get_sequence_timelog_list(
                self.source_sequence_model, index)

        if project_level_info:
            self.tableWidgetTimelog.setRowCount(0)
            self._project_level_info = project_level_info
            self.pushButtonSubmit.setEnabled(True)
        else:
            self.pushButtonSubmit.setEnabled(False)

        if timelog_list:
            self.show_timelog_info(timelog_list)

    def get_sequence_timelog_list(self, source_model, index):
        '''
        get the sequence published file from shotgun
        :param source_model: the source model
        :param index: the index of source model
        :return: file info list
        '''
        project_level_struct_item = []
        timelog_list = []
        project_level_info = []
        self.get_upper_level_item(source_model, project_level_struct_item,
                                  index)
        item_level = len(project_level_struct_item)
        if item_level >= 3:
            # it is 3 level in the treeview widget
            _sequence_name = project_level_struct_item[0]
            _sequence_step_name = project_level_struct_item[1]
            _sequence_step_task_name = project_level_struct_item[2]
            project_level_info = project_level_struct_item

            dict_data = sg_base_find.create_project_struct(
                self.project_name,
                self.user_name,
                "sequence",
                sequence_name=_sequence_name,
                sequence_step_name=_sequence_step_name,
                sequence_step_task_name=_sequence_step_task_name)
            timelog_list = self.sg.get_time_log(dict_data)
        return project_level_info, timelog_list

    def get_shot_timelog_list(self, source_model, index):
        '''
        get the shot published file from shotgun
        :param source_model: the source model
        :param index: the index of source model
        :return: file info list
        '''
        project_level_struct_item = []
        project_level_info = []
        timelog_list = []
        self.get_upper_level_item(source_model, project_level_struct_item,
                                  index)
        item_level = len(project_level_struct_item)
        if item_level >= 4:
            # it is 4 level in the treeview widget
            _sequence_name = project_level_struct_item[0]
            _sequence_shot_name = project_level_struct_item[1]
            _sequence_shot_step_name = project_level_struct_item[2]
            _sequence_shot_step_task_name = project_level_struct_item[3]
            project_level_info = project_level_struct_item

            dict_data = sg_base_find.create_project_struct(
                self.project_name,
                self.user_name,
                "shot",
                sequence_name=_sequence_name,
                sequence_shot_name=_sequence_shot_name,
                sequence_shot_step_name=_sequence_shot_step_name,
                sequence_shot_step_task_name=_sequence_shot_step_task_name)
            timelog_list = self.sg.get_time_log(dict_data)
        return project_level_info, timelog_list

    def get_asset_timelog_list(self, source_model, index):
        '''
        get the asset published file from shotgun
        :param source_model: the source model
        :param index: the index of source model
        :return: file info list
        '''
        project_level_struct_item = []
        project_level_info = []
        timelog_list = []
        self.get_upper_level_item(source_model, project_level_struct_item,
                                  index)
        item_level = len(project_level_struct_item)
        if item_level >= 4:
            # it is 4 level in the treeview widget
            _asset_name = project_level_struct_item[1]
            _asset_step_name = project_level_struct_item[2]
            _asset_step_task_name = project_level_struct_item[3]
            project_level_info = project_level_struct_item

            dict_data = sg_base_find.create_project_struct(
                self.project_name,
                self.user_name,
                "asset",
                asset_name=_asset_name,
                asset_step_name=_asset_step_name,
                asset_step_task_name=_asset_step_task_name)
            timelog_list = self.sg.get_time_log(dict_data)

        return project_level_info, timelog_list

    def get_mytask_timelog_list(self, source_model, index):
        '''
        get the mytask published file from shotgun
        :param source_model: the source model
        :param index: the index of source model
        :return: file info list
        '''
        project_level_struct_item = []
        project_level_info = []
        timelog_list = []
        self.get_upper_level_item(source_model, project_level_struct_item,
                                  index)
        item_level = len(project_level_struct_item)
        if item_level >= 4:
            # it is 4 level in the treeview widget
            mytask_type = project_level_struct_item[0]
            mytask_name = project_level_struct_item[1]
            mytask_step_name = project_level_struct_item[2]
            mytask_step_task_name = project_level_struct_item[3]
            project_level_info = project_level_struct_item

            if mytask_type == 'Asset':
                dict_data = sg_base_find.create_project_struct(
                    self.project_name,
                    self.user_name,
                    "asset",
                    asset_name=mytask_name,
                    asset_step_name=mytask_step_name,
                    asset_step_task_name=mytask_step_task_name)
                timelog_list = self.sg.get_time_log(dict_data)
            elif mytask_type == 'Shot':
                sequence_name = mytask_name.split("_")[0]
                dict_data = sg_base_find.create_project_struct(
                    self.project_name,
                    self.user_name,
                    "shot",
                    sequence_name=sequence_name,
                    sequence_shot_name=mytask_name,
                    sequence_shot_step_name=mytask_step_name,
                    sequence_shot_step_task_name=mytask_step_task_name)
                timelog_list = self.sg.get_time_log(dict_data)
            elif mytask_type == 'Sequence':
                dict_data = sg_base_find.create_project_struct(
                    self.project_name,
                    self.user_name,
                    "sequence",
                    sequence_name=mytask_name,
                    sequence_step_name=mytask_step_name,
                    sequence_step_task_name=mytask_step_task_name)
                timelog_list = self.sg.get_time_log(dict_data)

        return project_level_info, timelog_list

    # get item list for treeView***
    def get_upper_level_item(self, source_model, level_struct_item, index):
        '''
        get the upper item name from treeView
        :param source_model: the source model
        :param level_struct_item: item list
        :param index: the index of source model
        '''
        item = source_model.itemFromIndex(index)
        if item.parent():
            self.get_upper_level_item(source_model, level_struct_item,
                                      item.parent().index())
        text = item.text()
        # strip chinese name if source_model is asset
        text = text.split("|")[0]
        level_struct_item.append(text)

    @QtCore.Slot()
    def submit_slot(self):
        date = self.dateEditDate.date().toString(QtCore.Qt.ISODate)
        duration_temp = self.lineEditDuration.text()
        if not duration_temp:
            QMessageBox.warning(self,
                                "Error",
                                u'Please input duration',
                                buttons=QMessageBox.Ok,
                                defaultButton=QMessageBox.Ok)
            return
        duration = float(duration_temp) * 60
        description = self.lineEditDescription.text()
        dict_data = self.get_dict_data()
        result = self.sg.create_time_log(date, duration, dict_data,
                                         description)
        self.update_timelog_info()

    def get_dict_data(self):
        project_level_struct_item = self._project_level_info
        dict_data = {}
        tab_index = self._tab_index
        if tab_index == 0:
            mytask_type = project_level_struct_item[0]
            mytask_name = project_level_struct_item[1]
            mytask_step_name = project_level_struct_item[2]
            mytask_step_task_name = project_level_struct_item[3]

            if mytask_type == 'Asset':
                dict_data = sg_base_find.create_project_struct(
                    self.project_name,
                    self.user_name,
                    "asset",
                    asset_name=mytask_name,
                    asset_step_name=mytask_step_name,
                    asset_step_task_name=mytask_step_task_name)

            elif mytask_type == 'Shot':
                sequence_name = mytask_name.split("_")[0]
                dict_data = sg_base_find.create_project_struct(
                    self.project_name,
                    self.user_name,
                    "shot",
                    sequence_name=sequence_name,
                    sequence_shot_name=mytask_name,
                    sequence_shot_step_name=mytask_step_name,
                    sequence_shot_step_task_name=mytask_step_task_name)

            elif mytask_type == 'Sequence':
                dict_data = sg_base_find.create_project_struct(
                    self.project_name,
                    self.user_name,
                    "sequence",
                    sequence_name=mytask_name,
                    sequence_step_name=mytask_step_name,
                    sequence_step_task_name=mytask_step_task_name)
        elif tab_index == 1:
            _asset_name = project_level_struct_item[1]
            _asset_step_name = project_level_struct_item[2]
            _asset_step_task_name = project_level_struct_item[3]

            dict_data = sg_base_find.create_project_struct(
                self.project_name,
                self.user_name,
                "asset",
                asset_name=_asset_name,
                asset_step_name=_asset_step_name,
                asset_step_task_name=_asset_step_task_name)
        elif tab_index == 2:
            _sequence_name = project_level_struct_item[0]
            _sequence_shot_name = project_level_struct_item[1]
            _sequence_shot_step_name = project_level_struct_item[2]
            _sequence_shot_step_task_name = project_level_struct_item[3]

            dict_data = sg_base_find.create_project_struct(
                self.project_name,
                self.user_name,
                "shot",
                sequence_name=_sequence_name,
                sequence_shot_name=_sequence_shot_name,
                sequence_shot_step_name=_sequence_shot_step_name,
                sequence_shot_step_task_name=_sequence_shot_step_task_name)
        elif tab_index == 3:
            _sequence_name = project_level_struct_item[0]
            _sequence_step_name = project_level_struct_item[1]
            _sequence_step_task_name = project_level_struct_item[2]

            dict_data = sg_base_find.create_project_struct(
                self.project_name,
                self.user_name,
                "sequence",
                sequence_name=_sequence_name,
                sequence_step_name=_sequence_step_name,
                sequence_step_task_name=_sequence_step_task_name)
        return dict_data

    @QtCore.Slot(QPoint)
    def right_context_menu(self, pos):
        '''
        this is the right context menu for listwidget item which you selected
        it will call the function below
        '''
        pop_menu = QMenu()
        if self.tableWidgetTimelog.itemAt(pos):
            self.show_right_context_menu(pop_menu)
        pop_menu.exec_(QCursor.pos())

    def show_right_context_menu(self, pop_menu):
        pop_menu.addAction(
            QAction(u'delete', self, triggered=self.right_menu_process))

    def right_menu_process(self):
        current_row = self.tableWidgetTimelog.currentRow()
        timelog_id = self.tableWidgetTimelog.item(current_row, 4).text()
        self.sg.delete("TimeLog", int(timelog_id))
        self.update_timelog_info()

    def show_timelog_info(self, timelog_list):
        self.tableWidgetTimelog.setRowCount(len(timelog_list))
        row = -1
        for timelog in timelog_list:
            row += 1
            user = timelog['user']['name']
            date = timelog['date']
            duration = str(timelog['duration'] / 60.0)
            description = timelog['description']
            timelog_id = str(timelog['id'])
            timelog_info = [user, date, duration, description, timelog_id]
            self.update_table_item(row, timelog_info)

    def update_table_item(self, row, timelog_info):
        column = -1
        for timelog in timelog_info:
            column += 1
            item = QTableWidgetItem()
            item.setFlags(item.flags() & ~QtCore.Qt.ItemIsEditable)
            if column == 2:
                timelog += " hour"
            item.setText(timelog)
            if not column == 3:
                item.setTextAlignment(QtCore.Qt.AlignRight
                                      | QtCore.Qt.AlignVCenter)
            self.tableWidgetTimelog.setItem(row, column, item)

    def update_timelog_info(self):
        dict_data = self.get_dict_data()
        timelog_list = self.sg.get_time_log(dict_data)
        self.show_timelog_info(timelog_list)
예제 #5
0
class FitablesModel(BaseModel):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._log = logger.getLogger(self.__class__.__module__)
        # limits
        self._left_limit_for_zero_value = -1
        self._right_limit_for_zero_value = 1
        self._limit_percentage_deviation = 0.2
        # minor properties
        self._first_role = Qt.UserRole + 1
        self._edit_role_increment = 100
        self._edit_role_name_suffix = 'Edit'
        # major properties
        self._model = QStandardItemModel()
        # set role names
        self._role_names_list = [
            'path', 'label', 'value', 'error', 'min', 'max', 'refine', 'unit',
            'labelList'
        ]  # 257 - 265
        self._roles_list = []
        self._roles_dict = {}
        self._setRolesListAndDict()
        self._model.setItemRoleNames(self._roles_dict)
        # connect signals
        self._model.dataChanged.connect(self.onModelChanged)

    def _setRolesListAndDict(self):
        """
        Create the display and edit role list and dict from role names.
        """
        for i, role_name in enumerate(self._role_names_list):
            display_role = self._first_role + i
            edit_role = display_role + self._edit_role_increment

            self._roles_dict[display_role] = role_name.encode()
            self._roles_dict[edit_role] = '{}{}'.format(
                role_name, self._edit_role_name_suffix).encode()
            self._roles_list.append(display_role)
            self._roles_list.append(edit_role)

        self._log.debug(f"roles: {self._roles_dict}")

    def _setModelsFromProjectDict(self):
        """
        Create the initial data list with structure for GUI fitables table.
        """
        self._log.info("Starting to set Model from Project Dict")

        # block model signals
        self._model.blockSignals(True)

        # reset model
        self._model.setColumnCount(
            0)  # faster than clear(); clear() crashes app! why?
        self._model.setRowCount(0)

        # sort background
        for experiment in self._project_dict['experiments'].keys():
            self._project_dict['experiments'][experiment]['background'].sort()

        # set column
        column = []
        for path in find_in_obj(self._project_dict.asDict(), 'refine'):
            keys_list = path[:-1]
            hide = self._project_dict.getItemByPath(keys_list + ['hide'])
            if hide:
                continue

            item = QStandardItem()
            for role, role_name_bytes in self._roles_dict.items():
                role_name = role_name_bytes.decode()
                if role_name.endswith(self._edit_role_name_suffix):
                    continue
                if role_name == 'path':
                    value = keys_list
                elif role_name == 'labelList':
                    value = keys_list[0:-1]
                    # Insert elements according to CIF
                    if len(value) > 0 and value[-1] == "offset":
                        value.insert(-1, "setup")
                    if len(value) > 0 and value[-1] == "wavelength":
                        value.insert(-1, "setup")
                    # Renaming according to CIF
                    if len(value) > 0 and value[-1] == "offset":
                        value[-1] = "offset_2theta"
                    if len(value) > 2 and value[2] == "atoms":
                        value[2] = "atom_site"
                    if len(value) > 2 and value[2] == "resolution":
                        value[2] = "pd_instr_resolution"
                    if len(value) > 2 and value[2] == "polarization":
                        value[2] = "diffrn_radiation"
                    if len(value) > 2 and value[2] == "background":
                        value.insert(3, "2theta")
                    if len(value) > 5 and value[4] == "MSP":
                        value[5] = "susceptibility_" + value[5]
                        del value[4]
                elif role_name == 'label':
                    value = ' '.join(keys_list[:-1])
                elif role_name == 'value':
                    value = self._project_dict.getItemByPath(
                        keys_list[:-1]).value
                elif role_name == 'min':
                    value = self._project_dict.getItemByPath(keys_list).min
                elif role_name == 'max':
                    value = self._project_dict.getItemByPath(keys_list).max
                elif role_name == 'unit':
                    # conversion to str is needed if role = unit !
                    value = str(
                        nested_get(self._project_dict,
                                   keys_list + [role_name]))
                else:
                    value = nested_get(self._project_dict,
                                       keys_list + [role_name])
                item.setData(value, role)

            column.append(item)

        # set model
        self._model.appendColumn(column)  # dataChanged is not emited. why?

        # unblock signals and emit model layout changed
        self._model.blockSignals(False)
        self._model.layoutChanged.emit()
        self._log.info("Finished setting Model from Project Dict")
        # Emit signal which is caught by the QStandardItemModel-based
        # QML GUI elements in order to update their views

    def _updateProjectByIndexAndRole(self, index, edit_role):
        """
        Update project element, which is changed in the model, depends on its index and role.
        """
        self._log.info("Starting updating Project Dict from Model")

        display_role = edit_role - self._edit_role_increment
        display_role_name = self._roles_dict[display_role].decode()
        path_role = self._role_names_list.index('path') + self._first_role
        keys_list = self._model.data(index, path_role) + [display_role_name]
        edit_value = self._model.data(index, edit_role)
        display_value = self._model.data(index, display_role)
        self._log.debug(f"edit_role: {edit_role}")
        self._log.debug(f"display_role: {display_role}")
        self._log.debug(f"display_role_name: {display_role_name}")
        self._log.debug(f"path_role: {path_role}")
        self._log.debug(f"keys_list: {keys_list}")
        self._log.debug(f"edit_value: {edit_value}")
        self._log.debug(f"display_value: {display_value}")

        fitable_name = '.'.join(keys_list[:-2])
        fitable_value = edit_value
        data_block_name = keys_list[0]
        self._log.debug(f"fitable_name: {fitable_name}")
        self._log.debug(f"fitable_value: {fitable_value}")
        self._log.debug(f"data_block_name: {data_block_name}")

        if display_role_name == 'refine':
            undo_redo_text = f"Changing '{fitable_name}' refine state to '{fitable_value}'"
            self._log.debug(f"undo_redo_text: {undo_redo_text}")
            self._calculator_interface.project_dict.startBulkUpdate(
                undo_redo_text)
            self._calculator_interface.canUndoOrRedoChanged.emit()
            if data_block_name == 'phases':
                try:
                    self._calculator_interface.setPhaseRefine(
                        keys_list[1], keys_list[2:-2], edit_value)
                except AttributeError:
                    # In this case the calculator/dict are out of phase :-/ So fallback to manual.
                    self._calculator_interface.project_dict.setItemByPath(
                        keys_list, edit_value)
                # self._calculator_interface.updatePhases()
            elif data_block_name == 'experiments':
                try:
                    self._calculator_interface.setExperimentRefine(
                        keys_list[1], keys_list[2:-2], edit_value)
                except AttributeError:
                    self._calculator_interface.project_dict.setItemByPath(
                        keys_list, edit_value)
                # self._calculator_interface.updateExperiments()
            else:
                self._calculator_interface.setDictByPath(keys_list, edit_value)
            self._calculator_interface.projectDictChanged.emit()

        elif display_role_name == 'value':
            undo_redo_text = f"Changing '{fitable_name}' to '{fitable_value:.4f}'"
            self._log.debug(f"undo_redo_text: {undo_redo_text}")
            self._calculator_interface.project_dict.startBulkUpdate(
                undo_redo_text)
            self._calculator_interface.canUndoOrRedoChanged.emit()
            if data_block_name == 'phases':
                try:
                    self._calculator_interface.setPhaseValue(
                        keys_list[1], keys_list[2:-2], edit_value)
                except AttributeError:
                    self._calculator_interface.project_dict.setItemByPath(
                        keys_list, edit_value)
                    self._calculator_interface.updatePhases()
                self._calculator_interface.updateCalculations(
                )  # phases also updated ?
            elif data_block_name == 'experiments':
                try:
                    self._calculator_interface.setExperimentValue(
                        keys_list[1], keys_list[2:-2], edit_value)
                except AttributeError:
                    self._calculator_interface.project_dict.setItemByPath(
                        keys_list, edit_value)
                    self._calculator_interface.updateExperiments()
                self._calculator_interface.updateCalculations(
                )  # experiments also updated ?
            else:
                self._calculator_interface.setDictByPath(keys_list, edit_value)
            # Update min and max if value is outside [min, max] range
            value = self._calculator_interface.project_dict.getItemByPath(
                keys_list)
            min_value = self._calculator_interface.project_dict.getItemByPath(
                [*keys_list[:-1], 'min'])
            max_value = self._calculator_interface.project_dict.getItemByPath(
                [*keys_list[:-1], 'max'])
            self._log.debug(f"initial min: {min}, max: {max}")
            # TODO: the code below duplicates the code from BaseClasses.py - class Base - def updateMinMax
            # stacked changes (for GUI triggered changes)
            if np.isclose([value], [0]):
                min_value = self._left_limit_for_zero_value
                max_value = self._right_limit_for_zero_value
            if value < min_value:
                if value > 0:
                    min_value = value * (1 - self._limit_percentage_deviation)
                else:
                    min_value = value * (1 + self._limit_percentage_deviation)
            if value > max_value:
                if value > 0:
                    max_value = value * (1 + self._limit_percentage_deviation)
                else:
                    max_value = value * (1 - self._limit_percentage_deviation)
            # Update min and max in project dict
            self._log.debug(f"re-calculated min: {min}, max: {max}")
            self._calculator_interface.project_dict.setItemByPath(
                [*keys_list[:-1], 'min'], min_value)
            self._calculator_interface.project_dict.setItemByPath(
                [*keys_list[:-1], 'max'], max_value)
            self._calculator_interface.projectDictChanged.emit()

        elif display_role_name == 'min' or display_role_name == 'max':
            undo_redo_text = f"Changing '{fitable_name}' {display_role_name} to '{fitable_value}'"
            self._log.debug(f"undo_redo_text: {undo_redo_text}")
            self._calculator_interface.project_dict.startBulkUpdate(
                undo_redo_text)
            self._calculator_interface.canUndoOrRedoChanged.emit()
            # TODO: try to use setDictByPath below
            # self._calculator_interface.setDictByPath(keys_list, edit_value)
            # Temporary (?) solution until above is fixed
            self._calculator_interface.project_dict.setItemByPath(
                keys_list, edit_value)
            self._calculator_interface.projectDictChanged.emit()

        else:
            self._log.warning(f"unsupported role: {display_role_name}")
            return

        self._calculator_interface.project_dict.endBulkUpdate()
        self._calculator_interface.canUndoOrRedoChanged.emit()
        self._log.info("Finished updating Project Dict from Model")

    def onModelChanged(self, top_left_index, bottom_right_index, roles):
        """
        Define what to do if model is changed, e.g. from GUI.
        """
        role = roles[0]
        role_name = self._roles_dict[role].decode()
        self._log.debug(f"roles: {roles}")
        self._log.debug(f"role: {role}")
        self._log.debug(f"role_name: {role_name}")

        if role_name.endswith(self._edit_role_name_suffix):
            self._updateProjectByIndexAndRole(top_left_index, role)
예제 #6
0
class ComboCheckbox(QObject):
    """A combo box with its items as checkboxes."""
    def __init__(self,
                 combobox: Optional[QComboBox],
                 items: Optional[Iterable[QStandardItem]] = None):
        """
        Initialize instance

        Args:
            combobox: The underlying combobox, None to create a new one
            items: Items to put in the combobox, if any
        """
        super().__init__()
        self.combobox = combobox if combobox else QComboBox()
        self.model = QStandardItemModel()
        self.combobox.setModel(self.model)
        self.combobox.setItemDelegate(CheckMarkDelegate())
        self.combobox.view().pressed.connect(self.handle_item_pressed)
        self.checked_items = []
        if items:
            self.model.appendColumn(items)

    @staticmethod
    def _make_item(val: Any, checkable: bool) -> QStandardItem:
        """
        Make an item for the combobox

        Args:
            val: The value for the item
            checkable: Whether the item is checkable

        Returns:
            The item created
        """
        item = QStandardItem(val)
        if checkable:
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            item.setData(Qt.Unchecked, Qt.CheckStateRole)
        else:
            item.setFlags(~Qt.ItemIsUserCheckable & ~Qt.ItemIsSelectable)
        return item

    # pylint: disable=no-self-use
    def _on_check(self, item: QStandardItem):
        """
        Handles checking an item.

        Args:
            item: Item checked
        """
        item.setCheckState(Qt.Checked)
        assert item.text() not in self.checked_items
        self.checked_items.append(item.text())

    # pylint: disable=no-self-use
    def _on_uncheck(self, item: QStandardItem):
        """
        Handles unchecking an item.

        Args:
            item: Item unchecked
        """
        item.setCheckState(Qt.Unchecked)
        assert item.text() in self.checked_items
        self.checked_items.remove(item.text())

    def __getitem__(self, i: Union[int, QModelIndex]) -> QStandardItem:
        """
        Get item by index

        Args:
            i: The index
        Returns:
            Item at the index
        Raises:
            IndexError if out of bounds
        """
        if isinstance(i, int):
            if i < 0:
                i = len(self) - i
            if i >= len(self):
                raise IndexError
            index = self.model.createIndex(i, 0)
        elif isinstance(i, QModelIndex):
            if i.row() >= len(self):
                raise IndexError
            index = i
        else:
            return NotImplemented
        return self.model.itemFromIndex(index)

    def __len__(self):
        return self.combobox.count()

    def handle_item_pressed(self, index):
        """
        Handles a checkable item being pressed in a combo box

        Args:
            index: Index of the item
        """
        item = self[index]
        if item.isCheckable():
            if item.checkState() == Qt.Checked:
                self._on_uncheck(item)
            else:
                self._on_check(item)