kdeui Library API Documentation

kjanuswidget.cpp

00001 /*  This file is part of the KDE Libraries
00002  *  Copyright (C) 1999-2000 Espen Sand (espensa@online.no)
00003  *  Copyright (C) 2003 Ravikiran Rajagopal (ravi@kde.org)
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License as published by the Free Software Foundation; either
00008  *  version 2 of the License, or (at your option) any later version.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Library General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Library General Public License
00016  *  along with this library; see the file COPYING.LIB.  If not, write to
00017  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018  *  Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #include <qbitmap.h>
00022 #include <qgrid.h>
00023 #include <qhbox.h>
00024 #include <qheader.h>
00025 #include <qlabel.h>
00026 #include <qlayout.h>
00027 #include <qobjectlist.h>
00028 #include <qpixmap.h>
00029 #include <qsplitter.h>
00030 #include <qtabwidget.h>
00031 #include <qvbox.h>
00032 #include <qwidgetstack.h>
00033 #include <qpainter.h>
00034 #include <qstyle.h>
00035 
00036 #include <kapplication.h>
00037 #include <kdialog.h> // Access to some static members
00038 #include <klocale.h>
00039 #include <kglobal.h>
00040 #include <kglobalsettings.h>
00041 #include <kseparator.h>
00042 #include <kdebug.h>
00043 #include "kjanuswidget.h"
00044 #include <klistview.h>
00045 #include "kpushbutton.h"
00046 #include "kguiitem.h"
00047 
00048 class KJanusWidget::IconListItem : public QListBoxItem
00049 {
00050   public:
00051     IconListItem( QListBox *listbox, const QPixmap &pixmap,
00052                   const QString &text );
00053     virtual int height( const QListBox *lb ) const;
00054     virtual int width( const QListBox *lb ) const;
00055     int expandMinimumWidth( int width );
00056     void highlight( bool erase );        
00057 
00058   protected:
00059     const QPixmap &defaultPixmap();
00060     void paint( QPainter *painter );
00061     
00062   private:
00063     void paintContents( QPainter *painter );  
00064   
00065     QPixmap mPixmap;
00066     int mMinimumWidth;
00067 };
00068 
00069 class KJanusWidget::KJanusWidgetPrivate
00070 {
00071 public:
00072   KJanusWidgetPrivate() : mNextPageIndex(0), mListFrame( 0 ) { }
00073 
00074   int mNextPageIndex; // The next page index.
00075 
00076   // Dictionary for multipage modes.
00077   QMap<int,QWidget*> mIntToPage;
00078   // Reverse dictionary. Used because showPage() may be performance critical.
00079   QMap<QWidget*,int> mPageToInt;
00080   // Dictionary of title string associated with page.
00081   QMap<int, QString> mIntToTitle;
00082 
00083   QWidget * mListFrame;
00084   QSplitter * mSplitter;
00085 };
00086 
00087 template class QPtrList<QListViewItem>;
00088 
00089 
00090 KJanusWidget::KJanusWidget( QWidget *parent, const char *name, int face )
00091   : QWidget( parent, name, 0 ),
00092     mValid(false), mPageList(0),
00093     mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0),
00094     mShowIconsInTreeList(false), d(0)
00095 {
00096   QVBoxLayout *topLayout = new QVBoxLayout( this );
00097 
00098   if( mFace == TreeList || mFace == IconList )
00099   {
00100     d = new KJanusWidgetPrivate;
00101     d->mSplitter = 0;
00102 
00103     QFrame *page;
00104     if( mFace == TreeList )
00105     {
00106       d->mSplitter = new QSplitter( this );
00107       topLayout->addWidget( d->mSplitter, 10 );
00108       mTreeListResizeMode = QSplitter::KeepSize;
00109 
00110       d->mListFrame = new QWidget( d->mSplitter );
00111       QVBoxLayout *dummy = new QVBoxLayout( d->mListFrame, 0, 0 );
00112       dummy->setAutoAdd( true );
00113       mTreeList = new KListView( d->mListFrame );
00114       mTreeList->addColumn( QString::null );
00115       mTreeList->header()->hide();
00116       mTreeList->setRootIsDecorated(true);
00117       mTreeList->setSorting( -1 );
00118       connect( mTreeList, SIGNAL(selectionChanged()), SLOT(slotShowPage()) );
00119       connect( mTreeList, SIGNAL(clicked(QListViewItem *)), SLOT(slotItemClicked(QListViewItem *)));
00120 
00121       //
00122       // Page area. Title at top with a separator below and a pagestack using
00123       // all available space at bottom.
00124       //
00125       QFrame *p = new QFrame( d->mSplitter );
00126 
00127       QHBoxLayout *hbox = new QHBoxLayout( p, 0, 0 );
00128       hbox->addSpacing( KDialog::marginHint() );
00129 
00130       page = new QFrame( p );
00131       hbox->addWidget( page, 10 );
00132     }
00133     else
00134     {
00135       QHBoxLayout *hbox = new QHBoxLayout( topLayout );
00136       d->mListFrame = new QWidget( this );
00137       hbox->addWidget( d->mListFrame );
00138 
00139       ( new QVBoxLayout( d->mListFrame, 0, 0 ) )->setAutoAdd( true );
00140       mIconList = new IconListBox( d->mListFrame );
00141 
00142       QFont listFont( mIconList->font() );
00143       listFont.setBold( true );
00144       mIconList->setFont( listFont );
00145 
00146       mIconList->verticalScrollBar()->installEventFilter( this );
00147       connect( mIconList, SIGNAL(selectionChanged()), SLOT(slotShowPage()));
00148       connect( mIconList, SIGNAL(onItem(QListBoxItem *)), SLOT(slotOnItem(QListBoxItem *)));
00149 
00150       hbox->addSpacing( KDialog::marginHint() );
00151       page = new QFrame( this );
00152       hbox->addWidget( page, 10 );
00153     }
00154 
00155     //
00156     // Rest of page area. Title at top with a separator below and a
00157     // pagestack using all available space at bottom.
00158     //
00159 
00160     QVBoxLayout *vbox = new QVBoxLayout( page, 0, KDialog::spacingHint() );
00161 
00162     mTitleLabel = new QLabel( QString::fromLatin1("Empty Page"), page, "KJanusWidgetTitleLabel" );
00163     vbox->addWidget( mTitleLabel, 0, QApplication::reverseLayout() ? AlignRight : AlignLeft );
00164 
00165     QFont titleFont( mTitleLabel->font() );
00166     titleFont.setBold( true );
00167     mTitleLabel->setFont( titleFont );
00168 
00169     mTitleSep = new KSeparator( page );
00170     mTitleSep->setFrameStyle( QFrame::HLine|QFrame::Plain );
00171     vbox->addWidget( mTitleSep );
00172 
00173     mPageStack = new QWidgetStack( page );
00174     connect(mPageStack, SIGNAL(aboutToShow(QWidget *)),
00175             SIGNAL(aboutToShowPage(QWidget *)));
00176     vbox->addWidget( mPageStack, 10 );
00177   }
00178   else if( mFace == Tabbed )
00179   {
00180     d = new KJanusWidgetPrivate;
00181 
00182     mTabControl = new QTabWidget( this );
00183     mTabControl->setMargin (KDialog::marginHint());
00184     connect(mTabControl, SIGNAL(currentChanged(QWidget *)),
00185             SIGNAL(aboutToShowPage(QWidget *)));
00186     topLayout->addWidget( mTabControl, 10 );
00187   }
00188   else if( mFace == Swallow )
00189   {
00190     mSwallowPage = new QWidget( this );
00191     topLayout->addWidget( mSwallowPage, 10 );
00192   }
00193   else
00194   {
00195     mFace = Plain;
00196     mPlainPage = new QFrame( this );
00197     topLayout->addWidget( mPlainPage, 10 );
00198   }
00199 
00200   if ( kapp )
00201     connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged()));
00202   mValid = true;
00203 
00204   setSwallowedWidget(0); // Set default size if 'mFace' is Swallow.
00205 }
00206 
00207 
00208 KJanusWidget::~KJanusWidget()
00209 {
00210   delete d;
00211 }
00212 
00213 
00214 bool KJanusWidget::isValid() const
00215 {
00216   return mValid;
00217 }
00218 
00219 
00220 QFrame *KJanusWidget::plainPage()
00221 {
00222   return mPlainPage;
00223 }
00224 
00225 
00226 int KJanusWidget::face() const
00227 {
00228   return mFace;
00229 }
00230 
00231 QWidget *KJanusWidget::FindParent()
00232 {
00233   if( mFace == Tabbed ) {
00234     return mTabControl;
00235   }
00236   else {
00237     return this;
00238   }
00239 }
00240 
00241 QFrame *KJanusWidget::addPage( const QStringList &items, const QString &header,
00242                    const QPixmap &pixmap )
00243 {
00244   if( !mValid )
00245   {
00246     kdDebug() << "addPage: Invalid object" << endl;
00247     return 0;
00248   }
00249 
00250   QFrame *page = new QFrame( FindParent(), "page" );
00251   addPageWidget( page, items, header, pixmap );
00252 
00253   return page;
00254 }
00255 
00256 void KJanusWidget::pageGone( QObject *obj )
00257 {
00258   removePage( static_cast<QWidget*>( obj ) );
00259 }
00260 
00261 void KJanusWidget::slotReopen( QListViewItem * item )
00262 {
00263   if( item )
00264     item->setOpen( true );
00265 }
00266 
00267 QFrame *KJanusWidget::addPage( const QString &itemName, const QString &header,
00268           const QPixmap &pixmap )
00269 {
00270   QStringList items;
00271   items << itemName;
00272   return addPage(items, header, pixmap);
00273 }
00274 
00275 
00276 
00277 QVBox *KJanusWidget::addVBoxPage( const QStringList &items,
00278           const QString &header,
00279           const QPixmap &pixmap )
00280 {
00281   if( !mValid )
00282   {
00283     kdDebug() << "addPage: Invalid object" << endl;
00284     return 0;
00285   }
00286 
00287   QVBox *page = new QVBox(FindParent() , "page" );
00288   page->setSpacing( KDialog::spacingHint() );
00289   addPageWidget( page, items, header, pixmap );
00290 
00291   return page;
00292 }
00293 
00294 QVBox *KJanusWidget::addVBoxPage( const QString &itemName,
00295                   const QString &header,
00296                   const QPixmap &pixmap )
00297 {
00298   QStringList items;
00299   items << itemName;
00300   return addVBoxPage(items, header, pixmap);
00301 }
00302 
00303 QHBox *KJanusWidget::addHBoxPage( const QStringList &items,
00304                   const QString &header,
00305                   const QPixmap &pixmap )
00306 {
00307   if( !mValid ) {
00308     kdDebug() << "addPage: Invalid object" << endl;
00309     return 0;
00310   }
00311 
00312   QHBox *page = new QHBox(FindParent(), "page");
00313   page->setSpacing( KDialog::spacingHint() );
00314   addPageWidget( page, items, header, pixmap );
00315 
00316   return page;
00317 }
00318 
00319 QHBox *KJanusWidget::addHBoxPage( const QString &itemName,
00320                   const QString &header,
00321                   const QPixmap &pixmap )
00322 {
00323   QStringList items;
00324   items << itemName;
00325   return addHBoxPage(items, header, pixmap);
00326 }
00327 
00328 QGrid *KJanusWidget::addGridPage( int n, Orientation dir,
00329                   const QStringList &items,
00330                   const QString &header,
00331                   const QPixmap &pixmap )
00332 {
00333   if( !mValid )
00334   {
00335     kdDebug() << "addPage: Invalid object" << endl;
00336     return 0;
00337   }
00338 
00339   QGrid *page = new QGrid( n, dir, FindParent(), "page" );
00340   page->setSpacing( KDialog::spacingHint() );
00341   addPageWidget( page, items, header, pixmap );
00342 
00343   return page;
00344 }
00345 
00346 
00347 QGrid *KJanusWidget::addGridPage( int n, Orientation dir,
00348                   const QString &itemName,
00349                   const QString &header,
00350                   const QPixmap &pixmap )
00351 {
00352   QStringList items;
00353   items << itemName;
00354   return addGridPage(n, dir, items, header, pixmap);
00355 }
00356 
00357 void KJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page)
00358 {
00359   bool isTop = true;
00360   QListViewItem *curTop = 0, *child, *last, *newChild;
00361   unsigned int index = 1;
00362   QStringList curPath;
00363 
00364   for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) {
00365     QString name = (*it);
00366     bool isPath = ( index != items.count() );
00367 
00368     // Find the first child.
00369     if (isTop) {
00370       child = mTreeList->firstChild();
00371     }
00372     else {
00373       child = curTop->firstChild();
00374     }
00375 
00376     // Now search for a child with the current Name, and if it we doesn't
00377     // find it, then remember the location of the last child.
00378     for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling());
00379 
00380     if (!last && !child) {
00381       // This node didn't have any children at all, lets just insert the
00382       // new child.
00383       if (isTop)
00384         newChild = new QListViewItem(mTreeList, name);
00385       else
00386         newChild = new QListViewItem(curTop, name);
00387 
00388     }
00389     else if (child) {
00390       // we found the given name in this child.
00391       if (!isPath) {
00392         kdDebug() << "The element inserted was already in the TreeList box!" << endl;
00393         return;
00394       }
00395       else {
00396         // Ok we found the folder
00397         newChild  = child;
00398       }
00399     }
00400     else {
00401       // the node had some children, but we didn't find the given name
00402       if (isTop)
00403         newChild = new QListViewItem(mTreeList, last, name);
00404       else
00405         newChild = new QListViewItem(curTop, last, name);
00406     }
00407 
00408     // Now make the element expandable if it is a path component, and make
00409     // ready for next loop
00410     if (isPath) {
00411       newChild->setExpandable(true);
00412       curTop = newChild;
00413       isTop = false;
00414       curPath << name;
00415 
00416       QString key = curPath.join("_/_");
00417       if (mFolderIconMap.contains(key)) {
00418         QPixmap p = mFolderIconMap[key];
00419         newChild->setPixmap(0,p);
00420       }
00421     }
00422     else {
00423       if (mShowIconsInTreeList) {
00424         newChild->setPixmap(0, pixmap);
00425       }
00426       mTreeListToPageStack.insert(newChild, page);
00427     }
00428   }
00429 }
00430 
00431 void KJanusWidget::addPageWidget( QFrame *page, const QStringList &items,
00432                   const QString &header,const QPixmap &pixmap )
00433 {
00434   connect(page, SIGNAL(destroyed(QObject*)), SLOT(pageGone(QObject*)));
00435 
00436   if( mFace == Tabbed )
00437   {
00438     mTabControl->addTab (page, items.last());
00439     d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page);
00440     d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex;
00441     d->mNextPageIndex++;
00442   }
00443   else if( mFace == TreeList || mFace == IconList )
00444   {
00445     d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page);
00446     d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex;
00447     mPageStack->addWidget( page, 0 );
00448 
00449     if (items.isEmpty()) {
00450       kdDebug() << "Invalid QStringList, with zero items" << endl;
00451       return;
00452     }
00453 
00454     if( mFace == TreeList )
00455     {
00456       InsertTreeListItem(items, pixmap, page);
00457     }
00458     else // mFace == IconList
00459     {
00460       QString itemName = items.last();
00461       IconListItem *item = new IconListItem( mIconList, pixmap, itemName );
00462       mIconListToPageStack.insert(item, page);
00463       mIconList->invalidateHeight();
00464       mIconList->invalidateWidth();
00465 
00466       if (mIconList->isVisible())
00467         mIconList->updateWidth();
00468     }
00469 
00470     //
00471     // Make sure the title label is sufficiently wide
00472     //
00473     QString lastName = items.last();
00474     const QString &title = (!header.isNull() ? header : lastName);
00475     QRect r = mTitleLabel->fontMetrics().boundingRect( title );
00476     if( mTitleLabel->minimumWidth() < r.width() )
00477     {
00478       mTitleLabel->setMinimumWidth( r.width() );
00479     }
00480     d->mIntToTitle[d->mNextPageIndex] = title;
00481     if( d->mIntToTitle.count() == 1 )
00482     {
00483       showPage(0);
00484     }
00485     d->mNextPageIndex++;
00486   }
00487   else
00488   {
00489     kdDebug() << "KJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" << endl;
00490   }
00491 
00492 }
00493 
00494 void KJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap)
00495 {
00496   QString key = path.join("_/_");
00497   mFolderIconMap.insert(key,pixmap);
00498 }
00499 
00500 
00501 
00502 bool KJanusWidget::setSwallowedWidget( QWidget *widget )
00503 {
00504   if( mFace != Swallow || !mValid )
00505   {
00506     return false;
00507   }
00508 
00509   //
00510   // Remove current layout and make a new.
00511   //
00512   delete mSwallowPage->layout();
00513 
00514   QGridLayout *gbox = new QGridLayout( mSwallowPage, 1, 1, 0 );
00515 
00516   //
00517   // Hide old children
00518   //
00519   QObjectList *l = (QObjectList*)mSwallowPage->children(); // silence please
00520   for( uint i=0; i < l->count(); i++ )
00521   {
00522     QObject *o = l->at(i);
00523     if( o->isWidgetType() )
00524     {
00525       ((QWidget*)o)->hide();
00526     }
00527   }
00528 
00529   //
00530   // Add new child or make default size
00531   //
00532   if( !widget )
00533   {
00534     gbox->addRowSpacing(0,100);
00535     gbox->addColSpacing(0,100);
00536     mSwallowPage->setMinimumSize(100,100);
00537   }
00538   else
00539   {
00540     if( widget->parent() != mSwallowPage )
00541     {
00542       widget->reparent( mSwallowPage, 0, QPoint(0,0) );
00543     }
00544     gbox->addWidget(widget, 0, 0 );
00545     gbox->activate();
00546     mSwallowPage->setMinimumSize( widget->minimumSize() );
00547   }
00548 
00549   return true;
00550 }
00551 
00552 bool KJanusWidget::slotShowPage()
00553 {
00554   if( !mValid )
00555   {
00556     return false;
00557   }
00558 
00559   if( mFace == TreeList )
00560   {
00561     QListViewItem *node = mTreeList->selectedItem();
00562     if( !node ) { return false; }
00563 
00564     QWidget *stackItem = mTreeListToPageStack[node];
00565     // Make sure to call through the virtual function showPage(int)
00566     return showPage(d->mPageToInt[stackItem]);
00567   }
00568   else if( mFace == IconList )
00569   {
00570     QListBoxItem *node = mIconList->item( mIconList->currentItem() );
00571     if( !node ) { return false; }
00572     QWidget *stackItem = mIconListToPageStack[node];
00573     // Make sure to call through the virtual function showPage(int)
00574     return showPage(d->mPageToInt[stackItem]);
00575   }
00576 
00577   return false;
00578 }
00579 
00580 
00581 bool KJanusWidget::showPage( int index )
00582 {
00583   if( !d || !mValid )
00584   {
00585     return false;
00586   }
00587   else
00588   {
00589     return showPage(d->mIntToPage[index]);
00590   }
00591 }
00592 
00593 
00594 bool KJanusWidget::showPage( QWidget *w )
00595 {
00596   if( !w || !mValid )
00597   {
00598     return false;
00599   }
00600 
00601   if( mFace == TreeList || mFace == IconList )
00602   {
00603     mPageStack->raiseWidget( w );
00604     mActivePageWidget = w;
00605 
00606     int index = d->mPageToInt[w];
00607     mTitleLabel->setText( d->mIntToTitle[index] );
00608     if( mFace == TreeList )
00609     {
00610       QMap<QListViewItem *, QWidget *>::Iterator it;
00611       for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){
00612         QListViewItem *key = it.key();
00613         QWidget *val = it.data();
00614         if (val == w) {
00615           mTreeList->setSelected(key, true );
00616           break;
00617         }
00618       }
00619     }
00620     else
00621     {
00622       QMap<QListBoxItem *, QWidget *>::Iterator it;
00623       for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){
00624         QListBoxItem *key = it.key();
00625         QWidget *val = it.data();
00626         if (val == w) {
00627           mIconList->setSelected( key, true );
00628           break;
00629         }
00630       }
00631     }
00632   }
00633   else if( mFace == Tabbed )
00634   {
00635     mTabControl->showPage(w);
00636     mActivePageWidget = w;
00637   }
00638   else
00639   {
00640     return false;
00641   }
00642 
00643   return true;
00644 }
00645 
00646 
00647 int KJanusWidget::activePageIndex() const
00648 {
00649   if( mFace == TreeList) {
00650     QListViewItem *node = mTreeList->selectedItem();
00651     if( !node ) { return -1; }
00652     QWidget *stackItem = mTreeListToPageStack[node];
00653     return d->mPageToInt[stackItem];
00654   }
00655   else if (mFace == IconList) {
00656     QListBoxItem *node = mIconList->item( mIconList->currentItem() );
00657     if( !node ) { return false; }
00658     QWidget *stackItem = mIconListToPageStack[node];
00659     return d->mPageToInt[stackItem];
00660   }
00661   else if( mFace == Tabbed ) {
00662     QWidget *widget = mTabControl->currentPage();
00663     return ( !widget ? -1 : d->mPageToInt[widget] );
00664   }
00665   else {
00666     return -1;
00667   }
00668 }
00669 
00670 
00671 int KJanusWidget::pageIndex( QWidget *widget ) const
00672 {
00673   if( !widget )
00674   {
00675     return -1;
00676   }
00677   else if( mFace == TreeList || mFace == IconList )
00678   {
00679     return d->mPageToInt[widget];
00680   }
00681   else if( mFace == Tabbed )
00682   {
00683     //
00684     // The user gets the real page widget with addVBoxPage(), addHBoxPage()
00685     // and addGridPage() but not with addPage() which returns a child of
00686     // the toplevel page. addPage() returns a QFrame so I check for that.
00687     //
00688     if( widget->isA("QFrame") )
00689     {
00690       return d->mPageToInt[widget->parentWidget()];
00691     }
00692     else
00693     {
00694       return d->mPageToInt[widget];
00695     }
00696   }
00697   else
00698   {
00699     return -1;
00700   }
00701 }
00702 
00703 void KJanusWidget::slotFontChanged()
00704 {
00705   if( mTitleLabel )
00706   {
00707     mTitleLabel->setFont( KGlobalSettings::generalFont() );
00708     QFont titleFont( mTitleLabel->font() );
00709     titleFont.setBold( true );
00710     mTitleLabel->setFont( titleFont );
00711   }
00712 
00713   if( mFace == IconList )
00714   {
00715     QFont listFont( mIconList->font() );
00716     listFont.setBold( true );
00717     mIconList->setFont( listFont );
00718     mIconList->invalidateHeight();
00719     mIconList->invalidateWidth();
00720   }
00721 }
00722 
00723 // makes the treelist behave like the list of kcontrol
00724 void KJanusWidget::slotItemClicked(QListViewItem *it)
00725 {
00726   if(it && (it->childCount()>0))
00727     it->setOpen(!it->isOpen());
00728 }
00729 
00730 // hack because qt does not support Q_OBJECT in nested classes
00731 void KJanusWidget::slotOnItem(QListBoxItem *qitem)
00732 {
00733   mIconList->slotOnItem( qitem );
00734 }  
00735 
00736 void KJanusWidget::setFocus()
00737 {
00738   if( !mValid ) { return; }
00739   if( mFace == TreeList )
00740   {
00741     mTreeList->setFocus();
00742   }
00743   if( mFace == IconList )
00744   {
00745     mIconList->setFocus();
00746   }
00747   else if( mFace == Tabbed )
00748   {
00749     mTabControl->setFocus();
00750   }
00751   else if( mFace == Swallow )
00752   {
00753     mSwallowPage->setFocus();
00754   }
00755   else if( mFace == Plain )
00756   {
00757     mPlainPage->setFocus();
00758   }
00759 }
00760 
00761 
00762 QSize KJanusWidget::minimumSizeHint() const
00763 {
00764   if( mFace == TreeList || mFace == IconList )
00765   {
00766     QSize s1( KDialog::spacingHint(), KDialog::spacingHint()*2 );
00767     QSize s2(0,0);
00768     QSize s3(0,0);
00769     QSize s4( mPageStack->sizeHint() );
00770 
00771     if( mFace == TreeList )
00772     {
00773       s1.rwidth() += style().pixelMetric( QStyle::PM_SplitterWidth );
00774       s2 = mTreeList->minimumSize();
00775     }
00776     else
00777     {
00778       mIconList->updateMinimumHeight();
00779       mIconList->updateWidth();
00780       s2 = mIconList->minimumSize();
00781     }
00782 
00783     if( mTitleLabel->isVisible() )
00784     {
00785       s3 += mTitleLabel->sizeHint();
00786       s3.rheight() += mTitleSep->minimumSize().height();
00787     }
00788 
00789     //
00790     // Select the tallest item. It has only effect in IconList mode
00791     //
00792     int h1 = s1.rheight() + s3.rheight() + s4.height();
00793     int h2 = QMAX( h1, s2.rheight() );
00794 
00795     return QSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 );
00796   }
00797   else if( mFace == Tabbed )
00798   {
00799     return mTabControl->sizeHint();
00800   }
00801   else if( mFace == Swallow )
00802   {
00803     return mSwallowPage->minimumSize();
00804   }
00805   else if( mFace == Plain )
00806   {
00807     return mPlainPage->sizeHint();
00808   }
00809   else
00810   {
00811     return QSize( 100, 100 ); // Should never happen though.
00812   }
00813 
00814 }
00815 
00816 
00817 QSize KJanusWidget::sizeHint() const
00818 {
00819   return minimumSizeHint();
00820 }
00821 
00822 
00823 void KJanusWidget::setTreeListAutoResize( bool state )
00824 {
00825   if( mFace == TreeList )
00826   {
00827     mTreeListResizeMode = !state ?
00828       QSplitter::KeepSize : QSplitter::Stretch;
00829     if( d->mSplitter )
00830       d->mSplitter->setResizeMode( d->mListFrame, mTreeListResizeMode );
00831   }
00832 }
00833 
00834 
00835 void KJanusWidget::setIconListAllVisible( bool state )
00836 {
00837   if( mFace == IconList )
00838   {
00839     mIconList->setShowAll( state );
00840   }
00841 }
00842 
00843 void KJanusWidget::setShowIconsInTreeList( bool state )
00844 {
00845   mShowIconsInTreeList = state;
00846 }
00847 
00848 void KJanusWidget::setRootIsDecorated( bool state )
00849 {
00850   if( mFace == TreeList ) {
00851     mTreeList->setRootIsDecorated(state);
00852   }
00853 }
00854 
00855 void KJanusWidget::unfoldTreeList( bool persist )
00856 {
00857   if( mFace == TreeList )
00858   {
00859     if( persist )
00860       connect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
00861     else
00862       disconnect( mTreeList, SIGNAL( collapsed( QListViewItem * ) ), this, SLOT( slotReopen( QListViewItem * ) ) );
00863 
00864     for( QListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() )
00865       item->setOpen( true );
00866   }
00867 }
00868 
00869 void KJanusWidget::addWidgetBelowList( QWidget * widget )
00870 {
00871   if( ( mFace == TreeList || mFace == IconList ) && d->mListFrame )
00872   {
00873     widget->reparent( d->mListFrame, QPoint() );
00874   }
00875 }
00876 
00877 void KJanusWidget::addButtonBelowList( const QString & text, QObject * recv, const char * slot )
00878 {
00879   if( ( mFace == TreeList || mFace == IconList ) && d->mListFrame )
00880   {
00881     QPushButton * button = new QPushButton( text, d->mListFrame );
00882     connect( button, SIGNAL( clicked() ), recv, slot );
00883   }
00884 }
00885 
00886 void KJanusWidget::addButtonBelowList( const KGuiItem & item, QObject * recv, const char * slot )
00887 {
00888   if( ( mFace == TreeList || mFace == IconList ) && d->mListFrame )
00889   {
00890     KPushButton * button = new KPushButton( item, d->mListFrame );
00891     connect( button, SIGNAL( clicked() ), recv, slot );
00892   }
00893 }
00894 
00895 void KJanusWidget::showEvent( QShowEvent * )
00896 {
00897   if( mFace == TreeList )
00898   {
00899     if( d->mSplitter )
00900       d->mSplitter->setResizeMode( d->mListFrame, mTreeListResizeMode );
00901   }
00902 }
00903 
00904 
00905 //
00906 // 2000-13-02 Espen Sand
00907 // It should be obvious that this eventfilter must only be
00908 // be installed on the vertical scrollbar of the mIconList.
00909 //
00910 bool KJanusWidget::eventFilter( QObject *o, QEvent *e )
00911 {
00912   if( e->type() == QEvent::Show )
00913   {
00914     IconListItem *item = (IconListItem*)mIconList->item(0);
00915     if( item )
00916     {
00917       int lw = item->width( mIconList );
00918       int sw = mIconList->verticalScrollBar()->sizeHint().width();
00919       mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 );
00920     }
00921   }
00922   else if( e->type() == QEvent::Hide )
00923   {
00924     IconListItem *item = (IconListItem*)mIconList->item(0);
00925     if( item )
00926     {
00927       int lw = item->width( mIconList );
00928       mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 );
00929     }
00930   }
00931   return QWidget::eventFilter( o, e );
00932 }
00933 
00934 
00935 
00936 //
00937 // Code for the icon list box
00938 //
00939 
00940 
00941 KJanusWidget::IconListBox::IconListBox( QWidget *parent, const char *name,
00942                     WFlags f )
00943   :KListBox( parent, name, f ), mShowAll(false), mHeightValid(false),
00944    mWidthValid(false),
00945    mOldItem(0) 
00946 {
00947 }
00948 
00949 void KJanusWidget::IconListBox::updateMinimumHeight()
00950 {
00951   if( mShowAll && !mHeightValid )
00952   {
00953     int h = frameWidth()*2;
00954     for( QListBoxItem *i = item(0); i; i = i->next() )
00955     {
00956       h += i->height( this );
00957     }
00958     setMinimumHeight( h );
00959     mHeightValid = true;
00960   }
00961 }
00962 
00963 
00964 void KJanusWidget::IconListBox::updateWidth()
00965 {
00966   if( !mWidthValid )
00967   {
00968     int maxWidth = 10;
00969     for( QListBoxItem *i = item(0); i; i = i->next() )
00970     {
00971       int w = ((IconListItem *)i)->width(this);
00972       maxWidth = QMAX( w, maxWidth );
00973     }
00974 
00975     for( QListBoxItem *i = item(0); i; i = i->next() )
00976     {
00977       ((IconListItem *)i)->expandMinimumWidth( maxWidth );
00978     }
00979 
00980     if( verticalScrollBar()->isVisible() )
00981     {
00982       maxWidth += verticalScrollBar()->sizeHint().width();
00983     }
00984 
00985     setFixedWidth( maxWidth + frameWidth()*2 );
00986     mWidthValid = true;
00987   }
00988 }
00989 
00990 
00991 void KJanusWidget::IconListBox::invalidateHeight()
00992 {
00993   mHeightValid = false;
00994 }
00995 
00996 
00997 void KJanusWidget::IconListBox::invalidateWidth()
00998 {
00999   mWidthValid = false;
01000 }
01001 
01002 
01003 void KJanusWidget::IconListBox::setShowAll( bool showAll )
01004 {
01005   mShowAll = showAll;
01006   mHeightValid = false;
01007 }
01008 
01009 
01010 void KJanusWidget::IconListBox::leaveEvent( QEvent *ev )
01011 {
01012   KListBox::leaveEvent( ev ); 
01013 
01014   if ( mOldItem && !mOldItem->isSelected() )
01015   {
01016     ((KJanusWidget::IconListItem *) mOldItem)->highlight( true );
01017     mOldItem = 0;
01018   }
01019 } 
01020 
01021 // hack because qt does not support Q_OBJECT in nested classes
01022 void KJanusWidget::IconListBox::slotOnItem(QListBoxItem *qitem)
01023 {
01024   KListBox::slotOnItem( qitem );
01025 
01026   if ( qitem == mOldItem )
01027   {
01028     return;
01029   }
01030  
01031   if ( mOldItem && !mOldItem->isSelected() )
01032   {
01033     ((KJanusWidget::IconListItem *) mOldItem)->highlight( true );
01034   }
01035 
01036   KJanusWidget::IconListItem *item = dynamic_cast< KJanusWidget::IconListItem * >( qitem );
01037   if ( item && !item->isSelected() )
01038   {      
01039     item->highlight( false );
01040     mOldItem = item;
01041   }
01042   else
01043   {
01044     mOldItem = 0;
01045   }
01046 }  
01047 
01048 
01049 
01050 KJanusWidget::IconListItem::IconListItem( QListBox *listbox, const QPixmap &pixmap,
01051                                           const QString &text )
01052   : QListBoxItem( listbox )
01053 {
01054   mPixmap = pixmap;
01055   if( mPixmap.isNull() )
01056   {
01057     mPixmap = defaultPixmap();
01058   }
01059   setText( text );
01060   setCustomHighlighting( true );
01061   mMinimumWidth = 0;
01062 }
01063 
01064 
01065 int KJanusWidget::IconListItem::expandMinimumWidth( int width )
01066 {
01067   mMinimumWidth = QMAX( mMinimumWidth, width );
01068   return mMinimumWidth;
01069 }
01070 
01071 
01072 void KJanusWidget::IconListItem::highlight( bool erase )
01073 {   
01074    QRect r = listBox()->itemRect( this );
01075    r.addCoords( 1, 1, -1, -1 );  
01076    
01077    QPainter p( listBox()->viewport() );
01078    p.setClipRegion( r );
01079    
01080    const QColorGroup &cg = listBox()->colorGroup();
01081    if ( erase )
01082    {
01083       p.setPen( cg.base() );
01084       p.setBrush( cg.base() );
01085       p.drawRect( r );
01086    }
01087    else
01088    {
01089       p.setBrush( cg.highlight().light( 120 ) );
01090       p.drawRect( r );
01091 
01092       p.setPen( cg.highlight().dark( 140 ) );
01093       p.drawRect( r ); 
01094    }
01095       
01096    p.setPen( cg.foreground() );
01097    p.translate( r.x() - 1, r.y() - 1 );
01098    paintContents( &p );
01099 }
01100 
01101 
01102 const QPixmap &KJanusWidget::IconListItem::defaultPixmap()
01103 {
01104   static QPixmap *pix=0;
01105   if( !pix )
01106   {
01107     pix = new QPixmap( 32, 32 );
01108     QPainter p( pix );
01109     p.eraseRect( 0, 0, pix->width(), pix->height() );
01110     p.setPen( Qt::red );
01111     p.drawRect ( 0, 0, pix->width(), pix->height() );
01112     p.end();
01113 
01114     QBitmap mask( pix->width(), pix->height(), true );
01115     mask.fill( Qt::black );
01116     p.begin( &mask );
01117     p.setPen( Qt::white );
01118     p.drawRect ( 0, 0, pix->width(), pix->height() );
01119     p.end();
01120 
01121     pix->setMask( mask );
01122   }
01123   return *pix;
01124 }
01125 
01126 
01127 void KJanusWidget::IconListItem::paint( QPainter *painter )
01128 {
01129   QRect itemPaintRegion( listBox()->itemRect( this ) );
01130   QRect r( 1, 1, itemPaintRegion.width() - 2, itemPaintRegion.height() - 2);
01131 
01132   if ( isSelected() )
01133   {
01134     painter->eraseRect( r );
01135 
01136     painter->save();
01137     painter->setPen( listBox()->colorGroup().highlight().dark( 160 ) );
01138     painter->drawRect( r );
01139     painter->restore();
01140   }
01141 
01142   paintContents( painter );
01143 }
01144 
01145 
01146 void KJanusWidget::IconListItem::paintContents( QPainter *painter )
01147 {
01148   QFontMetrics fm = painter->fontMetrics();
01149   int ht = fm.boundingRect( 0, 0, 0, 0, Qt::AlignCenter, text() ).height();
01150   int wp = mPixmap.width();
01151   int hp = mPixmap.height();
01152   painter->drawPixmap( (mMinimumWidth - wp) / 2, 5, mPixmap );
01153 
01154   if( !text().isEmpty() )
01155   {
01156     painter->drawText( 1, hp + 7, mMinimumWidth - 2, ht, Qt::AlignCenter, text() );
01157   }
01158 }
01159 
01160 int KJanusWidget::IconListItem::height( const QListBox *lb ) const
01161 {
01162   if( text().isEmpty() )
01163   {
01164     return mPixmap.height();
01165   }
01166   else
01167   {
01168     int ht = lb->fontMetrics().boundingRect( 0, 0, 0, 0, Qt::AlignCenter, text() ).height();
01169     return (mPixmap.height() + ht + 10);
01170   }
01171 }
01172 
01173 
01174 int KJanusWidget::IconListItem::width( const QListBox *lb ) const
01175 {
01176   int wt = lb->fontMetrics().boundingRect( 0, 0, 0, 0, Qt::AlignCenter, text() ).width() + 10;
01177   int wp = mPixmap.width() + 10;
01178   int w  = QMAX( wt, wp );
01179   return QMAX( w, mMinimumWidth );
01180 }
01181 
01182 
01183 void KJanusWidget::virtual_hook( int, void* )
01184 { /*BASE::virtual_hook( id, data );*/ }
01185 
01186 
01187 // TODO: In TreeList, if the last child of a node is removed, and there is no corrsponding widget for that node, allow the caller to
01188 // delete the node.
01189 void KJanusWidget::removePage( QWidget *page )
01190 {
01191   if (!d || !d->mPageToInt.contains(page))
01192     return;
01193 
01194   int index = d->mPageToInt[page];
01195 
01196   if ( mFace == TreeList )
01197   {
01198     QMap<QListViewItem*, QWidget *>::Iterator i;
01199     for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i )
01200       if (i.data()==page)
01201       {
01202         delete i.key();
01203         mPageStack->removeWidget(page);
01204         mTreeListToPageStack.remove(i);
01205         d->mIntToTitle.remove(index);
01206         d->mPageToInt.remove(page);
01207         d->mIntToPage.remove(index);
01208         break;
01209       }
01210   }
01211   else if ( mFace == IconList )
01212   {
01213     QMap<QListBoxItem*, QWidget *>::Iterator i;
01214     for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i )
01215       if (i.data()==page)
01216       {
01217         delete i.key();
01218         mPageStack->removeWidget(page);
01219         mIconListToPageStack.remove(i);
01220         d->mIntToTitle.remove(index);
01221         d->mPageToInt.remove(page);
01222         d->mIntToPage.remove(index);
01223         break;
01224       }
01225   }
01226   else // Tabbed
01227   {
01228     mTabControl->removePage(page);
01229     d->mPageToInt.remove(page);
01230     d->mIntToPage.remove(index);
01231   }
01232 }
01233 
01234 
01235 QString KJanusWidget::pageTitle(int index) const
01236 {
01237   if (!d || !d->mIntToTitle.contains(index))
01238     return QString::null;
01239   else
01240     return d->mIntToTitle[index];
01241 }
01242 
01243 
01244 QWidget *KJanusWidget::pageWidget(int index) const
01245 {
01246   if (!d || !d->mIntToPage.contains(index))
01247     return 0;
01248   else
01249     return d->mIntToPage[index];
01250 }
01251 
01252 #include "kjanuswidget.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.4.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Oct 9 07:56:04 2005 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003