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