Skip to content

Commit

Permalink
Merge pull request #42 from calebweinreb/copy_tab_name
Browse files Browse the repository at this point in the history
refactored context menu and added menu for tab label
  • Loading branch information
calebweinreb authored Jul 12, 2024
2 parents a4f681a + 3c1f76d commit 2dea7e6
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 161 deletions.
42 changes: 39 additions & 3 deletions snub/gui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys, os, json
import numpy as np
from functools import partial
from snub.gui.utils import IntervalIndex, CheckBox
from snub.gui.utils import IntervalIndex, CheckBox, CustomContextMenu
from snub.gui.stacks import PanelStack, TrackStack
from snub.gui.tracks import TracePlot
from snub.gui.help import HelpMenu
Expand Down Expand Up @@ -60,6 +60,7 @@ def __init__(self, project_directory):
super().__init__()
# load config
self.project_directory = project_directory
self.name = project_directory.strip(os.path.sep).split(os.path.sep)[-1]
self.layout_mode = None
config_path = os.path.join(self.project_directory, "config.json")
config = json.load(open(config_path, "r"))
Expand Down Expand Up @@ -320,6 +321,41 @@ def pause(self):
self.play_button.setIcon(self.play_icon)
self.playing = False

def copy_tab_name(self):
clipboard = QApplication.clipboard()
clipboard.setText(self.name)


class CustomTabBar(QTabBar):
def __init__(self, parent=None):
super(CustomTabBar, self).__init__(parent)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.showContextMenu)

def mousePressEvent(self, event):
if event.button() == Qt.RightButton:
self.showContextMenu(event.pos())
else:
super(CustomTabBar, self).mousePressEvent(event)

def showContextMenu(self, pos):
global_pos = self.mapToGlobal(pos)
index = self.tabAt(pos)
if index != -1:
contextMenu = CustomContextMenu(self)
close_action = contextMenu.add_item(
"Close Tab", lambda: self.parent().removeTab(index)
)
copy_action = contextMenu.add_item(
"Copy Name", lambda: self.copyTabName(index)
)
contextMenu.exec_(global_pos)

def copyTabName(self, index):
clipboard = QApplication.clipboard()
tab_name = self.tabText(index)
clipboard.setText(tab_name)


class MainWindow(QMainWindow):
"""
Expand All @@ -330,6 +366,7 @@ class MainWindow(QMainWindow):
def __init__(self, args):
super().__init__()
self.tabs = QTabWidget()
self.tabs.setTabBar(CustomTabBar(self.tabs))
self.tabs.setTabsClosable(True)
self.tabs.tabCloseRequested.connect(self.close_tab)
self.tabs.currentChanged.connect(self.tab_changed)
Expand Down Expand Up @@ -435,9 +472,8 @@ def reload_data(self):
self.load_project(project_dir)

def load_project(self, project_directory):
name = project_directory.strip(os.path.sep).split(os.path.sep)[-1]
project_tab = ProjectTab(project_directory)
self.tabs.addTab(project_tab, name)
self.tabs.addTab(project_tab, project_tab.name)
self.tabs.setCurrentWidget(project_tab)

def getExistingDirectories(self):
Expand Down
27 changes: 4 additions & 23 deletions snub/gui/panels/roi.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from vispy.scene.visuals import Image, Line

from snub.gui.panels import Panel
from snub.gui.utils import HeaderMixin, AdjustColormapDialog
from snub.gui.utils import HeaderMixin, AdjustColormapDialog, CustomContextMenu
from snub.io.project import _random_color


Expand Down Expand Up @@ -161,27 +161,8 @@ def mouse_release(self, event):
self.context_menu(event)

def context_menu(self, event):
contextMenu = QMenu(self)

def add_menu_item(name, slot, item_type="label"):
action = QWidgetAction(self)
if item_type == "checkbox":
widget = QCheckBox(name)
widget.stateChanged.connect(slot)
elif item_type == "label":
widget = QLabel(name)
action.triggered.connect(slot)
action.setDefaultWidget(widget)
contextMenu.addAction(action)
return widget

# click to show adjust colormap range dialog
label = add_menu_item("Adjust colormap range", self.show_adjust_colormap_dialog)

contextMenu.setStyleSheet(
"""
QMenu::item, QLabel, QCheckBox { background-color : #3E3E3E; padding: 5px 6px 5px 6px;}
QMenu::item:selected, QLabel:hover, QCheckBox:hover { background-color: #999999;}
QMenu::separator { background-color: rgb(20,20,20);} """
contextMenu = CustomContextMenu(self)
label = contextMenu.add_item(
"Adjust colormap range", self.show_adjust_colormap_dialog
)
action = contextMenu.exec_(event.native.globalPos())
56 changes: 22 additions & 34 deletions snub/gui/panels/scatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
IntervalIndex,
UNCHECKED_ICON_PATH,
CHECKED_ICON_PATH,
CustomContextMenu,
)


Expand Down Expand Up @@ -191,38 +192,30 @@ def update_current_time(self, t):
self.current_node_marker.parent = None

def context_menu(self, event):
contextMenu = QMenu(self)

def add_menu_item(name, slot, item_type="label"):
action = QWidgetAction(self)
if item_type == "checkbox":
widget = QCheckBox(name)
widget.stateChanged.connect(slot)
elif item_type == "label":
widget = QLabel(name)
action.triggered.connect(slot)
action.setDefaultWidget(widget)
contextMenu.addAction(action)
return widget
contextMenu = CustomContextMenu(self)

# show/hide variable menu
if self.variable_menu.isVisible():
add_menu_item("Hide variables menu", self.hide_variable_menu)
contextMenu.add_item("Hide variables menu", self.hide_variable_menu)
else:
add_menu_item("Show variables menu", self.show_variable_menu)
contextMenu.add_item("Show variables menu", self.show_variable_menu)

# get enriched variables (only available is nodes are selected)
label = add_menu_item(
"Sort variables by enrichment", self.get_enriched_variables
label = contextMenu.add_item(
"Sort variables by enrichment",
self.get_enriched_variables,
)
if self.is_selected.sum() == 0:
label.setStyleSheet("QLabel { color: rgb(120,120,120); }")

add_menu_item("Restore original variable order", self.show_variable_menu)
contextMenu.add_item(
"Restore original variable order",
self.show_variable_menu,
)
contextMenu.addSeparator()

# toggle whether to plot high-variable-val nodes on top
checkbox = add_menu_item(
checkbox = contextMenu.add_item(
"Plot high values on top",
self.toggle_sort_by_color_value,
item_type="checkbox",
Expand All @@ -234,25 +227,20 @@ def add_menu_item(name, slot, item_type="label"):
contextMenu.addSeparator()

# click to show adjust colormap range dialog
add_menu_item("Adjust colormap range", self.show_adjust_colormap_dialog)
add_menu_item("Adjust marker appearance", self.show_adjust_marker_dialog)
contextMenu.add_item("Adjust colormap range", self.show_adjust_colormap_dialog)
contextMenu.add_item("Adjust marker appearance", self.show_adjust_marker_dialog)
contextMenu.addSeparator()

if self.show_marker_trail:
add_menu_item("Hide marker trail", partial(self.toggle_marker_trail, False))
contextMenu.add_item(
"Hide marker trail",
partial(self.toggle_marker_trail, False),
)
else:
add_menu_item("Show marker trail", partial(self.toggle_marker_trail, True))

contextMenu.setStyleSheet(
f"""
QMenu::item, QLabel, QCheckBox {{ background-color : #3e3e3e; padding: 5px 6px 5px 6px;}}
QMenu::item:selected, QLabel:hover, QCheckBox:hover {{ background-color: #999999;}}
QMenu::separator {{ background-color: rgb(20,20,20);}}
QCheckBox::indicator:unchecked {{ image: url({UNCHECKED_ICON_PATH}); }}
QCheckBox::indicator:checked {{ image: url({CHECKED_ICON_PATH}); }}
QCheckBox::indicator {{ width: 14px; height: 14px;}}
"""
)
contextMenu.add_item(
"Show marker trail",
partial(self.toggle_marker_trail, True),
)
action = contextMenu.exec_(event.native.globalPos())

def toggle_marker_trail(self, visibility):
Expand Down
41 changes: 12 additions & 29 deletions snub/gui/tracks/annotator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
import numpy as np
import json
from snub.gui.tracks import Track, TrackGroup, position_to_time
from snub.gui.utils import IntervalIndex, CHECKED_ICON_PATH, UNCHECKED_ICON_PATH
from snub.gui.utils import (
IntervalIndex,
CHECKED_ICON_PATH,
UNCHECKED_ICON_PATH,
CustomContextMenu,
)


class AnnotatorLabels(QWidget):
Expand Down Expand Up @@ -222,22 +227,10 @@ def _load(self, file_name):
self.update()

def contextMenuEvent(self, event):
contextMenu = QMenu(self)

def add_menu_item(name, slot, item_type="label"):
action = QWidgetAction(self)
if item_type == "checkbox":
widget = QCheckBox(name)
widget.stateChanged.connect(slot)
elif item_type == "label":
widget = QLabel(name)
action.triggered.connect(slot)
action.setDefaultWidget(widget)
contextMenu.addAction(action)
return widget
contextMenu = CustomContextMenu(self)

# toggle autosave
checkbox = add_menu_item(
checkbox = contextMenu.add_item(
"Automatically save",
self.toggle_autosave,
item_type="checkbox",
Expand All @@ -248,7 +241,7 @@ def add_menu_item(name, slot, item_type="label"):
checkbox.setChecked(False)

# toggle update_time_on_drag
checkbox = add_menu_item(
checkbox = contextMenu.add_item(
"Update time on drag",
self.toggle_update_time_on_drag,
item_type="checkbox",
Expand All @@ -259,19 +252,9 @@ def add_menu_item(name, slot, item_type="label"):
checkbox.setChecked(False)

# import/export annotations
add_menu_item("Export annotations", self.export_annotations)
add_menu_item("Import annotations", self.import_annotations)

contextMenu.setStyleSheet(
f"""
QMenu::item, QLabel, QCheckBox {{ background-color : #3e3e3e; padding: 5px 6px 5px 6px;}}
QMenu::item:selected, QLabel:hover, QCheckBox:hover {{ background-color: #999999;}}
QMenu::separator {{ background-color: rgb(20,20,20);}}
QCheckBox::indicator:unchecked {{ image: url({UNCHECKED_ICON_PATH}); }}
QCheckBox::indicator:checked {{ image: url({CHECKED_ICON_PATH}); }}
QCheckBox::indicator {{ width: 14px; height: 14px;}}
"""
)
contextMenu.add_item("Export annotations", self.export_annotations)
contextMenu.add_item("Import annotations", self.import_annotations)

action = contextMenu.exec_(self.mapToGlobal(event.pos()))

def toggle_autosave(self, state):
Expand Down
56 changes: 18 additions & 38 deletions snub/gui/tracks/heatmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
from numba import njit, prange

from snub.gui.tracks import Track, TracePlot, TrackGroup
from snub.gui.utils import AdjustColormapDialog, CHECKED_ICON_PATH, UNCHECKED_ICON_PATH
from snub.gui.utils import (
AdjustColormapDialog,
CHECKED_ICON_PATH,
UNCHECKED_ICON_PATH,
CustomContextMenu,
)
from snub.io.project import _random_color


Expand Down Expand Up @@ -310,24 +315,7 @@ def update_current_range(self, current_range):
self.heatmap_image.update_current_range(current_range)

def contextMenuEvent(self, event):
contextMenu = QMenu(self)

def add_menu_item(name, slot, item_type="label"):
action = QWidgetAction(self)
if item_type == "checkbox":
widget = QCheckBox(name)
widget.stateChanged.connect(slot)
elif item_type == "button":
widget = QPushButton(name)
widget.clicked.connect(slot)
elif item_type == "label":
widget = QLabel(name)
action.triggered.connect(slot)
else:
return
action.setDefaultWidget(widget)
contextMenu.addAction(action)
return widget
contextMenu = CustomContextMenu(self)

# used to get row label and for zooming
y = (
Expand All @@ -341,45 +329,37 @@ def add_menu_item(name, slot, item_type="label"):
if self.add_traceplot:
row_label = self.labels[self.row_order[int(y)]]
display_trace_slot = lambda: self.display_trace_signal.emit(row_label)
add_menu_item("Plot trace: {}".format(row_label), display_trace_slot)
contextMenu.add_item(
"Plot trace: {}".format(row_label),
display_trace_slot,
)

# show adjust colormap dialog
add_menu_item("Adjust colormap range", self.show_adjust_colormap_dialog)
contextMenu.add_item("Adjust colormap range", self.show_adjust_colormap_dialog)
contextMenu.addSeparator()

if self.heatmap_labels.isVisible():
add_menu_item("Hide row labels", self.hide_labels)
contextMenu.add_item("Hide row labels", self.hide_labels)
else:
add_menu_item("Show row labels", self.show_labels)
contextMenu.add_item("Show row labels", self.show_labels)
contextMenu.addSeparator()

# for reordering rows
add_menu_item("Reorder by selection", self.reorder_by_selection)
add_menu_item("Restore original order", self.restore_original_order)
contextMenu.add_item("Reorder by selection", self.reorder_by_selection)
contextMenu.add_item("Restore original order", self.restore_original_order)
contextMenu.addSeparator()

# for changing vertical range
add_menu_item(
contextMenu.add_item(
"Zoom in (vertical)",
partial(self.zoom_vertical, y, 2 / 3),
item_type="button",
)
add_menu_item(
contextMenu.add_item(
"Zoom out (vertical)",
partial(self.zoom_vertical, y, 3 / 2),
item_type="button",
)

contextMenu.setStyleSheet(
f"""
QMenu::item, QLabel, QCheckBox {{ background-color : #3e3e3e; padding: 5px 6px 5px 6px;}}
QMenu::item:selected, QLabel:hover, QCheckBox:hover {{ background-color: #999999;}}
QMenu::separator {{ background-color: rgb(20,20,20);}}
QCheckBox::indicator:unchecked {{ image: url({UNCHECKED_ICON_PATH}); }}
QCheckBox::indicator:checked {{ image: url({CHECKED_ICON_PATH}); }}
QCheckBox::indicator {{ width: 14px; height: 14px;}}
"""
)
action = contextMenu.exec_(self.mapToGlobal(event.pos()))

def show_labels(self):
Expand Down
Loading

0 comments on commit 2dea7e6

Please sign in to comment.