#include <qapplication.h>
#if QT_VERSION >= 0x40000
# include <QFocusEvent>
# include <QPaintEvent>
# include <QKeyEvent>
# include <QShowEvent>
# include <QResizeEvent>
# include <QMouseEvent>
# include <QCustomEvent>
# include <QImage>
# include <QDebug>
#endif /* QT_VERSION */
#include "TQtWidget.h"
#include "TQtTimer.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 "TWinNTSystem.h"
#include "Win32Constants.h"
#endif
TQtWidgetBuffer::TQtWidgetBuffer(const QWidget *w, bool clear)
: fWidget(w),fBuffer(0), fIsImage(clear)
{
if (fIsImage) {
fBuffer = new QImage(fWidget?fWidget->size():QSize(0,0),QImage::Format_ARGB32_Premultiplied);
} else {
fBuffer = new QPixmap(fWidget?fWidget->size():QSize(0,0));
}
}
TQtWidgetBuffer::TQtWidgetBuffer(const TQtWidgetBuffer &b)
: fWidget(b.fWidget),fBuffer(0), fIsImage(b.fIsImage)
{
if (fWidget && (fWidget->size() != QSize(0,0))) {
if (fIsImage) {
QImage resized =((QImage*)b.fBuffer)->scaled (fWidget->size());
fBuffer = new QImage(resized);
} else {
QPixmap resized =((QPixmap*) b.fBuffer)->scaled (fWidget->size());
fBuffer = new QPixmap(resized);
}
}
}
TQtWidgetBuffer:: ~TQtWidgetBuffer()
{
delete fBuffer;
fBuffer = 0;
}
void TQtWidgetBuffer::Clear()
{
if (fBuffer && !fIsImage ) {
#ifdef R__WIN32
((QPixmap*)fBuffer)->fill(Qt::transparent);
#else
QPainter p(fBuffer);
p.fillRect(QRect(0,0,fBuffer->width(), fBuffer->height())
,Qt::transparent);
#endif
}
}
ClassImp(TQtWidget)
TQtWidget::TQtWidget(QWidget* mother, const char* name, Qt::WFlags f,bool embedded) :
QWidget(mother,f)
,fBits(0),fNeedStretch(false),fCanvas(0),fPixmapID(0),fPixmapScreen(0)
,fPaint(TRUE),fSizeChanged(FALSE),fDoubleBufferOn(FALSE),fEmbedded(embedded)
,fWrapper(0),fSaveFormat("PNG"),fInsidePaintEvent(false),fOldMousePos(-1,-1)
,fIgnoreLeaveEnter(0),fRefreshTimer(0)
{
if (name && name[0]) setObjectName(name);
Init() ;
}
TQtWidget::TQtWidget(QWidget* mother, Qt::WFlags f,bool embedded) :
QWidget(mother,f)
,fBits(0),fNeedStretch(false),fCanvas(0),fPixmapID(0)
,fPixmapScreen(0),fPaint(TRUE),fSizeChanged(FALSE)
,fDoubleBufferOn(FALSE),fEmbedded(embedded),fWrapper(0),fSaveFormat("PNG")
,fInsidePaintEvent(false),fOldMousePos(-1,-1),fIgnoreLeaveEnter(0),fRefreshTimer(0)
{ setObjectName("tqtwidget"); Init() ;}
void TQtWidget::Init()
{
setFocusPolicy(Qt::WheelFocus);
setAttribute(Qt::WA_NoSystemBackground);
setAutoFillBackground(false);
QPalette p = palette();
p.setBrush(QPalette::Window, Qt::transparent);
setPalette(p);
if (fEmbedded) {
if (!gApplication) InitRint();
int minw = 10;
int minh = 10;
setMinimumSize(minw,minh);
Bool_t batch = gROOT->IsBatch();
if (!batch) gROOT->SetBatch(kTRUE);
TGQt::RegisterWid(this);
fCanvas = new TCanvas(objectName().toStdString().c_str(),minw,minh, TGQt::RegisterWid(this));
gROOT->SetBatch(batch);
Refresh();
}
fSizeHint = QWidget::sizeHint();
setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding));
#ifdef R__QTWIN32
static HICON rootIcon = 0;
if (!rootIcon) {
HICON hIcon = ::LoadIcon(::GetModuleHandle(NULL), MAKEINTRESOURCE(101));
if (!hIcon) hIcon = LoadIcon(NULL, IDI_APPLICATION);
rootIcon = hIcon;
SetClassLong(winId(),
GCL_HICON,
LONG(rootIcon)
);
}
#endif
}
TQtWidget::~TQtWidget()
{
TCanvas *c = 0;
gVirtualX->SelectWindow(-1);
TGQt::UnRegisterWid(this);
if (fEmbedded) {
c = fCanvas;
ResetCanvas();
delete c;
} else {
ResetCanvas();
}
delete fPixmapID; fPixmapID = 0;
delete fPixmapScreen; fPixmapScreen = 0;
}
void TQtWidget::AdjustBufferSize()
{
TQtWidgetBuffer &buf = SetBuffer();
QSize s(buf.Width(),buf.Height());
if ( s != size() ) {
#if 0
qDebug() << "TQtWidget::AdjustBufferSize(): "
<< this
<< s << size();
#endif
if (fPixmapID) {
TQtWidgetBuffer *bf = new TQtWidgetBuffer(*fPixmapID);
delete fPixmapID; fPixmapID = bf;
}
if (fPixmapScreen) {
TQtWidgetBuffer *bf = new TQtWidgetBuffer(*fPixmapScreen);
delete fPixmapScreen; fPixmapScreen = bf;
}
}
}
TCanvas *TQtWidget::Canvas()
{
return GetCanvas();
}
TCanvas *TQtWidget::Canvas(TQtWidget *widget)
{
return widget ? widget->Canvas() : 0 ;
}
TQtWidget *TQtWidget::Canvas(const TCanvas *canvas)
{
return canvas ? Canvas(canvas->GetCanvasID()) : 0;
}
TQtWidget *TQtWidget::Canvas(Int_t id)
{
return dynamic_cast<TQtWidget *>(TGQt::iwid(id));
}
TApplication *TQtWidget::InitRint( Bool_t , const char *appClassName, int *argc, char **argv,
void *options, int numOptions, Bool_t noLogo)
{
static int localArgc =0;
static char **localArgv =0;
if (!gApplication) {
QStringList args = QCoreApplication::arguments ();
localArgc = argc ? *argc : args.size();
TString guiBackend(gEnv->GetValue("Gui.Backend", "native"));
guiBackend.ToLower();
if (!guiBackend.BeginsWith("qt",TString::kIgnoreCase)) {
gEnv->SetValue("Gui.Backend", "qt");
}
TString guiFactory(gEnv->GetValue("Gui.Factory", "native"));
guiFactory.ToLower();
#if ROOT_VERSION_CODE >= ROOT_VERSION(5,16,0)
TApplication::NeedGraphicsLibs() ;
#endif
if (!guiFactory.BeginsWith("qt",TString::kIgnoreCase )){
char *extLib = gSystem->DynamicPathName("libQtRootGui",kTRUE);
if (extLib) {
gEnv->SetValue("Gui.Factory", "qtgui");
} else {
gEnv->SetValue("Gui.Factory", "qt");
}
delete [] extLib;
}
if (!argc && !argv ) {
localArgv = new char*[args.size()];
for (int i = 0; i < args.size(); ++i) {
QString nextarg = args.at(i);
Int_t nchi = nextarg.length()+1;
localArgv[i]= new char[nchi];
memcpy(localArgv[i], nextarg.toAscii().constData(),nchi-1);
localArgv[i][nchi-1]=0;
}
} else {
localArgv = argv;
}
TRint *rint = new TRint(appClassName, &localArgc, localArgv, options,numOptions,noLogo);
Int_t prompt= gEnv->GetValue("Gui.Prompt", (Int_t)0);
if (prompt) {
Getlinem(kInit, rint->GetPrompt());
} else {
TSeqCollection* col = gSystem->GetListOfFileHandlers();
TIter next(col);
TFileHandler* o=0;
while ( ( o=(TFileHandler*) next() ) ) {
if ( o->GetFd()== 0 ) {
o->Remove();
break;
}
}
gSystem->RemoveSignalHandler(rint->GetSignalHandler());
}
TQtTimer::Create()->start(0);
}
return gApplication;
}
void TQtWidget::Erase()
{
SetBuffer();
if (fPixmapScreen) fPixmapScreen->Clear();
if (fPixmapID) fPixmapID->Clear();
}
void TQtWidget::cd()
{
cd(0);
}
void TQtWidget::cd(int subpadnumber)
{
TCanvas *c = fCanvas;
if (c) {
c->cd(subpadnumber);
}
}
void TQtWidget::Disconnect()
{
fCanvas = 0;
}
void TQtWidget::Refresh()
{
if (!fRefreshTimer) {
fRefreshTimer = new QTimer(this);
fRefreshTimer->setSingleShot(true);
fRefreshTimer->setInterval(0);
connect(fRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshCB()));
}
fRefreshTimer->start();
}
void TQtWidget::RefreshCB()
{
TCanvas *c = Canvas();
if (c) {
c->Modified();
c->Resize();
c->Update();
}
if (!fInsidePaintEvent) { update(); }
else {
qDebug() << " TQtWidget::Refresh() update inside of paintEvent !!!" << this;
}
}
void TQtWidget::SetCanvas(TCanvas *c)
{
fCanvas = c;
setObjectName(fCanvas->GetName());
}
void
TQtWidget::customEvent(QEvent *e)
{
switch (e->type() - QEvent::User) {
case kEXITSIZEMOVE:
{
fPaint = TRUE;
exitSizeEvent();
break;
}
case kENTERSIZEMOVE:
{
fSizeChanged=FALSE;
fPaint = FALSE;
break;
}
case kFORCESIZE:
default:
{
fPaint = TRUE;
fSizeChanged = TRUE;
exitSizeEvent();
break;
}
};
}
void TQtWidget::contextMenuEvent(QContextMenuEvent *e)
{
TCanvas *c = Canvas();
if (e && c && (e->reason() != QContextMenuEvent::Mouse) ) {
e->accept();
c->HandleInput(kButton3Down, e->x(), e->y());
}
}
void TQtWidget::focusInEvent ( QFocusEvent *e )
{
if (!fWrapper && e->gotFocus()) {
setMouseTracking(TRUE);
}
}
void TQtWidget::focusOutEvent ( QFocusEvent *e )
{
if (!fWrapper && e->lostFocus()) {
setMouseTracking(FALSE);
}
}
void TQtWidget::mousePressEvent (QMouseEvent *e)
{
EEventType rootButton = kNoEvent;
Qt::ContextMenuPolicy currentPolicy = contextMenuPolicy();
fOldMousePos = e->pos();
TCanvas *c = Canvas();
if (c && !fWrapper ){
switch (e->button ())
{
case Qt::LeftButton: rootButton = kButton1Down; break;
case Qt::RightButton: {
if ( currentPolicy == Qt::DefaultContextMenu) {
e->accept();
QContextMenuEvent evt(QContextMenuEvent::Other, e->pos() );
QApplication::sendEvent(this, &evt);
} else {
rootButton = kButton3Down;
}
break;
}
case Qt::MidButton: rootButton = kButton2Down; break;
default: break;
};
if (rootButton != kNoEvent) {
e->accept();
if (rootButton == kButton3Down) {
bool lastvalue = c->TestBit(kNoContextMenu);
c->SetBit(kNoContextMenu);
c->HandleInput(rootButton, e->x(), e->y());
c->SetBit(kNoContextMenu, lastvalue);
} else {
c->HandleInput(rootButton, e->x(), e->y());
}
EmitSignal(kMousePressEvent);
return;
}
} else {
e->ignore();
}
QWidget::mousePressEvent(e);
}
void TQtWidget::mouseMoveEvent (QMouseEvent * e)
{
EEventType rootButton = kMouseMotion;
if ( fOldMousePos != e->pos() && fIgnoreLeaveEnter < 2 ) {
fOldMousePos = e->pos();
TCanvas *c = Canvas();
if (c && !fWrapper){
if (e->buttons() & Qt::LeftButton) { rootButton = kButton1Motion; }
e->accept();
c->HandleInput(rootButton, e->x(), e->y());
EmitSignal(kMouseMoveEvent);
return;
} else {
e->ignore();
}
}
QWidget::mouseMoveEvent(e);
}
void TQtWidget::mouseReleaseEvent(QMouseEvent * e)
{
EEventType rootButton = kNoEvent;
fOldMousePos = QPoint(-1,-1);
TCanvas *c = Canvas();
if (c && !fWrapper){
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) {
e->accept();
c->HandleInput(rootButton, e->x(), e->y());
gPad->Modified();
EmitSignal(kMouseReleaseEvent);
return;
}
} else {
e->ignore();
}
QWidget::mouseReleaseEvent(e);
}
void TQtWidget::mouseDoubleClickEvent(QMouseEvent * e)
{
EEventType rootButton = kNoEvent;
TCanvas *c = Canvas();
if (c && !fWrapper){
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) {
e->accept();
c->HandleInput(rootButton, e->x(), e->y());
EmitSignal(kMouseDoubleClickEvent);return;
}
} else {
e->ignore();
}
QWidget::mouseDoubleClickEvent(e);
}
void TQtWidget::keyPressEvent(QKeyEvent * e)
{
TCanvas *c = Canvas();
if (c && !fWrapper){
c->HandleInput(kKeyPress, e->text().toStdString().c_str()[0], e->key());
EmitSignal(kKeyPressEvent);
} else {
e->ignore();
}
QWidget::keyPressEvent(e);
}
void TQtWidget::keyReleaseEvent(QKeyEvent * e)
{
QWidget::keyReleaseEvent(e);
}
void TQtWidget::enterEvent(QEvent *e)
{
TCanvas *c = Canvas();
if (c && !fIgnoreLeaveEnter && !fWrapper){
c->HandleInput(kMouseEnter, 0, 0);
EmitSignal(kEnterEvent);
}
QWidget::enterEvent(e);
}
void TQtWidget::leaveEvent (QEvent *e)
{
TCanvas *c = Canvas();
if (c && !fIgnoreLeaveEnter && !fWrapper){
c->HandleInput(kMouseLeave, 0, 0);
EmitSignal(kLeaveEvent);
}
QWidget::leaveEvent(e);
}
void TQtWidget::resizeEvent(QResizeEvent *e)
{
if (!e) return;
if (topLevelWidget()->isMinimized()) { fSizeChanged=FALSE; }
else if (topLevelWidget()->isMaximized ()){
fSizeChanged=TRUE;
exitSizeEvent();
fSizeChanged=TRUE;
} else {
#ifdef R__QTWIN32
if (!fPaint) {
fSizeChanged=TRUE;
fNeedStretch=true;
} else {
#else
{
fSizeChanged=TRUE;
#if 0
if (Qt::LeftButton == QApplication::mouseButtons())
{
fNeedStretch=true;
fPaint = false;
} else
#endif
{
fPaint = kTRUE;
exitSizeEvent();
}
#endif
} }
}
void TQtWidget::SetSaveFormat(const char *format)
{
fSaveFormat = TGQt::QtFileFormat(format);
}
bool TQtWidget::Save(const char *fileName) const
{
return Save(QString(fileName));
}
bool TQtWidget::Save(const QString &fileName) const
{
QString fileNameExtension = QFileInfo(fileName).suffix().toUpper();
QString saveFormat;
if (fileNameExtension.isEmpty() ) {
saveFormat = fSaveFormat;
} else {
saveFormat = TGQt::QtFileFormat(fileNameExtension);
}
return Save(fileName,saveFormat.toStdString().c_str());
}
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
{
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(fileName.toStdString().c_str(),saveType.toStdString().c_str());
Ok = true;
} else if (GetOffScreenBuffer()) {
int dot = fileName.lastIndexOf('.');
int plus = 0;
if (dot > -1) {
plus = fileName.indexOf('+',dot+1);
}
QString fln = (plus > -1) ? TGQt::GetNewFileName(fileName.left(plus)) : fileName;
if (fCanvasDecorator.isNull()) {
Ok = GetOffScreenBuffer()->save(fln,saveType.toStdString().c_str(),quality);
} else {
}
}
emit ((TQtWidget *)this)->Saved(Ok);
return Ok;
}
void TQtWidget::SetDoubleBuffer(bool on)
{
if (fDoubleBufferOn != on ) {
fDoubleBufferOn = on;
if (on) SetBuffer();
}
}
void TQtWidget::stretchWidget(QResizeEvent * )
{
if (!paintingActive() && fPixmapID) {
QPainter pnt(this);
pnt.drawPixmap(rect(),*GetOffScreenBuffer());
}
fNeedStretch = false;
}
void TQtWidget::exitSizeEvent ()
{
if (!fSizeChanged ) return;
{
AdjustBufferSize();
}
TCanvas *c = Canvas();
if (c) c->Resize();
Refresh();
}
bool TQtWidget::paintFlag(bool mode)
{
bool flag = fPaint;
fPaint = mode;
return flag;
}
void TQtWidget::showEvent ( QShowEvent *)
{
TQtWidgetBuffer &buf = SetBuffer();
QSize s(buf.Width(),buf.Height());
if (s != size() )
{
fSizeChanged = kTRUE;
exitSizeEvent();
}
}
void TQtWidget::paintEvent (QPaintEvent *e)
{
fInsidePaintEvent = true;
if (fNeedStretch) {
stretchWidget((QResizeEvent *)0);
} else {
#ifdef R__QTWIN32
TQtWidgetBuffer &buf = SetBuffer();
QSize s(buf.Width(),buf.Height());
if ( fEmbedded && (s != size()) )
{
fSizeChanged = kTRUE;
exitSizeEvent();
fInsidePaintEvent = false;
return;
}
#endif
QRegion region = e->region();
if ( ( fPaint && !region.isEmpty() ) )
{
QPainter screen(this);
screen.setClipRegion(region);
if (fPixmapID) screen.drawPixmap(0,0,*GetOffScreenBuffer());
if (!fCanvasDecorator.isNull()) fCanvasDecorator->paintEvent(screen,e);
}
}
fInsidePaintEvent = false;
}
void TQtWidget::SetSizeHint (const QSize &sz) {
fSizeHint = sz;
}
QSize TQtWidget::sizeHint () const{
return QWidget::sizeHint();
}
QSize TQtWidget::minimumSizeHint () const{
return QWidget::minimumSizeHint ();
}
QSizePolicy TQtWidget::sizePolicy () const{
return QWidget::sizePolicy ();
}
void TQtWidget::EmitTestedSignal()
{
TCanvas *c = GetCanvas();
TObject *selected = GetSelected();
UInt_t evt = GetEvent();
emit RootEventProcessed(selected, evt, c);
}
void TQtWidget::SetBit(UInt_t f, Bool_t set)
{
if (set)
SetBit(f);
else
ResetBit(f);
}
TQtWidgetBuffer &TQtWidget::SetBuffer() {
TQtWidgetBuffer *buf = 0;
if (IsDoubleBuffered() ) {
if (!fPixmapID) fPixmapID = new TQtWidgetBuffer(this);
buf = fPixmapID;
} else {
if (!fPixmapScreen) fPixmapScreen = new TQtWidgetBuffer(this,true);
buf = fPixmapScreen;
}
return *buf;
}
QPixmap *TQtWidget::GetOffScreenBuffer() const {
return fPixmapID ? (QPixmap *)fPixmapID->Buffer():0;
}