/********************************************************************** ** Copyright (C) 2000 Trolltech AS. All rights reserved. ** ** This file is part of Qtopia Environment. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ** See http://www.trolltech.com/gpl/ for GPL licensing information. ** ** Contact info@trolltech.com if any conditions of this licensing are ** not clear to you. ** **********************************************************************/ #define QTOPIA_INTERNAL_LANGLIST #include #include #include #include #include #include #include "qcopenvelope_qws.h" #include "qpedecoration_qws.h" #include #include #include #include "qpeapplication.h" #include "resource.h" #include "global.h" #include #include #include extern QRect qt_maxWindowRect; //#define MINIMIZE_HELP_HACK // use minimize button when not a dialog //#define WHATSTHIS_MODE #ifndef QT_NO_QWS_QPE_WM_STYLE #ifndef QT_NO_IMAGEIO_XPM /* XPM */ static const char * const qpe_close_xpm[] = { "16 16 3 1", " c None", ". c #FFFFFF", "+ c #000000", " ", " ", " ..... ", " ..+++++.. ", " .+++++++++. ", " .+..+++..+. ", " .++...+...++. ", " .+++.....+++. ", " .++++...++++. ", " .+++.....+++. ", " .++...+...++. ", " .+..+++..+. ", " .+++++++++. ", " ..+++++.. ", " ..... ", " "}; /* XPM */ static const char * const qpe_accept_xpm[] = { "16 16 3 1", " c None", ". c #FFFFFF", "+ c #000000", " ", " ", " ..... ", " ..+++++.. ", " .+++++++++. ", " .+++++++++. ", " .+++++++..++. ", " .++.+++...++. ", " .+...+...+++. ", " .+......++++. ", " .++....+++++. ", " .++..+++++. ", " .+++++++++. ", " ..+++++.. ", " ..... ", " "}; #endif // QT_NO_IMAGEIO_XPM class TLWidget : public QWidget { public: QWSManager *manager() { return topData()->qwsManager; } QTLWExtra *topExtra() { return topData(); } }; QPEManager::QPEManager( QPEDecoration *d, QObject *parent ) : QObject( parent ), decoration( d ), helpState(0) { wtTimer = new QTimer( this ); connect( wtTimer, SIGNAL(timeout()), this, SLOT(whatsThisTimeout()) ); } void QPEManager::updateActive() { QWidget *newActive = qApp->activeWindow(); if ( (QWidget*)active == newActive ) return; if ( active ) { ((TLWidget *)(QWidget*)active)->manager()->removeEventFilter( this ); } if ( newActive && ((TLWidget *)newActive)->manager() ) { active = newActive; ((TLWidget *)(QWidget*)active)->manager()->installEventFilter( this ); } else { active = 0; } } int QPEManager::pointInQpeRegion( QWidget *w, const QPoint &p ) { if ( decoration->region( w, w->geometry(), (QWSDecoration::Region)QPEDecoration::Help ).contains(p) ) { return QPEDecoration::Help; } return QWSDecoration::None; } bool QPEManager::eventFilter( QObject *o, QEvent *e ) { QWSManager *mgr = (QWSManager *)o; QWidget *w = mgr->widget(); switch ( e->type() ) { case QEvent::MouseButtonPress: { if ( QWhatsThis::inWhatsThisMode() ) { QWhatsThis::leaveWhatsThisMode(); return true; } pressTime = QTime::currentTime(); QPoint p = ((QMouseEvent*)e)->globalPos(); if ( pointInQpeRegion( w, p ) == QPEDecoration::Help ) { helpState = QWSButton::Clicked|QWSButton::MouseOver; drawButton( w, QPEDecoration::Help, helpState ); return true; } } break; case QEvent::MouseButtonRelease: if ( helpState & QWSButton::Clicked ) { helpState = 0; drawButton( w, QPEDecoration::Help, helpState ); QPoint p = ((QMouseEvent*)e)->globalPos(); if ( pointInQpeRegion( w, p ) == QPEDecoration::Help ) { #ifdef WHATSTHIS_MODE if ( pressTime.msecsTo( QTime::currentTime() ) > 250 ) { decoration->help( w ); } else { QWhatsThis::enterWhatsThisMode(); wtTimer->start( 200 ); } #else decoration->help( w ); #endif } return true; } break; case QEvent::MouseMove: if ( helpState & QWSButton::Clicked ) { int oldState = helpState; QPoint p = ((QMouseEvent*)e)->globalPos(); if ( pointInQpeRegion( w, p ) == QPEDecoration::Help ) helpState = QWSButton::Clicked|QWSButton::MouseOver; else helpState = 0; if ( helpState != oldState ) drawButton( w, QPEDecoration::Help, helpState ); } break; default: break; } return QObject::eventFilter( o, e ); } void QPEManager::drawButton( QWidget *w, QPEDecoration::QPERegion r, int state ) { QPainter painter(w); QRegion rgn = ((TLWidget *)w)->topExtra()->decor_allocated_region; painter.internalGfx()->setWidgetDeviceRegion( rgn ); painter.setClipRegion(decoration->region(w, w->rect(),QWSDecoration::All)); decoration->paintButton( &painter, w, (QWSDecoration::Region)r, state ); } void QPEManager::whatsThisTimeout() { if ( !QWhatsThis::inWhatsThisMode() ) { wtTimer->stop(); if ( active ) drawButton( active, QPEDecoration::Help, 0 ); } else if ( active ) { static int state = 0; if ( !state ) state = QWSButton::Clicked|QWSButton::MouseOver; else state = 0; drawButton( active, QPEDecoration::Help, state ); } } //========= class HackWidget : public QWidget { public: bool needsOk() { return (getWState() & WState_Reserved1 ); } }; //=========================================================================== QPEDecoration::QPEDecoration() : QWSDefaultDecoration() { imageOk = Resource::loadImage( "OKButton" ); imageClose = Resource::loadImage( "CloseButton" ); imageHelp = Resource::loadImage( "HelpButton" ); helpFile = QString(qApp->argv()[0]) + ".html"; QStringList path = Global::helpPath(); helpExists = FALSE; for (QStringList::ConstIterator it=path.begin(); it!=path.end() && !helpExists; ++it) helpExists = QFile::exists( *it + "/" + helpFile ); #ifndef MINIMIZE_HELP_HACK qpeManager = new QPEManager( this ); #else qpeManager = 0; #endif } QPEDecoration::~QPEDecoration() { delete qpeManager; } const char **QPEDecoration::menuPixmap() { return (const char **)0; } const char **QPEDecoration::closePixmap() { return (const char **)qpe_close_xpm; } const char **QPEDecoration::minimizePixmap() { return (const char **)qpe_accept_xpm; } const char **QPEDecoration::maximizePixmap() { return (const char **)0; } const char **QPEDecoration::normalizePixmap() { return (const char **)0; } int QPEDecoration::getTitleHeight(const QWidget *) { return 15; } /* If rect is empty, no frame is added. (a hack, really) */ QRegion QPEDecoration::region(const QWidget *widget, const QRect &rect, QWSDecoration::Region type) { int titleHeight = getTitleHeight(widget); // int titleWidth = getTitleWidth(widget); // int bw = rect.isEmpty() ? 0 : BORDER_WIDTH; QRegion region; #ifndef MINIMIZE_HELP_HACK qpeManager->updateActive(); #endif switch ((int)type) { case Menu: case Maximize: break; case Minimize: { if ( ((HackWidget *)widget)->needsOk() || (widget->inherits( "QDialog" ) && !widget->inherits( "QMessageBox" ) ) ) { QRect r(rect.right() - imageOk.width(), rect.top() - titleHeight - 2, imageOk.width(), titleHeight); if (r.left() > rect.left() + titleHeight) region = r; } #ifdef MINIMIZE_HELP_HACK else if ( helpExists ) { QRect r; r = QRect(rect.right() - imageClose.width() - imageHelp.width(), rect.top() - titleHeight - 2, imageHelp.width(), titleHeight); if (r.left() > rect.left() + titleHeight) region = r; } #endif } break; case Close: { if ( ((HackWidget *)widget)->needsOk() || (widget->inherits( "QDialog" ) && !widget->inherits( "QMessageBox" ) ) ) { QRect r; r = QRect(rect.right() - imageOk.width() - imageClose.width(), rect.top() - titleHeight - 2, imageClose.width(), titleHeight); if (r.left() > rect.left() + titleHeight) region = r; } else { QRect r(rect.right() - imageClose.width(), rect.top() - titleHeight - 2, imageClose.width(), titleHeight); if (r.left() > rect.left() + titleHeight) region = r; } break; } case Title: { if ( widget->isMaximized() ) { region = QRegion(); } else { int btnWidth = imageClose.width(); if ( ((HackWidget *)widget)->needsOk() || (widget->inherits( "QDialog" ) && !widget->inherits( "QMessageBox" ) ) ) btnWidth += imageOk.width(); QRect r(rect.left() + 1, rect.top() - titleHeight, rect.width() - btnWidth - 2, titleHeight); if (r.width() > 0) region = r; } break; } case Help: { if ( helpExists ) { QRect r; int l = rect.right() - imageClose.width() - imageHelp.width(); if ( ((HackWidget *)widget)->needsOk() || (widget->inherits( "QDialog" ) && !widget->inherits( "QMessageBox" ) ) ) l -= imageOk.width(); r = QRect(l, rect.top() - titleHeight - 2, imageHelp.width(), titleHeight); if (r.left() > rect.left() + titleHeight) region = r; } break; } case Top: case Left: case Right: case Bottom: case TopLeft: case TopRight: case BottomLeft: case BottomRight: if ( widget->isMaximized() ) { region = QRegion(); break; } //else fallthrough!!! case All: default: region = QWSDefaultDecoration::region(widget, rect, type); break; } return region; } void QPEDecoration::paint(QPainter *painter, const QWidget *widget) { #ifndef QT_NO_STYLE // QStyle &style = QApplication::style(); #endif int titleWidth = getTitleWidth(widget); int titleHeight = getTitleHeight(widget); QRect rect(widget->rect()); // Border rect QRect br( rect.left() - BORDER_WIDTH, rect.top() - BORDER_WIDTH - titleHeight, rect.width() + 2 * BORDER_WIDTH, rect.height() + BORDER_WIDTH + BOTTOM_BORDER_WIDTH + titleHeight ); // title bar rect QRect tr; tr = QRect( rect.left(), rect.top() - titleHeight, rect.width(), titleHeight ); QRegion oldClip = painter->clipRegion(); painter->setClipRegion( oldClip - QRegion( tr ) ); // reduce flicker #ifndef QT_NO_PALETTE // const QColorGroup &cg = QApplication::palette().active(); const QColorGroup &cg = widget->palette().active(); qDrawWinPanel(painter, br.x(), br.y(), br.width(), br.height() - 4, cg, FALSE, &cg.brush(QColorGroup::Background)); painter->setClipRegion( oldClip ); if (titleWidth > 0) { QBrush titleBrush; QPen titlePen; QPen titleLines; int titleLeft = titleHeight + 4; if (widget == qApp->activeWindow()) { titleBrush = cg.brush(QColorGroup::Highlight); titlePen = cg.color(QColorGroup::HighlightedText); } else { titleBrush = cg.brush(QColorGroup::Background); titlePen = cg.color(QColorGroup::Text); } titleLines = titleBrush.color().dark(150); #define CLAMP(x, y) ( ((x) > (y)) ? (y) : (x) ) titleLeft = rect.left() + 5; painter->setPen( cg.midlight() ); painter->drawLine( rect.left() - BORDER_WIDTH + 2, rect.bottom() + 1, rect.right() + BORDER_WIDTH - 2, rect.bottom() + 1 ); fillTitle( painter, widget, rect.left() - 2, rect.top() - titleHeight - 2, rect.width() + 3, titleHeight + 2 ); /* painter->fillRect(rect.left() - 2, rect.top() - titleHeight - 2, rect.width() + 3, titleHeight + 2, titleBrush); painter->setPen( titleLines ); for ( int i = rect.top() - titleHeight - 2; i < rect.top(); i += 2 ) painter->drawLine( rect.left() - 2, i, rect.left() + rect.width() + 2, i ); */ painter->setPen(titlePen); QFont f( QApplication::font() ); f.setWeight( QFont::Bold ); painter->setFont(f); painter->drawText( titleLeft, -titleHeight, rect.width() - titleHeight - 10, titleHeight-1, QPainter::AlignVCenter, widget->caption()); } #endif //QT_NO_PALETTE #ifndef MINIMIZE_HELP_HACK paintButton( painter, widget, (QWSDecoration::Region)Help, 0 ); #endif } void QPEDecoration::paintButton(QPainter *painter, const QWidget *w, QWSDecoration::Region type, int state) { #ifndef QT_NO_PALETTE #ifndef QT_NO_STYLE // QStyle &style = QApplication::style(); #endif const QColorGroup &cg = w->palette().active(); QRect brect(region(w, w->rect(), type).boundingRect()); // int xoff=2; // int yoff=2; // const QPixmap *pm=pixmapFor(w,type,state & QWSButton::On, xoff, yoff); const QImage *img = 0; switch ((int)type) { case Close: img = &imageClose; break; case Minimize: if ( ((HackWidget *)w)->needsOk() || (w->inherits( "QDialog" ) && !w->inherits( "QMessageBox" ) ) ) img = &imageOk; else if ( helpExists ) img = &imageHelp; break; case Help: img = &imageHelp; break; default: return; } QBrush titleBrush; if (w == qApp->activeWindow()) { titleBrush = cg.brush(QColorGroup::Highlight); } else { titleBrush = cg.brush(QColorGroup::Background); } fillTitle( painter, w, brect.x(), brect.y(), brect.width()+1, brect.height()+1 ); if ((state & QWSButton::MouseOver) && (state & QWSButton::Clicked)) { if (img) painter->drawImage(brect.x()+1, brect.y()+3, *img); } else { if (img) painter->drawImage(brect.x(), brect.y()+2, *img); } #endif } void QPEDecoration::fillTitle( QPainter *p, const QWidget *widget, int x, int y, int w, int h ) { QBrush titleBrush; QPen topLine; QPen titleLines; const QColorGroup &cg = widget->palette().active(); if (widget == qApp->activeWindow()) { titleBrush = cg.brush(QColorGroup::Highlight); titleLines = titleBrush.color().dark(); topLine = titleBrush.color().light(); } else { titleBrush = cg.brush(QColorGroup::Background); titleLines = titleBrush.color(); topLine = titleBrush.color(); } p->fillRect( x, y, w, h, titleBrush); p->setPen( topLine ); p->drawLine( x, y+1, x+w-1, y+1 ); p->setPen( titleLines ); for ( int i = y; i < y+h; i += 2 ) p->drawLine( x, i, x+w-1, i ); } //#define QPE_DONT_SHOW_TITLEBAR void QPEDecoration::maximize( QWidget *widget ) { #ifdef QPE_DONT_SHOW_TITLEBAR if ( !widget->inherits( "QDialog" ) ) { widget->setGeometry( qt_maxWindowRect ); } else #endif { QWSDecoration::maximize( widget ); } } #ifndef QT_NO_DIALOG class HackDialog : public QDialog { public: void acceptIt() { if ( isA( "QMessageBox" ) ) qApp->postEvent( this, new QKeyEvent( QEvent::KeyPress, Key_Enter, '\n', 0, "\n" ) ); else accept(); } }; #endif void QPEDecoration::minimize( QWidget *widget ) { #ifndef QT_NO_DIALOG // We use the minimize button as an "accept" button. if ( widget->inherits( "QDialog" ) ) { HackDialog *d = (HackDialog *)widget; d->acceptIt(); } #endif else if ( ((HackWidget *)widget)->needsOk() ) { QSignal s; s.connect( widget, SLOT( accept() ) ); s.activate(); } else { help( widget ); } } void QPEDecoration::help( QWidget * ) { if ( helpExists ) { Global::execute( "helpbrowser", helpFile ); } } /* #ifndef QT_NO_POPUPMENU QPopupMenu *QPEDecoration::menu(QWSManager*, const QWidget*, const QPoint&) { return 0; } #endif */ #endif // QT_NO_QWS_QPE_WM_STYLE