• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kdeui
 

kdeui

kpassivepopup.cpp
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 <tqapplication.h>
00012 #include <tqlabel.h>
00013 #include <tqlayout.h>
00014 #include <tqtimer.h>
00015 #include <tqvbox.h>
00016 #include <tqpainter.h>
00017 #include <tqtooltip.h>
00018 #include <tqbitmap.h>
00019 #include <tqpointarray.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   TQPointArray               surround;
00040   TQPoint                    anchor;
00041   TQPoint                    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 = TQt::WStyle_Customize | TQt::WDestructiveClose | TQt::WX11BypassWM
00047                              | TQt::WStyle_StaysOnTop | TQt::WStyle_Tool | TQt::WStyle_NoBorder;
00048 
00049 KPassivePopup::KPassivePopup( TQWidget *parent, const char *name, WFlags f )
00050     : TQFrame( 0, name, (WFlags)(f ? (int)f : POPUP_FLAGS) ),
00051       window( parent ? parent->winId() : 0L ), msgView( 0 ), topLayout( 0 ),
00052       hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new TQTimer( 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     : TQFrame( 0, name, (WFlags)(f ? (int)f : POPUP_FLAGS) ),
00060       window( win ), msgView( 0 ), topLayout( 0 ),
00061       hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new TQTimer( this, "hide_timer" ) ),
00062       m_autoDelete( false )
00063 {
00064     init( DEFAULT_POPUP_TYPE );
00065 }
00066 
00067 KPassivePopup::KPassivePopup( int popupStyle, TQWidget *parent, const char *name, WFlags f )
00068     : TQFrame( 0, name, (WFlags)(f ? (int)f : POPUP_FLAGS) ),
00069       window( parent ? parent->winId() : 0L ), msgView( 0 ), topLayout( 0 ),
00070       hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new TQTimer( 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     : TQFrame( 0, name, (WFlags)(f ? (int)f : POPUP_FLAGS) ),
00078       window( win ), msgView( 0 ), topLayout( 0 ),
00079       hideDelay( DEFAULT_POPUP_TIME ), hideTimer( new TQTimer( 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( TQFrame::Box| TQFrame::Plain );
00092         setLineWidth( 2 );
00093     }
00094     else if( popupStyle == Balloon )
00095     {
00096         setPalette(TQToolTip::palette());
00097         setAutoMask(TRUE);
00098     }
00099     connect( hideTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( hide() ) );
00100     connect( this, TQT_SIGNAL( clicked() ), TQT_SLOT( hide() ) );
00101 }
00102 
00103 KPassivePopup::~KPassivePopup()
00104 {
00105     delete d;
00106 }
00107 
00108 void KPassivePopup::setView( TQWidget *child )
00109 {
00110     delete msgView;
00111     msgView = child;
00112 
00113     delete topLayout;
00114     topLayout = new TQVBoxLayout( this, d->popupStyle == Balloon ? 22 : KDialog::marginHint(), KDialog::spacingHint() );
00115     topLayout->addWidget( msgView );
00116     topLayout->activate();
00117 }
00118 
00119 void KPassivePopup::setView( const TQString &caption, const TQString &text,
00120                              const TQPixmap &icon )
00121 {
00122     // kdDebug() << "KPassivePopup::setView " << caption << ", " << text << endl;
00123     setView( standardView( caption, text, icon, this ) );
00124 }
00125 
00126 static void truncateStringToFit(TQString &string, TQFont font, int max_width) {
00127     bool truncated = false;
00128     TQFontMetrics fm(font);
00129     while (fm.width(string) > max_width) {
00130         string.truncate(string.length() - 1);
00131         truncated = true;
00132     }
00133     if (truncated) {
00134         string += " ...";
00135     }
00136 }
00137 
00138 TQVBox * KPassivePopup::standardView(const TQString& caption,
00139                                      const TQString& text,
00140                                      const TQPixmap& icon,
00141                                      TQWidget *parent)
00142 {
00143     TQString sizedCaption = caption;
00144     TQString sizedText = text;
00145 
00146 #ifdef Q_WS_X11
00147     int max_width;
00148 
00149     NETRootInfo info( qt_xdisplay(),
00150             NET::NumberOfDesktops |
00151             NET::CurrentDesktop |
00152             NET::WorkArea,
00153             -1, false );
00154     info.activate();
00155     NETRect workArea = info.workArea(info.currentDesktop());
00156     max_width = workArea.size.width / 3;
00157 #endif
00158 
00159     TQVBox *vb = new TQVBox( parent ? parent : this );
00160     vb->setSpacing( KDialog::spacingHint() );
00161     
00162     TQHBox *hb=0;
00163     if ( !icon.isNull() ) {
00164         hb = new TQHBox( vb );
00165         hb->setMargin( 0 );
00166         hb->setSpacing( KDialog::spacingHint() );
00167         ttlIcon = new TQLabel( hb, "title_icon" );
00168         ttlIcon->setPixmap( icon );
00169         ttlIcon->setAlignment( AlignLeft );
00170     }
00171 
00172     if ( !sizedCaption.isEmpty() ) {
00173         ttl = new TQLabel( sizedCaption, hb ? hb : vb, "title_label" );
00174         TQFont fnt = ttl->font();
00175 #ifdef Q_WS_X11
00176         truncateStringToFit(sizedCaption, fnt, max_width);
00177         ttl->setText(sizedCaption);
00178 #endif
00179         fnt.setBold( true );
00180         ttl->setFont( fnt );
00181         ttl->setAlignment( Qt::AlignHCenter );
00182         if ( hb ) {
00183             hb->setStretchFactor( ttl, 10 ); // enforce centering
00184         }
00185     }
00186 
00187     if ( !sizedText.isEmpty() ) {
00188         msg = new TQLabel( sizedText, vb, "msg_label" );
00189 #ifdef Q_WS_X11
00190         TQStringList textLines = TQStringList::split("\n", sizedText, true);
00191         for (TQStringList::Iterator it = textLines.begin(); it != textLines.end(); ++it) {
00192             truncateStringToFit(*it, msg->font(), max_width);
00193         }
00194 
00195         // Limit message to 5 lines of text
00196         if (textLines.count() > 5) {
00197             int count = 3;
00198             TQStringList truncatedLines;
00199             for (TQStringList::Iterator it = textLines.begin(); it != textLines.end(); ++it) {
00200                 truncatedLines.append(*it);
00201                 if (count > 5) {
00202                     truncatedLines.append("...");
00203                     break;
00204                 }
00205                 count++;
00206             }
00207             textLines = truncatedLines;
00208         }
00209         sizedText = textLines.join("\n");
00210         msg->setText(sizedText);
00211 #endif
00212         msg->setAlignment( AlignLeft );
00213     }
00214 
00215     return vb;
00216 }
00217 
00218 void KPassivePopup::setView( const TQString &caption, const TQString &text )
00219 {
00220     setView( caption, text, TQPixmap() );
00221 }
00222 
00223 void KPassivePopup::setTimeout( int delay )
00224 {
00225     hideDelay = delay;
00226     if( hideTimer->isActive() )
00227     {
00228         if( delay ) {
00229             hideTimer->changeInterval( delay );
00230         } else {
00231             hideTimer->stop();
00232         }
00233     }
00234 }
00235 
00236 void KPassivePopup::setAutoDelete( bool autoDelete )
00237 {
00238     m_autoDelete = autoDelete;
00239 }
00240 
00241 void KPassivePopup::mouseReleaseEvent( TQMouseEvent *e )
00242 {
00243     emit clicked();
00244     emit clicked( e->pos() );
00245 }
00246 
00247 //
00248 // Main Implementation
00249 //
00250 
00251 void KPassivePopup::show()
00252 {
00253     TQSize desiredSize = sizeHint();
00254 
00255     if (size() != desiredSize) {
00256         resize(desiredSize);
00257     }
00258 
00259     if (d->fixedPosition.isNull()) {
00260         positionSelf();
00261     }
00262     else {
00263         if( d->popupStyle == Balloon ) {
00264             setAnchor(d->fixedPosition);
00265         }
00266         else {
00267             move(d->fixedPosition);
00268         }
00269     }
00270     TQFrame::show();
00271 
00272     int delay = hideDelay;
00273     if ( delay < 0 ) {
00274         delay = DEFAULT_POPUP_TIME;
00275     }
00276 
00277     if ( delay > 0 ) {
00278         hideTimer->start( delay );
00279     }
00280 }
00281 
00282 void KPassivePopup::show(const TQPoint &p)
00283 {
00284     d->fixedPosition = p;
00285     show();
00286 }
00287 
00288 void KPassivePopup::hideEvent( TQHideEvent * )
00289 {
00290     hideTimer->stop();
00291     emit( hidden( this ) );
00292     if ( m_autoDelete )
00293         deleteLater();
00294 }
00295 
00296 TQRect KPassivePopup::defaultArea() const
00297 {
00298 #ifdef Q_WS_X11
00299     NETRootInfo info( qt_xdisplay(),
00300                       NET::NumberOfDesktops |
00301                       NET::CurrentDesktop |
00302                       NET::WorkArea,
00303                       -1, false );
00304     info.activate();
00305     NETRect workArea = info.workArea( info.currentDesktop() );
00306     TQRect r;
00307     r.setRect( workArea.pos.x, workArea.pos.y, 0, 0 ); // top left
00308 #else
00309     // FIX IT
00310     TQRect r;
00311     r.setRect( 100, 100, 200, 200 ); // top left
00312 #endif
00313     return r;
00314 }
00315 
00316 void KPassivePopup::positionSelf()
00317 {
00318     TQRect target;
00319 
00320 #ifdef Q_WS_X11
00321     if ( !window ) {
00322         target = defaultArea();
00323     }
00324 
00325     else {
00326         NETWinInfo ni( qt_xdisplay(), window, qt_xrootwin(),
00327                        NET::WMIconGeometry | NET::WMKDESystemTrayWinFor );
00328 
00329         // Figure out where to put the popup. Note that we must handle
00330         // windows that skip the taskbar cleanly
00331         if ( ni.kdeSystemTrayWinFor() ) {
00332             NETRect frame, win;
00333             ni.kdeGeometry( frame, win );
00334             target.setRect( win.pos.x, win.pos.y,
00335                             win.size.width, win.size.height );
00336         }
00337         else if ( ni.state() & NET::SkipTaskbar ) {
00338             target = defaultArea();
00339         }
00340         else {
00341             NETRect r = ni.iconGeometry();
00342             target.setRect( r.pos.x, r.pos.y, r.size.width, r.size.height );
00343                 if ( target.isNull() ) { // bogus value, use the exact position
00344                     NETRect dummy;
00345                     ni.kdeGeometry( dummy, r );
00346                     target.setRect( r.pos.x, r.pos.y, 
00347                                     r.size.width, r.size.height);
00348                 }
00349         }
00350     }
00351 #else
00352         target = defaultArea();
00353 #endif
00354     moveNear( target );
00355 }
00356 
00357 void KPassivePopup::moveNear( TQRect target )
00358 {
00359     TQPoint pos = target.topLeft();
00360     int x = pos.x();
00361     int y = pos.y();
00362     int w = width();
00363     int h = height();
00364 
00365     TQRect r = KGlobalSettings::desktopGeometry(TQPoint(x+w/2,y+h/2));
00366 
00367     if( d->popupStyle == Balloon )
00368     {
00369         // find a point to anchor to
00370         if( x + w > r.width() ){
00371             x = x + target.width();
00372         }
00373 
00374         if( y + h > r.height() ){
00375             y = y + target.height();
00376         }
00377     } else
00378     {
00379         if ( x < r.center().x() )
00380             x = x + target.width();
00381         else
00382             x = x - w;
00383 
00384         // It's apparently trying to go off screen, so display it ALL at the bottom.
00385         if ( (y + h) > r.bottom() )
00386             y = r.bottom() - h;
00387 
00388         if ( (x + w) > r.right() )
00389             x = r.right() - w;
00390     }
00391     if ( y < r.top() )
00392         y = r.top();
00393 
00394     if ( x < r.left() )
00395         x = r.left();
00396 
00397     if( d->popupStyle == Balloon )
00398         setAnchor( TQPoint( x, y ) );
00399     else
00400         move( x, y );
00401 }
00402 
00403 void KPassivePopup::setAnchor(const TQPoint &anchor)
00404 {
00405     d->anchor = anchor;
00406     updateMask();
00407 }
00408 
00409 void KPassivePopup::paintEvent( TQPaintEvent* pe )
00410 {
00411     if( d->popupStyle == Balloon ) {
00412         TQPainter p;
00413         p.begin( this );
00414         p.drawPolygon( d->surround );
00415     }
00416     else {
00417         TQFrame::paintEvent( pe );
00418     }
00419 }
00420 
00421 void KPassivePopup::updateMask()
00422 {
00423     // get screen-geometry for screen our anchor is on
00424     // (geometry can differ from screen to screen!
00425     TQRect deskRect = KGlobalSettings::desktopGeometry(d->anchor);
00426 
00427     int xh = 70, xl = 40;
00428     if( width() < 80 )
00429         xh = xl = 40;
00430     else if( width() < 110 )
00431         xh = width() - 40;
00432 
00433     bool bottom = (d->anchor.y() + height()) > ((deskRect.y() + deskRect.height()-48));
00434     bool right = (d->anchor.x() + width()) > ((deskRect.x() + deskRect.width()-48));
00435 
00436     TQPoint corners[4] = {
00437         TQPoint( width() - 50, 10 ),
00438         TQPoint( 10, 10 ),
00439         TQPoint( 10, height() - 50 ),
00440         TQPoint( width() - 50, height() - 50 )
00441     };
00442 
00443     TQBitmap mask( width(), height(), true );
00444     TQPainter p( &mask );
00445     TQBrush brush( Qt::white, Qt::SolidPattern );
00446     p.setBrush( brush );
00447 
00448     int i = 0, z = 0;
00449     for (; i < 4; ++i) {
00450         TQPointArray corner;
00451         corner.makeArc(corners[i].x(), corners[i].y(), 40, 40, i * 16 * 90, 16 * 90);
00452 
00453         d->surround.resize( z + corner.count() );
00454         for (unsigned int s = 0; s < corner.count() - 1; s++) {
00455             d->surround.setPoint( z++, corner[s] );
00456         }
00457         
00458         if (bottom && i == 2) {
00459             if (right) {
00460                 d->surround.resize( z + 3 );
00461                 d->surround.setPoint( z++, TQPoint( width() - xh, height() - 11 ) );
00462                 d->surround.setPoint( z++, TQPoint( width() - 20, height() ) );
00463                 d->surround.setPoint( z++, TQPoint( width() - xl, height() - 11 ) );
00464             } else {
00465                 d->surround.resize( z + 3 );
00466                 d->surround.setPoint( z++, TQPoint( xl, height() - 11 ) );
00467                 d->surround.setPoint( z++, TQPoint( 20, height() ) );
00468                 d->surround.setPoint( z++, TQPoint( xh, height() - 11 ) );
00469             }
00470         } else if (!bottom && i == 0) {
00471             if (right) {
00472                 d->surround.resize( z + 3 );
00473                 d->surround.setPoint( z++, TQPoint( width() - xl, 10 ) );
00474                 d->surround.setPoint( z++, TQPoint( width() - 20, 0 ) );
00475                 d->surround.setPoint( z++, TQPoint( width() - xh, 10 ) );
00476             } else {
00477                 d->surround.resize( z + 3 );
00478                 d->surround.setPoint( z++, TQPoint( xh, 10 ) );
00479                 d->surround.setPoint( z++, TQPoint( 20, 0 ) );
00480                 d->surround.setPoint( z++, TQPoint( xl, 10 ) );
00481             }
00482         }
00483     }
00484 
00485     d->surround.resize( z + 1 );
00486     d->surround.setPoint( z, d->surround[0] );
00487     p.drawPolygon( d->surround );
00488     setMask(mask);
00489 
00490     move( right ? d->anchor.x() - width() + 20 : ( d->anchor.x() < 11 ? 11 : d->anchor.x() - 20 ),
00491           bottom ? d->anchor.y() - height() : ( d->anchor.y() < 11 ? 11 : d->anchor.y() ) );
00492 
00493     update();
00494 }
00495 
00496 //
00497 // Convenience Methods
00498 //
00499 
00500 KPassivePopup *KPassivePopup::message( const TQString &caption, const TQString &text,
00501                        const TQPixmap &icon,
00502                        TQWidget *parent, const char *name, int timeout )
00503 {
00504     return message( DEFAULT_POPUP_TYPE, caption, text, icon, parent, name, timeout );
00505 }
00506 
00507 KPassivePopup *KPassivePopup::message( const TQString &text, TQWidget *parent, const char *name )
00508 {
00509     return message( DEFAULT_POPUP_TYPE, TQString::null, text, TQPixmap(), parent, name );
00510 }
00511 
00512 KPassivePopup *KPassivePopup::message( const TQString &caption, const TQString &text,
00513                        TQWidget *parent, const char *name )
00514 {
00515     return message( DEFAULT_POPUP_TYPE, caption, text, TQPixmap(), parent, name );
00516 }
00517 
00518 KPassivePopup *KPassivePopup::message( const TQString &caption, const TQString &text,
00519                        const TQPixmap &icon, WId parent, const char *name, int timeout )
00520 {
00521     return message( DEFAULT_POPUP_TYPE, caption, text, icon, parent, name, timeout );
00522 }
00523 
00524 KPassivePopup *KPassivePopup::message( int popupStyle, const TQString &caption, const TQString &text,
00525                        const TQPixmap &icon,
00526                        TQWidget *parent, const char *name, int timeout )
00527 {
00528     KPassivePopup *pop = new KPassivePopup( popupStyle, parent, name );
00529     pop->setAutoDelete( true );
00530     pop->setView( caption, text, icon );
00531     pop->hideDelay = timeout;
00532     pop->show();
00533 
00534     return pop;
00535 }
00536 
00537 KPassivePopup *KPassivePopup::message( int popupStyle, const TQString &text, TQWidget *parent, const char *name )
00538 {
00539     return message( popupStyle, TQString::null, text, TQPixmap(), parent, name );
00540 }
00541 
00542 KPassivePopup *KPassivePopup::message( int popupStyle, const TQString &caption, const TQString &text,
00543                        TQWidget *parent, const char *name )
00544 {
00545     return message( popupStyle, caption, text, TQPixmap(), parent, name );
00546 }
00547 
00548 KPassivePopup *KPassivePopup::message( int popupStyle, const TQString &caption, const TQString &text,
00549                        const TQPixmap &icon, WId parent, const char *name, int timeout )
00550 {
00551     KPassivePopup *pop = new KPassivePopup( popupStyle, parent, name );
00552     pop->setAutoDelete( true );
00553     pop->setView( caption, text, icon );
00554     pop->hideDelay = timeout;
00555     pop->show();
00556 
00557     return pop;
00558 }
00559 
00560 // Local Variables:
00561 // c-basic-offset: 4
00562 // End:

kdeui

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

kdeui

Skip menu "kdeui"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kdeui by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |