// @(#)root/qt:$Name: $:$Id: TQtWidget.cxx,v 1.18 2005/09/20 06:38:10 brun Exp $
// Author: Valeri Fine 23/01/2003
/*************************************************************************
* Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
* Copyright (C) 2003 by Valeri Fine. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
// Definition of TQtWidget class
// "double-buffere widget
#include <qapplication.h>
#include "TQtWidget.h"
#include "TQtTimer.h"
#include "TQtLock.h"
#include "TROOT.h"
#include "TEnv.h"
#include "TRint.h"
#include "TSystem.h"
#include "Getline.h"
#include "TGQt.h"
#include "TCanvas.h"
#include "Buttons.h"
#include <qevent.h>
#include <qpainter.h>
#include <qpixmap.h>
#include <qfileinfo.h>
#ifdef R__QTWIN32
// #include "Windows4Root.h"
#include "TWinNTSystem.h"
#include "Win32Constants.h"
#endif
ClassImp(TQtWidget)
////////////////////////////////////////////////////////////////////////////////
//
// TQtWidget is a QWidget with the QPixmap double buffer
// It is designed to back the ROOT TCanvasImp class interface and it can be used
// as a regular Qt Widget to create Qt-based GUI with the embedded TCanvas objects
//
// This widget can be used as a Qt "custom widget"
// to build a custom GUI interfaces with Qt Designer
//
// class emits Qt signals and has a Qt public slots
//
// Public slots: (Qt)
//
// virtual void cd(); // make the associated TCanvas the current one (shortcut to TCanvas::cd())
// virtual void cd(int subpadnumber); // as above - shortcut to Canvas::cd(int subpadnumber)
// void Disconnect(); // disconnect the Qidget from the ROOT TCanvas (used in the class dtor)
// void Refresh(); // forece the aasociated TCanvas::Update to be called
// virtual bool Save(const QString &fileName) const; // Save the widget image with some ppixmap file
// virtual bool Save(const char *fileName) const;
// virtual bool Save(const QString &fileName,const char *format,int quality=60) const;
// virtual bool Save(const char *fileName,const char *format,int quality=60) const;
//
// 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
//
//
// For example to create the custom responce to the mouse crossing TCanvas
// connect the RootEventProsecced signal witrh your qt slot:
//
// connect(tQtWidget,SIGNAL(RootEventProcessed(TObject *, unsigned int, TCanvas *))
// ,this,SLOT(CanvasEvent(TObject *, unsigned int, TCanvas *)));
// . . .
//
//void qtrootexample1::CanvasEvent(TObject *obj, unsigned int event, TCanvas *)
//{
// TQtWidget *tipped = (TQtWidget *)sender();
// const char *objectInfo =
// obj->GetObjectInfo(tipped->GetEventX(),tipped->GetEventY());
// QString tipText ="You have ";
// if (tipped == tQtWidget1)
// tipText +="clicked";
// else
// tipText +="passed";
// tipText += " the object <";
// tipText += obj->GetName();
// tipText += "> of class ";
// tipText += obj->ClassName();
// tipText += " : ";
// tipText += objectInfo;
//
// QToolTip::remove(tipped);
// QToolTip::add(tipped,tipText);
// }
//
////////////////////////////////////////////////////////////////////////////////
//_____________________________________________________________________________
TCanvas *TQtWidget::Canvas()
{
#ifdef R__QTGUITHREAD
if (qApp->tryLock() ) {
TCanvas *c = 0;
if (fCanvas)
c = gROOT->IsLineProcessing() ? 0 : GetCanvas();
qApp->unlock();
return c;
}
return 0;
#else
return GetCanvas();
#endif
};
//_____________________________________________________________________________
TQtWidget::TQtWidget(QWidget* parent, const char* name, WFlags f,bool embedded):QWidget(parent,name,f)
,fBits(0),fCanvas(0),fPixmapID(this),fPaint(TRUE),fSizeChanged(FALSE)
,fDoubleBufferOn(FALSE),fEmbedded(embedded),fWrapper(0),fSaveFormat("PNG")
{
setFocusPolicy(QWidget::WheelFocus);
setWFlags(getWFlags () | Qt::WRepaintNoErase | Qt:: WResizeNoErase );
setBackgroundMode(Qt::NoBackground);
if (fEmbedded) {
if (!gApplication) InitRint();
Bool_t batch = gROOT->IsBatch();
if (!batch) gROOT->SetBatch(kTRUE); // to avoid the recursion within TCanvas ctor
TGQt::RegisterWid(this);
fCanvas = new TCanvas(name, 4, 4, TGQt::RegisterWid(this));
// fprintf(stderr,"TQtWidget::TQtWidget fEditable %d\n", fCanvas->IsEditable());
gROOT->SetBatch(batch);
}
fSizeHint = QWidget::sizeHint();
setSizePolicy (QSizePolicy::Expanding ,QSizePolicy::Expanding );
#ifdef R__QTWIN32
// Set the application icon for all ROOT widgets
static HICON rootIcon = 0;
if (!rootIcon) {
HICON hIcon = ((TWinNTSystem *)gSystem)->GetSmallIcon(kMainROOTIcon);
if (!hIcon) hIcon = LoadIcon(NULL, IDI_APPLICATION);
rootIcon = hIcon;
SetClassLong(winId(), // handle to window
GCL_HICON, // index of value to change
LONG(rootIcon) // new value
);
}
#endif
}
//______________________________________________________________________________
TQtWidget::~TQtWidget()
{
TCanvas *c = 0;
// to block the double deleting from
TGQt::UnRegisterWid(this);
qApp->lock();
if (fEmbedded) {
// one has to set CanvasID = 0 to disconnect things properly.
c = fCanvas;
fCanvas = 0;
qApp->unlock();
delete c;
} else {
fCanvas = 0;
qApp->unlock();
}
}
//_____________________________________________________________________________
TApplication *TQtWidget::InitRint( Bool_t /*prompt*/, const char *appClassName, int *argc, char **argv,
void *options, int numOptions, Bool_t /*noLogo*/)
{
//
// Instantiate ROOT from within Qt application if needed
// Return the TRint pointer
// Most parametrs are passed to TRint class ctor
//
// Bool_t prompt = kTRUE; Instantiate ROOT with ROOT command prompt
// kFALSE; No ROOT prompt. The default for Qt GUI applications
//
// The prompt option can be defined via ROOT parameter file ".rootrc"
// .rootrc:
// . . .
// Gui.Prompt yes
//
static int localArgc =0;
if (!gApplication) {
localArgc = argc ? *argc : qApp->argc();
TRint *rint = new TRint(appClassName, &localArgc, argv ? argv : qApp->argv(),options,numOptions,kFALSE);
// To mimic what TRint::Run(kTRUE) does.
const char *prompt= gEnv->GetValue("Gui.Prompt", (char*)0);
if (prompt)
Getlinem(kInit, rint->GetPrompt());
TQtTimer::Create()->start(0,TRUE);
}
return gApplication;
}
//_____________________________________________________________________________
void TQtWidget::adjustSize()
{
// Adjusts the size of the widget to fit the contents.
// Adjust the size of the double buffer to the
// current Widget size
QWidget::adjustSize ();
AdjustBufferSize();
update();
}
//_____________________________________________________________________________
void TQtWidget::erase ()
{
// Erases the specified area (x, y, w, h) in the widget
// without generating a paint event.
QWidget::erase();
fPixmapID.fill();
}
//_____________________________________________________________________________
void TQtWidget::cd()
{
// [slot] to make this embedded canvas the current one
cd(0);
}
//______________________________________________________________________________
void TQtWidget::cd(int subpadnumber)
{
// [slot] to make this embedded canvas / pad the current one
TQtLock lock;
TCanvas *c = fCanvas;
if (c) c->cd(subpadnumber);
}
//______________________________________________________________________________
void TQtWidget::Disconnect()
{
// [slot] Disconnect the Qt widget from TCanvas object before deleting
// to avoid the dead lock
// one has to set CanvasID = 0 to disconnect things properly.
TQtLock lock;
fCanvas = 0;
}
//_____________________________________________________________________________
void TQtWidget::Refresh()
{
// [slot] to allow Qt signal refreshing TOOT TCanvas if needed
TCanvas *c = Canvas();
if (!fPixmapID.paintingActive()) AdjustBufferSize();
if (c) {
c->Resize();
c->Update();
}
}
//_____________________________________________________________________________
void TQtWidget::resize (int w, int h)
{
// resize the widget and its double buffer
// fprintf(stderr,"TQtWidget::resize (int w=%d, int h=%d)\n",w,h);
QWidget::resize(w,h);
AdjustBufferSize();
// fPixmapID.fill();
}
//_____________________________________________________________________________
void TQtWidget::customEvent(QCustomEvent *e)
{
// The custom responce to the special WIN32 events
// These events are not present with X11 systems
switch (e->type() - QEvent::User) {
case kEXITSIZEMOVE:
{ // WM_EXITSIZEMOVE
fPaint = TRUE;
setUpdatesEnabled( TRUE );
exitSizeEvent();
break;
}
case kENTERSIZEMOVE:
{
// WM_ENTERSIZEMOVE
fSizeChanged=FALSE;
fPaint = FALSE;
setUpdatesEnabled( FALSE );
}
case kFORCESIZE:
default:
{
// Force resize
fPaint = TRUE;
fSizeChanged = TRUE;
setUpdatesEnabled( TRUE );
exitSizeEvent();
break;
}
};
}
//_____________________________________________________________________________
void TQtWidget::focusInEvent ( QFocusEvent *e )
{
// The custom responce to the Qt QFocusEvent "in"
// this imposes an extra protection to avoid TObject interaction with
// mouse event accidently
if (!fWrapper && e->gotFocus()) {
setMouseTracking(TRUE);
}
if ( autoMask() ) updateMask();
}
//_____________________________________________________________________________
void TQtWidget::focusOutEvent ( QFocusEvent *e )
{
// The custom responce to the Qt QFocusEvent "out"
// this imposes an extra protection to avoid TObject interaction with
// mouse event accidently
if (!fWrapper && e->lostFocus()) {
setMouseTracking(FALSE);
}
if ( autoMask() ) updateMask();
}
//_____________________________________________________________________________
void TQtWidget::mousePressEvent (QMouseEvent *e)
{
// Map the Qt mouse press button event to the ROOT TCanvas events
// Mouse events occur when a mouse button is pressed or released inside
// a widget or when the mouse cursor is moved.
// kButton1Down = 1, kButton2Down = 2, kButton3Down = 3,
EEventType rootButton = kNoEvent;
TCanvas *c = Canvas();
if (c){
switch (e->button ())
{
case Qt::LeftButton: rootButton = kButton1Down; break;
case Qt::RightButton: rootButton = kButton3Down; break;
case Qt::MidButton: rootButton = kButton2Down; break;
default: break;
};
if (rootButton != kNoEvent) {
c->HandleInput(rootButton, e->x(), e->y());
e->accept(); EmitSignal(kMousePressEvent); return;
}
}
QWidget::mousePressEvent(e);
}
//_____________________________________________________________________________
void TQtWidget::mouseMoveEvent (QMouseEvent * e)
{
// Map the Qt mouse move pointer event to the ROOT TCanvas events
// kMouseMotion = 51,
// kButton1Motion = 21, kButton2Motion = 22, kButton3Motion = 23, kKeyPress = 24
EEventType rootButton = kMouseMotion;
TCanvas *c = Canvas();
if (c){
if (e->state() & LeftButton) { rootButton = kButton1Motion; }
c->HandleInput(rootButton, e->x(), e->y());
e->accept(); EmitSignal(kMouseMoveEvent); return;
}
QWidget::mouseMoveEvent(e);
}
//_____________________________________________________________________________
void TQtWidget::mouseReleaseEvent(QMouseEvent * e)
{
// Map the Qt mouse button release event to the ROOT TCanvas events
// kButton1Up = 11, kButton2Up = 12, kButton3Up = 13
EEventType rootButton = kNoEvent;
TCanvas *c = Canvas();
if (c){
switch (e->button())
{
case Qt::LeftButton: rootButton = kButton1Up; break;
case Qt::RightButton: rootButton = kButton3Up; break;
case Qt::MidButton: rootButton = kButton2Up; break;
default: break;
};
if (rootButton != kNoEvent) {
c->HandleInput(rootButton, e->x(), e->y());
gPad->Modified();
e->accept(); EmitSignal(kMouseReleaseEvent);return;
}
}
QWidget::mouseReleaseEvent(e);
}
//_____________________________________________________________________________
void TQtWidget::mouseDoubleClickEvent(QMouseEvent * e)
{
// Map the Qt mouse double click button event to the ROOT TCanvas events
// kButton1Double = 61, kButton2Double = 62, kButton3Double = 63
EEventType rootButton = kNoEvent;
TCanvas *c = Canvas();
if (c){
switch (e->button())
{
case Qt::LeftButton: rootButton = kButton1Double; break;
case Qt::RightButton: rootButton = kButton3Double; break;
case Qt::MidButton: rootButton = kButton2Double; break;
default: break;
};
if (rootButton != kNoEvent) {
c->HandleInput(rootButton, e->x(), e->y());
e->accept(); EmitSignal(kMouseDoubleClickEvent);return;
}
}
QWidget::mouseDoubleClickEvent(e);
}
//_____________________________________________________________________________
void TQtWidget::keyPressEvent(QKeyEvent * e)
{
// Map the Qt key press event to the ROOT TCanvas events
// kKeyDown = 4
TCanvas *c = Canvas();
if (c){
c->HandleInput(kKeyPress, e->ascii(), e->key());
EmitSignal(kKeyPressEvent);
}
QWidget::keyPressEvent(e);
}
//_____________________________________________________________________________
void TQtWidget::keyReleaseEvent(QKeyEvent * e)
{
// Map the Qt key release event to the ROOT TCanvas events
// kKeyUp = 14
QWidget::keyReleaseEvent(e);
}
//_____________________________________________________________________________
void TQtWidget::enterEvent(QEvent *e)
{
// Map the Qt mouse enters widget event to the ROOT TCanvas events
// kMouseEnter = 52
TCanvas *c = Canvas();
if (c){
c->HandleInput(kMouseEnter, 0, 0);
EmitSignal(kEnterEvent);
}
QWidget::enterEvent(e);
}
//_____________________________________________________________________________
void TQtWidget::leaveEvent (QEvent *e)
{
// Map the Qt mouse leaves widget event to the ROOT TCanvas events
// kMouseLeave = 53
TCanvas *c = Canvas();
if (c){
c->HandleInput(kMouseLeave, 0, 0);
EmitSignal(kLeaveEvent);
}
QWidget::leaveEvent(e);
}
//_____________________________________________________________________________
void TQtWidget::resizeEvent(QResizeEvent *e)
{
// The widget will be erased and receive a paint event immediately after
// processing the resize event.
// No drawing need be (or should be) done inside this handler.
if (!e) return;
if (topLevelWidget()->isMinimized()) { fSizeChanged=FALSE; }
else if (topLevelWidget()->isMaximized ()){
fSizeChanged=TRUE;
exitSizeEvent();
fSizeChanged=TRUE;
} else {
#ifdef R__QTWIN32
if (!fPaint) {
// real resize event
fSizeChanged=TRUE;
stretchWidget(e);
}
#else
fSizeChanged=TRUE;
fPaint = kTRUE;
exitSizeEvent();
#endif
}
if ( autoMask() )
updateMask();
}
//____________________________________________________________________________
void TQtWidget::SetSaveFormat(const char *format)
{
// Set the default save format for the widget
fSaveFormat = TGQt::QtFileFormat(format);
}
//____________________________________________________________________________
bool TQtWidget::Save(const char *fileName) const
{
//
// TQtWidget::Save(const QString &fileName) is a public Qt slot.
// it saves the double buffer of this object using the default save
// format defined the file extension
// If the "fileName" has no extension the "default" format is to be used instead
// The deafult format is "PNG".
// It can be changed with the TQtWidget::SetSaveFormat method
//
return Save(QString(fileName));
}
//____________________________________________________________________________
bool TQtWidget::Save(const QString &fileName) const
{
//
// TQtWidget::Save(const QString &fileName) is a public Qt slot.
// it saves the double buffer of this object using the default save
// format defined the file extension
// If the "fileName" has no extension the "default" format is to be used instead
// The deafult format is "PNG".
// It can be changed with the TQtWidget::SetSaveFormat method
//
QString fileNameExtension = QFileInfo(fileName).extension(FALSE).upper();
QString saveFormat;
if (fileNameExtension.isEmpty() ) {
saveFormat = fSaveFormat; // this is default
} else {
saveFormat = TGQt::QtFileFormat(fileNameExtension);
}
return Save(fileName,saveFormat);
}
//____________________________________________________________________________
bool TQtWidget::Save(const char *fileName,const char *format,int quality)const
{
return Save(QString(fileName),format,quality);
}
//____________________________________________________________________________
bool TQtWidget::Save(const QString &fileName,const char *format,int quality)const
{
// TQtWidget::save is a public Qt slot.
// it saves the double buffer of this object using QPixmap facility
bool Ok = false;
bool rootFormatFound=kTRUE;
QString saveType = TGQt::RootFileFormat(format);
if (saveType.isEmpty() ) {
rootFormatFound = false;
saveType = TGQt::QtFileFormat(format);
}
TCanvas *c = GetCanvas();
if (rootFormatFound && c) {
c->Print((const char *)fileName,(const char *)saveType);
Ok = true;
} else {
Ok = GetBuffer().save(fileName,saveType,quality);
}
emit ((TQtWidget *)this)->Saved(Ok);
return Ok;
}
//_____________________________________________________________________________
void TQtWidget::stretchWidget(QResizeEvent * /*s*/)
{
// Stretch the widget during sizing
if (!paintingActive()) {
#ifdef R__QTWIN32
QPainter painter( this );
if (!StretchBlt(
painter.handle(), // handle of destination device context
0, // x-coordinate of upper-left corner of dest. rect.
0, // y-coordinate of upper-left corner of dest. rect.
width(), // width of destination rectangle
height(), // height of destination rectangle
GetBuffer().handle(), // handle of source device context
0, // x-coordinate of upper-left corner of source rectangle
0, // y-coordinate of upper-left corner of source rectangle
GetBuffer().width(), // width of source rectangle
GetBuffer().height(), // height of source rectangle
SRCCOPY // raster operation code
)) {
qSystemWarning("StretchBlt failed!" );
printf("last error %d\n",GetLastError());
}
#else
QPainter pnt(this);
pnt.drawPixmap(rect(),GetBuffer());
#endif
}
}
//_____________________________________________________________________________
void TQtWidget::exitSizeEvent ()
{
// Responce to the "exit size event"
if (!fSizeChanged) return;
Refresh();
}
//____________________________________________________________________________
bool TQtWidget::paintFlag(bool mode)
{
// Set new fPaint flag
// Returns: the previous version of the flag
bool flag = fPaint;
fPaint = mode;
return flag;
}
//____________________________________________________________________________
void TQtWidget::showEvent ( QShowEvent *)
{
// Custom handler of the Qt show event
// Non-spontaneous show events are sent to widgets immediately before
// they are shown.
// The spontaneous show events of top-level widgets are delivered afterwards.
if ( fPixmapID.size() != size() )
{
fSizeChanged = kTRUE;
exitSizeEvent();
}
}
//____________________________________________________________________________
void TQtWidget::paintEvent (QPaintEvent *e)
{
// Custom handler of the Qt paint event
// A paint event is a request to repaint all or part of the widget.
// It can happen as a result of repaint() or update(), or because the widget
// was obscured and has now been uncovered, or for many other reasons.
#ifdef R__QTWIN32
if ( fEmbedded && fPixmapID.size() != size() )
{
fSizeChanged = kTRUE;
exitSizeEvent();
update();
return;
}
#endif
QRect rect = e->rect();
if ( fPaint && !rect.isEmpty() )
{
// fprintf(stderr,"TQtWidget::paintEvent: window = %p; buffer = %p\n",
// (QPaintDevice *)this, (QPaintDevice *)&GetBuffer());
bitBlt(this, rect.x(),rect.y(),&GetBuffer(),rect.x(), rect.y(), rect.width(), rect.height());
}
}
// Layout methods:
//____________________________________________________________________________
void TQtWidget::SetSizeHint (const QSize &size) {
// sets the preferred size of the widget.
fSizeHint = size;
}
//____________________________________________________________________________
QSize TQtWidget::sizeHint () const{
// returns the preferred size of the widget.
return QWidget::sizeHint();
}
//____________________________________________________________________________
QSize TQtWidget::minimumSizeHint () const{
// returns the smallest size the widget can have.
return QWidget::minimumSizeHint ();
}
//____________________________________________________________________________
QSizePolicy TQtWidget::sizePolicy () const{
// returns a QSizePolicy; a value describing the space requirements
return QWidget::sizePolicy ();
}
//____________________________________________________________________________
void TQtWidget::EmitTestedSignal()
{
TCanvas *c = GetCanvas();
TObject *selected = GetSelected();
UInt_t event = GetEvent();
emit RootEventProcessed(selected, event, c);
}
//____________________________________________________________________________
void TQtWidget::SetBit(UInt_t f, Bool_t set)
{
// Set or unset the user status bits as specified in f.
if (set)
SetBit(f);
else
ResetBit(f);
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.