Changeset 1857:abf1cbef7844 in orange-bioinformatics


Ignore:
Timestamp:
10/03/13 18:25:34 (7 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Added saved selections to the Select Genes widget.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • _bioinformatics/widgets/OWSelectGenes.py

    r1854 r1857  
    2727 
    2828 
     29def toString(variant): 
     30    if isinstance(variant, QVariant): 
     31        return unicode(variant.toString()) 
     32    else: 
     33        return unicode(variant) 
     34 
     35 
     36def toBool(variant): 
     37    if isinstance(variant, QVariant): 
     38        return bool(variant.toPyObject()) 
     39    else: 
     40        return bool(variant) 
     41 
     42 
     43class SaveSlot(QStandardItem): 
     44    ModifiedRole = next(OWGUI.OrangeUserRole) 
     45 
     46    def __init__(self, name, savedata=None, modified=False): 
     47        super(SaveSlot, self).__init__(name) 
     48 
     49        self.savedata = savedata 
     50        self.modified = modified 
     51        self.document = None 
     52 
     53    @property 
     54    def name(self): 
     55        return unicode(self.text()) 
     56 
     57    @property 
     58    def modified(self): 
     59        return toBool(self.data(SaveSlot.ModifiedRole)) 
     60 
     61    @modified.setter 
     62    def modified(self, state): 
     63        self.setData(bool(state), SaveSlot.ModifiedRole) 
     64 
     65 
     66class SavedSlotDelegate(QStyledItemDelegate): 
     67 
     68    def paint(self, painter, option, index): 
     69        option = QStyleOptionViewItemV4(option) 
     70        self.initStyleOption(option, index) 
     71 
     72        modified = toBool(index.data(SaveSlot.ModifiedRole)) 
     73        if modified: 
     74            option.palette.setColor(QPalette.Text, QColor(Qt.red)) 
     75            option.palette.setColor(QPalette.Highlight, QColor(Qt.darkRed)) 
     76            option.text = "*" + option.text 
     77 
     78        if option.widget: 
     79            widget = option.widget 
     80            style = widget.style() 
     81        else: 
     82            widget = None 
     83            style = QApplication.style() 
     84 
     85        style.drawControl(QStyle.CE_ItemViewItem, option, painter, widget) 
     86 
     87 
    2988class OWSelectGenes(OWWidget): 
    3089 
    3190    contextHandlers = { 
    3291        "": DomainContextHandler( 
    33             "", ["geneIndex", "selection"] 
     92            "", ["geneIndex"] 
    3493        ) 
    3594    } 
    3695 
    37     settingsList = ["autoCommit", "preserveOrder"] 
     96    settingsList = ["autoCommit", "preserveOrder", "savedSelections", 
     97                    "selectedSelectionIndex"] 
    3898 
    3999    def __init__(self, parent=None, signalManager=None, title=NAME): 
     
    41101                          wantMainArea=False) 
    42102 
    43         self.selection = [] 
    44103        self.geneIndex = None 
    45104        self.autoCommit = False 
    46105        self.preserveOrder = True 
     106        self.savedSelections = [ 
     107            ("Example", ["MRE11A", "RAD51", "MLH1", "MSH2", "DMC1"]) 
     108        ] 
     109 
     110        self.selectedSelectionIndex = -1 
    47111 
    48112        self.loadSettings() 
     
    55119        self._changedFlag = False 
    56120        self.data = None 
     121        # Current gene names 
     122        self.selection = [] 
    57123 
    58124        box = OWGUI.widgetBox(self.controlArea, "Gene Attribute") 
     
    68134        self.entryField.setTabChangesFocus(True) 
    69135        self.entryField.setToolTip("Enter selected gene names") 
    70         self.entryField.itemsChanged.connect(self._itemsChanged) 
     136        self.entryField.setDocument(self._createDocument()) 
     137        self.entryField.itemsChanged.connect(self._onItemsChanged) 
    71138 
    72139        box.layout().addWidget(self.entryField) 
    73140 
    74         completer = ListCompleter(self) 
     141        completer = ListCompleter() 
    75142        completer.setCompletionMode(QCompleter.PopupCompletion) 
    76143        completer.setCaseSensitivity(Qt.CaseInsensitive) 
     
    81148        self.entryField.setCompleter(completer) 
    82149 
    83         self.hightlighter = NameHighlight(self.entryField.document()) 
     150        box = OWGUI.widgetBox(self.controlArea, "Saved Selections") 
     151        box.layout().setSpacing(1) 
     152 
     153        self.selectionsModel = QStandardItemModel() 
     154        self.selectionsView = QListView() 
     155        self.selectionsView.setAlternatingRowColors(True) 
     156        self.selectionsView.setModel(self.selectionsModel) 
     157        self.selectionsView.setItemDelegate(SavedSlotDelegate(self)) 
     158        self.selectionsView.selectionModel().selectionChanged.connect( 
     159            self._onSelectedSaveSlotChanged 
     160        ) 
     161 
     162        box.layout().addWidget(self.selectionsView) 
     163 
     164        self.actionSave = QAction("Save", self) 
     165        self.actionAdd = QAction("+", self) 
     166        self.actionRemove = QAction("-", self) 
     167 
     168        toolbar = QFrame() 
     169        layout = QHBoxLayout() 
     170        layout.setContentsMargins(0, 0, 0, 0) 
     171        layout.setSpacing(1) 
     172 
     173        def button(action): 
     174            b = QToolButton() 
     175            b.setDefaultAction(action) 
     176            return b 
     177 
     178        b = button(self.actionAdd) 
     179        layout.addWidget(b) 
     180 
     181        b = button(self.actionSave) 
     182        b.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) 
     183        layout.addWidget(b, stretch=10) 
     184 
     185        b = button(self.actionRemove) 
     186        layout.addWidget(b) 
     187 
     188        toolbar.setLayout(layout) 
     189 
     190        box.layout().addWidget(toolbar) 
     191 
     192        self.actionSave.triggered.connect(self.saveSelection) 
     193        self.actionAdd.triggered.connect(self.addSelection) 
     194        self.actionRemove.triggered.connect(self.removeSelection) 
    84195 
    85196        box = OWGUI.widgetBox(self.controlArea, "Output") 
     
    92203 
    93204        OWGUI.setStopper(self, button, cb, "_changedFlag", self.commit) 
     205 
     206        # restore saved selections model. 
     207        for name, names in self.savedSelections: 
     208            item = SaveSlot(name, names) 
     209            self.selectionsModel.appendRow([item]) 
     210 
     211        if self.selectedSelectionIndex != -1: 
     212            self.selectionsView.selectionModel().select( 
     213                self.selectionsModel.index(self.selectedSelectionIndex, 0), 
     214                QItemSelectionModel.Select 
     215            ) 
     216        self._updateActions() 
    94217 
    95218    def set_data(self, data): 
     
    109232                self.geneIndex = -1 
    110233                self.warning(0, "No suitable columns for gene names.") 
    111  
    112             self.selection = [] 
    113234        else: 
    114235            self.variables[:] = [] 
     
    119240 
    120241        self.openContext("", data) 
    121  
    122         self.entryField.setPlainText(" ".join(self.selection)) 
    123242 
    124243        self.commit() 
     
    175294        self.geneNames = names 
    176295        self.entryField.completer().model().setStringList(sorted(set(names))) 
    177         self.hightlighter.setNames(names) 
     296        self.entryField.document().highlighter.setNames(names) 
    178297 
    179298    def _onGeneIndexChanged(self): 
     
    181300        self.invalidateOutput() 
    182301 
    183     def _itemsChanged(self, names): 
     302    def _onItemsChanged(self, names): 
    184303        selection = set(names).intersection(self.geneNames) 
    185304        curr_selection = set(self.selection).intersection(self.geneNames) 
    186305 
     306        self.selection = names 
     307 
    187308        if selection != curr_selection: 
    188             self.selection = names 
    189309            self.invalidateOutput() 
    190  
    191             names = set(self.geneNames) - set(names) 
    192             self.entryField.completer().model().setStringList(sorted(names)) 
     310            to_complete = sorted(set(self.geneNames) - set(names)) 
     311            self.entryField.completer().model().setStringList(to_complete) 
     312 
     313        item = self._selectedSaveSlot() 
     314        if item: 
     315            item.modified = item.savedata != names 
     316 
     317    def _selectedSaveSlot(self): 
     318        """ 
     319        Return the current selected saved selection slot. 
     320        """ 
     321        indexes = self.selectionsView.selectedIndexes() 
     322        if indexes: 
     323            return self.selectionsModel.item(indexes[0].row()) 
     324        else: 
     325            return None 
     326 
     327    def saveSelection(self): 
     328        """ 
     329        Save (update) the items in the current selected selection. 
     330        """ 
     331        item = self._selectedSaveSlot() 
     332        if item: 
     333            item.savedata = self.entryField.items() 
     334            item.modified = False 
     335 
     336    def addSelection(self, name=None): 
     337        """ 
     338        Add a new saved selection entry initialized by the current items. 
     339 
     340        The new slot will be selected. 
     341 
     342        """ 
     343        item = SaveSlot(name or "New selection") 
     344        item.savedata = self.entryField.items() 
     345        self.selectionsModel.appendRow([item]) 
     346        self.selectionsView.setCurrentIndex(item.index()) 
     347 
     348        if not name: 
     349            self.selectionsView.edit(item.index()) 
     350 
     351    def removeSelection(self): 
     352        """ 
     353        Remove the current selected save slot. 
     354        """ 
     355        item = self._selectedSaveSlot() 
     356        if item: 
     357            self.selectionsModel.removeRow(item.row()) 
     358 
     359    def _onSelectedSaveSlotChanged(self): 
     360        item = self._selectedSaveSlot() 
     361        if item: 
     362            if not item.document: 
     363                item.document = self._createDocument() 
     364                if item.savedata: 
     365                    item.document.setPlainText(" ".join(item.savedata)) 
     366 
     367            item.document.highlighter.setNames(self.geneNames) 
     368 
     369            self.entryField.setDocument(item.document) 
     370 
     371        self._updateActions() 
     372 
     373    def _createDocument(self): 
     374        """ 
     375        Create and new QTextDocument instance for editing gene names. 
     376        """ 
     377        doc = QTextDocument(self) 
     378        doc.setDocumentLayout(QPlainTextDocumentLayout(doc)) 
     379        doc.highlighter = NameHighlight(doc) 
     380        return doc 
     381 
     382    def _updateActions(self): 
     383        """ 
     384        Update the Save/remove action enabled state. 
     385        """ 
     386        selected = bool(self._selectedSaveSlot()) 
     387        self.actionRemove.setEnabled(selected) 
     388        self.actionSave.setEnabled(selected) 
     389 
     390    def getSettings(self, *args, **kwargs): 
     391        # copy the saved selections model back to widget settings. 
     392        selections = [] 
     393        for i in range(self.selectionsModel.rowCount()): 
     394            item = self.selectionsModel.item(i) 
     395            selections.append((item.name, item.savedata)) 
     396        self.savedSelections = selections 
     397 
     398        item = self._selectedSaveSlot() 
     399        if item is None: 
     400            self.selectedSelectionIndex = -1 
     401        else: 
     402            self.selectedSelectionIndex = item.row() 
     403 
     404        return OWWidget.getSettings(self, *args, **kwargs) 
    193405 
    194406 
     
    437649 
    438650            self.setFormat(match.start(), match_len, format) 
    439  
    440  
    441 def toString(variant): 
    442     if isinstance(variant, QVariant): 
    443         return unicode(variant.toString()) 
    444     else: 
    445         return unicode(variant) 
    446651 
    447652 
     
    522727    w.show() 
    523728    app.exec_() 
     729    w.saveSettings() 
    524730    w.deleteLater() 
    525731    del w 
Note: See TracChangeset for help on using the changeset viewer.