Opened 9 years ago

Closed 7 years ago

Last modified 7 years ago

#626 closed enhancement (fixed)

If a volume is selected in the Models panel, Density Map Toolbar buttons should act only on that one

Reported by: Tristan Croll Owned by: Tom Goddard
Priority: moderate Milestone:
Component: Volume Data Version:
Keywords: Cc: meng@…, pett
Blocked By: Blocking:
Notify when closed: Platform: all
Project: ChimeraX

Description

At present, restricting the display buttons to act on one volume requires "physically" selecting it in the main OpenGL window. I think allowing selection by name in the Models panel to do the same would provide a very intuitive second route to the same effect. I guess if a map is selected in the OpenGL window and a different map in the Models panel then there would be a conundrum, but in that case I'd lean towards letting the OpenGL selection take precedence.

Change History (12)

comment:1 by Tom Goddard, 9 years ago

Cc: meng@… added

This is an interesting idea, and I definitely see that it could be useful. But I also see that it could very easily cause confusion where you clicked in model panel and now the shortcut icons don't act on the models you expect because you don't know they are connected to the model panel. Already rules for what shortcut icons act on are tricky (selected and if none selected then displayed models). But at least it is visually apparent in the graphics window. This ticket proposes making a factor that is not visible in the graphics window influence what happens. The Model Panel has its own set of buttons in the panel itself that act on models chosen in the panel -- in Chimera 1 this list of buttons is quite long. Maybe we should simply add the buttons you find useful to Model Panel itself?

I'd like to get Elaine's opinion on this. Added her to the CC list on this ticket.

in reply to:  2 ; comment:2 by Elaine Meng, 9 years ago

There are so many possible functions of interest, I was thinking it might be simpler and more consistent to add just a select-model button to the Model Panel. There could also be preferences for default action from merely choosing the model in the Model Pane (or double-clicking it like we have for the Chimera Model Panel).  Then the icons would continue to work with the “selected” paradigm.

(Tom I cc’d you since I wasn’t sure if ChimeraX trac is connected to emails correctly; apologies if you get this twice)
Elaine

comment:3 by pett, 8 years ago

Component: UnassignedVolume Data

comment:4 by Tristan Croll, 8 years ago

I'm happy with either solution (although with Elaine's approach I think it would then also be important to add a deselect button to make it easy to deselect the model without accidentally clearing any other active selections).

By the way, I'm not sure what I'm doing wrong but I'm not getting emails for any tickets I add via the web interface.

comment:5 by Tristan Croll, 8 years ago

The below changes to model_panel/tool.py add a select button as per Elaine's suggestion). It's a checkbox that automatically updates its state to reflect the selection status of the Model (Qt.Unchecked for not selected, Qt.Checked for fully selected, and Qt.PartiallyChecked if any_part_selected() returns true but selected is false. Clicking the check box selects the whole model if unselected or partially selected, otherwise deselects it.

diff --git a/src/bundles/model_panel/src/tool.py b/src/bundles/model_panel/src/tool.py
index 93bea94..50fdf32 100644
--- a/src/bundles/model_panel/src/tool.py
+++ b/src/bundles/model_panel/src/tool.py
@@ -41,8 +41,9 @@ class ModelPanel(ToolInstance):
         layout.addWidget(self.tree)
         layout.setStretchFactor(self.tree, 1)
         parent.setLayout(layout)
-        title = "S" if short_titles else "Shown"
-        self.tree.setHeaderLabels(["Name", "ID", " ", title])
+        shown_title = "D" if short_titles else "Display"
+        sel_title = "S" if short_titles else "Select"
+        self.tree.setHeaderLabels(["Name", "ID", " ", shown_title, sel_title])
         self.tree.setColumnWidth(self.NAME_COLUMN, 200)
         self.tree.setSelectionBehavior(QAbstractItemView.SelectRows)
         self.tree.setSelectionMode(QAbstractItemView.ExtendedSelection)
@@ -68,6 +69,8 @@ class ModelPanel(ToolInstance):
         self.session.triggers.add_handler(MODEL_ID_CHANGED,
             lambda *args: self._fill_tree(*args, always_rebuild=True))
         self.session.triggers.add_handler(MODEL_NAME_CHANGED, self._fill_tree)
+        from chimerax.core.selection import SELECTION_CHANGED
+        self.session.triggers.add_handler(SELECTION_CHANGED, self._fill_tree)
         from chimerax.core import atomic
         atomic.get_triggers(self.session).add_handler("changes", self._changes_cb)
         self._frame_drawn_handler = None
@@ -78,6 +81,7 @@ class ModelPanel(ToolInstance):
     ID_COLUMN = 1
     COLOR_COLUMN = 2
     SHOWN_COLUMN = 3
+    SELECT_COLUMN = 4
     
     def _shown_changed(self, shown):
         if shown:
@@ -126,7 +130,7 @@ class ModelPanel(ToolInstance):
         from PyQt5.QtGui import QColor
         item_stack = [self.tree.invisibleRootItem()]
         for model in self.models:
-            model_id, model_id_string, bg_color, display, name = self._get_info(model)
+            model_id, model_id_string, bg_color, display, name, selected, part_selected = self._get_info(model)
             len_id = len(model_id)
             if update:
                 if len_id == len(item_stack):
@@ -153,6 +157,9 @@ class ModelPanel(ToolInstance):
                     but.color_changed.connect(set_single_color)
                     but.set_color(bg_color)
                     self.tree.setItemWidget(item, self.COLOR_COLUMN, but)
+                
+                    
+                
             item.setText(self.ID_COLUMN, model_id_string)
             bg = item.background(self.ID_COLUMN)
             if bg_color is False:
@@ -164,6 +171,12 @@ class ModelPanel(ToolInstance):
             item.setBackground(self.COLOR_COLUMN, bg)
             if display is not None:
                 item.setCheckState(self.SHOWN_COLUMN, Qt.Checked if display else Qt.Unchecked)
+            if selected:
+                item.setCheckState(self.SELECT_COLUMN, Qt.Checked)
+            elif part_selected:
+                item.setCheckState(self.SELECT_COLUMN, Qt.PartiallyChecked)
+            else:
+                item.setCheckState(self.SELECT_COLUMN, Qt.Unchecked)
             item.setText(self.NAME_COLUMN, name)
             if not update:
                 # Expand new top-level displayed models, or if previously expanded
@@ -185,7 +198,9 @@ class ModelPanel(ToolInstance):
         bg_color = self._model_color(obj)
         display = obj.display
         name = getattr(obj, "name", "(unnamed)")
-        return model_id, model_id_string, bg_color, display, name
+        selected = obj.selected
+        part_selected = obj.any_part_selected()
+        return model_id, model_id_string, bg_color, display, name, selected, part_selected
 
     def _header_click_cb(self, index):
         if index == 0:
@@ -198,7 +213,11 @@ class ModelPanel(ToolInstance):
         if event.Col == self.SHOWN_COLUMN:
             model = self.models[event.Row]
             model.display = not model.display
-        event.Skip()
+        elif event.Col == self.SELECT_COLUMN:
+            model = self.models[event.Row]
+            model.selected = not model.selected
+        else:
+            event.Skip()
 
     def _label_click(self, event):
         if event.Col == self.ID_COLUMN:
@@ -224,11 +243,11 @@ class ModelPanel(ToolInstance):
         return update
 
     def _tree_change_cb(self, item, column):
-        if column != self.SHOWN_COLUMN:
-            # not the shown check box
-            return
-        from PyQt5.QtCore import Qt
-        self.models[self._items.index(item)].display = item.checkState(self.SHOWN_COLUMN) == Qt.Checked
+        from PyQt5.QtCore import Qt        
+        if column == self.SHOWN_COLUMN:
+            self.models[self._items.index(item)].display = item.checkState(self.SHOWN_COLUMN) == Qt.Checked
+        elif column == self.SELECT_COLUMN:
+            self.models[self._items.index(item)].selected = item.checkState(self.SELECT_COLUMN) == Qt.Checked
 
 from chimerax.core.settings import Settings
 class ModelPanelSettings(Settings):

comment:6 by Tristan Croll, 8 years ago

... Actually, this also requires the SELECTION_CHANGED trigger to be fired when the selection changes for *any* Model, not just a Structure:

diff --git a/src/core/models.py b/src/core/models.py
index 0942e30..00061cb 100644
--- a/src/core/models.py
+++ b/src/core/models.py
@@ -101,7 +101,14 @@ class Model(State, Drawing):
         if self._id != None:  # model actually open
             self.session.triggers.activate_trigger(MODEL_NAME_CHANGED, self)
     name = property(_get_name, _set_name)
+    
+    def set_selected(self, sel):
+        Drawing.set_selected(self, sel)
+        from chimerax.core.selection import SELECTION_CHANGED
+        self.session.triggers.activate_trigger(SELECTION_CHANGED, None)
 
+    selected = property(Drawing.get_selected, set_selected)
+    
     def _model_set_position(self, pos):
         if pos != self.position:
             Drawing.position.fset(self, pos)

comment:7 by Tom Goddard, 8 years ago

Cc: pett added

Having a "selected" checkbutton for each line in model panel in addition to the "shown" checkbutton is an interesting idea. I don't think that is what Elaine suggested -- I thought she meant adding a Select button to the right hand column of buttons. Let's see what other's think about it. I think your intent is that this allows using Toolbar buttons that act on the selection in conjunction with Model Panel. In general, models can be chosen directly in the graphics window or in the list in Model panel, and each has its own way of performing operations on the chosen models, toolbar buttons for selected models, and the Model panel right column of buttons for highlighted models in the Model panel list. It is a puzzle how to get these two similar capabilities to operate better together, and your "selected" checkbutton idea helps do that.

in reply to:  8 ; comment:8 by tic20@…, 8 years ago

Selecting models via the main window becomes problematic when you have (for example), multiple overlapping pickable Volumes, or a pickable Volume contour in front of atoms. In those cases, only the front most surface can be picked by ctrl-click.

 
 
Tristan Croll
Research Fellow
Cambridge Institute for Medical Research
University of Cambridge CB2 0XY
 

 


comment:9 by pett, 7 years ago

Priority: blockermoderate
Resolution: fixed
Status: assignedclosed

Okay, this is implemented (thanks for the code Tristan!), along with some fix-ups and improvements.

comment:10 by pett, 7 years ago

Well, the selection-column-in-model-panel is implemented. I think we decided that toolbar icons interacting with model panel selection was too confusing.

comment:11 by pett, 7 years ago

Selecting surfaces still needs some work. It works if you select-unselect-select!

Will investigate tomorrow or Monday.

comment:12 by Tom Goddard, 7 years ago

Not sure if comment 9 "Okay, this is implemented..." means that density map toolbar icons consider which lines of Model Panel are highlighted. If that change was made I think it requires more discussion -- I think it makes the behavior hard to fathom and causes more harm than good as I described in comment 1.

Note: See TracTickets for help on using tickets.