TQtWidget.cxx

Go to the documentation of this file.
00001 // @(#)root/qt:$Id: TQtWidget.cxx 36066 2010-10-04 19:41:50Z brun $
00002 // Author: Valeri Fine   23/01/2003
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
00006  * Copyright (C) 2003 by Valeri Fine.                                    *
00007  * All rights reserved.                                                  *
00008  *                                                                       *
00009  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00010  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00011  *************************************************************************/
00012 
00013 // Definition of TQtWidget class
00014 // "double-buffere widget
00015 
00016 #include <qapplication.h>
00017 
00018 #if QT_VERSION >= 0x40000
00019 #  include <QFocusEvent>
00020 #  include <QPaintEvent>
00021 #  include <QKeyEvent>
00022 #  include <QShowEvent>
00023 #  include <QResizeEvent>
00024 #  include <QMouseEvent>
00025 #  include <QCustomEvent>
00026 #  include <QImage>
00027 #  include <QDebug>
00028 #endif /* QT_VERSION */
00029 
00030 #include "TQtWidget.h"
00031 #include "TQtTimer.h"
00032 
00033 #include "TROOT.h"
00034 #include "TEnv.h"
00035 #include "TRint.h"
00036 #include "TSystem.h"
00037 #include "Getline.h"
00038 #include "TGQt.h"
00039 #include "TCanvas.h"
00040 #include "Buttons.h"
00041 #include <qevent.h>
00042 #include <qpainter.h>
00043 #include <qpixmap.h>
00044 #include <qfileinfo.h>
00045 
00046 #ifdef R__QTWIN32
00047 // #include "Windows4Root.h"
00048 #include "TWinNTSystem.h"
00049 #include "Win32Constants.h"
00050 #endif
00051 
00052 // Class to adjust buffer within the method scope if needed
00053 
00054 //___________________________________________________________________
00055 TQtWidgetBuffer::TQtWidgetBuffer(const QWidget *w, bool clear)
00056 : fWidget(w),fBuffer(0), fIsImage(clear)
00057 {
00058    if (fIsImage) {
00059       fBuffer = new  QImage(fWidget?fWidget->size():QSize(0,0),QImage::Format_ARGB32_Premultiplied);
00060 //      ((QImage*)fBuffer)->fill(0);
00061    } else {
00062       fBuffer = new  QPixmap(fWidget?fWidget->size():QSize(0,0));
00063    }
00064 }
00065 //___________________________________________________________________
00066 TQtWidgetBuffer::TQtWidgetBuffer(const TQtWidgetBuffer &b)
00067 : fWidget(b.fWidget),fBuffer(0), fIsImage(b.fIsImage)
00068 {
00069    // Copy ctor. Create the copy and account the new widget size
00070    if (fWidget && (fWidget->size() != QSize(0,0))) { 
00071       if (fIsImage) {
00072          QImage resized =((QImage*)b.fBuffer)->scaled (fWidget->size());
00073          fBuffer = new  QImage(resized);
00074       } else {
00075          QPixmap resized =((QPixmap*) b.fBuffer)->scaled (fWidget->size());
00076          fBuffer = new  QPixmap(resized);
00077       }
00078    }
00079 } 
00080 //___________________________________________________________________
00081 TQtWidgetBuffer:: ~TQtWidgetBuffer()
00082 {
00083    // dtor
00084    delete fBuffer;
00085    fBuffer = 0;
00086 }
00087 
00088 //___________________________________________________________________
00089 void TQtWidgetBuffer::Clear()
00090 {
00091    // Clear the buffer with the transparent color
00092    if (fBuffer &&  !fIsImage ) {
00093 #ifdef R__WIN32   
00094          ((QPixmap*)fBuffer)->fill(Qt::transparent);
00095 #else
00096          QPainter p(fBuffer);
00097          p.fillRect(QRect(0,0,fBuffer->width(), fBuffer->height())
00098             ,Qt::transparent);
00099 #endif
00100    }
00101 }
00102 
00103 
00104 //___________________________________________________________________
00105 
00106 ClassImp(TQtWidget)
00107 
00108 ////////////////////////////////////////////////////////////////////////////////
00109 //
00110 //  TQtWidget is a QWidget with the QPixmap double buffer
00111 //  It is designed to back the ROOT TCanvasImp class interface  and it can be used
00112 //  as a regular Qt Widget to create Qt-based GUI with the embedded TCanvas objects
00113 //
00114 //           This widget can be used as a Qt "custom widget"
00115 //         to build a custom GUI interfaces with  Qt Designer
00116 //
00117 // The class emits the Qt signals and has Qt public slots
00118 //
00119 //  Public slots:  (Qt)
00120 //
00121 //   virtual void cd();  // make the associated TCanvas the current one (shortcut to TCanvas::cd())
00122 //   virtual void cd(int subpadnumber); // as above - shortcut to Canvas::cd(int subpadnumber)
00123 //   void Disconnect(); // disconnect the QWidget from the ROOT TCanvas (used in the class dtor)
00124 //   void Refresh();    // force the associated TCanvas::Update to be called
00125 //   virtual bool Save(const QString &fileName) const;  // Save the widget image with some ppixmap file
00126 //   virtual bool Save(const char    *fileName) const;
00127 //   virtual bool Save(const QString &fileName,const char *format,int quality=60) const;
00128 //   virtual bool Save(const char    *fileName,const char *format,int quality=60) const;
00129 //
00130 //  signals        (Qt)
00131 //
00132 //    CanvasPainted();  // Signal the TCanvas has been painted onto the screen
00133 //    Saved(bool ok);   // Signal the TCanvas has been saved into the file
00134 //    RootEventProcessed(TObject *selected, unsigned int event, TCanvas *c);
00135 //                      // Signal the Qt mouse/keyboard event has been process by ROOT
00136 //                      // This "signal" is emitted by the enabled mouse events only.
00137 //                      // See: EnableSignalEvents
00138 //                      // ---  DisableSignalEvents
00139 //
00140 //  public methods:
00141 //    The methods below define whether the TQtWidget object emits "RootEventProcessed" Qt signals
00142 //     (By default no  RootEventProcessed Qt signal is emitted )
00143 //     void EnableSignalEvents (UInt_t f)
00144 //     void DisableSignalEvents(UInt_t f),
00145 //         where f is a bitwise OR of the mouse event flags:
00146 //                  kMousePressEvent       // TCanvas processed QEvent mousePressEvent
00147 //                  kMouseMoveEvent        // TCanvas processed QEvent mouseMoveEvent
00148 //                  kMouseReleaseEvent     // TCanvas processed QEvent mouseReleaseEvent
00149 //                  kMouseDoubleClickEvent // TCanvas processed QEvent mouseDoubleClickEvent
00150 //                  kKeyPressEvent         // TCanvas processed QEvent keyPressEvent
00151 //                  kEnterEvent            // TCanvas processed QEvent enterEvent
00152 //                  kLeaveEvent            // TCanvas processed QEvent leaveEvent
00153 //
00154 //  For example to create the custom responce to the mouse crossing TCanvas
00155 //  connect the RootEventProsecced signal with your qt slot:
00156 //
00157 // connect(tQtWidget,SIGNAL(RootEventProcessed(TObject *, unsigned int, TCanvas *))
00158 //          ,this,SLOT(CanvasEvent(TObject *, unsigned int, TCanvas *)));
00159 //  . . .
00160 //
00161 //void qtrootexample1::CanvasEvent(TObject *obj, unsigned int event, TCanvas *)
00162 //{
00163 //  TQtWidget *tipped = (TQtWidget *)sender();
00164 //  const char *objectInfo =
00165 //        obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
00166 //  QString tipText ="You have ";
00167 //  if  (tipped == tQtWidget1)
00168 //     tipText +="clicked";
00169 //  else
00170 //     tipText +="passed";
00171 //  tipText += " the object <";
00172 //  tipText += obj->GetName();
00173 //  tipText += "> of class ";
00174 //  tipText += obj->ClassName();
00175 //  tipText += " : ";
00176 //  tipText += objectInfo;
00177 //
00178 //   QWhatsThis::display(tipText)
00179 // }
00180 //
00181 ////////////////////////////////////////////////////////////////////////////////
00182 
00183 //_____________________________________________________________________________
00184 TQtWidget::TQtWidget(QWidget* mother, const char* name, Qt::WFlags f,bool embedded) :
00185       QWidget(mother,f)
00186         ,fBits(0),fNeedStretch(false),fCanvas(0),fPixmapID(0),fPixmapScreen(0)
00187         ,fPaint(TRUE),fSizeChanged(FALSE),fDoubleBufferOn(FALSE),fEmbedded(embedded)
00188         ,fWrapper(0),fSaveFormat("PNG"),fInsidePaintEvent(false),fOldMousePos(-1,-1)
00189         ,fIgnoreLeaveEnter(0),fRefreshTimer(0)
00190 {
00191    if (name && name[0]) setObjectName(name);
00192    Init() ;
00193 }
00194 
00195 //_____________________________________________________________________________
00196 TQtWidget::TQtWidget(QWidget* mother, Qt::WFlags f,bool embedded) :
00197       QWidget(mother,f)
00198      ,fBits(0),fNeedStretch(false),fCanvas(0),fPixmapID(0)
00199      ,fPixmapScreen(0),fPaint(TRUE),fSizeChanged(FALSE)
00200      ,fDoubleBufferOn(FALSE),fEmbedded(embedded),fWrapper(0),fSaveFormat("PNG")
00201      ,fInsidePaintEvent(false),fOldMousePos(-1,-1),fIgnoreLeaveEnter(0),fRefreshTimer(0) 
00202 { setObjectName("tqtwidget"); Init() ;}
00203 
00204 //_____________________________________________________________________________
00205 void TQtWidget::Init()
00206 {
00207   setFocusPolicy(Qt::WheelFocus);
00208   setAttribute(Qt::WA_NoSystemBackground);
00209   setAutoFillBackground(false);
00210   QPalette  p = palette();
00211   p.setBrush(QPalette::Window, Qt::transparent);
00212   setPalette(p);
00213 
00214   if (fEmbedded) {
00215     if (!gApplication) InitRint();
00216     int minw = 10;
00217     int minh = 10;
00218     setMinimumSize(minw,minh);
00219      Bool_t batch = gROOT->IsBatch();
00220     if (!batch) gROOT->SetBatch(kTRUE); // to avoid the recursion within TCanvas ctor
00221     TGQt::RegisterWid(this);
00222     fCanvas = new TCanvas(objectName().toStdString().c_str(),minw,minh, TGQt::RegisterWid(this));
00223     gROOT->SetBatch(batch);
00224     //   schedule the flush operation fCanvas->Flush(); via timer
00225     Refresh();
00226   }
00227   fSizeHint = QWidget::sizeHint();
00228   setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding));
00229 #ifdef R__QTWIN32
00230    // Set the application icon for all ROOT widgets
00231    static HICON rootIcon = 0;
00232    if (!rootIcon) {
00233       HICON hIcon = ::LoadIcon(::GetModuleHandle(NULL), MAKEINTRESOURCE(101));
00234       if (!hIcon) hIcon = LoadIcon(NULL, IDI_APPLICATION);
00235       rootIcon = hIcon;
00236       SetClassLong(winId(),        // handle to window
00237                    GCL_HICON,      // index of value to change
00238                    LONG(rootIcon)  // new value
00239       );
00240     }
00241 #endif
00242 }
00243 //______________________________________________________________________________
00244 TQtWidget::~TQtWidget()
00245 {
00246    TCanvas *c = 0;
00247    // to block the double deleting from
00248    gVirtualX->SelectWindow(-1);
00249    TGQt::UnRegisterWid(this);
00250    if (fEmbedded) {
00251       // one has to set CanvasID = 0 to disconnect things properly.
00252       c = fCanvas;
00253       ResetCanvas();
00254       delete c;
00255    } else {
00256       ResetCanvas();
00257    }
00258    delete fPixmapID;     fPixmapID = 0;
00259    delete fPixmapScreen; fPixmapScreen = 0;
00260 }
00261 
00262 //______________________________________________________________________________
00263 void TQtWidget::AdjustBufferSize() 
00264 {
00265    // Adjust the widget buffer size
00266    TQtWidgetBuffer &buf = SetBuffer();
00267    QSize s(buf.Width(),buf.Height());
00268    if ( s != size() )  {
00269 #if 0
00270        qDebug() << "TQtWidget::AdjustBufferSize(): " 
00271              << this 
00272              << s << size();
00273 #endif
00274       if (fPixmapID) {
00275          TQtWidgetBuffer *bf = new TQtWidgetBuffer(*fPixmapID);
00276          delete  fPixmapID;     fPixmapID = bf;
00277       }
00278       if (fPixmapScreen) {
00279          TQtWidgetBuffer *bf = new TQtWidgetBuffer(*fPixmapScreen);
00280          delete  fPixmapScreen; fPixmapScreen = bf;
00281       }
00282    }
00283 }
00284 //_____________________________________________________________________________
00285 TCanvas  *TQtWidget::Canvas()
00286 {
00287    // Alias for GetCanvas method
00288    return GetCanvas();
00289 }
00290 
00291 //_____________________________________________________________________________
00292 TCanvas   *TQtWidget::Canvas(TQtWidget *widget)
00293 {
00294     // static: return TCanvas by TQtWidget pointer
00295    return widget ? widget->Canvas() : 0 ;
00296 }
00297 
00298 //_____________________________________________________________________________
00299 TQtWidget *TQtWidget::Canvas(const TCanvas *canvas)
00300 {
00301    // static: return the TQtWidget backend for TCanvas *canvas object
00302    return canvas ? Canvas(canvas->GetCanvasID()) : 0;
00303 }
00304 //_____________________________________________________________________________
00305 TQtWidget *TQtWidget::Canvas(Int_t id)
00306 {
00307    // static: return TQtWidget by TCanvas id
00308    return dynamic_cast<TQtWidget *>(TGQt::iwid(id));
00309 }
00310 
00311 //_____________________________________________________________________________
00312 TApplication *TQtWidget::InitRint( Bool_t /*prompt*/, const char *appClassName, int *argc, char **argv,
00313           void *options, int numOptions, Bool_t noLogo)
00314 {
00315    //
00316    // Instantiate ROOT from within Qt application if needed
00317    // Return the TRint pointer
00318    // Most parametrs are passed to TRint class ctor
00319    //
00320    // Bool_t prompt = kTRUE;  Instantiate ROOT with ROOT command prompt
00321    //                 kFALSE; No ROOT prompt. The default for Qt GUI applications
00322    //
00323    //  The prompt option can be defined via ROOT parameter file ".rootrc"
00324    // .rootrc:
00325    //    . . .
00326    //  Gui.Prompt   yes
00327    //
00328    static int localArgc      =0;
00329    static char **localArgv  =0;
00330    if (!gApplication) {
00331        QStringList args  = QCoreApplication::arguments ();
00332        localArgc = argc ? *argc : args.size();
00333        // check the Gui.backend and Factory
00334        TString guiBackend(gEnv->GetValue("Gui.Backend", "native"));
00335        guiBackend.ToLower();
00336        // Enforce Qt-base Gui.Backend and Gui.Factory from within ROOT-based Qt-application
00337        if (!guiBackend.BeginsWith("qt",TString::kIgnoreCase)) {
00338          gEnv->SetValue("Gui.Backend", "qt");
00339        }
00340        TString guiFactory(gEnv->GetValue("Gui.Factory", "native"));
00341        guiFactory.ToLower();
00342 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,16,0)
00343        TApplication::NeedGraphicsLibs() ;
00344 #endif
00345        if (!guiFactory.BeginsWith("qt",TString::kIgnoreCase )){
00346          // Check for the extention
00347          char *extLib = gSystem->DynamicPathName("libQtRootGui",kTRUE);
00348          if (extLib) {
00349             gEnv->SetValue("Gui.Factory", "qtgui");
00350          } else {
00351             gEnv->SetValue("Gui.Factory", "qt");
00352          }
00353          delete [] extLib;
00354        }
00355        if (!argc && !argv ) {
00356           localArgv  = new char*[args.size()]; // leaking :-(
00357           for (int i = 0; i < args.size(); ++i) {
00358              QString nextarg = args.at(i);
00359              Int_t nchi = nextarg.length()+1;
00360              localArgv[i]= new char[nchi]; 
00361              memcpy(localArgv[i], nextarg.toAscii().constData(),nchi-1);
00362              localArgv[nchi-1]=0;
00363           } 
00364        } else {
00365          localArgv  = argv;
00366        }
00367 
00368        TRint *rint = new TRint(appClassName, &localArgc, localArgv, options,numOptions,noLogo);
00369        // To mimic what TRint::Run(kTRUE) does.
00370        Int_t prompt= gEnv->GetValue("Gui.Prompt", (Int_t)0);
00371        if (prompt) {
00372            Getlinem(kInit, rint->GetPrompt());
00373        } else {
00374            // disable the TTermInputHandler too to avoid the crash under X11
00375            // to get the pure "GUI" application
00376            TSeqCollection* col = gSystem->GetListOfFileHandlers();
00377            TIter next(col);
00378            TFileHandler* o=0;
00379            while ( ( o=(TFileHandler*) next() ) ) {
00380               if ( o->GetFd()== 0 ) {
00381                 o->Remove();
00382                 break;
00383               }
00384            }
00385            // Remove Ctrl-C, there will be ROOT prompt anyway
00386            gSystem->RemoveSignalHandler(rint->GetSignalHandler());
00387        }
00388        TQtTimer::Create()->start(0);
00389    }
00390    return gApplication;
00391 }
00392 
00393 //_____________________________________________________________________________
00394 void TQtWidget::Erase()
00395 {
00396   // Erases the entire widget and its double buffer
00397  
00398   SetBuffer();
00399 //  buf.fill(this,QPoint(0,0));
00400   if (fPixmapScreen)  fPixmapScreen->Clear();
00401   if (fPixmapID)      fPixmapID->Clear();
00402   // erase();
00403 }
00404 
00405 //_____________________________________________________________________________
00406 void TQtWidget::cd()
00407 {
00408  // [slot] to make this embedded canvas the current one
00409   cd(0);
00410 }
00411  //______________________________________________________________________________
00412 void TQtWidget::cd(int subpadnumber)
00413 {
00414  // [slot] to make this embedded canvas / pad the current one
00415   TCanvas *c = fCanvas;
00416   if (c) {
00417      c->cd(subpadnumber);
00418   }
00419 }
00420 //______________________________________________________________________________
00421 void TQtWidget::Disconnect()
00422 {
00423    // [slot] Disconnect the Qt widget from TCanvas object before deleting
00424    // to avoid the dead lock
00425    // one has to set CanvasID = 0 to disconnect things properly.
00426    fCanvas = 0;
00427 }
00428 //_____________________________________________________________________________
00429 void TQtWidget::Refresh()
00430 {
00431    // [slot]  to allow Qt signal refreshing the ROOT TCanvas if needed
00432    // use the permanent single shot timer to eliminate 
00433    // the redundand refreshing for the sake of the performance
00434    if (!fRefreshTimer) {
00435       fRefreshTimer  = new QTimer(this);
00436       fRefreshTimer->setSingleShot(true);
00437       fRefreshTimer->setInterval(0);
00438       connect(fRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshCB()));
00439    }
00440    fRefreshTimer->start();
00441 }
00442 //_____________________________________________________________________________
00443 void TQtWidget::RefreshCB()
00444 {
00445    // [slot]  to allow Qt signal refreshing the ROOT TCanvas if needed
00446 
00447    TCanvas *c = Canvas();
00448    if (c) {
00449       c->Modified();
00450       c->Resize();
00451       c->Update();
00452    }
00453    if (!fInsidePaintEvent) { update(); }
00454    else {
00455       qDebug() << " TQtWidget::Refresh() update inside of paintEvent !!!" << this; 
00456    }
00457 }
00458 //_____________________________________________________________________________
00459 void TQtWidget::SetCanvas(TCanvas *c) 
00460 { 
00461    //  remember my host TCanvas and adopt its name
00462    fCanvas = c;
00463    // qDebug() << "TQtWidget::SetCanvas(TCanvas *c)" << fCanvas << fCanvas->GetName() ;
00464    setObjectName(fCanvas->GetName());
00465 }
00466 
00467 //_____________________________________________________________________________
00468 void
00469 TQtWidget::customEvent(QEvent *e)
00470 {
00471    // The custom response to the special WIN32 events
00472    // These events are not present with X11 systems
00473    switch (e->type() - QEvent::User) {
00474    case kEXITSIZEMOVE:
00475       { // WM_EXITSIZEMOVE
00476          fPaint = TRUE;
00477          exitSizeEvent();
00478          break;
00479       }
00480    case kENTERSIZEMOVE:
00481       {
00482          //  WM_ENTERSIZEMOVE
00483          fSizeChanged=FALSE;
00484          fPaint = FALSE;
00485          break;
00486       }
00487    case kFORCESIZE:
00488    default:
00489       {
00490          // Force resize
00491          fPaint       = TRUE;
00492          fSizeChanged = TRUE;
00493          exitSizeEvent();
00494          break;
00495       }
00496    };
00497 }
00498  //_____________________________________________________________________________
00499 void TQtWidget::contextMenuEvent(QContextMenuEvent *e)
00500 {
00501    // The custom response to the Qt QContextMenuEvent
00502    // Map QContextMenuEvent to the ROOT kButton3Down = 3  event
00503    TCanvas *c = Canvas();
00504    if (e && c && (e->reason() != QContextMenuEvent::Mouse) ) {
00505       e->accept();
00506       c->HandleInput(kButton3Down, e->x(), e->y());
00507    }
00508 }
00509 //_____________________________________________________________________________
00510 void TQtWidget::focusInEvent ( QFocusEvent *e )
00511 {
00512    // The custom response to the Qt QFocusEvent "in"
00513    // this imposes an extra protection to avoid TObject interaction with
00514    // mouse event accidently
00515    if (!fWrapper && e->gotFocus()) {
00516       setMouseTracking(TRUE);
00517    }
00518 }
00519 //_____________________________________________________________________________
00520 void TQtWidget::focusOutEvent ( QFocusEvent *e )
00521 {
00522    // The custom response to the Qt QFocusEvent "out"
00523    // this imposes an extra protection to avoid TObject interaction with
00524    // mouse event accidently
00525    if (!fWrapper && e->lostFocus()) {
00526       setMouseTracking(FALSE);
00527    }
00528 }
00529 
00530 //_____________________________________________________________________________
00531 void TQtWidget::mousePressEvent (QMouseEvent *e)
00532 {
00533    // Map the Qt mouse press button event to the ROOT TCanvas events
00534    // Mouse events occur when a mouse button is pressed or released inside
00535    // a widget or when the mouse cursor is moved.
00536 
00537    //    kButton1Down   =  1, kButton2Down   =  2, kButton3Down   =  3,
00538 
00539    EEventType rootButton = kNoEvent;
00540    Qt::ContextMenuPolicy currentPolicy = contextMenuPolicy();
00541    fOldMousePos = e->pos();
00542    TCanvas *c = Canvas();
00543    if (c && !fWrapper ){
00544       switch (e->button ())
00545       {
00546       case Qt::LeftButton:  rootButton = kButton1Down; break;
00547       case Qt::RightButton: {
00548          // respect the QWidget::contextMenuPolicy
00549          // treat this event as QContextMenuEvent
00550          if ( currentPolicy == Qt::DefaultContextMenu) {
00551             e->accept();
00552             QContextMenuEvent evt(QContextMenuEvent::Other, e->pos() );
00553             QApplication::sendEvent(this, &evt);
00554          } else {
00555             rootButton = kButton3Down;
00556          }
00557          break;
00558       }
00559       case Qt::MidButton:   rootButton = kButton2Down; break;
00560       default: break;
00561       };
00562       if (rootButton != kNoEvent) {
00563          e->accept();
00564          if (rootButton == kButton3Down) {
00565            bool lastvalue = c->TestBit(kNoContextMenu);
00566            c->SetBit(kNoContextMenu);
00567            c->HandleInput(rootButton, e->x(), e->y());
00568            c->SetBit(kNoContextMenu, lastvalue);
00569          } else {
00570            c->HandleInput(rootButton, e->x(), e->y());
00571          }
00572          EmitSignal(kMousePressEvent);
00573          return;
00574       }
00575    } else {
00576       e->ignore();
00577    }
00578    QWidget::mousePressEvent(e);
00579 }
00580 
00581 //_____________________________________________________________________________
00582 void TQtWidget::mouseMoveEvent (QMouseEvent * e)
00583 {
00584    //  Map the Qt mouse move pointer event to the ROOT TCanvas events
00585    //  kMouseMotion   = 51,
00586    //  kButton1Motion = 21, kButton2Motion = 22, kButton3Motion = 23, kKeyPress = 24
00587    EEventType rootButton = kMouseMotion;
00588    if ( fOldMousePos != e->pos() && fIgnoreLeaveEnter < 2  ) { // workaround of Qt 4.5.x bug
00589       fOldMousePos = e->pos(); 
00590       TCanvas *c = Canvas();
00591       if (c && !fWrapper){
00592          if (e->buttons() & Qt::LeftButton) { rootButton = kButton1Motion; }
00593          e->accept();
00594          c->HandleInput(rootButton, e->x(), e->y());
00595          EmitSignal(kMouseMoveEvent);
00596          return;
00597       } else {
00598          e->ignore();
00599       }
00600    }
00601    QWidget::mouseMoveEvent(e);
00602 }
00603 
00604 //_____________________________________________________________________________
00605 void TQtWidget::mouseReleaseEvent(QMouseEvent * e)
00606 {
00607    //  Map the Qt mouse button release event to the ROOT TCanvas events
00608    //   kButton1Up     = 11, kButton2Up     = 12, kButton3Up     = 13
00609 
00610    EEventType rootButton = kNoEvent;
00611    fOldMousePos = QPoint(-1,-1);
00612    TCanvas *c = Canvas();
00613    if (c && !fWrapper){
00614       switch (e->button())
00615       {
00616       case Qt::LeftButton:  rootButton = kButton1Up; break;
00617       case Qt::RightButton: rootButton = kButton3Up; break;
00618       case Qt::MidButton:   rootButton = kButton2Up; break;
00619       default: break;
00620       };
00621       if (rootButton != kNoEvent) {
00622          e->accept();
00623          c->HandleInput(rootButton, e->x(), e->y());
00624          gPad->Modified();
00625          EmitSignal(kMouseReleaseEvent);
00626          return;
00627       }
00628    } else {
00629       e->ignore();
00630    }
00631    QWidget::mouseReleaseEvent(e);
00632 }
00633 
00634 //_____________________________________________________________________________
00635 void TQtWidget::mouseDoubleClickEvent(QMouseEvent * e)
00636 {
00637    //  Map the Qt mouse double click button event to the ROOT TCanvas events
00638    //  kButton1Double = 61, kButton2Double = 62, kButton3Double = 63
00639    EEventType rootButton = kNoEvent;
00640    TCanvas *c = Canvas();
00641    if (c && !fWrapper){
00642       switch (e->button())
00643       {
00644       case Qt::LeftButton:  rootButton = kButton1Double; break;
00645       case Qt::RightButton: rootButton = kButton3Double; break;
00646       case Qt::MidButton:   rootButton = kButton2Double; break;
00647       default: break;
00648       };
00649       if (rootButton != kNoEvent) {
00650          e->accept();
00651          c->HandleInput(rootButton, e->x(), e->y());
00652          EmitSignal(kMouseDoubleClickEvent);return;
00653       }
00654    }  else {
00655       e->ignore();
00656    }
00657    QWidget::mouseDoubleClickEvent(e);
00658 }
00659 //_____________________________________________________________________________
00660 void TQtWidget::keyPressEvent(QKeyEvent * e)
00661 {
00662    // Map the Qt key press event to the ROOT TCanvas events
00663    // kKeyDown  =  4
00664    TCanvas *c = Canvas();
00665    if (c && !fWrapper){
00666       c->HandleInput(kKeyPress, e->text().toStdString().c_str()[0], e->key());
00667       EmitSignal(kKeyPressEvent);
00668    } else {
00669       e->ignore();
00670    }
00671    QWidget::keyPressEvent(e);
00672 }
00673 //_____________________________________________________________________________
00674 void TQtWidget::keyReleaseEvent(QKeyEvent * e)
00675 {
00676    // Map the Qt key release event to the ROOT TCanvas events
00677    // kKeyUp    = 14
00678    QWidget::keyReleaseEvent(e);
00679 }
00680 //_____________________________________________________________________________
00681 void TQtWidget::enterEvent(QEvent *e)
00682 {
00683    // Map the Qt mouse enters widget event to the ROOT TCanvas events
00684    // kMouseEnter    = 52
00685    TCanvas *c = Canvas();
00686    if (c && !fIgnoreLeaveEnter && !fWrapper){
00687       c->HandleInput(kMouseEnter, 0, 0);
00688       EmitSignal(kEnterEvent);
00689    }
00690    QWidget::enterEvent(e);
00691 }
00692 //_____________________________________________________________________________
00693 void TQtWidget::leaveEvent (QEvent *e)
00694 {
00695    //  Map the Qt mouse leaves widget event to the ROOT TCanvas events
00696    // kMouseLeave    = 53
00697    TCanvas *c = Canvas();
00698    if (c && !fIgnoreLeaveEnter && !fWrapper){
00699       c->HandleInput(kMouseLeave, 0, 0);
00700       EmitSignal(kLeaveEvent);
00701    }
00702    QWidget::leaveEvent(e);
00703 }
00704 //_____________________________________________________________________________
00705 void TQtWidget::resizeEvent(QResizeEvent *e)
00706 {
00707    // The widget will be erased and receive a paint event immediately after
00708    // processing the resize event.
00709    // No drawing need be (or should be) done inside this handler.
00710    if (!e) return;
00711    if (topLevelWidget()->isMinimized())      { fSizeChanged=FALSE; }
00712    else if (topLevelWidget()->isMaximized ()){
00713       fSizeChanged=TRUE;
00714       exitSizeEvent();
00715       fSizeChanged=TRUE;
00716    } else {
00717 #ifdef R__QTWIN32
00718       if (!fPaint)  {
00719          // real resize event
00720          fSizeChanged=TRUE;
00721          fNeedStretch=true;
00722       } else {
00723 #else
00724       {
00725          fSizeChanged=TRUE;
00726 #if 0
00727          if (Qt::LeftButton == QApplication::mouseButtons()) 
00728          {
00729             fNeedStretch=true;
00730             fPaint = false;
00731          } else 
00732 #endif
00733          {
00734             fPaint = kTRUE;
00735             exitSizeEvent();
00736          }
00737 #endif
00738       } }
00739 }
00740 //____________________________________________________________________________
00741 void TQtWidget::SetSaveFormat(const char *format)
00742 {
00743      // Set the default save format for the widget
00744    fSaveFormat = TGQt::QtFileFormat(format);
00745 }
00746 //____________________________________________________________________________
00747 bool TQtWidget::Save(const char *fileName) const
00748 {
00749    //
00750    //  TQtWidget::Save(const QString &fileName) is a public Qt slot.
00751    //  it saves the double buffer of this object using the default save
00752    //  format  defined the file extension
00753    //  If the "fileName" has no extension the "default" format is to be used instead
00754    //  The deafult format is "PNG".
00755    //  It can be changed with the TQtWidget::SetSaveFormat method
00756    //
00757     return Save(QString(fileName));
00758 }
00759 //____________________________________________________________________________
00760 bool TQtWidget::Save(const QString &fileName) const
00761 {
00762    //
00763    //  TQtWidget::Save(const QString &fileName) is a public Qt slot.
00764    //  it saves the double buffer of this object using the default save
00765    //  format  defined the file extension
00766    //  If the "fileName" has no extension the "default" format is to be used instead
00767    //  The deafult format is "PNG".
00768    //  It can be changed with the TQtWidget::SetSaveFormat method
00769    //
00770    QString fileNameExtension = QFileInfo(fileName).suffix().toUpper();
00771    QString saveFormat;
00772    if (fileNameExtension.isEmpty() ) {
00773       saveFormat = fSaveFormat; // this is default
00774    } else {
00775       saveFormat = TGQt::QtFileFormat(fileNameExtension);
00776    }
00777    return Save(fileName,saveFormat.toStdString().c_str());
00778 }
00779 
00780 //____________________________________________________________________________
00781 bool TQtWidget::Save(const char *fileName,const char *format,int quality)const
00782 {
00783    return Save(QString(fileName),format,quality);
00784 }
00785 //____________________________________________________________________________
00786 bool TQtWidget::Save(const QString &fileName,const char *format,int quality)const
00787 {
00788    //  TQtWidget::save is a public Qt slot.
00789    //  it saves the double buffer of this object using QPixmap facility
00790    bool Ok = false;
00791    bool rootFormatFound=kTRUE;
00792    QString saveType =  TGQt::RootFileFormat(format);
00793    if (saveType.isEmpty() )  {
00794       rootFormatFound = false;
00795       saveType = TGQt::QtFileFormat(format);
00796    }
00797    TCanvas *c = GetCanvas();
00798    if (rootFormatFound && c) {
00799       c->Print(fileName.toStdString().c_str(),saveType.toStdString().c_str());
00800       Ok = true;
00801    } else if (GetOffScreenBuffer()) {
00802       // Since the "+" is a legal part of the file name and it is used by Onuchin
00803       // to indicate  the "animation" mode, we have to proceed very carefully
00804       int dot = fileName.lastIndexOf('.');
00805       int plus = 0;
00806       if (dot > -1) {
00807          plus = fileName.indexOf('+',dot+1);
00808       }
00809       QString fln = (plus > -1) ? TGQt::GetNewFileName(fileName.left(plus)) : fileName;
00810       if (fCanvasDecorator.isNull()) {
00811          Ok = GetOffScreenBuffer()->save(fln,saveType.toStdString().c_str(),quality);
00812       } else {
00813          /// add decoration
00814       }
00815    }
00816    emit ((TQtWidget *)this)->Saved(Ok);
00817    return Ok;
00818 }
00819 //_____________________________________________________________________________
00820 void  TQtWidget::SetDoubleBuffer(bool on)
00821 {
00822      // Set the double buffered mode on/off
00823    if (fDoubleBufferOn != on ) {
00824       fDoubleBufferOn = on;
00825       if (on) SetBuffer();
00826    }
00827 }
00828 //_____________________________________________________________________________
00829 void TQtWidget::stretchWidget(QResizeEvent * /*s*/)
00830 {
00831    // Stretch the widget during sizing
00832 
00833    if  (!paintingActive() && fPixmapID) {
00834       QPainter pnt(this);
00835       pnt.drawPixmap(rect(),*GetOffScreenBuffer());
00836    }
00837    fNeedStretch = false;
00838 }
00839 //_____________________________________________________________________________
00840 void TQtWidget::exitSizeEvent ()
00841 {
00842    // Response to the "exit size event"
00843 
00844    if (!fSizeChanged ) return;
00845    {
00846       AdjustBufferSize();
00847    }
00848    //Refresh();
00849    TCanvas *c = Canvas();
00850    if (c)   c->Resize();
00851    // One more time to catch the last size
00852    Refresh();
00853 }
00854 
00855 //____________________________________________________________________________
00856 bool TQtWidget::paintFlag(bool mode)
00857 {
00858    //  Set new fPaint flag
00859    //  Returns: the previous version of the flag
00860    bool flag = fPaint;
00861    fPaint = mode;
00862    return flag;
00863 }
00864 //____________________________________________________________________________
00865 void TQtWidget::showEvent ( QShowEvent *)
00866 {
00867    // Custom handler of the Qt show event
00868    // Non-spontaneous show events are sent to widgets immediately before
00869    // they are shown.
00870    // The spontaneous show events of top-level widgets are delivered afterwards.
00871    TQtWidgetBuffer &buf = SetBuffer();
00872    QSize s(buf.Width(),buf.Height());
00873    if (s != size() )
00874    {
00875       fSizeChanged = kTRUE;
00876       exitSizeEvent();
00877    }
00878 }
00879 
00880 //____________________________________________________________________________
00881 void TQtWidget::paintEvent (QPaintEvent *e)
00882 {
00883    // Custom handler of the Qt paint event
00884    // A paint event is a request to repaint all or part of the widget.
00885    // It can happen as a result of repaint() or update(), or because the widget
00886    // was obscured and has now been uncovered, or for many other reasons.
00887    fInsidePaintEvent = true;
00888    if (fNeedStretch) {
00889       stretchWidget((QResizeEvent *)0);
00890    } else {
00891 #ifdef R__QTWIN32
00892       TQtWidgetBuffer &buf = SetBuffer();
00893       QSize s(buf.Width(),buf.Height());
00894       if ( fEmbedded && (s != size()) )
00895       {
00896          fSizeChanged = kTRUE;
00897          exitSizeEvent();
00898          fInsidePaintEvent = false;
00899          return;
00900       }
00901 #endif
00902       QRegion region = e->region();
00903       if ( ( fPaint && !region.isEmpty() ) )
00904       {
00905          //  fprintf(stderr,"TQtWidget::paintEvent: window = %p; buffer =  %p\n",
00906          //  (QPaintDevice *)this, (QPaintDevice *)&GetBuffer());
00907          //  qDebug() << "1. TQtWidget::paintEvent this =" << (QPaintDevice *)this  << " buffer = " << fPixmapID << "redirected = " << QPainter::redirected(this)
00908          //    <<" IsDoubleBuffered()=" << IsDoubleBuffered() ;
00909          // qDebug() << "2. TQtWidget::paintEvent this =" << (QPaintDevice *)this  << " buffer = " << fPixmapID << " IsDoubleBuffered()=" << IsDoubleBuffered() ;
00910          QPainter screen(this);
00911          screen.setClipRegion(region);
00912          // paint the the TCanvas double buffer
00913          if (fPixmapID)  screen.drawPixmap(0,0,*GetOffScreenBuffer());
00914          if (!fCanvasDecorator.isNull()) fCanvasDecorator->paintEvent(screen,e);
00915       }
00916    }
00917    fInsidePaintEvent = false;
00918 }
00919 //  Layout methods:
00920 //____________________________________________________________________________
00921 void TQtWidget::SetSizeHint (const QSize &sz) {
00922    //  sets the preferred size of the widget.
00923    fSizeHint = sz;
00924 }
00925 //____________________________________________________________________________
00926 QSize TQtWidget::sizeHint () const{
00927    //  returns the preferred size of the widget.
00928    return QWidget::sizeHint();
00929 }
00930 //____________________________________________________________________________
00931 QSize TQtWidget::minimumSizeHint () const{
00932    // returns the smallest size the widget can have.
00933    return QWidget::minimumSizeHint ();
00934 }
00935 //____________________________________________________________________________
00936 QSizePolicy TQtWidget::sizePolicy () const{
00937    //  returns a QSizePolicy; a value describing the space requirements
00938    return QWidget::sizePolicy ();
00939 }
00940 //____________________________________________________________________________
00941 void  TQtWidget::EmitTestedSignal()
00942 {
00943    TCanvas *c        = GetCanvas();
00944    TObject *selected = GetSelected();
00945    UInt_t evt      = GetEvent();
00946    emit RootEventProcessed(selected, evt, c);
00947 }
00948 //____________________________________________________________________________
00949 void  TQtWidget::SetBit(UInt_t f, Bool_t set)
00950 {
00951    // Set or unset the user status bits as specified in f.
00952 
00953    if (set)
00954       SetBit(f);
00955    else
00956       ResetBit(f);
00957 }
00958 //____________________________________________________________________________
00959 TQtWidgetBuffer  &TQtWidget::SetBuffer() {
00960    // Create (if needed) and return the buffer
00961    TQtWidgetBuffer *buf = 0;
00962    if (IsDoubleBuffered() ) {
00963       if (!fPixmapID) fPixmapID = new TQtWidgetBuffer(this);
00964       buf = fPixmapID;
00965    } else {
00966       if (!fPixmapScreen) fPixmapScreen = new TQtWidgetBuffer(this,true);
00967       // qDebug() << "TQtWidget::SetBuffer() " << fPixmapScreen;
00968       buf = fPixmapScreen;
00969    }
00970    return  *buf;
00971 }
00972 //______________________________________________________________________________
00973 QPixmap  *TQtWidget::GetOffScreenBuffer()  const { 
00974    //  return the current widget buffer;
00975    return fPixmapID ? (QPixmap  *)fPixmapID->Buffer():0;
00976 }

Generated on Tue Jul 5 14:14:36 2011 for ROOT_528-00b_version by  doxygen 1.5.1