Skip to content
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
14 changes: 14 additions & 0 deletions PyReconstruct/modules/datatypes/series_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,20 @@ def getTags(self, obj_name : str) -> set:
tags = tags.union(trace_data.getTags())
return tags

def usedTags(self) -> set:
"""Every tag on a trace anywhere in the series.

Read from this cache, which is kept current after each edit, so no
section file is opened.
"""
tags = set()
for obj_data in self.data["objects"].values():
for trace_list in obj_data.traces.values():
for trace_data in trace_list:
if trace_data.tags:
tags.update(trace_data.tags)
return tags

def getAvgRadius(self, obj_name : str) -> float:
"""Get the average stamp radius of an object.

Expand Down
14 changes: 12 additions & 2 deletions PyReconstruct/modules/gui/dialog/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def __init__(self, parent : QWidget, entries : list = None, combo=False, combo_i
self.inputs = []
for entry in entries:
if self.is_combo:
w = CompleterBox(self, self.combo_items, allow_new=(not restrict_to_opts))
w = self.makeCombo()
w.setCurrentText(entry)
else:
w = QLineEdit(self, text=entry)
Expand Down Expand Up @@ -138,10 +138,20 @@ def mark(*args):
else:
w.textEdited.connect(mark)

def makeCombo(self):
"""One dropdown row: the options, blank when free text is allowed."""
w = CompleterBox(self, self.combo_items, allow_new=(not self.restrict_to_opts))
if not self.restrict_to_opts:
# an editable combobox opens on its first option; a free-text row
# starts empty, like the line edit it replaces, so "+" does not
# silently propose the alphabetically first option
w.setCurrentText("")
return w

def add(self):
"""Add a line edit row to the field."""
if self.is_combo:
w = CompleterBox(self, self.combo_items)
w = self.makeCombo()
else:
w = QLineEdit(self)
self._trackEdits(w)
Expand Down
23 changes: 21 additions & 2 deletions PyReconstruct/modules/gui/dialog/trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@ def __init__(
tags=None,
is_palette=False,
is_obj_list=False,
pos=None):
pos=None,
used_tags=None):
"""Create an attribute dialog.

Params:
parent (QWidget): the parent widget
traces (list): a list of traces
pos (tuple): the point to create the dialog
used_tags (iterable): every tag already on a trace in the
series, offered in the Tags rows (SeriesData.usedTags)
"""
super().__init__(parent)

Expand Down Expand Up @@ -119,12 +122,28 @@ def __init__(
# sorted because trace.tags is a set: unsorted, a tag lands on a
# different row every time the dialog opens, so the row a user is part
# way through editing is not the row they left off on
self.tags_input = MultiInput(self, sorted(tags))
#
# When the series already has tags, each row is a dropdown of them that
# completes as you type (issue #132). Typed text outside the list is
# still accepted, so a new tag is entered the same way as before.
known_tags = [t for t in (used_tags or ()) if t]
if known_tags:
self.tags_input = MultiInput(
self,
sorted(tags),
combo=True,
combo_items=known_tags,
restrict_to_opts=False,
)
else:
self.tags_input = MultiInput(self, sorted(tags))

if self.tags_differ:
# the field is blank because there is no single set of tags to show,
# not because the traces are untagged
for w in self.tags_input.inputs:
if self.tags_input.is_combo:
w = w.lineEdit()
w.setPlaceholderText("(tags differ -- left alone unless edited)")

self.selected_input = QCheckBox("Fill when selected")
Expand Down
1 change: 1 addition & 0 deletions PyReconstruct/modules/gui/main/field_widget_2_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,7 @@ def traceDialog(self, traces : list):
t, confirmed = TraceDialog(
self,
traces,
used_tags=self.series.data.usedTags(),
).exec()
if not confirmed:
return
Expand Down
3 changes: 2 additions & 1 deletion PyReconstruct/modules/gui/main/field_widget_3_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ def editAttributes(self, obj_names : list):
self,
name=displayed_name,
tags=tags,
is_obj_list=True
is_obj_list=True,
used_tags=self.series.data.usedTags(),
).exec()

if not confirmed:
Expand Down
3 changes: 2 additions & 1 deletion PyReconstruct/modules/gui/palette/buttons.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ def openDialog(self):
t, confirmed = TraceDialog(
self,
[self.trace],
is_palette=True
is_palette=True,
used_tags=self.manager.mainwindow.series.data.usedTags(),
).exec()
if not confirmed:
return
Expand Down
Loading