How to create a plugin

Hi all,
I need to particularize graphics editors like TAxisEditor, TPaveText. This in order to provide adapted editors to the neutronic’s work.

I use the Qt layer and extension. By modifing the source code of the qtged, it is very easy to create the adapted editor.

How can I build my own plugin ? How can I overload some editors with using the .rootrc file ?

Thanks for your attention,

Pierre

I 'm using ROOT 5.11 on a Linux box running Mandriva 2006 (kernel 2.6 and gcc 4.01)

Hi Rooters

I am Pierre’s advisor. To clarify things a little bit, we would like to create customized graphic editors. Some are just fine and can be used as such (TPadEditor, TFrameEditor…) but other would be best replaced to fit our kind of work (TGraphEditor, TH1Editor, TH2Editor…).

What is the best way to do that? I read lka Antcheva’s presentation at ROOT2005 workshop (transparencies 13 and 14) and according to her there are a set of rules to follow but we don’t know where we can find such an example. Furthermore we are not using ROOT’s native GUI, but QT implementation from BNL (don’t ask why, this is a political decision).

Pierre thinks that we can do it another way and create our own library with objects like “MyGraphEditor”, “MyTH1Editor” and let ROOT select those instead of regular one using directives in the .rootrc. There is such an example provided by BNL .rootrc :

Plugin.TPaletteEditor: * TQtPaletteEditor QtImage "TQtPaletteEditor(TAttImage*,UInt_t,UInt_t)"
Gui.Factory: qtgui
Plugin.TGuiFactory: qtgui TQtGUIFactory QtGui “TQtGUIFactory()”

At that point we need some advise.

Thanks for your help

matthieuguillo[quote]Hi Rooters

I am Pierre’s advisor. To clarify things a little bit, we would like to create customized graphic editors. Some are just fine and can be used as such (TPadEditor, TFrameEditor…) but other would be best replaced to fit our kind of work (TGraphEditor, TH1Editor, TH2Editor…).

What is the best way to do that? I read lka Antcheva’s presentation at ROOT2005 workshop (transparencies 13 and 14) and according to her there are a set of rules to follow but we don’t know where we can find such an example. Furthermore we are not using ROOT’s native GUI, but QT implementation from BNL (don’t ask why, this is a political decision).

Pierre thinks that we can do it another way and create our own library with objects like “MyGraphEditor”, “MyTH1Editor” and let ROOT select those instead of regular one using directives in the .rootrc. There is such an example provided by BNL .rootrc :

Plugin.TPaletteEditor: * TQtPaletteEditor QtImage "TQtPaletteEditor(TAttImage*,UInt_t,UInt_t)" Gui.Factory: qtgui Plugin.TGuiFactory: qtgui TQtGUIFactory QtGui "TQtGUIFactory()"

At that point we need some advise.

Thanks for your help[/quote]

Hello
I am begging pardon, I missed :frowning: this post, because the Subj doesn’t attract me.

First the example you mentioned contains the typo. To provide the custom
ROOT object editor one should provide TVirtualPadEditor plugin.
For example:Plugin.TVirtualPadEditor: Ged TQtGedEditor QtGed "TQtGedEditor(TCanvas*)"

Please, can you clarify your troubles, may be in private message.
I mean the qtged suggests the solution. One can find there the “base class” all custom “editors” can be derived from. The base TQtGedAttFrame class provides the ROOT Signal / Slot Qt Signal Slot mapping".
So you shoud subclass it.

[size=42][code]class TQtArrowEditor : public TQtGedAttFrame {
#ifndef CINT
Q_OBJECT
#endif
protected:

TArrow *fModel; // arrow object
TQtArrowStyleSelect *fOptionCombo; // arrow shapes combo box
TQtFloatSpinBox *fAngleEntry; // opening angle entry
TQtFloatSpinBox *fSizeEntry; // size entry
TQtFloatSpinBox *fStartPointXEntry; // start point x entry
TQtFloatSpinBox *fEndPointXEntry; // end point x entry
TQtFloatSpinBox *fStartPointYEntry; // start point y entry
TQtFloatSpinBox *fEndPointYEntry; // end point y entry

void Ctor();
virtual void ConnectSignals2Slots();
virtual void Connect() { TQtGedAttInterface::ConnectToCanvas(fCanvas,Class
Name(), this); }
virtual void Disconnect() { TQtGedAttInterface::ConnectToCanvas(fCanvas,Class
Name(), this,kFALSE); }

public:
TQtArrowEditor(QMainWindow *mainWidget, TCanvas *canvas, Int_t id=0,
Int_t width = 140, Int_t height = 30,
UInt_t options = 0, // kChildFrame,
Pixel_t back = 0) ;
TQtArrowEditor(TCanvas *canvas, QWidget *parent=0, Int_t id=0,
Int_t width = 140, Int_t height = 30,
UInt_t options = 0, // kChildFrame,
Pixel_t back = 0) ;
virtual ~TQtArrowEditor() ;
virtual void ConnectToCanvas(TCanvas *c) { TQtGedAttInterface::ConnectToCanva
s(c,ClassName(), this); }
virtual void SetModel(TVirtualPad *pad, TObject *obj, Int_t event) ;

public slots:
virtual void DoAngle(int );
virtual void DoOption(int );
virtual void DoSize(int );
virtual void DoStartPoint();
virtual void DoEndPoint();

#ifndef Q_MOC_RUN
//MOC_SKIP_BEGIN
ClassDef(TQtArrowEditor,0) // axis editor
//MOC_SKIP_END
#endif
};[/code][/size]
May be you should send me the idea of your custom editor and I will show you how to implement it. Normally, it takes a few hours to start and complete any custom Qt-based ROOT object editor. If you do not like some particular editor you can sub-sub-class it further.

The QtGed implementation relies on the list of object editors. One can provide a public interface to edit the list instead of the protected one. class TQtGedEditor : public TVirtualPadEditor { . . . protected: . . . void Insert(Int_t indx, TQtGedAttFrame *frame);This way one can add his/her own custom implementation to the list and remove some thing hi/she doesn’t like.

In fact, if you want to provide your own editor you should understand quite simple technique that is behind the scene and is demonstrated by the code:

void TQtGedAttInterface::ConnectToCanvas(TCanvas* c,const char *className, void *thisPointer, Bool_t connect) { // Connect/Disconnect the GUI attribute frames to the selected object in the canvas. if (c) { if (connect) { assert(TQObject::Connect(c, "Selected(TVirtualPad*,TObject*,Int_t)", className, thisPointer, "SetModel(TVirtualPad*,TObject*,Int_t)")); } else { assert(TQObject::Disconnect(c, "Selected(TVirtualPad*,TObject*,Int_t)", thisPointer, "SetModel(TVirtualPad*,TObject*,Int_t)")); } } } Now, to force ROOT to invoke your editor you should
[ul]- Make sure the current TCanvas “Selected” ROOT signal is disconnected

[code] signals (Qt)

CanvasPainted();  // Signal the TCanvas has been painted onto the screen
Saved(bool ok);   // Signal the TCanvas has been saved into the file
RootEventProcessed(TObject *selected, unsigned int event, TCanvas *c);
                  // Signal the Qt mouse/keyboard event has been process by ROOT
                  // This "signal" is emitted by the enabled mouse events only.
                  // See: EnableSignalEvents
                  // ---  DisableSignalEvents[/code]QtExamples package from the BNL CVS provides a bunch of the "Hello World" examples that demonstrates the technique as well.

I am willing to provide you futher information and guidiance. Let me know

Hi Valeri

Thank you for your answer, the Subject was not very clear, indeed.

Actually we figured out last week what you wrote and it worked.

Here are a couple of suggestions what would make life easier:

As you suggested, for the class TQtGedEditor, make a public method “static void Register(Int_t indx, TQtGedAttFrame *frame);” that would check if a indx exists and add or remove the correponding TQtGedAttFrame. This method should be static so that all TQtGedEditor register the same editors.
The different kAxisEditor, kArrowEditor, and so on should also be inside the class and “static public”.

That way, for a given application, GUI builders can easily provide their own editors, writing something like:
TQtGedEditor::Register(TQtGedEditor::kAxisEditor, myOwnAxisEditor);

As you said, there are plenty of examples on how to write “myOwnAxisEditor”, starting from the qtRoot/qtged/src directory.

Best regards

[quote]Here are a couple of suggestions what would make life easier:

As you suggested, for the class TQtGedEditor, make a public method “static void Register(Int_t indx, TQtGedAttFrame *frame);” that would check if a indx exists and add or remove the correponding TQtGedAttFrame. This method should be static so that all TQtGedEditor register the same editors.
The different kAxisEditor, kArrowEditor, and so on should also be inside the class and “static public”.

That way, for a given application, GUI builders can easily provide their own editors, writing something like:
TQtGedEditor::Register(TQtGedEditor::kAxisEditor, myOwnAxisEditor);[/quote]
I have made a new version of qtged package that is supposed to significantly simplify the concrete object editor class. I hope you appreciate it. However, this requires you to change the classes you may have already written. It should not be too trouble because one is required to remove common code from his implementation. That is provided by the base class now.

Please, pay your attention, to port your code to the new package you should:
[ul] 1. Change the concrete class ctor (Take TQtArrowEditor, for example)
2. Rename the “SetModel” method to “ChangeModel” and remove some redundant operators from there. Please compare the old and new version of TQtArrowEditor.
3. Remove a bunch of the methods, those are provided by the base class[/ul]

What about registration. There is some constrain from the ROOT TVirtualPadEditor design (see: root.cern.ch/root/htmldoc//TGedEditor.html. That I can not subclass. Of course, the right thing to do would be to move the interface definition from TGedEditor to the TVirtualPadEditor classes. I mean the list
of the methods:

protected: virtual void GetEditors(); virtual void GetClassEditor(TClass *cl); virtual void GetBaseClassEditor(TClass *cl); public: virtual void CloseWindow(); virtual void ConnectToCanvas(TCanvas *c); virtual void DisconnectEditors(TCanvas *canvas); TCanvas *GetCanvas() const; virtual void SetCanvas(TCanvas *c); virtual void SetGlobal(Bool_t global) { fGlobal = global; } virtual void SetModel(TVirtualPad* pad, TObject* obj, Int_t event); virtual void RecursiveRemove(TObject* obj);. By some reasons those methods are not part of the ROOT interface.

Another “design” problem is the lack of the “abstract primitive object editor” interface. The TVirtualPadEditor is the interface to the collection of the primitive object editors. However no “abstract / base” interface for those “primitive editors” is provided yet. The “qtged” package does contain the prototype of such interface (see TQtAttGedInterfcaeB class) that has no Qt or any other GUI dependency. It could be adopted as the "ROOT-wide abstract interface for the “primitive object editor” I hope.

Anyway, I’ll provide a method to register the custom Qt-based object editors tomorrow (let me think a little bit more :wink:
Mean time I would appreciate you check the new version and let me know what you think.

Since you message suggested you did some Qt-based ROOT object editors or customized the existent ones, I would like to remind you that Qt/Root repository is open for the contribution :wink:

Valeri,

What is THIS BIG MESS???
What is qtged? Looks like a total non sense.
Not only you are going the wrong direction, but in addition you are seriously
confusing users.

It must be clear to users of your package that we do not take any responsability, nor answer questions about something we disagree with.
Why make things so complex when there is a nice graphics editor correctly working.

Rene

[quote]What is qtged? [/quote]qtged is the standard ROOT plugin, the implementation of the TVirtualPadEditor ROOT interface. It was published first time 3 years ago and it was not changed much since that.
See Chep06
Using the Qt to create the complex interactive HENP applications at STAR slide
indico.cern.ch/getFile.py/access … nfId=048#9

qtged is to simplify the creation the custom Qt-based implementation of the TVirtualPadEditor ROOT interface. The common actions those require some deep Qt knowledge and needed by all such editors are provided by the base class and the user should subclass it to code his own special actions only.

I see no mess here. it is a standard OO C++ approach.

The existence of Qt-Extension portion of Qt/ROOT supported by Brookhaven National Laboratory was published several times too, including the ROOT Workshops.

[quote]It must be clear to users of your package that we do not take any responsability,[/quote] I agree, the proper place to discuss the Qt -Extension is qt-root-l@lists.bnl.gov

Valeri,

I am sorry, but I see nowhere in the ROOT workshops a presentation from you about qtged. Why do you need this stuff?
Why is TVirtualX not sufficient to do the job? There is something terribly wrong somewhere.

Rene

  1. TVirtualPadEditor ROOT interface provides two different “ROOT Object Editor” interfaces. One of them is so-called “old” interface and another “new” one. It sounds like the user concern is the “new object editor”. This means the issue has nothing to do with TVirtualX, the “old” interface is based on.

  2. The Qt / ROOT integration comes in several “flavors”, “use cases”, described in details by the ROOT Manual and many times discussed. It seems to me that this particular case is about so-called “ROOT-based Qt application”. That choice is not mine, it was done by the user.

  3. The clause “Qt application” implies that the user opted to create QMainWindow doc.trolltech.com/3.3/qdockwindow.html#details to be populated with the custom ROOT primitive object editors he /she wants to write him/herself (by some reason)

  4. To do that as I had mentioned above no qtged packages is required. However, to do that one should learn very Qt, follow some Qt rules those are common for all such widgets.

  5. To simplify this, qtged provides the tiny base class that performs the common actions needed to connect user widgets to the QMainWindows dock area and map Qt and ROOT signals / slots. The prospected user can decide to subclass that base class or “borrow” the idea which is expressed in a few lines of the code (that had provided above in full) to be “qtged” independent.

  6. Either way he/she still needs to write his/her own code to implement the custom ROOT object editor alone. Inside such implementation one is free to use any GUI API. It can be either Qt or ROOT or whatever one is comfortable with.

  7. Personally, I do not see yet any big flaw with such user (not mine) approach

  8. Therefore I would appreciate a lot you could specify which steps above you think is terribly wrong to be fixed?

Hi valeriy,

Thanks for this clarification and the confirmation of all the many side-effects
of using the Qt interface.

It would be so much simpler if the user could use directly the ROOT GUI.
This would save a lot of time to him, to you and to me ::slight_smile:

Rene

Hello Valeri and René

I will try what Valeri suggests and move the discussion to the Qt mailing list (qt-root-l@lists.bnl.gov) so that other people don’t get confused.
I may also try what Ilka suggested using regular ROOT widgets.

Thank for your help

[quote=“matthieuguillo”]I will try what Valeri suggests and move the discussion to the Qt mailing list (root.cern.ch/phpBB2/viewtopic.php?t=2415
What about the original question. To register the custom Qt-based implementation of the ROOT object editor one needs to add to his/her implementation C++ code the line:// Register the GED factory interfaces: static TQtGedFactory<TQtArrowEditor> gQtArrowEditor;where “TQtArrowEditor” is the name of your custom editor class and gQtArrowEditor is an arbitrary C++ identificator. I’ve added a short README file to qtged directory. Thank you.