• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdeui

kpassivepopup.cpp

Go to the documentation of this file.
00001 /*
00002  *   copyright            : (C) 2001-2002 by Richard Moore
00003  *   copyright            : (C) 2004-2005 by Sascha Cunz
00004  *   License              : This file is released under the terms of the LGPL, version 2.
00005  *   email                : rich@kde.org
00006  *   email                : sascha.cunz@tiscali.de
00007  */
00008 
00009 #include <kconfig.h>
00010 
00011 #include <qapplication.h>
00012 #include <qlabel.h>
00013 #include <qlayout.h>
00014 #include <qtimer.h>
00015 #include <qvbox.h>
00016 #include <qpainter.h>
00017 #include <qtooltip.h>
00018 #include <qbitmap.h>
00019 #include <qpointarray.h>
00020 
00021 #include <kdebug.h>
00022 #include <kdialog.h>
00023 #include <kpixmap.h>
00024 #include <kpixmapeffect.h>
00025 #include <kglobalsettings.h>
00026 
00027 #include "config.h"
00028 #ifdef Q_WS_X11
00029 #include <netwm.h>
00030 #endif
00031 
00032 #include "kpassivepopup.h"
00033 #include "kpassivepopup.moc"
00034 
00035 class KPassivePopup::Private
00036 {
00037 public:
00038   int popupStyle;
00039   QPointArray               surround;
00040   QPoint                    anchor;
00041   QPoint                    fixedPosition;
00042 };
00043 
00044 static const int DEFAULT_POPUP_TYPE = KPassivePopup::Boxed;
00045 static const int DEFAULT_POPUP_TIME = 6*1000;
00046 static const int POPUP_FLAGS = Qt::WStyle_Customize | Qt::WDestructiveClose | Qt::WX11BypassWM
00047                              | Qt::WStyle_StaysOnTop | Qt::WStyle_Tool | Qt::WStyle_NoBorder;
00048 
00049 KPassivePopup::KPassivePopup( QWidget *parent, const char *name, WFlags f )
00050     : QFrame( 0, name, f ? f : POPUP_FLAGS ),
00051       window( parent ? parent->winId() : 0L ), msgView( 0 ), topLayout( 0 ),
00052       hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ),
00053       m_autoDelete( false )
00054 {
00055     init( DEFAULT_POPUP_TYPE );
00056 }
00057 
00058 KPassivePopup::KPassivePopup( WId win, const char *name, WFlags f )
00059     : QFrame( 0, name, f ? f : POPUP_FLAGS ),
00060       window( win ), msgView( 0 ), topLayout( 0 ),
00061       hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ),
00062       m_autoDelete( false )
00063 {
00064     init( DEFAULT_POPUP_TYPE );
00065 }
00066 
00067 KPassivePopup::KPassivePopup( int popupStyle, QWidget *parent, const char *name, WFlags f )
00068     : QFrame( 0, name, f ? f : POPUP_FLAGS ),
00069       window( parent ? parent->winId() : 0L ), msgView( 0 ), topLayout( 0 ),
00070       hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ),
00071       m_autoDelete( false )
00072 {
00073     init( popupStyle );
00074 }
00075 
00076 KPassivePopup::KPassivePopup( int popupStyle, WId win, const char *name, WFlags f )
00077     : QFrame( 0, name, f ? f : POPUP_FLAGS ),
00078       window( win ), msgView( 0 ), topLayout( 0 ),
00079       hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new QTimer( this, "hide_timer" ) ),
00080       m_autoDelete( false )
00081 {
00082     init( popupStyle );
00083 }
00084 
00085 void KPassivePopup::init( int popupStyle )
00086 {
00087     d = new Private;
00088     d->popupStyle = popupStyle;
00089     if( popupStyle == Boxed )
00090     {
00091         setFrameStyle( QFrame::Box| QFrame::Plain );
00092         setLineWidth( 2 );
00093     }
00094     else if( popupStyle == Balloon )
00095     {
00096         setPalette(QToolTip::palette());
00097         setAutoMask(TRUE);
00098     }
00099     connect( hideTimer, SIGNAL( timeout() ), SLOT( hide() ) );
00100     connect( this, SIGNAL( clicked() ), SLOT( hide() ) );
00101 }
00102 
00103 KPassivePopup::~KPassivePopup()
00104 {
00105     delete d;
00106 }
00107 
00108 void KPassivePopup::setView( QWidget *child )
00109 {
00110     delete msgView;
00111     msgView = child;
00112 
00113     delete topLayout;
00114     topLayout = new QVBoxLayout( this, d->popupStyle == Balloon ? 22 : KDialog::marginHint(), KDialog::spacingHint() );
00115     topLayout->addWidget( msgView );
00116     topLayout->activate();
00117 }
00118 
00119 void KPassivePopup::setView( const QString &caption, const QString &text,
00120                              const QPixmap &icon )
00121 {
00122     // kdDebug() << "KPassivePopup::setView " << caption << ", " << text << endl;
00123     setView( standardView( caption, text, icon, this ) );
00124 }
00125 
00126 QVBox * KPassivePopup::standardView( const QString& caption,
00127                                      const QString& text,
00128                                      const QPixmap& icon,
00129                                      QWidget *parent )
00130 {
00131     QVBox *vb = new QVBox( parent ? parent : this );
00132     vb->setSpacing( KDialog::spacingHint() );
00133 
00134     QHBox *hb=0;
00135     if ( !icon.isNull() ) {
00136     hb = new QHBox( vb );
00137     hb->setMargin( 0 );
00138     hb->setSpacing( KDialog::spacingHint() );
00139     ttlIcon = new QLabel( hb, "title_icon" );
00140     ttlIcon->setPixmap( icon );
00141         ttlIcon->setAlignment( AlignLeft );
00142     }
00143 
00144     if ( !caption.isEmpty() ) {
00145     ttl = new QLabel( caption, hb ? hb : vb, "title_label" );
00146     QFont fnt = ttl->font();
00147     fnt.setBold( true );
00148     ttl->setFont( fnt );
00149     ttl->setAlignment( Qt::AlignHCenter );
00150         if ( hb )
00151             hb->setStretchFactor( ttl, 10 ); // enforce centering
00152     }
00153 
00154     if ( !text.isEmpty() ) {
00155         msg = new QLabel( text, vb, "msg_label" );
00156         msg->setAlignment( AlignLeft );
00157     }
00158 
00159     return vb;
00160 }
00161 
00162 void KPassivePopup::setView( const QString &caption, const QString &text )
00163 {
00164     setView( caption, text, QPixmap() );
00165 }
00166 
00167 void KPassivePopup::setTimeout( int delay )
00168 {
00169     hideDelay = delay;
00170     if( hideTimer->isActive() )
00171     {
00172         if( delay ) {
00173             hideTimer->changeInterval( delay );
00174         } else {
00175             hideTimer->stop();
00176         }
00177     }
00178 }
00179 
00180 void KPassivePopup::setAutoDelete( bool autoDelete )
00181 {
00182     m_autoDelete = autoDelete;
00183 }
00184 
00185 void KPassivePopup::mouseReleaseEvent( QMouseEvent *e )
00186 {
00187     emit clicked();
00188     emit clicked( e->pos() );
00189 }
00190 
00191 //
00192 // Main Implementation
00193 //
00194 
00195 void KPassivePopup::show()
00196 {
00197     if ( size() != sizeHint() )
00198     resize( sizeHint() );
00199 
00200     if ( d->fixedPosition.isNull() )
00201     positionSelf();
00202     else {
00203     if( d->popupStyle == Balloon )
00204         setAnchor( d->fixedPosition );
00205     else
00206         move( d->fixedPosition );
00207     }
00208     QFrame::show();
00209 
00210     int delay = hideDelay;
00211     if ( delay < 0 ) {
00212         delay = DEFAULT_POPUP_TIME;
00213     }
00214 
00215     if ( delay > 0 ) {
00216         hideTimer->start( delay );
00217     }
00218 }
00219 
00220 void KPassivePopup::show(const QPoint &p)
00221 {
00222     d->fixedPosition = p;
00223     show();
00224 }
00225 
00226 void KPassivePopup::hideEvent( QHideEvent * )
00227 {
00228     hideTimer->stop();
00229     if ( m_autoDelete )
00230         deleteLater();
00231 }
00232 
00233 QRect KPassivePopup::defaultArea() const
00234 {
00235 #ifdef Q_WS_X11
00236     NETRootInfo info( qt_xdisplay(),
00237                       NET::NumberOfDesktops |
00238                       NET::CurrentDesktop |
00239                       NET::WorkArea,
00240                       -1, false );
00241     info.activate();
00242     NETRect workArea = info.workArea( info.currentDesktop() );
00243     QRect r;
00244     r.setRect( workArea.pos.x, workArea.pos.y, 0, 0 ); // top left
00245 #else
00246     // FIX IT
00247     QRect r;
00248     r.setRect( 100, 100, 200, 200 ); // top left
00249 #endif
00250     return r;
00251 }
00252 
00253 void KPassivePopup::positionSelf()
00254 {
00255     QRect target;
00256 
00257 #ifdef Q_WS_X11
00258     if ( !window ) {
00259         target = defaultArea();
00260     }
00261 
00262     else {
00263         NETWinInfo ni( qt_xdisplay(), window, qt_xrootwin(),
00264                        NET::WMIconGeometry | NET::WMKDESystemTrayWinFor );
00265 
00266         // Figure out where to put the popup. Note that we must handle
00267         // windows that skip the taskbar cleanly
00268         if ( ni.kdeSystemTrayWinFor() ) {
00269             NETRect frame, win;
00270             ni.kdeGeometry( frame, win );
00271             target.setRect( win.pos.x, win.pos.y,
00272                             win.size.width, win.size.height );
00273         }
00274         else if ( ni.state() & NET::SkipTaskbar ) {
00275             target = defaultArea();
00276         }
00277         else {
00278             NETRect r = ni.iconGeometry();
00279             target.setRect( r.pos.x, r.pos.y, r.size.width, r.size.height );
00280                 if ( target.isNull() ) { // bogus value, use the exact position
00281                     NETRect dummy;
00282                     ni.kdeGeometry( dummy, r );
00283                     target.setRect( r.pos.x, r.pos.y, 
00284                                     r.size.width, r.size.height);
00285                 }
00286         }
00287     }
00288 #else
00289         target = defaultArea();
00290 #endif
00291     moveNear( target );
00292 }
00293 
00294 void KPassivePopup::moveNear( QRect target )
00295 {
00296     QPoint pos = target.topLeft();
00297     int x = pos.x();
00298     int y = pos.y();
00299     int w = width();
00300     int h = height();
00301 
00302     QRect r = KGlobalSettings::desktopGeometry(QPoint(x+w/2,y+h/2));
00303 
00304     if( d->popupStyle == Balloon )
00305     {
00306         // find a point to anchor to
00307         if( x + w > r.width() ){
00308             x = x + target.width();
00309         }
00310 
00311         if( y + h > r.height() ){
00312             y = y + target.height();
00313         }
00314     } else
00315     {
00316         if ( x < r.center().x() )
00317             x = x + target.width();
00318         else
00319             x = x - w;
00320 
00321         // It's apparently trying to go off screen, so display it ALL at the bottom.
00322         if ( (y + h) > r.bottom() )
00323             y = r.bottom() - h;
00324 
00325         if ( (x + w) > r.right() )
00326             x = r.right() - w;
00327     }
00328     if ( y < r.top() )
00329         y = r.top();
00330 
00331     if ( x < r.left() )
00332         x = r.left();
00333 
00334     if( d->popupStyle == Balloon )
00335         setAnchor( QPoint( x, y ) );
00336     else
00337         move( x, y );
00338 }
00339 
00340 void KPassivePopup::setAnchor(const QPoint &anchor)
00341 {
00342     d->anchor = anchor;
00343     updateMask();
00344 }
00345 
00346 void KPassivePopup::paintEvent( QPaintEvent* pe )
00347 {
00348     if( d->popupStyle == Balloon )
00349     {
00350         QPainter p;
00351         p.begin( this );
00352         p.drawPolygon( d->surround );
00353     } else
00354         QFrame::paintEvent( pe );
00355 }
00356 
00357 void KPassivePopup::updateMask()
00358 {
00359     // get screen-geometry for screen our anchor is on
00360     // (geometry can differ from screen to screen!
00361     QRect deskRect = KGlobalSettings::desktopGeometry(d->anchor);
00362 
00363     int xh = 70, xl = 40;
00364     if( width() < 80 )
00365         xh = xl = 40;
00366     else if( width() < 110 )
00367         xh = width() - 40;
00368 
00369     bool bottom = (d->anchor.y() + height()) > ((deskRect.y() + deskRect.height()-48));
00370     bool right = (d->anchor.x() + width()) > ((deskRect.x() + deskRect.width()-48));
00371 
00372     QPoint corners[4] = {
00373         QPoint( width() - 50, 10 ),
00374         QPoint( 10, 10 ),
00375         QPoint( 10, height() - 50 ),
00376         QPoint( width() - 50, height() - 50 )
00377     };
00378 
00379     QBitmap mask( width(), height(), true );
00380     QPainter p( &mask );
00381     QBrush brush( Qt::white, Qt::SolidPattern );
00382     p.setBrush( brush );
00383 
00384     int i = 0, z = 0;
00385     for (; i < 4; ++i) {
00386         QPointArray corner;
00387         corner.makeArc(corners[i].x(), corners[i].y(), 40, 40, i * 16 * 90, 16 * 90);
00388 
00389         d->surround.resize( z + corner.count() );
00390         for (unsigned int s = 0; s < corner.count() - 1; s++) {
00391             d->surround.setPoint( z++, corner[s] );
00392         }
00393         
00394         if (bottom && i == 2) {
00395             if (right) {
00396                 d->surround.resize( z + 3 );
00397                 d->surround.setPoint( z++, QPoint( width() - xh, height() - 11 ) );
00398                 d->surround.setPoint( z++, QPoint( width() - 20, height() ) );
00399                 d->surround.setPoint( z++, QPoint( width() - xl, height() - 11 ) );
00400             } else {
00401                 d->surround.resize( z + 3 );
00402                 d->surround.setPoint( z++, QPoint( xl, height() - 11 ) );
00403                 d->surround.setPoint( z++, QPoint( 20, height() ) );
00404                 d->surround.setPoint( z++, QPoint( xh, height() - 11 ) );
00405             }
00406         } else if (!bottom && i == 0) {
00407             if (right) {
00408                 d->surround.resize( z + 3 );
00409                 d->surround.setPoint( z++, QPoint( width() - xl, 10 ) );
00410                 d->surround.setPoint( z++, QPoint( width() - 20, 0 ) );
00411                 d->surround.setPoint( z++, QPoint( width() - xh, 10 ) );
00412             } else {
00413                 d->surround.resize( z + 3 );
00414                 d->surround.setPoint( z++, QPoint( xh, 10 ) );
00415                 d->surround.setPoint( z++, QPoint( 20, 0 ) );
00416                 d->surround.setPoint( z++, QPoint( xl, 10 ) );
00417             }
00418         }
00419     }
00420 
00421     d->surround.resize( z + 1 );
00422     d->surround.setPoint( z, d->surround[0] );
00423     p.drawPolygon( d->surround );
00424     setMask(mask);
00425 
00426     move( right ? d->anchor.x() - width() + 20 : ( d->anchor.x() < 11 ? 11 : d->anchor.x() - 20 ),
00427           bottom ? d->anchor.y() - height() : ( d->anchor.y() < 11 ? 11 : d->anchor.y() ) );
00428 
00429     update();
00430 }
00431 
00432 //
00433 // Convenience Methods
00434 //
00435 
00436 KPassivePopup *KPassivePopup::message( const QString &caption, const QString &text,
00437                        const QPixmap &icon,
00438                        QWidget *parent, const char *name, int timeout )
00439 {
00440     return message( DEFAULT_POPUP_TYPE, caption, text, icon, parent, name, timeout );
00441 }
00442 
00443 KPassivePopup *KPassivePopup::message( const QString &text, QWidget *parent, const char *name )
00444 {
00445     return message( DEFAULT_POPUP_TYPE, QString::null, text, QPixmap(), parent, name );
00446 }
00447 
00448 KPassivePopup *KPassivePopup::message( const QString &caption, const QString &text,
00449                        QWidget *parent, const char *name )
00450 {
00451     return message( DEFAULT_POPUP_TYPE, caption, text, QPixmap(), parent, name );
00452 }
00453 
00454 KPassivePopup *KPassivePopup::message( const QString &caption, const QString &text,
00455                        const QPixmap &icon, WId parent, const char *name, int timeout )
00456 {
00457     return message( DEFAULT_POPUP_TYPE, caption, text, icon, parent, name, timeout );
00458 }
00459 
00460 KPassivePopup *KPassivePopup::message( int popupStyle, const QString &caption, const QString &text,
00461                        const QPixmap &icon,
00462                        QWidget *parent, const char *name, int timeout )
00463 {
00464     KPassivePopup *pop = new KPassivePopup( popupStyle, parent, name );
00465     pop->setAutoDelete( true );
00466     pop->setView( caption, text, icon );
00467     pop->hideDelay = timeout;
00468     pop->show();
00469 
00470     return pop;
00471 }
00472 
00473 KPassivePopup *KPassivePopup::message( int popupStyle, const QString &text, QWidget *parent, const char *name )
00474 {
00475     return message( popupStyle, QString::null, text, QPixmap(), parent, name );
00476 }
00477 
00478 KPassivePopup *KPassivePopup::message( int popupStyle, const QString &caption, const QString &text,
00479                        QWidget *parent, const char *name )
00480 {
00481     return message( popupStyle, caption, text, QPixmap(), parent, name );
00482 }
00483 
00484 KPassivePopup *KPassivePopup::message( int popupStyle, const QString &caption, const QString &text,
00485                        const QPixmap &icon, WId parent, const char *name, int timeout )
00486 {
00487     KPassivePopup *pop = new KPassivePopup( popupStyle, parent, name );
00488     pop->setAutoDelete( true );
00489     pop->setView( caption, text, icon );
00490     pop->hideDelay = timeout;
00491     pop->show();
00492 
00493     return pop;
00494 }
00495 
00496 // Local Variables:
00497 // c-basic-offset: 4
00498 // End:

kdeui

Skip menu "kdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal