#include "Riostream.h"
#include "qevent.h"
#include "qdialog.h"
#include "qpushbutton.h"
#include "qlabel.h"
#include "qpainter.h"
#if (QT_VERSION > 0x039999) // Added by cholm@nbi.dk - for Qt 4
# include "qmenu.h"
# include "q3popupmenu.h"
typedef Q3PopupMenu QPopupMenu;
#else
# include "qpopupmenu.h"
#endif
#include "TQCanvasMenu.h"
#include "TClass.h"
#include "TROOT.h"
#include "TMethod.h"
#include "TMethodCall.h"
#include "TMethodArg.h"
#include "TCanvas.h"
#include "TDataType.h"
#include "TQRootDialog.h"
ClassImp(TQCanvasMenu)
TQCanvasMenu::TQCanvasMenu(QWidget* parent, TCanvas *canvas)
{
fc = canvas;
fPopup = new QPopupMenu;
fCurrObj = 0;
fParent = parent;
fTabWin = 0;
fDialog = 0;
fMousePosX = fMousePosY = 0;
}
TQCanvasMenu::TQCanvasMenu(QWidget* parent, QWidget *tabWin, TCanvas *canvas)
{
fc = canvas;
fPopup = new QPopupMenu;
fParent = parent;
fTabWin = tabWin;
fCurrObj = 0;
fDialog = 0;
fMousePosX = fMousePosY = 0;
}
TQCanvasMenu::~TQCanvasMenu()
{
if (fPopup) delete fPopup;
}
char *TQCanvasMenu::CreateDialogTitle( TObject *object, TMethod *method )
{
static char methodTitle[128];
if (object && method)
snprintf(methodTitle, 127, "%s::%s", object->ClassName(), method->GetName());
else
*methodTitle = 0;
return methodTitle;
}
char *TQCanvasMenu::CreateArgumentTitle(TMethodArg *argument)
{
static Char_t argTitle[128];
if (argument) {
snprintf(argTitle, 127, "(%s) %s", argument->GetTitle(), argument->GetName());
const char *arg_def = argument->GetDefault();
if (arg_def && *arg_def) {
strncat(argTitle, " [default: ", 127 - strlen(argTitle));
strncat(argTitle, arg_def, 127 - strlen(argTitle));
strncat(argTitle, "]", 127 - strlen(argTitle));
}
}
else
*argTitle = 0;
return argTitle;
}
void TQCanvasMenu::Popup(TObject *obj, double x, double y, QMouseEvent *e)
{
TClass *klass=obj->IsA();
Int_t curId=-1;
fCurrObj=obj;
fPopup->clear();
fMethods.Clear();
QString buffer=klass->GetName();
buffer+="::";
buffer+=obj->GetName();
fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId); curId++;
klass->GetMenuItems(&fMethods);
fPopup->insertSeparator();
TIter iter(&fMethods);
TMethod *method=0;
while ( (method = dynamic_cast<TMethod*>(iter())) != 0) {
buffer=method->GetName();
fPopup->insertItem(buffer, this, SLOT( Execute(int) ), 0,curId);
curId++;
}
fMousePosX= x;
fMousePosY= y;
fPopup->popup(e->globalPos(), 0);
}
void TQCanvasMenu::Execute(int id)
{
QString text="";
TVirtualPad *psave = gROOT->GetSelectedPad();
TMethod *method=(TMethod *)fMethods.At(id);
fc->HandleInput(kButton3Up,gPad->XtoAbsPixel(fMousePosX), gPad->YtoAbsPixel(fMousePosY) );
if ( method->GetListOfMethodArgs()->First() ) {
Dialog(fCurrObj,method);
}
else {
gROOT->SetFromPopUp(kTRUE);
fCurrObj->Execute((char *) method->GetName(), "");
}
fc->GetPadSave()->Update();
fc->GetPadSave()->Modified();
gROOT->SetSelectedPad(psave);
gROOT->GetSelectedPad()->Update();
gROOT->GetSelectedPad()->Modified();
fc->Modified();
fc->ForceUpdate();
gROOT->SetFromPopUp( kFALSE );
}
void TQCanvasMenu::Dialog(TObject* object, TMethod* method)
{
if (!(object && method)) return;
fDialog = new TQRootDialog(fParent,CreateDialogTitle(object, method),0,object ,method);
fDialog->SetTCanvas(fc);
TMethodArg *argument = 0;
TIter next(method->GetListOfMethodArgs());
while ((argument = (TMethodArg *) next())) {
char *argname = CreateArgumentTitle(argument);
const char *type = argument->GetTypeName();
TDataType *datatype = gROOT->GetType(type);
const char *charstar = "char*";
char basictype [32];
if (datatype) {
strlcpy(basictype, datatype->GetTypeName(),32);
}
else {
if (strncmp(type, "enum", 4) != 0)
cout << "*** Warning in Dialog(): data type is not basic type, assuming (int)\n";
strcpy(basictype, "int");
}
if (strchr(argname, '*')) {
strcat(basictype, "*");
type = charstar;
}
TDataMember *m = argument->GetDataMember();
if (m && m->GetterMethod()) {
char gettername[256] = "";
strlcpy(gettername, m->GetterMethod()->GetMethodName(),256);
m->GetterMethod()->Init(object->IsA(), gettername, "");
char val[256];
if (!strncmp(basictype, "char*", 5)) {
char *tdefval;
m->GetterMethod()->Execute(object, "", &tdefval);
strlcpy(val, tdefval, 256);
}
else if (!strncmp(basictype, "float", 5) ||
!strncmp(basictype, "double", 6)) {
Double_t ddefval;
m->GetterMethod()->Execute(object, "", ddefval);
snprintf(val, 255, "%g", ddefval);
}
else if (!strncmp(basictype, "char", 4) ||
!strncmp(basictype, "int", 3) ||
!strncmp(basictype, "long", 4) ||
!strncmp(basictype, "short", 5)) {
Long_t ldefval;
m->GetterMethod()->Execute(object, "", ldefval);
snprintf(val, 255, "%li", ldefval);
}
TList *opt;
if ((opt = m->GetOptions())) {
cout << "*** Warning in Dialog(): option menu not yet implemented " << opt << endl;
return;
}
else {
fDialog->Add(argname, val, type);
}
}
else {
char val[256] = "";
const char *tval = argument->GetDefault();
if (tval) strlcpy(val, tval, 256);
fDialog->Add(argname, val, type);
}
}
fDialog->Popup();
}