Ignore:
Timestamp:
Jan 16, 2018 4:50:31 AM (7 years ago)
Author:
Piotr Rozyczko <rozyczko@…>
Branches:
ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
Children:
47d7d2d
Parents:
676f137
Message:

Context menus for tab and constraint list widgets.
Dynamic bindings of add/remove for FPs and the C&S widget

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py

    r676f137 rbe8f4b0  
    88 
    99from sas.qtgui.Perspectives.Fitting.UI.ConstraintWidgetUI import Ui_ConstraintWidgetUI 
     10from sas.qtgui.Perspectives.Fitting.FittingWidget import FittingWidget 
    1011 
    1112class ConstraintWidget(QtWidgets.QWidget, Ui_ConstraintWidgetUI): 
    1213    """ 
    13     Constraints Dialog to select the desired parameter/model constraints 
     14    Constraints Dialog to select the desired parameter/model constraints. 
    1415    """ 
    1516 
     
    2021        self.currentType = "FitPage" 
    2122 
     23        # Set up the widgets 
     24        self.initializeWidgets() 
     25 
    2226        # Set up signals/slots 
    2327        self.initializeSignals() 
    2428 
    2529        # Create the list of tabs 
    26         self.updateFitList() 
     30        self.initializeFitList() 
     31 
     32    def acceptsData(self): 
     33        """ Tells the caller this widget doesn't accept data """ 
     34        return False 
     35 
     36    def initializeWidgets(self): 
     37        """ 
     38        Set up various widget states 
     39        """ 
     40        labels = ['FitPage', 'Model', 'Data', 'Mnemonics'] 
     41        # tab widget - headers 
     42        self.tblTabList.setColumnCount(len(labels)) 
     43        self.tblTabList.setHorizontalHeaderLabels(labels) 
     44        self.tblTabList.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch) 
     45 
     46        self.tblTabList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 
     47        self.tblTabList.customContextMenuRequested.connect(self.showModelContextMenu) 
     48 
     49        # disabled constraint  
     50        labels = ['Constraint'] 
     51        self.tblConstraints.setColumnCount(len(labels)) 
     52        self.tblConstraints.setHorizontalHeaderLabels(labels) 
     53        self.tblConstraints.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch) 
     54        self.tblConstraints.setEnabled(False) 
     55 
     56        self.tblConstraints.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 
     57        self.tblConstraints.customContextMenuRequested.connect(self.showConstrContextMenu) 
    2758 
    2859    def initializeSignals(self): 
     
    3263        self.btnSingle.toggled.connect(self.onFitTypeChange) 
    3364        self.btnBatch.toggled.connect(self.onFitTypeChange) 
    34         self.cbSeries.indexChanged.connect(self.onSpecialCaseChange) 
     65        self.cbCases.currentIndexChanged.connect(self.onSpecialCaseChange) 
    3566        self.cmdFit.clicked.connect(self.onFit) 
    3667        self.cmdHelp.clicked.connect(self.onHelp) 
     68        self.parent.tabsModifiedSignal.connect(self.initializeFitList) 
     69 
     70    def updateSignalsFromTab(self, tab=None): 
     71        """ 
     72        Intercept update signals from fitting tabs 
     73        """ 
     74        if tab is not None: 
     75            ObjectLibrary.getObject(tab).constraintAddedSignal.connect(self.initializeFitList) 
     76            ObjectLibrary.getObject(tab).newModelSignal.connect(self.initializeFitList) 
    3777 
    3878    def onFitTypeChange(self, checked): 
     
    61101        pass 
    62102 
    63     def updateFitList(self): 
     103    def isTabImportable(self, tab): 
     104        """ 
     105        Determines if the tab can be imported and included in the widget 
     106        """ 
     107        if not self.currentType in tab: return False 
     108        object = ObjectLibrary.getObject(tab) 
     109        if not isinstance(object, FittingWidget): return False 
     110        if object.data is None: return False 
     111        return True 
     112 
     113    def showModelContextMenu(self, position): 
     114        """ 
     115        Show context specific menu in the tab table widget. 
     116        """ 
     117        menu = QtWidgets.QMenu() 
     118        rows = [s.row() for s in self.tblTabList.selectionModel().selectedRows()] 
     119        num_rows = len(rows) 
     120        if num_rows <= 0: 
     121            return 
     122        # Select for fitting 
     123        param_string = "Fit Page " if num_rows==1 else "Fit Pages " 
     124        to_string = "to its current value" if num_rows==1 else "to their current values" 
     125 
     126        self.actionSelect = QtWidgets.QAction(self) 
     127        self.actionSelect.setObjectName("actionSelect") 
     128        self.actionSelect.setText(QtCore.QCoreApplication.translate("self", "Select "+param_string+" for fitting")) 
     129        # Unselect from fitting 
     130        self.actionDeselect = QtWidgets.QAction(self) 
     131        self.actionDeselect.setObjectName("actionDeselect") 
     132        self.actionDeselect.setText(QtCore.QCoreApplication.translate("self", "De-select "+param_string+" from fitting")) 
     133 
     134        self.actionRemoveConstraint = QtWidgets.QAction(self) 
     135        self.actionRemoveConstraint.setObjectName("actionRemoveConstrain") 
     136        self.actionRemoveConstraint.setText(QtCore.QCoreApplication.translate("self", "Remove all constraints on selected models")) 
     137 
     138        self.actionMutualMultiConstrain = QtWidgets.QAction(self) 
     139        self.actionMutualMultiConstrain.setObjectName("actionMutualMultiConstrain") 
     140        self.actionMutualMultiConstrain.setText(QtCore.QCoreApplication.translate("self", "Mutual constrain of parameters in selected models...")) 
     141 
     142        menu.addAction(self.actionSelect) 
     143        menu.addAction(self.actionDeselect) 
     144        menu.addSeparator() 
     145 
     146        #menu.addAction(self.actionRemoveConstraint) 
     147        if num_rows >= 2: 
     148            menu.addAction(self.actionMutualMultiConstrain) 
     149 
     150        # Define the callbacks 
     151        #self.actionConstrain.triggered.connect(self.addSimpleConstraint) 
     152        #self.actionRemoveConstraint.triggered.connect(self.deleteConstraint) 
     153        #self.actionMutualMultiConstrain.triggered.connect(self.showMultiConstraint) 
     154        self.actionSelect.triggered.connect(self.selectModels) 
     155        self.actionDeselect.triggered.connect(self.deselectModels) 
     156        try: 
     157            menu.exec_(self.tblTabList.viewport().mapToGlobal(position)) 
     158        except AttributeError as ex: 
     159            logging.error("Error generating context menu: %s" % ex) 
     160        return 
     161 
     162    def showConstrContextMenu(self, position): 
     163        """ 
     164        Show context specific menu in the tab table widget. 
     165        """ 
     166        menu = QtWidgets.QMenu() 
     167        rows = [s.row() for s in self.tblConstraints.selectionModel().selectedRows()] 
     168        num_rows = len(rows) 
     169        if num_rows <= 0: 
     170            return 
     171        # Select for fitting 
     172        param_string = "constraint " if num_rows==1 else "constraints " 
     173        to_string = "to its current value" if num_rows==1 else "to their current values" 
     174 
     175        self.actionSelect = QtWidgets.QAction(self) 
     176        self.actionSelect.setObjectName("actionSelect") 
     177        self.actionSelect.setText(QtCore.QCoreApplication.translate("self", "Select "+param_string+" for fitting")) 
     178        # Unselect from fitting 
     179        self.actionDeselect = QtWidgets.QAction(self) 
     180        self.actionDeselect.setObjectName("actionDeselect") 
     181        self.actionDeselect.setText(QtCore.QCoreApplication.translate("self", "De-select "+param_string+" from fitting")) 
     182 
     183        self.actionRemoveConstraint = QtWidgets.QAction(self) 
     184        self.actionRemoveConstraint.setObjectName("actionRemoveConstrain") 
     185        self.actionRemoveConstraint.setText(QtCore.QCoreApplication.translate("self", "Remove "+param_string)) 
     186 
     187        menu.addAction(self.actionSelect) 
     188        menu.addAction(self.actionDeselect) 
     189        menu.addSeparator() 
     190        menu.addAction(self.actionRemoveConstraint) 
     191 
     192        # Define the callbacks 
     193        #self.actionConstrain.triggered.connect(self.addSimpleConstraint) 
     194        self.actionRemoveConstraint.triggered.connect(self.deleteConstraint) 
     195        #self.actionMutualMultiConstrain.triggered.connect(self.showMultiConstraint) 
     196        self.actionSelect.triggered.connect(self.selectConstraints) 
     197        self.actionDeselect.triggered.connect(self.deselectConstraints) 
     198        try: 
     199            menu.exec_(self.tblConstraints.viewport().mapToGlobal(position)) 
     200        except AttributeError as ex: 
     201            logging.error("Error generating context menu: %s" % ex) 
     202        return 
     203 
     204    def selectConstraints(self): 
     205        """ 
     206        Selected constraints are chosen for fitting 
     207        """ 
     208        status = QtCore.Qt.Checked 
     209        self.setRowSelection(self.tblConstraints, status) 
     210 
     211    def deselectConstraints(self): 
     212        """ 
     213        Selected constraints are removed for fitting 
     214        """ 
     215        status = QtCore.Qt.Unchecked 
     216        self.setRowSelection(self.tblConstraints, status) 
     217 
     218    def selectModels(self): 
     219        """ 
     220        Selected models are chosen for fitting 
     221        """ 
     222        status = QtCore.Qt.Checked 
     223        self.setRowSelection(self.tblTabList, status) 
     224 
     225    def deselectModels(self): 
     226        """ 
     227        Selected models are removed for fitting 
     228        """ 
     229        status = QtCore.Qt.Unchecked 
     230        self.setRowSelection(self.tblTabList, status) 
     231 
     232    def selectedParameters(self, widget): 
     233        """ Returns list of selected (highlighted) parameters """ 
     234        return [s.row() for s in widget.selectionModel().selectedRows()] 
     235 
     236    def setRowSelection(self, widget, status=QtCore.Qt.Unchecked): 
     237        """ 
     238        Selected models are chosen for fitting 
     239        """ 
     240        # Convert to proper indices and set requested enablement 
     241        for row in self.selectedParameters(widget): 
     242            widget.item(row, 0).setCheckState(status) 
     243 
     244    def deleteConstraint(self):#, row): 
     245        """ 
     246        Delete all selected constraints. 
     247        """ 
     248        constraints_to_delete = [] 
     249        for row in self.selectedParameters(self.tblConstraints): 
     250            constraints_to_delete.append(self.tblConstraints.item(row, 0).data(0)) 
     251        for constraint in constraints_to_delete: 
     252            moniker = constraint[:constraint.index(':')] 
     253            param = constraint[constraint.index(':')+1:constraint.index('=')].strip() 
     254            tab = self.available_tabs[moniker] 
     255            tab.deleteConstraintOnParameter(param) 
     256        # Constraints removed - refresh the table widget 
     257        self.initializeFitList() 
     258 
     259    def updateFitLine(self, tab): 
     260        """ 
     261        Update a single line of the table widget with tab info 
     262        """ 
     263        model = ObjectLibrary.getObject(tab).kernel_module 
     264        if model is None: 
     265            return 
     266        tab_name = tab 
     267        model_name = model.id 
     268        moniker = model.name 
     269        model_data = ObjectLibrary.getObject(tab).data 
     270        model_filename = model_data.filename 
     271        self.available_tabs[moniker] = ObjectLibrary.getObject(tab) 
     272 
     273        # Update the model table widget 
     274        item = QtWidgets.QTableWidgetItem(tab_name) 
     275        item.setCheckState(QtCore.Qt.Checked) 
     276        pos = self.tblTabList.rowCount() 
     277        self.tblTabList.insertRow(pos) 
     278        self.tblTabList.setItem(pos, 0, item) 
     279        self.tblTabList.setItem(pos, 1, QtWidgets.QTableWidgetItem(model_name)) 
     280        self.tblTabList.setItem(pos, 2, QtWidgets.QTableWidgetItem(model_filename)) 
     281        self.tblTabList.setItem(pos, 3, QtWidgets.QTableWidgetItem(moniker)) 
     282 
     283        #self.available_tabs[pos] = (model, model_data) 
     284        #self.available_tabs[moniker] = tab 
     285 
     286        # Check if any constraints present in tab 
     287        constraints = ObjectLibrary.getObject(tab).getConstraintsForModel() 
     288        if not constraints:  
     289            return 
     290        self.tblConstraints.setEnabled(True) 
     291        for constraint in constraints: 
     292            # Create the text for widget item 
     293            label = moniker + ":"+ constraint[0] + " = " + constraint[1] 
     294 
     295            # Show the text in the constraint table 
     296            item = QtWidgets.QTableWidgetItem(label) 
     297            item.setCheckState(QtCore.Qt.Checked) 
     298            pos = self.tblConstraints.rowCount() 
     299            self.tblConstraints.insertRow(pos) 
     300            self.tblConstraints.setItem(pos, 0, item) 
     301            self.available_constraints[pos] = constraints 
     302 
     303    def initializeFitList(self): 
    64304        """ 
    65305        Fill the list of model/data sets for fitting/constraining 
    66306        """ 
    67307        # look at the object library to find all fit tabs 
     308        # Show the content of the current "model" 
    68309        objects = ObjectLibrary.listObjects() 
     310 
     311        # Tab dict 
     312        # moniker -> (kernel_module, data) 
     313        self.available_tabs = {} 
     314        # Constraint dict 
     315        # moniker -> [constraints] 
     316        self.available_constraints = {} 
     317 
     318        # Reset the table widgets 
     319        self.tblTabList.setRowCount(0) 
     320        self.tblConstraints.setRowCount(0) 
     321 
     322        # Fit disabled 
     323        self.cmdFit.setEnabled(False) 
     324 
    69325        if not objects: 
    70326            return 
    71         tabs = [tab for tab in ObjectLibrary.listObjects() if self.currentType in tab] 
    72  
    73         pass 
    74  
    75     def updateConstraintList(self): 
    76         """ 
    77         Fill the list of constraints for the current selection of model/data sets 
    78         """ 
    79         pass 
    80  
    81  
     327 
     328        tabs = [tab for tab in ObjectLibrary.listObjects() if self.isTabImportable(tab)] 
     329        for tab in tabs: 
     330            self.updateFitLine(tab) 
     331            self.updateSignalsFromTab(tab) 
     332            # We have at least 1 fit page, allow fitting 
     333            self.cmdFit.setEnabled(True) 
Note: See TracChangeset for help on using the changeset viewer.