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