Skip to content

Commit

Permalink
enh: add some magic to let only the relevant schema widgets show
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmueller committed Oct 7, 2020
1 parent 3eeab64 commit 491f3aa
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 33 deletions.
41 changes: 37 additions & 4 deletions dcoraid/gui/upload/widget_schema.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from PyQt5 import QtCore, QtWidgets

from .widget_supplement_item import RSSItem, RSSTagsItem
from .widget_supplement_item import RSSItem, RSSTagsItem, TitleItem


#: These items displayed differently to the user and may populate other keys
Expand Down Expand Up @@ -66,29 +66,50 @@ def get_current_schema(self):
schema[sec][key] = widget.get_value()
return schema

@QtCore.pyqtSlot(str, str, object, bool)
def on_hide_show_items(self, section, key, value, enabled):
"""Send a value_changed signal to all widgets
...so they can decide whether they are visible or not.
"""
for sec in self.schema_widgets:
for item in self.schema_widgets[sec]:
item.on_schema_key_toggled(section, key, value, enabled)
for label in self.schema_title_widgets:
label.on_schema_key_toggled(section, key, value, enabled)

def populate_schema(self, schema_dict):
"""Create all widgets corresponding to the schema
Omits any :const:`HIDDEN_ITEMS` and creates special widgets
for :const:`MAGIC_ITEMS`.
"""
self.schema_title_widgets = []
for sec in schema_dict:
widget_list = []
label = QtWidgets.QLabel(sec.capitalize())
label = TitleItem(schema_dict[sec].get("requires", {}),
schema_dict[sec]["name"])
self.schema_title_widgets.append(label)
self.verticalLayout.addWidget(label)
for item in schema_dict[sec]["items"]:
key = item["key"]
# Update item requirements with section requirements
if "requires" not in item:
item["requires"] = schema_dict[sec].get("requires", {})
if sec in MAGIC_ITEMS and key in MAGIC_ITEMS[sec]:
# is a special widget (e.g. tags)
wrss = MAGIC_ITEMS[sec][key]["widget"](item, self)
wrss = MAGIC_ITEMS[sec][key]["widget"](item,
section=sec,
parent=self)
elif sec in HIDDEN_ITEMS and key in HIDDEN_ITEMS[sec]:
# should not be displayed
continue
else:
wrss = RSSItem(item, self)
wrss = RSSItem(item, section=sec, parent=self)
self.verticalLayout.addWidget(wrss)
widget_list.append(wrss)
wrss.value_changed.connect(self.schema_changed)
wrss.value_changed.connect(self.on_hide_show_items)
self.schema_widgets[sec] = widget_list

def set_schema(self, schema_dict):
Expand All @@ -114,3 +135,15 @@ def set_schema(self, schema_dict):
value = schema_dict[sec][key]
wrss.set_value(value)
self.blockSignals(False)
self.update_visible_widgets()

def update_visible_widgets(self):
"""Cause all schema data widgets to emit their values
This effectively updates the visibility of all schema
widgets (including titles).
"""
# Force all updates
for sec in self.schema_widgets:
for widget in self.schema_widgets[sec]:
widget.emit_value()
108 changes: 79 additions & 29 deletions dcoraid/gui/upload/widget_supplement_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,89 @@
from PyQt5 import uic, QtCore, QtWidgets


class RSSTagsItem(QtWidgets.QWidget):
value_changed = QtCore.pyqtSignal()
class TitleItem(QtWidgets.QWidget):
def __init__(self, requires, title, *args, **kwargs):
"""A schema widget for the section titles
def __init__(self, rss_dict, *args, **kwargs):
Parameters
----------
requires: dict
Requirements dictionary
title: str
Section title
"""
super(TitleItem, self).__init__(*args, **kwargs)

self.verticalLayout = QtWidgets.QVBoxLayout(self)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)

self.label = QtWidgets.QLabel("<b>{}</b>".format(title))
self.verticalLayout.addWidget(self.label)

self.requires = requires

@QtCore.pyqtSlot(str, str, object, bool)
def on_schema_key_toggled(self, section, key, value, enabled):
"""Hide or show this widget based on self.requires"""
if not self.requires:
self.setVisible(True)
elif section in self.requires and key in self.requires[section]:
if value in self.requires[section][key]:
self.setVisible(enabled)
else:
self.setVisible(False)


class RSSItemBase(QtWidgets.QWidget):
value_changed = QtCore.pyqtSignal(str, str, object, bool)

def __init__(self, rss_dict, section, *args, **kwargs):
super(RSSItemBase, self).__init__(*args, **kwargs)
self.rss_dict = rss_dict
self.section = section
self.key = rss_dict["key"]
self.requires = rss_dict.get("requires", {})

def emit_value(self):
"""Emit `value_changed` with current data"""
self.value_changed.emit(self.section, self.key, self.get_value(),
self.checkBox.isChecked())

@QtCore.pyqtSlot()
def on_value_changed(self):
"""Activate checkbox and call `emit_value`"""
if self.sender() == self.checkBox and not self.checkBox.isChecked():
# Do not check the checkBox again if the user unchecks it
pass
else:
self.check(True)
self.emit_value()

@QtCore.pyqtSlot(str, str, object, bool)
def on_schema_key_toggled(self, section, key, value, enabled):
"""Hide or show this widget based on self.rss_dict["requires"]"""
if not self.requires:
visible = True
elif section in self.requires and key in self.requires[section]:
if value in self.requires[section][key]:
visible = enabled
else:
visible = False
else:
visible = self.isVisible()
self.setVisible(visible)
if not visible:
# uncheck the widget if it is hidden
self.checkBox.setChecked(False)


class RSSTagsItem(RSSItemBase):
def __init__(self, *args, **kwargs):
"""Represents an item in the supplementary resource schema"""
super(RSSTagsItem, self).__init__(*args, **kwargs)
path_ui = pkg_resources.resource_filename(
"dcoraid.gui.upload", "widget_supplement_tags.ui")
uic.loadUi(path_ui, self)
self.rss_dict = rss_dict
self.tableWidget.setRowCount(3)
self.on_assert_row_count()

Expand Down Expand Up @@ -79,27 +152,14 @@ def on_assert_row_count(self):
self.tableWidget.setItem(ii, jj,
QtWidgets.QTableWidgetItem())

@QtCore.pyqtSlot()
def on_value_changed(self):
"""Activate checkbox and emit value_changed signal"""
if self.sender() == self.checkBox and not self.checkBox.isChecked():
# Do not check the checkBox again if the user unchecks it
pass
else:
self.check(True)
self.value_changed.emit()


class RSSItem(QtWidgets.QWidget):
value_changed = QtCore.pyqtSignal()

def __init__(self, rss_dict, *args, **kwargs):
class RSSItem(RSSItemBase):
def __init__(self, *args, **kwargs):
"""Represents an item in the supplementary resource schema"""
super(RSSItem, self).__init__(*args, **kwargs)
path_ui = pkg_resources.resource_filename(
"dcoraid.gui.upload", "widget_supplement_item.ui")
uic.loadUi(path_ui, self)
self.rss_dict = rss_dict
self.apply_schema()

# signals
Expand Down Expand Up @@ -196,16 +256,6 @@ def get_data_widget(self, retval=False):
else:
return widget

@QtCore.pyqtSlot()
def on_value_changed(self):
"""Activate checkbox and emit value_changed signal"""
if self.sender() == self.checkBox and not self.checkBox.isChecked():
# Do not check the checkBox again if the user unchecks it
pass
else:
self.check(True)
self.value_changed.emit()

def show_only_data_widget(self):
"""Convenience function that hides all but the data widget"""
widget = self.get_data_widget()
Expand Down

0 comments on commit 491f3aa

Please sign in to comment.