Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix linking of subset visual properties with subset group visual properties #1365

Merged
merged 3 commits into from
Aug 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Full changelog
v0.11.0 (unreleased)
--------------------

* If a subset's visual properties are changed, change the visual
properties of the parent SubsetGroup. [#1365]

* Give an error if the user selects a session file when going through
the 'Open Data Set' menu. [#1364]

Expand Down
3 changes: 3 additions & 0 deletions glue/app/qt/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class PreferencesDialog(QtWidgets.QDialog):
data_alpha = ValueProperty('ui.slider_alpha', value_range=(0, 1))
data_apply = ButtonProperty('ui.checkbox_apply')
show_large_data_warning = ButtonProperty('ui.checkbox_show_large_data_warning')
individual_subset_color = ButtonProperty('ui.checkbox_individual_subset_color')
save_to_disk = ButtonProperty('ui.checkbox_save')

def __init__(self, application, parent=None):
Expand All @@ -49,6 +50,7 @@ def __init__(self, application, parent=None):
self.data_color = settings.DATA_COLOR
self.data_alpha = settings.DATA_ALPHA
self.show_large_data_warning = settings.SHOW_LARGE_DATA_WARNING
self.individual_subset_color = settings.INDIVIDUAL_SUBSET_COLOR

self._update_theme_from_colors()

Expand Down Expand Up @@ -94,6 +96,7 @@ def accept(self):
settings.DATA_COLOR = self.data_color
settings.DATA_ALPHA = self.data_alpha
settings.SHOW_LARGE_DATA_WARNING = self.show_large_data_warning
settings.INDIVIDUAL_SUBSET_COLOR = self.individual_subset_color

for pane in self.panes:
pane.finalize()
Expand Down
109 changes: 63 additions & 46 deletions glue/app/qt/preferences.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>447</width>
<height>357</height>
<width>617</width>
<height>420</height>
</rect>
</property>
<property name="windowTitle">
Expand All @@ -30,10 +30,13 @@
<property name="verticalSpacing">
<number>15</number>
</property>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<item row="9" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Background color:</string>
<string>Allow subsets within a subset group to have different visual properties</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
Expand All @@ -44,52 +47,31 @@
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="checkbox_apply">
<property name="text">
<string/>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QColorBox" name="color_background">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Default data transparency:</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="4" column="0" colspan="3">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<item row="7" column="2">
<widget class="QCheckBox" name="checkbox_apply">
<property name="text">
<string>Foreground color:</string>
<string/>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Default data color:</string>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<item row="0" column="2">
<widget class="QComboBox" name="combo_theme">
<item>
<property name="text">
Expand All @@ -108,38 +90,42 @@
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Theme for viewers:</string>
<string>Background color:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSlider" name="slider_alpha">
<property name="maximum">
<number>100</number>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Foreground color:</string>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Default data color:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="5" column="2">
<widget class="QColorBox" name="color_default_data">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="3" column="2">
<widget class="QColorBox" name="color_foreground">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<item row="1" column="0" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
Expand All @@ -159,7 +145,7 @@
</property>
</spacer>
</item>
<item row="8" column="1">
<item row="8" column="2">
<widget class="QCheckBox" name="checkbox_show_large_data_warning">
<property name="text">
<string/>
Expand All @@ -173,6 +159,37 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Theme for viewers:</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QSlider" name="slider_alpha">
<property name="maximum">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QColorBox" name="color_background">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QCheckBox" name="checkbox_individual_subset_color">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
Expand Down
1 change: 1 addition & 0 deletions glue/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,3 +695,4 @@ def _default_search_order():
settings.add('BACKGROUND_COLOR', '#FFFFFF')
settings.add('FOREGROUND_COLOR', '#000000')
settings.add('SHOW_LARGE_DATA_WARNING', True, validator=bool)
settings.add('INDIVIDUAL_SUBSET_COLOR', False, validator=bool)
18 changes: 17 additions & 1 deletion glue/core/subset_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

from glue.external import six
from glue.core.contracts import contract
from glue.core.message import (DataCollectionAddMessage,
from glue.core.message import (SubsetUpdateMessage,
DataCollectionAddMessage,
DataCollectionDeleteMessage)
from glue.core.visual import VisualAttributes
from glue.core.hub import HubListener
Expand Down Expand Up @@ -147,11 +148,26 @@ def _remove_data(self, data):
self.subsets.remove(s)

def register_to_hub(self, hub):

hub.subscribe(self, DataCollectionAddMessage,
lambda x: self._add_data(x.data))

hub.subscribe(self, DataCollectionDeleteMessage,
lambda x: self._remove_data(x.data))

def has_subset(msg):
return msg.attribute == 'style' and msg.subset in self.subsets

hub.subscribe(self, SubsetUpdateMessage,
self._sync_style_from_subset,
filter=has_subset)

def _sync_style_from_subset(self, msg):
if settings.INDIVIDUAL_SUBSET_COLOR:
return
self._style.set(msg.subset.style)
self.broadcast('style')

@property
def style(self):
return self._style
Expand Down
66 changes: 66 additions & 0 deletions glue/core/tests/test_subset_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@
import numpy as np
from mock import MagicMock, patch

from ...config import settings
from .. import DataCollection, Data, SubsetGroup
from .. import subset
from ..subset import SubsetState
from ..subset_group import coerce_subset_groups
from .test_state import clone


def restore_settings(func):
def wrapper(*args, **kwargs):
settings.reset_defaults()
results = func(*args, **kwargs)
settings.reset_defaults()
return results
return wrapper


class TestSubsetGroup(object):

def setup_method(self, method):
Expand Down Expand Up @@ -40,20 +50,31 @@ def test_attributes_synced_to_group(self):
assert sub.subset_state is sg.subset_state
assert sub.label is sg.label

@restore_settings
def test_set_style_overrides(self):

# Test to make sure that if the user has selected to allow individual
# subset colors, the subset color can become out of sync with the
# group color.

settings.INDIVIDUAL_SUBSET_COLOR = True

self.sg.register(self.dc)
sg = self.sg
sg.subsets[0].style.color = 'blue'
for sub in sg.subsets[1:]:
assert sub.style.color != 'blue'

assert sg.subsets[0].style.color == 'blue'

def test_new_subset_group_syncs_style(self):
sg = self.dc.new_subset_group()
for sub in sg.subsets:
assert sub.style == sg.style

@restore_settings
def test_set_group_style_clears_override(self):
settings.INDIVIDUAL_SUBSET_COLOR = True
sg = self.dc.new_subset_group()
style = sg.style.copy()
style.parent = sg.subsets[0]
Expand All @@ -62,6 +83,51 @@ def test_set_group_style_clears_override(self):
sg.style.color = 'red'
assert sg.subsets[0].style.color == 'red'

def test_changing_subset_style_changes_group(self):

# Test to make sure that if a subset's visual properties are changed,
# the visual properties of all subsets in the same subset group are changed

# This is just to make sure the default setting is still False
assert not settings.INDIVIDUAL_SUBSET_COLOR

d1 = Data(x=[1, 2, 3], label='d1')
d2 = Data(y=[2, 3, 4], label='d2')
d3 = Data(y=[2, 3, 4], label='d3')

dc = DataCollection([d1, d2, d3])

sg = dc.new_subset_group(subset_state=d1.id['x'] > 1, label='A')

# Changing d1 subset properties changes group and other subsets

d1.subsets[0].style.color = '#c0b4a1'
assert sg.style.color == '#c0b4a1'
assert d2.subsets[0].style.color == '#c0b4a1'
assert d3.subsets[0].style.color == '#c0b4a1'

d2.subsets[0].style.alpha = 0.2
assert sg.style.alpha == 0.2
assert d1.subsets[0].style.alpha == 0.2
assert d3.subsets[0].style.alpha == 0.2

d3.subsets[0].style.markersize = 16
assert sg.style.markersize == 16
assert d1.subsets[0].style.markersize == 16
assert d2.subsets[0].style.markersize == 16

# Changing subset group changes subsets

sg.style.color = '#abcdef'
assert d1.subsets[0].style.color == '#abcdef'
assert d2.subsets[0].style.color == '#abcdef'
assert d3.subsets[0].style.color == '#abcdef'

sg.style.linewidth = 12
assert d1.subsets[0].style.linewidth == 12
assert d2.subsets[0].style.linewidth == 12
assert d3.subsets[0].style.linewidth == 12

def test_new_data_creates_subset(self):
sg = self.dc.new_subset_group()
d = Data(label='z', z=[10, 20, 30])
Expand Down