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     connect(mTabControl, SIGNAL(currentChanged(QWidget *)),
00180             SIGNAL(aboutToShowPage(QWidget *)));
00181     topLayout->addWidget( mTabControl, 10 );
00182   }
00183   else if( mFace == Swallow )
00184   {
00185     mSwallowPage = new QWidget( this );
00186     topLayout->addWidget( mSwallowPage, 10 );
00187   }
00188   else
00189   {
00190     mFace = Plain;
00191     mPlainPage = new QFrame( this );
00192     topLayout->addWidget( mPlainPage, 10 );
00193   }
00194 
00195   if ( kapp )
00196     connect(kapp,SIGNAL(kdisplayFontChanged()),SLOT(slotFontChanged()));
00197   mValid = true;
00198 
00199   setSwallowedWidget(0); // Set default size if 'mFace' is Swallow.
00200 }
00201 
00202 
00203 KJanusWidget::~KJanusWidget()
00204 {
00205   delete d;
00206 }
00207 
00208 
00209 bool KJanusWidget::isValid() const
00210 {
00211   return mValid;
00212 }
00213 
00214 
00215 QFrame *KJanusWidget::plainPage()
00216 {
00217   return mPlainPage;
00218 }
00219 
00220 
00221 int KJanusWidget::face() const
00222 {
00223   return mFace;
00224 }
00225 
00226 QWidget *KJanusWidget::FindParent()
00227 {
00228   if( mFace == Tabbed ) {
00229     return mTabControl;
00230   }
00231   else {
00232     return this;
00233   }
00234 }
00235 
00236 QFrame *KJanusWidget::addPage( const QStringList &items, const QString &header,
00237                    const QPixmap &pixmap )
00238 {
00239   if( !mValid )
00240   {
00241     kdDebug() << "addPage: Invalid object" << endl;
00242     return 0;
00243   }
00244 
00245   QFrame *page = new QFrame( FindParent(), "page" );
00246   addPageWidget( page, items, header, pixmap );
00247 
00248   return page;
00249 }
00250 
00251 void KJanusWidget::pageGone( QObject *obj )
00252 {
00253   removePage( static_cast<QWidget*>( obj ) );
00254 }
00255 
00256 void KJanusWidget::slotReopen( QListViewItem * item )
00257 {
00258   if( item )
00259     item->setOpen( true );
00260 }
00261 
00262 QFrame *KJanusWidget::addPage( const QString &itemName, const QString &header,
00263                    const QPixmap &pixmap )
00264 {
00265   QStringList items;
00266   items << itemName;
00267   return addPage(items, header, pixmap);
00268 }
00269 
00270 
00271 
00272 QVBox *KJanusWidget::addVBoxPage( const QStringList &items,
00273                   const QString &header,
00274                   const QPixmap &pixmap )
00275 {
00276   if( !mValid )
00277   {
00278     kdDebug() << "addPage: Invalid object" << endl;
00279     return 0;
00280   }
00281 
00282   QVBox *page = new QVBox(FindParent() , "page" );
00283   page->setSpacing( KDialog::spacingHint() );
00284   addPageWidget( page, items, header, pixmap );
00285 
00286   return page;
00287 }
00288 
00289 QVBox *KJanusWidget::addVBoxPage( const QString &itemName,
00290                   const QString &header,
00291                   const QPixmap &pixmap )
00292 {
00293   QStringList items;
00294   items << itemName;
00295   return addVBoxPage(items, header, pixmap);
00296 }
00297 
00298 QHBox *KJanusWidget::addHBoxPage( const QStringList &items,
00299                   const QString &header,
00300                   const QPixmap &pixmap )
00301 {
00302   if( !mValid ) {
00303     kdDebug() << "addPage: Invalid object" << endl;
00304     return 0;
00305   }
00306 
00307   QHBox *page = new QHBox(FindParent(), "page");
00308   page->setSpacing( KDialog::spacingHint() );
00309   addPageWidget( page, items, header, pixmap );
00310 
00311   return page;
00312 }
00313 
00314 QHBox *KJanusWidget::addHBoxPage( const QString &itemName,
00315                   const QString &header,
00316                   const QPixmap &pixmap )
00317 {
00318   QStringList items;
00319   items << itemName;
00320   return addHBoxPage(items, header, pixmap);
00321 }
00322 
00323 QGrid *KJanusWidget::addGridPage( int n, Orientation dir,
00324                   const QStringList &items,
00325                   const QString &header,
00326                   const QPixmap &pixmap )
00327 {
00328   if( !mValid )
00329   {
00330     kdDebug() << "addPage: Invalid object" << endl;
00331     return 0;
00332   }
00333 
00334   QGrid *page = new QGrid( n, dir, FindParent(), "page" );
00335   page->setSpacing( KDialog::spacingHint() );
00336   addPageWidget( page, items, header, pixmap );
00337 
00338   return page;
00339 }
00340 
00341 
00342 QGrid *KJanusWidget::addGridPage( int n, Orientation dir,
00343                   const QString &itemName,
00344                   const QString &header,
00345                   const QPixmap &pixmap )
00346 {
00347   QStringList items;
00348   items << itemName;
00349   return addGridPage(n, dir, items, header, pixmap);
00350 }
00351 
00352 void KJanusWidget::InsertTreeListItem(const QStringList &items, const QPixmap &pixmap, QFrame *page)
00353 {
00354   bool isTop = true;
00355   QListViewItem *curTop = 0, *child, *last, *newChild;
00356   unsigned int index = 1;
00357   QStringList curPath;
00358 
00359   for ( QStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) {
00360     QString name = (*it);
00361     bool isPath = ( index != items.count() );
00362 
00363     // Find the first child.
00364     if (isTop) {
00365       child = mTreeList->firstChild();
00366     }
00367     else {
00368       child = curTop->firstChild();
00369     }
00370 
00371     // Now search for a child with the current Name, and if it we doesn't
00372     // find it, then remember the location of the last child.
00373     for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling());
00374 
00375     if (!last && !child) {
00376       // This node didn't have any children at all, lets just insert the
00377       // new child.
00378       if (isTop)
00379         newChild = new QListViewItem(mTreeList, name);
00380       else
00381         newChild = new QListViewItem(curTop, name);
00382 
00383     }
00384     else if (child) {
00385       // we found the given name in this child.
00386       if (!isPath) {
00387         kdDebug() << "The element inserted was already in the TreeList box!" << endl;
00388         return;
00389       }
00390       else {
00391         // Ok we found the folder
00392         newChild  = child;
00393       }
00394     }
00395     else {
00396       // the node had some children, but we didn't find the given name
00397       if (isTop)
00398         newChild = new QListViewItem(mTreeList, last, name);
00399       else
00400         newChild = new QListViewItem(curTop, last, name);
00401     }
00402 
00403     // Now make the element expandable if it is a path component, and make
00404     // ready for next loop
00405     if (isPath) {
00406       newChild->setExpandable(true);
00407       curTop = newChild;
00408       isTop = false;
00409       curPath << name;
00410 
00411       QString key = curPath.join("_/_");
00412       if (mFolderIconMap.contains(key)) {
00413         QPixmap p = mFolderIconMap[key];
00414         newChild->setPixmap(0,p);
00415       }
00416     }
00417     else {
00418       if (mShowIconsInTreeList) {
00419         newChild->setPixmap(0, pixmap);
00420       }
00421       mTreeListToPageStack.insert(newChild, page);
00422     }
00423   }
00424 }
00425 
00426 void KJanusWidget::addPageWidget( QFrame *page, const QStringList &items,
00427                   const QString &header,const QPixmap &pixmap )
00428 {
00429   connect(page, SIGNAL(destroyed(QObject*)), SLOT(pageGone(QObject*)));
00430 
00431   if( mFace == Tabbed )
00432   {
00433     mTabControl->addTab (page, items.last());
00434     d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page);
00435     d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex;
00436     d->mNextPageIndex++;
00437   }
00438   else if( mFace == TreeList || mFace == IconList )
00439   {
00440     d->mIntToPage[d->mNextPageIndex] = static_cast<QWidget*>(page);
00441     d->mPageToInt[static_cast<QWidget*>(page)] = d->mNextPageIndex;
00442     mPageStack->addWidget( page, 0 );
00443 
00444     if (items.isEmpty()) {
00445       kdDebug() << "Invalid QStringList, with zero items" << endl;
00446       return;
00447     }
00448 
00449     if( mFace == TreeList )
00450     {
00451       InsertTreeListItem(items, pixmap, page);
00452     }
00453     else // mFace == IconList
00454     {
00455       QString itemName = items.last();
00456       IconListItem *item = new IconListItem( mIconList, pixmap, itemName );
00457       mIconListToPageStack.insert(item, page);
00458       mIconList->invalidateHeight();
00459       mIconList->invalidateWidth();
00460 
00461       if (mIconList->isVisible())
00462         mIconList->updateWidth();
00463     }
00464 
00465     //
00466     // Make sure the title label is sufficiently wide
00467     //
00468     QString lastName = items.last();
00469     const QString &title = (!header.isNull() ? header : lastName);
00470     QRect r = mTitleLabel->fontMetrics().boundingRect( title );
00471     if( mTitleLabel->minimumWidth() < r.width() )
00472     {
00473       mTitleLabel->setMinimumWidth( r.width() );
00474     }
00475     d->mIntToTitle[d->mNextPageIndex] = title;
00476     if( d->mIntToTitle.count() == 1 )
00477     {
00478       showPage(0);
00479     }
00480     d->mNextPageIndex++;
00481   }
00482   else
00483   {
00484     kdDebug() << "KJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" << endl;
00485   }
00486 
00487 }
00488 
00489 void KJanusWidget::setFolderIcon(const QStringList &path, const QPixmap &pixmap)
00490 {
00491   QString key = path.join("_/_");
00492   mFolderIconMap.insert(key,pixmap);
00493 }
00494 
00495 
00496 
00497 bool KJanusWidget::setSwallowedWidget( QWidget *widget )
00498 {
00499   if( mFace != Swallow || !mValid )
00500   {
00501     return false;
00502   }
00503 
00504   //
00505   // Remove current layout and make a new.
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 )
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 )
00550   {
00551     return false;
00552   }
00553 
00554   if( mFace == TreeList )
00555   {
00556     QListViewItem *node = mTreeList->selectedItem();
00557     if( !node ) { 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 ) { 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 || !mValid )
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 || !mValid )
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 ) { 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 ) { 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 ? -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 )
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 )
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 ) { 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() )
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 ?
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 )
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 )
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 && !mHeightValid )
00941   {
00942     int h = frameWidth()*2;
00943     for( QListBoxItem *i = item(0); i; 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 )
00956   {
00957     int maxWidth = 10;
00958     for( QListBoxItem *i = item(0); i; 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; 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() )
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 )
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() )
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() )
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.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Aug 2 12:23:19 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003