Help with Attribute Trigger

I'm fairly new to DXL and was hoping that someone can help me with this. Here is what I want to do:
1) prevent user modifications to an object's Object Text, if the NO_MOD attribute is true.

approach:
1) create modue trigger that would fire when Object main column is double clicked (is this possible?)
2) trigger code would check NO_MOD attribute, if true, display cannot modifiy message and UNDO user mods.

Thanks a ton!!
DOORS_USER - Wed Jun 16 17:45:44 EDT 2010

Re: Help with Attribute Trigger
DOORS_USER - Thu Jun 17 00:25:54 EDT 2010

I think I figured it out.
1) Create sync trigger on module

2) use getInPlaceColumnIndex() in trigger code to get current column that has been double clicked.
-If column is main colmn, then check the NO_MOD attribute value.
  • If NO_MOD is true, then popup warning message and use gotoObject(intOf(identifier(obj)) to goto current object. This would deactivate the object preventing the user from typing in the main column.
  • If user doubleclicks again, it should refire the trigger and the process repeats.

Re: Help with Attribute Trigger
Mathias Mamsch - Thu Jun 17 09:54:15 EDT 2010

DOORS_USER - Thu Jun 17 00:25:54 EDT 2010
I think I figured it out.
1) Create sync trigger on module

2) use getInPlaceColumnIndex() in trigger code to get current column that has been double clicked.
-If column is main colmn, then check the NO_MOD attribute value.

  • If NO_MOD is true, then popup warning message and use gotoObject(intOf(identifier(obj)) to goto current object. This would deactivate the object preventing the user from typing in the main column.
  • If user doubleclicks again, it should refire the trigger and the process repeats.

Sync Trigger is not the way to go here. Too unreliable. Use a pre-save-attribute trigger on object text to cancel any modification if the NO_MOD is true. Regards, Mathias


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Re: Help with Attribute Trigger
DOORS_USER - Thu Jun 17 10:52:42 EDT 2010

Mathias Mamsch - Thu Jun 17 09:54:15 EDT 2010
Sync Trigger is not the way to go here. Too unreliable. Use a pre-save-attribute trigger on object text to cancel any modification if the NO_MOD is true. Regards, Mathias


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Thanks for the pointer. However, how would I go about cancelling/undoing the user mods?

Thanks again!

Re: Help with Attribute Trigger
Mathias Mamsch - Thu Jun 17 12:02:17 EDT 2010

DOORS_USER - Thu Jun 17 10:52:42 EDT 2010
Thanks for the pointer. However, how would I go about cancelling/undoing the user mods?

Thanks again!

You can set the trigger status to cancelled -> check the DXL help for triggers. In this case the modification will not be made. Note: make sure not to pop up an error box if you have scripts that try to change object text. This will effectively freeze the module (if it is large), since you need to click away 1000 error boxes.

Regards, Mathias


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Re: Help with Attribute Trigger
llandale - Thu Jun 17 12:42:25 EDT 2010

Enhancing Malius' reply: a 'pre' trigger allows the code to prevent the event. So your pre-save-attr trigger will check if the value is NO_MOD, and set the trigger status to fail if so. The the user will double click and edit the text, and when she clicks somewhere else, the trigger fires. Here's some actual code, tweaked, to create and deploy such a trigger:

string    NameTrig = "IntVerif_IRS_trigProtectParentAttrs"
 
string  DXLCode = "
        // Trigger: '" NameTrig "'
        // Prevent the typical user from editing Object Text
 
        Trigger trg = current;          if (null trg) halt()    // Error?
        AttrDef ad  = attrdef(trg);     if (null ad)  halt()    // Error?
        Object  obj = object(trg);      if (null obj) halt()    // Error?
 
        string   NameAttr = ad.name
        if (NameAttr != \"Object Text\")    halt()  // only protect Object Text
        if (obj.\"NameAttrBoolean\" != \"True\")  halt()  // edits are allowed
        set(trigPreConFail)                     // disallow the user's edit
                   // Now inform the user, if its a user actually making the edit.
                   //   try to not display error when its DXL code making the edit.
        Module mod      = module(trg)
        Object oCurr    = current(mod)
        if (isVisible(mod)      and
            obj == oCurr)                       //-
        then infoBox(\"" NameTrig ":\\nYou may not change values of this attr '\" NameAttr \"' manually.\\n\")
        else{}         // Don't infoBox when DXL is modifying the value
"  // end DXLCode
 
Trigger trg
bool    TrigOK  = true
string  ErrMess = checkDXL(DXLCode)
 
if (!null ErrMess)
{  print ErrMess "\n***********\n" DXLCode "**********\n"
   TrigOK       = false
}
 
if (confirm("Delete trigger '" NameTrig "' ??"))
   ErrMess = delete (NameTrig, module->attribute, pre, save, 5)
 
if (TrigOK              and
    confirm("Deploy trigger '" NameTrig "' ??"))
   trg     = trigger(NameTrig, module->attribute, pre, save, 5, DXLCode)


Notice the code of the trigger is defined in variable DXLCode, and back slashes and quotes must be escaped with a backslash when doing so.

My actual code cleverly uses whether triggers are running to allow or disallow the edit. So my DXL code that mass changes this attr value can effectively turn off the trigger; but lets not go there now.

 

 

  • Louie

 

 

Re: Help with Attribute Trigger
DOORS_USER - Thu Jun 17 14:02:50 EDT 2010

llandale - Thu Jun 17 12:42:25 EDT 2010

Enhancing Malius' reply: a 'pre' trigger allows the code to prevent the event. So your pre-save-attr trigger will check if the value is NO_MOD, and set the trigger status to fail if so. The the user will double click and edit the text, and when she clicks somewhere else, the trigger fires. Here's some actual code, tweaked, to create and deploy such a trigger:

string    NameTrig = "IntVerif_IRS_trigProtectParentAttrs"
 
string  DXLCode = "
        // Trigger: '" NameTrig "'
        // Prevent the typical user from editing Object Text
 
        Trigger trg = current;          if (null trg) halt()    // Error?
        AttrDef ad  = attrdef(trg);     if (null ad)  halt()    // Error?
        Object  obj = object(trg);      if (null obj) halt()    // Error?
 
        string   NameAttr = ad.name
        if (NameAttr != \"Object Text\")    halt()  // only protect Object Text
        if (obj.\"NameAttrBoolean\" != \"True\")  halt()  // edits are allowed
        set(trigPreConFail)                     // disallow the user's edit
                   // Now inform the user, if its a user actually making the edit.
                   //   try to not display error when its DXL code making the edit.
        Module mod      = module(trg)
        Object oCurr    = current(mod)
        if (isVisible(mod)      and
            obj == oCurr)                       //-
        then infoBox(\"" NameTrig ":\\nYou may not change values of this attr '\" NameAttr \"' manually.\\n\")
        else{}         // Don't infoBox when DXL is modifying the value
"  // end DXLCode
 
Trigger trg
bool    TrigOK  = true
string  ErrMess = checkDXL(DXLCode)
 
if (!null ErrMess)
{  print ErrMess "\n***********\n" DXLCode "**********\n"
   TrigOK       = false
}
 
if (confirm("Delete trigger '" NameTrig "' ??"))
   ErrMess = delete (NameTrig, module->attribute, pre, save, 5)
 
if (TrigOK              and
    confirm("Deploy trigger '" NameTrig "' ??"))
   trg     = trigger(NameTrig, module->attribute, pre, save, 5, DXLCode)


Notice the code of the trigger is defined in variable DXLCode, and back slashes and quotes must be escaped with a backslash when doing so.

My actual code cleverly uses whether triggers are running to allow or disallow the edit. So my DXL code that mass changes this attr value can effectively turn off the trigger; but lets not go there now.

 

 

  • Louie

 

 

Thanks Matthias and Louie. I was able to get it to work.

Re: Help with Attribute Trigger
Mike_Peters - Sun Jul 29 22:43:21 EDT 2012

llandale - Thu Jun 17 12:42:25 EDT 2010

Enhancing Malius' reply: a 'pre' trigger allows the code to prevent the event. So your pre-save-attr trigger will check if the value is NO_MOD, and set the trigger status to fail if so. The the user will double click and edit the text, and when she clicks somewhere else, the trigger fires. Here's some actual code, tweaked, to create and deploy such a trigger:

string    NameTrig = "IntVerif_IRS_trigProtectParentAttrs"
 
string  DXLCode = "
        // Trigger: '" NameTrig "'
        // Prevent the typical user from editing Object Text
 
        Trigger trg = current;          if (null trg) halt()    // Error?
        AttrDef ad  = attrdef(trg);     if (null ad)  halt()    // Error?
        Object  obj = object(trg);      if (null obj) halt()    // Error?
 
        string   NameAttr = ad.name
        if (NameAttr != \"Object Text\")    halt()  // only protect Object Text
        if (obj.\"NameAttrBoolean\" != \"True\")  halt()  // edits are allowed
        set(trigPreConFail)                     // disallow the user's edit
                   // Now inform the user, if its a user actually making the edit.
                   //   try to not display error when its DXL code making the edit.
        Module mod      = module(trg)
        Object oCurr    = current(mod)
        if (isVisible(mod)      and
            obj == oCurr)                       //-
        then infoBox(\"" NameTrig ":\\nYou may not change values of this attr '\" NameAttr \"' manually.\\n\")
        else{}         // Don't infoBox when DXL is modifying the value
"  // end DXLCode
 
Trigger trg
bool    TrigOK  = true
string  ErrMess = checkDXL(DXLCode)
 
if (!null ErrMess)
{  print ErrMess "\n***********\n" DXLCode "**********\n"
   TrigOK       = false
}
 
if (confirm("Delete trigger '" NameTrig "' ??"))
   ErrMess = delete (NameTrig, module->attribute, pre, save, 5)
 
if (TrigOK              and
    confirm("Deploy trigger '" NameTrig "' ??"))
   trg     = trigger(NameTrig, module->attribute, pre, save, 5, DXLCode)


Notice the code of the trigger is defined in variable DXLCode, and back slashes and quotes must be escaped with a backslash when doing so.

My actual code cleverly uses whether triggers are running to allow or disallow the edit. So my DXL code that mass changes this attr value can effectively turn off the trigger; but lets not go there now.

 

 

  • Louie

 

 

Hi louie,

I am trying to run this script on my module but i keep getting 2 errors (incorrect argument for != and incorrect argument for if) on the following:

if (obj.\"NameAttrBoolean\" != \"True\") halt() // edits are allowed

I have created the attribute with "true" "false" options but i keep getting the error. if I comment that line out it works and locks all of object texts, but I only want to lock object text if "NameAttrBoolean" is true. Do you know what can be going wrong?

Any help would be much appreciated.

Re: Help with Attribute Trigger
llandale - Mon Jul 30 15:09:57 EDT 2012

Mike_Peters - Sun Jul 29 22:43:21 EDT 2012
Hi louie,

I am trying to run this script on my module but i keep getting 2 errors (incorrect argument for != and incorrect argument for if) on the following:

if (obj.\"NameAttrBoolean\" != \"True\") halt() // edits are allowed

I have created the attribute with "true" "false" options but i keep getting the error. if I comment that line out it works and locks all of object texts, but I only want to lock object text if "NameAttrBoolean" is true. Do you know what can be going wrong?

Any help would be much appreciated.

forgot the escaped-double-double-quotes
  • if (obj.\"NameAttrBoolean\" \"\" != \"True\") halt() // edits are allowed
That works because a boolean attribute with value "true" comes back as a string "True".

Re: Help with Attribute Trigger
Jagtattoo - Thu Sep 26 11:42:17 EDT 2013

Thank you all for posting to this thread.  It allowed me to quickly create an attribute based pre-save trigger to prevent specific edits to specific attributes in our database.

Re: Help with Attribute Trigger
llandale - Thu Sep 26 12:22:39 EDT 2013

Jagtattoo - Thu Sep 26 11:42:17 EDT 2013

Thank you all for posting to this thread.  It allowed me to quickly create an attribute based pre-save trigger to prevent specific edits to specific attributes in our database.

BTW, I am now strongly in favor of eschewing module-level triggers and putting them all in the Project.  This DRASTICALLY improves maintenance.  Such triggers, then, would first get the module that is firing the trigger and decide if that module is subject to approval by the Trigger.  If not, the trigger stops without preventing the event.

  • Module m = module(trg)
  • string NameBase = name(m)
  • string NameFull = fullName(m)
  • set(trigPreConPass)     // Allow event by Default
  • either: if (NameBase != "OneModuleTriggerCaresAbout) then halt
  • or: if (!matches("SomeFolderTriggerCaresAbout", NameFull)) then halt
  •  // OK, trigger is firing in a module this code cares about

-Louie

Re: Help with Attribute Trigger
GregM_dxler - Fri Oct 04 09:25:44 EDT 2013

llandale - Thu Sep 26 12:22:39 EDT 2013

BTW, I am now strongly in favor of eschewing module-level triggers and putting them all in the Project.  This DRASTICALLY improves maintenance.  Such triggers, then, would first get the module that is firing the trigger and decide if that module is subject to approval by the Trigger.  If not, the trigger stops without preventing the event.

  • Module m = module(trg)
  • string NameBase = name(m)
  • string NameFull = fullName(m)
  • set(trigPreConPass)     // Allow event by Default
  • either: if (NameBase != "OneModuleTriggerCaresAbout) then halt
  • or: if (!matches("SomeFolderTriggerCaresAbout", NameFull)) then halt
  •  // OK, trigger is firing in a module this code cares about

-Louie

Thanks Louie,

I've learned so much in dxl from you and this forum.  All the way from simple dxl code to skip lists, OLE manipulation and even automation.  But I have stayed away from triggers because I've been told how dangerous they may be in the hands of the novice.  But now this thread is getting me interested in delving into the abyss.

Could the trigger be modified to not use an attribute but instead the access of the user?  And additionally, can the trigger be inhibited by another dxl script?

The reason why I am thinking about this is because in our project, we would like to prevent users from modifying the Object Text/Object Heading.  Only admins would have that ability.  However, I can't just set access to the attributes that way because we have specialized scripts that the users use to propose changes to the text and in some cases (mostly because of inserting new objects, the object text gets filled with "New Object - See Proposed Change") the attributes get modified and then put back.  So what I'm thinking is having the trigger preventing changes unless the user has Admin rights, but then having the proposed change script be able to inhibit the trigger when it needs to.

Is this possible?

Thanks,

Greg

Re: Help with Attribute Trigger
llandale - Fri Oct 04 11:32:39 EDT 2013

GregM_dxler - Fri Oct 04 09:25:44 EDT 2013

Thanks Louie,

I've learned so much in dxl from you and this forum.  All the way from simple dxl code to skip lists, OLE manipulation and even automation.  But I have stayed away from triggers because I've been told how dangerous they may be in the hands of the novice.  But now this thread is getting me interested in delving into the abyss.

Could the trigger be modified to not use an attribute but instead the access of the user?  And additionally, can the trigger be inhibited by another dxl script?

The reason why I am thinking about this is because in our project, we would like to prevent users from modifying the Object Text/Object Heading.  Only admins would have that ability.  However, I can't just set access to the attributes that way because we have specialized scripts that the users use to propose changes to the text and in some cases (mostly because of inserting new objects, the object text gets filled with "New Object - See Proposed Change") the attributes get modified and then put back.  So what I'm thinking is having the trigger preventing changes unless the user has Admin rights, but then having the proposed change script be able to inhibit the trigger when it needs to.

Is this possible?

Thanks,

Greg

[1]  Useful user stuff.  IIRC, the "usr.property" may not be used directly in an if statement but must be by itself on right side of equal sign; forcing you to stage values as follows:

  • User usr = find()
  • UserClass uc = usr.class
  • bool MayManageDB = usr.mayManage
  • if (uc == administrator) then User is the super "Administrator"
  • if (uc == databaseManager) then User is a DB Manager
  • if (MayManageDB) then User has power to manage DB propertes
  • if (hasPermission(oCurr, control)) then user has "A" control access to this Object
  • if (hasPermission(mCurr, control)) then user has "A" control access to this Module

[2] I found a "sloppy" way for some on-demand script to temporarily disable a trigger.  I think it wise not to advertise this technique to users who may liken themselves to clever DXL coders.

Trigger:

  • set(trigPreConPass)
  • if (!getTriggerState_()) then halt   // Triggers are disabled; don't protect attr values

Script:

  • bool TrigState = getTrigerState_()
  • setTriggerState_(false)     // temporiliy disable triggers
  • make changes without worrying about triggers
  • setTriggerState(TrigState)  // reinstate trigger state

Note that for Standard users, turning off triggers sets the flag to false but triggers still run.  Thus the trigger itself needs to, well, act as if it didn't run at all.

I'm staying away from "top context" sharing of information, but if you find that acceptable someone may show us how to do that.

In your specific case however, this is preferable:

  • set(trigPreConPass)
  • if (oCurr is a Proposal Object) then halt

 

-Louie

Re: Help with Attribute Trigger
GregM_dxler - Fri Oct 04 11:51:52 EDT 2013

llandale - Fri Oct 04 11:32:39 EDT 2013

[1]  Useful user stuff.  IIRC, the "usr.property" may not be used directly in an if statement but must be by itself on right side of equal sign; forcing you to stage values as follows:

  • User usr = find()
  • UserClass uc = usr.class
  • bool MayManageDB = usr.mayManage
  • if (uc == administrator) then User is the super "Administrator"
  • if (uc == databaseManager) then User is a DB Manager
  • if (MayManageDB) then User has power to manage DB propertes
  • if (hasPermission(oCurr, control)) then user has "A" control access to this Object
  • if (hasPermission(mCurr, control)) then user has "A" control access to this Module

[2] I found a "sloppy" way for some on-demand script to temporarily disable a trigger.  I think it wise not to advertise this technique to users who may liken themselves to clever DXL coders.

Trigger:

  • set(trigPreConPass)
  • if (!getTriggerState_()) then halt   // Triggers are disabled; don't protect attr values

Script:

  • bool TrigState = getTrigerState_()
  • setTriggerState_(false)     // temporiliy disable triggers
  • make changes without worrying about triggers
  • setTriggerState(TrigState)  // reinstate trigger state

Note that for Standard users, turning off triggers sets the flag to false but triggers still run.  Thus the trigger itself needs to, well, act as if it didn't run at all.

I'm staying away from "top context" sharing of information, but if you find that acceptable someone may show us how to do that.

In your specific case however, this is preferable:

  • set(trigPreConPass)
  • if (oCurr is a Proposal Object) then halt

 

-Louie

Thanks again Louie.  This is good information to get me started with.  I'm not sure how soon I can start playing around with it, as dxl'ing and DOORS is not my primary job.  Mainly do it for fun  :-)

Appreciate the help.

Greg