TQtClientWidget.cxx

Go to the documentation of this file.
00001 // @(#)root/qt:$Id: TQtClientWidget.cxx 28205 2009-04-14 19:38:00Z brun $
00002 // Author: Valeri Fine   21/01/2002
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
00006  * Copyright (C) 2002 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 #include "TQtWidget.h"
00014 #include "TQtClientWidget.h"
00015 #include "TQtClientFilter.h"
00016 #include "TQtClientGuard.h"
00017 #include "TGQt.h"
00018 #include "TQtLock.h"
00019 
00020 #include <QKeySequence>
00021 #include <QShortcut>
00022 #include <QKeyEvent>
00023 #include <QCloseEvent>
00024 #include <QEvent>
00025 #include <QDebug>
00026 
00027 #include "TGClient.h"
00028 
00029 ////////////////////////////////////////////////////////////////////////////////
00030 //
00031 //  TQtClientWidget is QFrame designed to back the ROOT GUI TGWindow class objects
00032 //
00033 //
00034 // TQtClientWidget  is a QFrame implementation backing  ROOT TGWindow objects
00035 // It tries to mimic the X11 Widget behaviour, that kind the ROOT Gui relies on heavily.
00036 //
00037 // Since ROOT has a habit to destroy the widget many times, to protect the C++ QWidget
00038 // against of double deleting all TQtClientWidgets are to be registered with a special
00039 // "guard" container
00040 //
00041 ////////////////////////////////////////////////////////////////////////////////
00042 
00043 //______________________________________________________________________________
00044 TQtClientWidget::TQtClientWidget(TQtClientGuard *guard, QWidget* mother, const char* name, Qt::WFlags f ):
00045           QFrame(mother,f)
00046          ,fGrabButtonMask(kAnyModifier),      fGrabEventPointerMask(kNoEventMask)
00047          ,fGrabEventButtonMask(kNoEventMask), fSelectEventMask(kNoEventMask), fSaveSelectInputMask(kNoEventMask) // ,fAttributeEventMask(0)
00048          ,fButton(kAnyButton), fPointerOwner(kFALSE)
00049          ,fNormalPointerCursor(0),fGrabPointerCursor(0),fGrabButtonCursor(0)
00050          ,fIsClosing(false)  ,fDeleteNotify(false), fGuard(guard)
00051          ,fCanvasWidget(0),fMyRootWindow(0),fEraseColor(0), fErasePixmap(0)
00052 {
00053    setObjectName(name);
00054    setAttribute(Qt::WA_PaintOnScreen);
00055    setAttribute(Qt::WA_PaintOutsidePaintEvent);
00056    setAutoFillBackground(true); 
00057  //   fEraseColor  = new QColor("red");
00058 //   fErasePixmap = new QPixmap(palette().brush(QPalette::Window).texture());
00059 }
00060 
00061 //______________________________________________________________________________
00062 TQtClientWidget::~TQtClientWidget()
00063 {
00064    // fprintf(stderr, "TQtClientWidget::~TQtClientWidget dtor %p\n", this);
00065    // remove the event filter
00066    TQtClientFilter *f = gQt->QClientFilter();
00067    // Do we still grabbing anything ?
00068    if (f) f->GrabPointer(this, 0, 0, 0, kFALSE);  // ungrab pointer
00069    disconnect();
00070    if (fGuard) fGuard->DisconnectChildren(this);
00071    fNormalPointerCursor = 0; // to prevent the cursor shape restoring
00072    UnSetButtonMask(true);
00073    UnSetKeyMask();
00074    delete fEraseColor;  fEraseColor  = 0; 
00075    delete fErasePixmap; fErasePixmap = 0;
00076    if (!IsClosing())
00077       gQt->SendDestroyEvent(this);  // notify TGClient we have been destroyed
00078 }
00079 
00080 //______________________________________________________________________________
00081 void TQtClientWidget::closeEvent(QCloseEvent *ev)
00082 {
00083    // This Qt QCloseEvent event handler
00084 
00085    // Close events are sent to widgets that the user wants to close,
00086    // usually by choosing "Close" from the window menu, or by clicking
00087    // the `X' titlebar button. They are also sent when you call QWidget::close()
00088    // to close a widget programmatically.
00089 
00090    printf("TQtClientWidget::closeEvent(QCloseEvent *ev)\n");
00091    QWidget::closeEvent(ev);
00092 }
00093 //______________________________________________________________________________
00094 void TQtClientWidget::setEraseColor(const QColor &color)
00095 {
00096    // Color to paint widget background with our PainEvent
00097    if (!fEraseColor) 
00098       fEraseColor = new QColor(color);
00099    else 
00100       *fEraseColor = color;
00101    QPalette pp = palette();
00102    pp.setColor(QPalette::Window, *fEraseColor);
00103    setPalette(pp);
00104 //            win->setBackgroundRole(QPalette::Window);
00105 }
00106 
00107 //______________________________________________________________________________
00108 void TQtClientWidget::setErasePixmap (const QPixmap &pixmap)
00109 {
00110    // pixmap to paint widget background with our PainEvent
00111    if (!fErasePixmap) 
00112       fErasePixmap = new QPixmap(pixmap);
00113    else
00114       *fErasePixmap = pixmap;
00115 
00116    QPalette pp = palette();
00117    pp.setBrush(QPalette::Window, QBrush(*fErasePixmap));
00118    setPalette(pp);
00119 //            win->setBackgroundRole(QPalette::Window);
00120 }
00121 
00122 //______________________________________________________________________________
00123 bool TQtClientWidget::IsGrabbed(Event_t &ev)
00124 {
00125    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00126    // XGrabButton(3X11)         XLIB FUNCTIONS        XGrabButton(3X11)
00127    //   ·    The pointer is not grabbed, and the specified button is logically
00128    //        pressed when the specified modifier keys are logically down,
00129    //        and no other buttons or modifier keys are logically down.
00130    //   ·    The grab_window contains the pointer.
00131    //   ·    The confine_to window (if any) is viewable.
00132    //   ·    A passive grab on the same button/key combination does not exist
00133    //        on any ancestor of grab_window.
00134    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00135    bool grab = false;
00136    QWidget *mother = parentWidget();
00137 //   fprintf(stderr,"\n -1- TQtClientWidget::IsGrabbed  parent = %p mask %o register = %d "
00138 //          , parent, ButtonEventMask(),TGQt::IsRegistered(parent));
00139    if (     ButtonEventMask()
00140          && !isHidden() 
00141          && !(   mother 
00142                && dynamic_cast<TQtClientWidget*>(mother)  // TGQt::IsRegistered(parent)
00143                && ((TQtClientWidget *)mother)->IsGrabbed(ev)
00144              )
00145       )
00146       {
00147 
00148         //Test whether the current button is grabbed by this window
00149         bool msk = (ev.fState & fGrabButtonMask) || (fGrabButtonMask & kAnyModifier);
00150         
00151         if ((fButton == kAnyButton) && msk)
00152            grab = true;
00153         else 
00154            grab = (fButton == EMouseButton(ev.fCode)) && msk;
00155         
00156         // Check whether this window holds the pointer coordinate
00157         TQtClientWidget *w = (TQtClientWidget *)TGQt::wid(ev.fWindow);
00158         if (grab && (w != this) ) {
00159            QRect absRect = geometry();
00160            QPoint absPos = mapToGlobal(QPoint(0,0));
00161            absRect.moveTopLeft(absPos);
00162            grab = absRect.contains(ev.fXRoot,ev.fYRoot);
00163         }
00164 
00165         if (grab)   GrabEvent(ev);
00166      }
00167    //  fprintf(stderr," this = %p grab=%d \n", this, grab);
00168    // TGQt::PrintEvent(ev);
00169 
00170    return grab;
00171 }
00172 //______________________________________________________________________________
00173 TQtClientWidget *TQtClientWidget::IsKeyGrabbed(const Event_t &ev)
00174 {
00175    // Check ROOT Event_t ev structure for the KeyGrab mask
00176 
00177    // fprintf(stderr,"Do we grab ? current window %p; event window = %p  code <%c>, grabber = %p\n",TGQt::wid(this), TGQt::rootwid(TGQt::wid(ev.fWindow)), ev.fCode,fGrabbedKey);
00178    TQtClientWidget *grabbed = 0;
00179    UInt_t modifier = ev.fState;
00180     
00181    if (SetKeyMask(ev.fCode,  modifier, kTestKey)) grabbed = this;
00182    if (grabbed && ( ev.fType == kKeyRelease)) {
00183       SetKeyMask(ev.fCode,  modifier, kRemove);
00184    }
00185    TQtClientWidget *wg = this;
00186    if (!grabbed) {
00187       // check parent 
00188       do {
00189           wg = (TQtClientWidget *)wg->parentWidget();
00190       }  while ( wg && (grabbed = wg->IsKeyGrabbed(ev)) );
00191    }
00192    if (!grabbed) {
00193       // Check children
00194      const QObjectList &childList = children();
00195       if (!childList.isEmpty()) {
00196          QListIterator<QObject*> next(childList);
00197          while(next.hasNext() && (wg = dynamic_cast<TQtClientWidget *>(next.next ())) && !(grabbed=wg->IsKeyGrabbed(ev)) ){;}
00198       }
00199    }
00200    return grabbed;
00201 }
00202 //______________________________________________________________________________
00203 void TQtClientWidget::GrabEvent(Event_t &ev, bool /*own*/)
00204 {
00205    // replace the original Windows_t  with the grabbing id and
00206    // re-caclulate the mouse coordinate
00207    // to respect the new Windows_t id if any
00208    TQtClientWidget *w = (TQtClientWidget *)TGQt::wid(ev.fWindow);
00209    if (w != this) {
00210       QPoint mapped = mapFromGlobal(QPoint(ev.fXRoot,ev.fYRoot));
00211       // Correct the event
00212       ev.fX      = mapped.x();
00213       ev.fY      = mapped.y();
00214       // replace the original Windows_t  with the grabbing id
00215       ev.fWindow          = TGQt::wid(this);
00216       // fprintf(stderr,"---- TQtClientWidget::GrabEvent\n");
00217    }
00218   // TGQt::PrintEvent(ev);
00219 }
00220 //______________________________________________________________________________
00221 void TQtClientWidget::SelectInput (UInt_t evmask) 
00222 {
00223    // Select input and chech whether qwe nat mouse tracking
00224    fSelectEventMask=evmask;
00225    assert(fSelectEventMask != (UInt_t) -1);
00226    setMouseTracking( fSelectEventMask & kPointerMotionMask );
00227 }
00228 //______________________________________________________________________________
00229 void TQtClientWidget::SetButtonMask(UInt_t modifier,EMouseButton button)
00230 {
00231    // Set the Button mask
00232    fGrabButtonMask  = modifier; fButton = button;
00233    TQtClientFilter *f = gQt->QClientFilter();
00234    if (f) {
00235       f->AppendButtonGrab(this);
00236       connect(this,SIGNAL(destroyed(QObject *)),f,SLOT(RemoveButtonGrab(QObject *)));
00237    }
00238 }
00239 //______________________________________________________________________________
00240 void TQtClientWidget::UnSetButtonMask(bool dtor)
00241 {
00242    // Unset the Button mask
00243 
00244    if (fGrabButtonMask) {
00245       fGrabButtonMask = 0;
00246       TQtClientFilter *f = gQt->QClientFilter();
00247       if (f) {
00248          if ( !dtor ) disconnect(this,SIGNAL(destroyed(QObject *)),f,SLOT(RemoveButtonGrab(QObject *)));
00249          f->RemoveButtonGrab(this);
00250       }
00251    }
00252 }
00253 //______________________________________________________________________________
00254 Bool_t TQtClientWidget::SetKeyMask(Int_t keycode, UInt_t modifier, int insert)
00255 {
00256    // Set the key button mask
00257    // insert   = -1 - remove
00258    //             0 - test
00259    //            +1 - insert
00260    Bool_t found = kTRUE;
00261    int ikeys = 0;
00262    if (keycode) {
00263       if (modifier & kKeyShiftMask)   ikeys |= Qt::SHIFT;
00264       if (modifier & kKeyLockMask)    ikeys |= Qt::META;
00265       if (modifier & kKeyControlMask) ikeys |= Qt::CTRL;
00266       if (modifier & kKeyMod1Mask)    ikeys |= Qt::ALT;
00267                                       ikeys |= keycode;
00268    }
00269    QKeySequence keys(ikeys);
00270 
00271    std::map<QKeySequence,QShortcut*>::iterator i = fGrabbedKey.find(keys);
00272    switch (insert) {
00273       case kInsert:
00274          if (keycode) {
00275             if ( i == fGrabbedKey.end()) {
00276                fGrabbedKey.insert(
00277                      std::pair<QKeySequence,QShortcut*>(keys,new QShortcut(keys,this,SLOT(Accelerate()),SLOT(Accelerate()),Qt::ApplicationShortcut))
00278                      );
00279                 // qDebug() << "TQtClientWidget::SetKeyMask()" << this << " key=" << keys;
00280             } else {
00281                (*i).second->setEnabled(true);
00282             }
00283          }
00284          break;
00285       case kRemove:
00286          if (keycode) {
00287             if ( i != fGrabbedKey.end())
00288                (*i).second->setEnabled(false);
00289         } else {
00290             // keycode ==0 - means delete all accelerators
00291             // fprintf(stderr,"-%p: TQtClientWidget::SetKeyMask modifier=%d keycode \'%c\' \n", this, modifier, keycode);
00292             std::map<QKeySequence,QShortcut*>::iterator j = fGrabbedKey.begin();
00293             while (j != fGrabbedKey.end()) {
00294                (*j).second->setEnabled(false);
00295                ++j;
00296            }
00297          }
00298          break;
00299       case kTestKey:
00300          found = i != fGrabbedKey.end();
00301          break;
00302       default: break;
00303   }
00304   return found;
00305 }
00306 //______________________________________________________________________________
00307 void TQtClientWidget::SetCanvasWidget(TQtWidget *widget)
00308 {
00309    // Associate this widget with the parent ROOT gui widget
00310    TQtLock lock;
00311    if (fCanvasWidget)
00312       disconnect(fCanvasWidget,SIGNAL(destroyed()), this, SLOT(disconnect()));
00313    fCanvasWidget = widget;
00314    if (fCanvasWidget) {
00315       // may be transparent
00316 #if QT_VERSION < 0x40000
00317       setWFlags(getWFlags () | Qt::WRepaintNoErase | Qt:: WResizeNoErase );
00318 #endif /* QT_VERSION */
00319       connect(fCanvasWidget,SIGNAL(destroyed()),this,SLOT(Disconnect()));
00320    }
00321 }
00322 //______________________________________________________________________________
00323 void TQtClientWidget::UnSetKeyMask(Int_t keycode, UInt_t modifier)
00324 {
00325   // Unset the key button mask
00326 
00327   SetKeyMask(keycode, modifier, kRemove);
00328 }
00329 //_____slot _________________________________________________________________________
00330 void TQtClientWidget::Accelerate()
00331 {
00332   // Qt slot to respond to the "Keyboard accelerator signal"
00333   QShortcut *cut = (QShortcut *)sender();
00334   QKeySequence key = cut->key ();
00335   qDebug() << "TQtClientWidget::Accelerate()" << key;
00336   int l = key.count();
00337   int keycode = key[l-1];
00338   Qt::KeyboardModifiers state = Qt::NoModifier;
00339   
00340   if (keycode & Qt::SHIFT) state |=  Qt::ShiftModifier;
00341   if (keycode & Qt::META)  state |=  Qt::MetaModifier;
00342   if (keycode & Qt::CTRL)  state |=  Qt::ControlModifier;
00343   if (keycode & Qt::ALT)   state |=  Qt::AltModifier;
00344         
00345   // Create ROOT event
00346   QKeyEvent ac(QEvent::KeyPress,keycode & 0x01FFFFFF,state);
00347   // call Event filter directly 
00348   TQtClientFilter *f = gQt->QClientFilter();
00349   if (f) f->AddKeyEvent(ac,this); 
00350   QKeyEvent acRelease(QEvent::KeyRelease,keycode & 0x01FFFFFF,state);
00351   if (f) f->AddKeyEvent(acRelease,this); 
00352 }
00353 //______________________________________________________________________________
00354 void TQtClientWidget::Disconnect()
00355 {
00356   // Disconnect the Canvas and ROOT gui widget before destroy.
00357 
00358    SetCanvasWidget(0);           }
00359 
00360 //______________________________________________________________________________
00361 void TQtClientWidget::paintEvent( QPaintEvent *e )
00362 {
00363    QFrame::paintEvent(e);
00364 #if ROOT_VERSION_CODE >= ROOT_VERSION(9,15,9)
00365    if (gClient) {
00366       // Find my host ROOT TGWindow
00367       if (!fMyRootWindow)
00368          fMyRootWindow = gClient->GetWindowById(TGQt::rootwid(this));
00369       if (fMyRootWindow) {
00370          gClient->NeedRedraw(fMyRootWindow,kTRUE);
00371       }
00372    }
00373 #endif   
00374 }

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