Here's my QOL addition. Parameter presets. There are certain view usages that have a predetermined set of parameters, like a view to be used in a perspective table cell. I have a hot key that lets me pick from a set of predefined parameter sets and applies them to the view.
This sparked another idea, something to auto gen the columns list in a perspective table, taken from the columns in the data so you don't have to do this manually all the time.
+1 ! This is so ideal.
Also, it would be great to have the option to show the row count, just like when you filter.
I just bind the columns key to the data key and run this script transform.
return [
{'field': col,
'sortable': True,
'visible': True,
'editable': False,
'resizable':True,
'header': {
'title': col
}
} for col in value[0]
]
Then I disable the binding, Of course add/remove whatever properties you normally use on your table columns, but this gets me 99% there.
The item that would be of most use to me in some of my projects would be to allow tag folders to be opened in the tag editor, to allow viewing and editing of custom properties. The can be written by script and read by scripts and bindings, but there is no convenient manual editing UI.
Wrong thread?
I think you meant to post to Designer quality of life "mods"
Clanker generated 'edit folder' addition to tag browser context menu. Only available on a single folder selection in the tag browser. I actually use custom properties on folders all the time so this might be my new favourite hahaha.
# QoL add-on: adds an "Edit Folder..." item to the Tag Browser right-click menu that
# opens the (folder-scoped) Tag Editor for the selected folder
from java.awt import Frame
_MENU_ITEM_KEY = "qolEditFolderItem"
_LISTENER_KEY = "qolEditFolderListener"
# Latest Tag Browser selection (list of tree nodes), kept fresh by the selection listener.
_selection = []
def _ctx_and_frame():
for f in Frame.getFrames():
try:
c = f.getContext()
if c is not None:
return c, f
except:
pass
return None, None
def _is_folder(node):
from com.inductiveautomation.ignition.designer.tags.tree.node import FolderNode
# Flip this to `return True` to show the item for tags/UDTs/folders alike.
return isinstance(node, FolderNode)
def _open_editor_for_selection():
if not _selection:
return
ctx, _ = _ctx_and_frame()
if ctx is None:
return
ctx.getTagEditor().editTag(_selection[0].getTagPath())
def install():
from java.awt.event import ActionListener
from javax.swing import JMenuItem, Action
from com.inductiveautomation.ignition.designer.sqltags.dialog import OnTagSelectedListener
ctx, frame = _ctx_and_frame()
if ctx is None:
return
rp = frame.getRootPane()
if rp.getClientProperty(_MENU_ITEM_KEY) is not None:
print "Edit Folder item already installed."
return
tb = ctx.getTagBrowser()
item = JMenuItem(u"Edit Folder…")
try:
edit_icon = tb.getActions().getEdit().getValue(Action.SMALL_ICON)
if edit_icon is not None:
item.setIcon(edit_icon) # reuse Ignition's built-in edit icon
except:
pass
class _Open(ActionListener):
def actionPerformed(self, e):
_open_editor_for_selection()
item.addActionListener(_Open())
class _Sel(OnTagSelectedListener):
def tagSelectionChanged(self, tags):
global _selection
_selection = list(tags) if tags else []
# show the item only when a single folder is selected
item.setVisible(len(_selection) == 1 and _is_folder(_selection[0]))
listener = _Sel()
tb.addOnTagSelectedListener(listener)
tb.addTagPopupMenuComponent(item, 0) # 0 = top of the right-click menu
item.setVisible(False) # hidden until a folder is selected
rp.putClientProperty(_MENU_ITEM_KEY, item)
rp.putClientProperty(_LISTENER_KEY, listener)
print "Installed: 'Edit Folder' tag context-menu item (folders only)."
def uninstall():
# NOTE: the Tag Browser has no API to remove a popup item, so we can only HIDE it and
# stop the listener. The item object lingers in the popup until the Designer restarts.
ctx, frame = _ctx_and_frame()
if frame is None:
return
rp = frame.getRootPane()
item = rp.getClientProperty(_MENU_ITEM_KEY)
if item is not None:
item.setVisible(False)
rp.putClientProperty(_MENU_ITEM_KEY, None)
listener = rp.getClientProperty(_LISTENER_KEY)
if listener is not None and ctx is not None:
ctx.getTagBrowser().removeOnTagSelectedListener(listener)
rp.putClientProperty(_LISTENER_KEY, None)
print "Uninstalled: 'Edit Folder' item hidden and listener removed (restart to fully clear)."
def _is_designer():
from com.inductiveautomation.ignition.common.model import ApplicationScope
return ApplicationScope.isDesigner(system.util.getSystemFlags())
if _is_designer():
install()
I'm a little behind in the Ignition updates, maybe this is already in there but...
The ability to make copies of alarms on a tag! When I have 32 alarms, one for each bit in an alarm word I hate having to type in the same alarm configuration over and over again when only the alarm name and bit number need to change.
You can already do this! Ctrl+C then Ctrl+V and you will see the alarm get copied on the tag UI editor interface.
Damn.. I can't believe I didn't try that before. lol. I assumed since it wasn't a right click menu it wasn't possible. Well, that's my problem solved ![]()
With tags in general it's also good to note the "Copy as JSON" feature. You can copy an alarm configuration to a text editor like this and copy/paste the JSON into the tag database really easily.
It's also very useful if you're trying to make a lot of tags programmatically. You can use a script transform to convert tags from whatever format to Ignition tags for example.
Hmmm. This is universal enough that it makes me want to implement it in my Integration Toolkit. (Life cycle is simpler...) Objections?
Coming soon to the Exchange... Hopefully
This version is considerably more robust than the one I originally posted. I had a colleague intentionally try to poke holes in it, and that process led to several improvements.
Rather than disabling the OK button, the patch now uses a document listener to detect tag() expressions and display a warning icon. For enforcement, it intercepts the OK button's ActionListener and displays a lightweight popup if the user attempts to save an expression containing a tag() call.
I also added a selection listener to the binding type pane, so the warning automatically disappears when the user switches to a binding type other than an Expression Binding.



