diff options
Diffstat (limited to 'tdeui/kjanuswidget.cpp')
-rw-r--r-- | tdeui/kjanuswidget.cpp | 1255 |
1 files changed, 1255 insertions, 0 deletions
diff --git a/tdeui/kjanuswidget.cpp b/tdeui/kjanuswidget.cpp new file mode 100644 index 000000000..d42f67e35 --- /dev/null +++ b/tdeui/kjanuswidget.cpp @@ -0,0 +1,1255 @@ +/* This file is part of the KDE Libraries + * Copyright (C) 1999-2000 Espen Sand (espensa@online.no) + * Copyright (C) 2003 Ravikiran Rajagopal (ravi@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include <tqbitmap.h> +#include <tqgrid.h> +#include <tqhbox.h> +#include <tqheader.h> +#include <tqlabel.h> +#include <tqlayout.h> +#include <tqobjectlist.h> +#include <tqpixmap.h> +#include <tqsplitter.h> +#include <tqtabwidget.h> +#include <tqvbox.h> +#include <tqwidgetstack.h> +#include <tqpainter.h> +#include <tqstyle.h> + +#include <kapplication.h> +#include <kdialog.h> // Access to some static members +#include <klocale.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kseparator.h> +#include <kdebug.h> +#include "kjanuswidget.h" +#include <klistview.h> +#include "kpushbutton.h" +#include "kguiitem.h" + +class KJanusWidget::IconListItem : public TQListBoxItem +{ + public: + IconListItem( TQListBox *listbox, const TQPixmap &pixmap, + const TQString &text ); + virtual int height( const TQListBox *lb ) const; + virtual int width( const TQListBox *lb ) const; + int expandMinimumWidth( int width ); + void highlight( bool erase ); + + protected: + const TQPixmap &defaultPixmap(); + void paint( TQPainter *painter ); + + private: + void paintContents( TQPainter *painter ); + + TQPixmap mPixmap; + int mMinimumWidth; +}; + +class KJanusWidget::KJanusWidgetPrivate +{ +public: + KJanusWidgetPrivate() : mNextPageIndex(0), mListFrame( 0 ) { } + + int mNextPageIndex; // The next page index. + + // Dictionary for multipage modes. + TQMap<int,TQWidget*> mIntToPage; + // Reverse dictionary. Used because showPage() may be performance critical. + TQMap<TQWidget*,int> mPageToInt; + // Dictionary of title string associated with page. + TQMap<int, TQString> mIntToTitle; + + TQWidget * mListFrame; + TQSplitter * mSplitter; +}; + +template class TQPtrList<TQListViewItem>; + + +KJanusWidget::KJanusWidget( TQWidget *parent, const char *name, int face ) + : TQWidget( parent, name, 0 ), + mValid(false), mPageList(0), + mTitleList(0), mFace(face), mTitleLabel(0), mActivePageWidget(0), + mShowIconsInTreeList(false), d(0) +{ + TQVBoxLayout *topLayout = new TQVBoxLayout( this ); + + if( mFace == TreeList || mFace == IconList ) + { + d = new KJanusWidgetPrivate; + d->mSplitter = 0; + + TQFrame *page; + if( mFace == TreeList ) + { + d->mSplitter = new TQSplitter( this ); + topLayout->addWidget( d->mSplitter, 10 ); + mTreeListResizeMode = TQSplitter::KeepSize; + + d->mListFrame = new TQWidget( d->mSplitter ); + TQVBoxLayout *dummy = new TQVBoxLayout( d->mListFrame, 0, KDialog::spacingHint() ); + dummy->setAutoAdd( true ); + mTreeList = new KListView( d->mListFrame ); + mTreeList->addColumn( TQString::null ); + mTreeList->header()->hide(); + mTreeList->setRootIsDecorated(true); + mTreeList->setSorting( -1 ); + connect( mTreeList, TQT_SIGNAL(selectionChanged()), TQT_SLOT(slotShowPage()) ); + connect( mTreeList, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(slotItemClicked(TQListViewItem *))); + + // + // Page area. Title at top with a separator below and a pagestack using + // all available space at bottom. + // + TQFrame *p = new TQFrame( d->mSplitter ); + + TQHBoxLayout *hbox = new TQHBoxLayout( p, 0, 0 ); + + page = new TQFrame( p ); + hbox->addWidget( page, 10 ); + } + else + { + TQHBoxLayout *hbox = new TQHBoxLayout( topLayout ); + d->mListFrame = new TQWidget( this ); + hbox->addWidget( d->mListFrame ); + + ( new TQVBoxLayout( d->mListFrame, 0, 0 ) )->setAutoAdd( true ); + mIconList = new IconListBox( d->mListFrame ); + + TQFont listFont( mIconList->font() ); + listFont.setBold( true ); + mIconList->setFont( listFont ); + + mIconList->verticalScrollBar()->installEventFilter( this ); + connect( mIconList, TQT_SIGNAL(selectionChanged()), TQT_SLOT(slotShowPage())); + connect( mIconList, TQT_SIGNAL(onItem(TQListBoxItem *)), TQT_SLOT(slotOnItem(TQListBoxItem *))); + + hbox->addSpacing( KDialog::marginHint() ); + page = new TQFrame( this ); + hbox->addWidget( page, 10 ); + } + + // + // Rest of page area. Title at top with a separator below and a + // pagestack using all available space at bottom. + // + + TQVBoxLayout *vbox = new TQVBoxLayout( page, 0, KDialog::spacingHint() ); + + mTitleLabel = new TQLabel( i18n("Empty Page"), page, "KJanusWidgetTitleLabel" ); + vbox->addWidget( mTitleLabel, 0, TQApplication::reverseLayout() ? AlignRight : AlignLeft ); + + TQFont titleFont( mTitleLabel->font() ); + titleFont.setBold( true ); + mTitleLabel->setFont( titleFont ); + + mTitleSep = new KSeparator( page ); + mTitleSep->setFrameStyle( TQFrame::HLine|TQFrame::Plain ); + vbox->addWidget( mTitleSep ); + + mPageStack = new TQWidgetStack( page ); + connect(mPageStack, TQT_SIGNAL(aboutToShow(TQWidget *)), + TQT_SIGNAL(aboutToShowPage(TQWidget *))); + vbox->addWidget( mPageStack, 10 ); + } + else if( mFace == Tabbed ) + { + d = new KJanusWidgetPrivate; + + mTabControl = new TQTabWidget( this ); + mTabControl->setMargin (KDialog::marginHint()); + connect(mTabControl, TQT_SIGNAL(currentChanged(TQWidget *)), + TQT_SIGNAL(aboutToShowPage(TQWidget *))); + topLayout->addWidget( mTabControl, 10 ); + } + else if( mFace == Swallow ) + { + mSwallowPage = new TQWidget( this ); + topLayout->addWidget( mSwallowPage, 10 ); + } + else + { + mFace = Plain; + mPlainPage = new TQFrame( this ); + topLayout->addWidget( mPlainPage, 10 ); + } + + if ( kapp ) + connect(kapp,TQT_SIGNAL(kdisplayFontChanged()),TQT_SLOT(slotFontChanged())); + mValid = true; + + setSwallowedWidget(0); // Set default size if 'mFace' is Swallow. +} + + +KJanusWidget::~KJanusWidget() +{ + delete d; +} + + +bool KJanusWidget::isValid() const +{ + return mValid; +} + + +TQFrame *KJanusWidget::plainPage() +{ + return mPlainPage; +} + + +int KJanusWidget::face() const +{ + return mFace; +} + +TQWidget *KJanusWidget::FindParent() +{ + if( mFace == Tabbed ) { + return mTabControl; + } + else { + return this; + } +} + +TQFrame *KJanusWidget::addPage( const TQStringList &items, const TQString &header, + const TQPixmap &pixmap ) +{ + if( !mValid ) + { + kdDebug() << "addPage: Invalid object" << endl; + return 0; + } + + TQFrame *page = new TQFrame( FindParent(), "page" ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +void KJanusWidget::pageGone( TQObject *obj ) +{ + removePage( TQT_TQWIDGET( obj ) ); +} + +void KJanusWidget::slotReopen( TQListViewItem * item ) +{ + if( item ) + item->setOpen( true ); +} + +TQFrame *KJanusWidget::addPage( const TQString &itemName, const TQString &header, + const TQPixmap &pixmap ) +{ + TQStringList items; + items << itemName; + return addPage(items, header, pixmap); +} + + + +TQVBox *KJanusWidget::addVBoxPage( const TQStringList &items, + const TQString &header, + const TQPixmap &pixmap ) +{ + if( !mValid ) + { + kdDebug() << "addPage: Invalid object" << endl; + return 0; + } + + TQVBox *page = new TQVBox(FindParent() , "page" ); + page->setSpacing( KDialog::spacingHint() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +TQVBox *KJanusWidget::addVBoxPage( const TQString &itemName, + const TQString &header, + const TQPixmap &pixmap ) +{ + TQStringList items; + items << itemName; + return addVBoxPage(items, header, pixmap); +} + +TQHBox *KJanusWidget::addHBoxPage( const TQStringList &items, + const TQString &header, + const TQPixmap &pixmap ) +{ + if( !mValid ) { + kdDebug() << "addPage: Invalid object" << endl; + return 0; + } + + TQHBox *page = new TQHBox(FindParent(), "page"); + page->setSpacing( KDialog::spacingHint() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + +TQHBox *KJanusWidget::addHBoxPage( const TQString &itemName, + const TQString &header, + const TQPixmap &pixmap ) +{ + TQStringList items; + items << itemName; + return addHBoxPage(items, header, pixmap); +} + +TQGrid *KJanusWidget::addGridPage( int n, Orientation dir, + const TQStringList &items, + const TQString &header, + const TQPixmap &pixmap ) +{ + if( !mValid ) + { + kdDebug() << "addPage: Invalid object" << endl; + return 0; + } + + TQGrid *page = new TQGrid( n, dir, FindParent(), "page" ); + page->setSpacing( KDialog::spacingHint() ); + addPageWidget( page, items, header, pixmap ); + + return page; +} + + +TQGrid *KJanusWidget::addGridPage( int n, Orientation dir, + const TQString &itemName, + const TQString &header, + const TQPixmap &pixmap ) +{ + TQStringList items; + items << itemName; + return addGridPage(n, dir, items, header, pixmap); +} + +void KJanusWidget::InsertTreeListItem(const TQStringList &items, const TQPixmap &pixmap, TQFrame *page) +{ + bool isTop = true; + TQListViewItem *curTop = 0, *child, *last, *newChild; + unsigned int index = 1; + TQStringList curPath; + + for ( TQStringList::ConstIterator it = items.begin(); it != items.end(); ++it, index++ ) { + TQString name = (*it); + bool isPath = ( index != items.count() ); + + // Find the first child. + if (isTop) { + child = mTreeList->firstChild(); + } + else { + child = curTop->firstChild(); + } + + // Now search for a child with the current Name, and if it we doesn't + // find it, then remember the location of the last child. + for (last = 0; child && child->text(0) != name ; last = child, child = child->nextSibling()); + + if (!last && !child) { + // This node didn't have any children at all, lets just insert the + // new child. + if (isTop) + newChild = new TQListViewItem(mTreeList, name); + else + newChild = new TQListViewItem(curTop, name); + + } + else if (child) { + // we found the given name in this child. + if (!isPath) { + kdDebug() << "The element inserted was already in the TreeList box!" << endl; + return; + } + else { + // Ok we found the folder + newChild = child; + } + } + else { + // the node had some children, but we didn't find the given name + if (isTop) + newChild = new TQListViewItem(mTreeList, last, name); + else + newChild = new TQListViewItem(curTop, last, name); + } + + // Now make the element expandable if it is a path component, and make + // ready for next loop + if (isPath) { + newChild->setExpandable(true); + curTop = newChild; + isTop = false; + curPath << name; + + TQString key = curPath.join("_/_"); + if (mFolderIconMap.contains(key)) { + TQPixmap p = mFolderIconMap[key]; + newChild->setPixmap(0,p); + } + } + else { + if (mShowIconsInTreeList) { + newChild->setPixmap(0, pixmap); + } + mTreeListToPageStack.insert(newChild, page); + } + } +} + +void KJanusWidget::addPageWidget( TQFrame *page, const TQStringList &items, + const TQString &header,const TQPixmap &pixmap ) +{ + connect(page, TQT_SIGNAL(destroyed(TQObject*)), TQT_SLOT(pageGone(TQObject*))); + + if( mFace == Tabbed ) + { + mTabControl->addTab (page, items.last()); + d->mIntToPage[d->mNextPageIndex] = static_cast<TQWidget*>(page); + d->mPageToInt[static_cast<TQWidget*>(page)] = d->mNextPageIndex; + d->mNextPageIndex++; + } + else if( mFace == TreeList || mFace == IconList ) + { + d->mIntToPage[d->mNextPageIndex] = static_cast<TQWidget*>(page); + d->mPageToInt[static_cast<TQWidget*>(page)] = d->mNextPageIndex; + mPageStack->addWidget( page, 0 ); + + if (items.isEmpty()) { + kdDebug() << "Invalid TQStringList, with zero items" << endl; + return; + } + + if( mFace == TreeList ) + { + InsertTreeListItem(items, pixmap, page); + } + else // mFace == IconList + { + TQString itemName = items.last(); + IconListItem *item = new IconListItem( mIconList, pixmap, itemName ); + mIconListToPageStack.insert(item, page); + mIconList->invalidateHeight(); + mIconList->invalidateWidth(); + + if (mIconList->isVisible()) + mIconList->updateWidth(); + } + + // + // Make sure the title label is sufficiently wide + // + TQString lastName = items.last(); + const TQString &title = (!header.isNull() ? header : lastName); + TQRect r = mTitleLabel->fontMetrics().boundingRect( title ); + if( mTitleLabel->minimumWidth() < r.width() ) + { + mTitleLabel->setMinimumWidth( r.width() ); + } + d->mIntToTitle[d->mNextPageIndex] = title; + if( d->mIntToTitle.count() == 1 ) + { + showPage(0); + } + d->mNextPageIndex++; + } + else + { + kdDebug() << "KJanusWidget::addPageWidget: can only add a page in Tabbed, TreeList or IconList modes" << endl; + } + +} + +void KJanusWidget::setFolderIcon(const TQStringList &path, const TQPixmap &pixmap) +{ + TQString key = path.join("_/_"); + mFolderIconMap.insert(key,pixmap); +} + + + +bool KJanusWidget::setSwallowedWidget( TQWidget *widget ) +{ + if( mFace != Swallow || !mValid ) + { + return false; + } + + // + // Remove current layout and make a new. + // + delete mSwallowPage->layout(); + + TQGridLayout *gbox = new TQGridLayout( mSwallowPage, 1, 1, 0 ); + + // + // Hide old children + // + TQObjectList l = mSwallowPage->childrenListObject(); // silence please + for( uint i=0; i < l.count(); i++ ) + { + TQObject *o = l.tqat(i); + if( o->isWidgetType() ) + { + ((TQWidget*)o)->hide(); + } + } + + // + // Add new child or make default size + // + if( !widget ) + { + gbox->addRowSpacing(0,100); + gbox->addColSpacing(0,100); + mSwallowPage->setMinimumSize(100,100); + } + else + { + if( TQT_BASE_OBJECT(widget->parent()) != TQT_BASE_OBJECT(mSwallowPage) ) + { + widget->reparent( mSwallowPage, 0, TQPoint(0,0) ); + } + gbox->addWidget(widget, 0, 0 ); + gbox->activate(); + mSwallowPage->setMinimumSize( widget->tqminimumSize() ); + } + + return true; +} + +bool KJanusWidget::slotShowPage() +{ + if( !mValid ) + { + return false; + } + + if( mFace == TreeList ) + { + TQListViewItem *node = mTreeList->selectedItem(); + if( !node ) { return false; } + + TQWidget *stackItem = mTreeListToPageStack[node]; + // Make sure to call through the virtual function showPage(int) + return showPage(d->mPageToInt[stackItem]); + } + else if( mFace == IconList ) + { + TQListBoxItem *node = mIconList->item( mIconList->currentItem() ); + if( !node ) { return false; } + TQWidget *stackItem = mIconListToPageStack[node]; + // Make sure to call through the virtual function showPage(int) + return showPage(d->mPageToInt[stackItem]); + } + + return false; +} + + +bool KJanusWidget::showPage( int index ) +{ + if( !d || !mValid ) + { + return false; + } + else + { + return showPage(d->mIntToPage[index]); + } +} + + +bool KJanusWidget::showPage( TQWidget *w ) +{ + if( !w || !mValid ) + { + return false; + } + + if( mFace == TreeList || mFace == IconList ) + { + mPageStack->raiseWidget( w ); + mActivePageWidget = w; + + int index = d->mPageToInt[w]; + mTitleLabel->setText( d->mIntToTitle[index] ); + if( mFace == TreeList ) + { + TQMap<TQListViewItem *, TQWidget *>::Iterator it; + for (it = mTreeListToPageStack.begin(); it != mTreeListToPageStack.end(); ++it){ + TQListViewItem *key = it.key(); + TQWidget *val = it.data(); + if (val == w) { + mTreeList->setSelected(key, true ); + break; + } + } + } + else + { + TQMap<TQListBoxItem *, TQWidget *>::Iterator it; + for (it = mIconListToPageStack.begin(); it != mIconListToPageStack.end(); ++it){ + TQListBoxItem *key = it.key(); + TQWidget *val = it.data(); + if (val == w) { + mIconList->setSelected( key, true ); + break; + } + } + } + } + else if( mFace == Tabbed ) + { + mTabControl->showPage(w); + mActivePageWidget = w; + } + else + { + return false; + } + + return true; +} + + +int KJanusWidget::activePageIndex() const +{ + if( mFace == TreeList) { + TQListViewItem *node = mTreeList->selectedItem(); + if( !node ) { return -1; } + TQWidget *stackItem = mTreeListToPageStack[node]; + return d->mPageToInt[stackItem]; + } + else if (mFace == IconList) { + TQListBoxItem *node = mIconList->item( mIconList->currentItem() ); + if( !node ) { return false; } + TQWidget *stackItem = mIconListToPageStack[node]; + return d->mPageToInt[stackItem]; + } + else if( mFace == Tabbed ) { + TQWidget *widget = mTabControl->currentPage(); + return ( !widget ? -1 : d->mPageToInt[widget] ); + } + else { + return -1; + } +} + + +int KJanusWidget::pageIndex( TQWidget *widget ) const +{ + if( !widget ) + { + return -1; + } + else if( mFace == TreeList || mFace == IconList ) + { + return d->mPageToInt[widget]; + } + else if( mFace == Tabbed ) + { + // + // The user gets the real page widget with addVBoxPage(), addHBoxPage() + // and addGridPage() but not with addPage() which returns a child of + // the toplevel page. addPage() returns a TQFrame so I check for that. + // + if( widget->isA(TQFRAME_OBJECT_NAME_STRING) ) + { + return d->mPageToInt[widget->parentWidget()]; + } + else + { + return d->mPageToInt[widget]; + } + } + else + { + return -1; + } +} + +void KJanusWidget::slotFontChanged() +{ + if( mTitleLabel ) + { + mTitleLabel->setFont( KGlobalSettings::generalFont() ); + TQFont titleFont( mTitleLabel->font() ); + titleFont.setBold( true ); + mTitleLabel->setFont( titleFont ); + } + + if( mFace == IconList ) + { + TQFont listFont( mIconList->font() ); + listFont.setBold( true ); + mIconList->setFont( listFont ); + mIconList->invalidateHeight(); + mIconList->invalidateWidth(); + } +} + +// makes the treelist behave like the list of kcontrol +void KJanusWidget::slotItemClicked(TQListViewItem *it) +{ + if(it && (it->childCount()>0)) + it->setOpen(!it->isOpen()); +} + +// hack because qt does not support Q_OBJECT in nested classes +void KJanusWidget::slotOnItem(TQListBoxItem *qitem) +{ + mIconList->slotOnItem( qitem ); +} + +void KJanusWidget::setFocus() +{ + if( !mValid ) { return; } + if( mFace == TreeList ) + { + mTreeList->setFocus(); + } + if( mFace == IconList ) + { + mIconList->setFocus(); + } + else if( mFace == Tabbed ) + { + mTabControl->setFocus(); + } + else if( mFace == Swallow ) + { + mSwallowPage->setFocus(); + } + else if( mFace == Plain ) + { + mPlainPage->setFocus(); + } +} + + +TQSize KJanusWidget::tqminimumSizeHint() const +{ + if( mFace == TreeList || mFace == IconList ) + { + TQSize s1( KDialog::spacingHint(), KDialog::spacingHint()*2 ); + TQSize s2(0,0); + TQSize s3(0,0); + TQSize s4( mPageStack->tqsizeHint() ); + + if( mFace == TreeList ) + { + s1.rwidth() += tqstyle().tqpixelMetric( TQStyle::PM_SplitterWidth ); + s2 = mTreeList->tqminimumSize(); + } + else + { + mIconList->updateMinimumHeight(); + mIconList->updateWidth(); + s2 = mIconList->tqminimumSize(); + } + + if( mTitleLabel->isVisible() ) + { + s3 += mTitleLabel->tqsizeHint(); + s3.rheight() += mTitleSep->tqminimumSize().height(); + } + + // + // Select the tallest item. It has only effect in IconList mode + // + int h1 = s1.rheight() + s3.rheight() + s4.height(); + int h2 = QMAX( h1, s2.rheight() ); + + return TQSize( s1.width()+s2.width()+QMAX(s3.width(),s4.width()), h2 ); + } + else if( mFace == Tabbed ) + { + return mTabControl->tqsizeHint(); + } + else if( mFace == Swallow ) + { + return mSwallowPage->tqminimumSize(); + } + else if( mFace == Plain ) + { + return mPlainPage->tqsizeHint(); + } + else + { + return TQSize( 100, 100 ); // Should never happen though. + } + +} + + +TQSize KJanusWidget::tqsizeHint() const +{ + return tqminimumSizeHint(); +} + + +void KJanusWidget::setTreeListAutoResize( bool state ) +{ + if( mFace == TreeList ) + { + mTreeListResizeMode = !state ? + TQSplitter::KeepSize : TQSplitter::Stretch; + if( d->mSplitter ) + d->mSplitter->setResizeMode( d->mListFrame, mTreeListResizeMode ); + } +} + + +void KJanusWidget::setIconListAllVisible( bool state ) +{ + if( mFace == IconList ) + { + mIconList->setShowAll( state ); + } +} + +void KJanusWidget::setShowIconsInTreeList( bool state ) +{ + mShowIconsInTreeList = state; +} + +void KJanusWidget::setRootIsDecorated( bool state ) +{ + if( mFace == TreeList ) { + mTreeList->setRootIsDecorated(state); + } +} + +void KJanusWidget::unfoldTreeList( bool persist ) +{ + if( mFace == TreeList ) + { + if( persist ) + connect( mTreeList, TQT_SIGNAL( collapsed( TQListViewItem * ) ), this, TQT_SLOT( slotReopen( TQListViewItem * ) ) ); + else + disconnect( mTreeList, TQT_SIGNAL( collapsed( TQListViewItem * ) ), this, TQT_SLOT( slotReopen( TQListViewItem * ) ) ); + + for( TQListViewItem * item = mTreeList->firstChild(); item; item = item->itemBelow() ) + item->setOpen( true ); + } +} + +void KJanusWidget::addWidgetBelowList( TQWidget * widget ) +{ + if( ( mFace == TreeList || mFace == IconList ) && d->mListFrame ) + { + widget->reparent( d->mListFrame, TQPoint() ); + } +} + +void KJanusWidget::addButtonBelowList( const TQString & text, TQObject * recv, const char * slot ) +{ + if( ( mFace == TreeList || mFace == IconList ) && d->mListFrame ) + { + TQPushButton * button = new TQPushButton( text, d->mListFrame, "KJanusWidget::buttonBelowList" ); + connect( button, TQT_SIGNAL( clicked() ), recv, slot ); + } +} + +void KJanusWidget::addButtonBelowList( const KGuiItem & item, TQObject * recv, const char * slot ) +{ + if( ( mFace == TreeList || mFace == IconList ) && d->mListFrame ) + { + KPushButton * button = new KPushButton( item, d->mListFrame, "KJanusWidget::buttonBelowList" ); + connect( button, TQT_SIGNAL( clicked() ), recv, slot ); + } +} + +void KJanusWidget::showEvent( TQShowEvent * ) +{ + if( mFace == TreeList ) + { + if( d->mSplitter ) + d->mSplitter->setResizeMode( d->mListFrame, mTreeListResizeMode ); + } +} + + +// +// 2000-13-02 Espen Sand +// It should be obvious that this eventfilter must only be +// be installed on the vertical scrollbar of the mIconList. +// +bool KJanusWidget::eventFilter( TQObject *o, TQEvent *e ) +{ + if( e->type() == TQEvent::Show ) + { + IconListItem *item = (IconListItem*)mIconList->item(0); + if( item ) + { + int lw = item->width( mIconList ); + int sw = mIconList->verticalScrollBar()->tqsizeHint().width(); + mIconList->setFixedWidth( lw+sw+mIconList->frameWidth()*2 ); + } + } + else if( e->type() == TQEvent::Hide ) + { + IconListItem *item = (IconListItem*)mIconList->item(0); + if( item ) + { + int lw = item->width( mIconList ); + mIconList->setFixedWidth( lw+mIconList->frameWidth()*2 ); + } + } + return TQWidget::eventFilter( o, e ); +} + + + +// +// Code for the icon list box +// + + +KJanusWidget::IconListBox::IconListBox( TQWidget *parent, const char *name, + WFlags f ) + :KListBox( parent, name, f ), mShowAll(false), mHeightValid(false), + mWidthValid(false), + mOldItem(0) +{ +} + +void KJanusWidget::IconListBox::updateMinimumHeight() +{ + if( mShowAll && !mHeightValid ) + { + int h = frameWidth()*2; + for( TQListBoxItem *i = item(0); i; i = i->next() ) + { + h += i->height( this ); + } + setMinimumHeight( h ); + mHeightValid = true; + } +} + + +void KJanusWidget::IconListBox::updateWidth() +{ + if( !mWidthValid ) + { + int maxWidth = 10; + for( TQListBoxItem *i = item(0); i; i = i->next() ) + { + int w = ((IconListItem *)i)->width(this); + maxWidth = QMAX( w, maxWidth ); + } + + for( TQListBoxItem *i = item(0); i; i = i->next() ) + { + ((IconListItem *)i)->expandMinimumWidth( maxWidth ); + } + + if( verticalScrollBar()->isVisible() ) + { + maxWidth += verticalScrollBar()->tqsizeHint().width(); + } + + setFixedWidth( maxWidth + frameWidth()*2 ); + mWidthValid = true; + } +} + + +void KJanusWidget::IconListBox::invalidateHeight() +{ + mHeightValid = false; +} + + +void KJanusWidget::IconListBox::invalidateWidth() +{ + mWidthValid = false; +} + + +void KJanusWidget::IconListBox::setShowAll( bool showAll ) +{ + mShowAll = showAll; + mHeightValid = false; +} + + +void KJanusWidget::IconListBox::leaveEvent( TQEvent *ev ) +{ + KListBox::leaveEvent( ev ); + + if ( mOldItem && !mOldItem->isSelected() ) + { + ((KJanusWidget::IconListItem *) mOldItem)->highlight( true ); + mOldItem = 0; + } +} + +// hack because qt does not support Q_OBJECT in nested classes +void KJanusWidget::IconListBox::slotOnItem(TQListBoxItem *qitem) +{ + KListBox::slotOnItem( qitem ); + + if ( qitem == mOldItem ) + { + return; + } + + if ( mOldItem && !mOldItem->isSelected() ) + { + ((KJanusWidget::IconListItem *) mOldItem)->highlight( true ); + } + + KJanusWidget::IconListItem *item = dynamic_cast< KJanusWidget::IconListItem * >( qitem ); + if ( item && !item->isSelected() ) + { + item->highlight( false ); + mOldItem = item; + } + else + { + mOldItem = 0; + } +} + + + +KJanusWidget::IconListItem::IconListItem( TQListBox *listbox, const TQPixmap &pixmap, + const TQString &text ) + : TQListBoxItem( listbox ) +{ + mPixmap = pixmap; + if( mPixmap.isNull() ) + { + mPixmap = defaultPixmap(); + } + setText( text ); + setCustomHighlighting( true ); + mMinimumWidth = 0; +} + + +int KJanusWidget::IconListItem::expandMinimumWidth( int width ) +{ + mMinimumWidth = QMAX( mMinimumWidth, width ); + return mMinimumWidth; +} + + +void KJanusWidget::IconListItem::highlight( bool erase ) +{ + // FIXME: Add configuration option to disable highlighting + // For now, always disable highlighting + erase = true; + + TQRect r = listBox()->tqitemRect( this ); + r.addCoords( 1, 1, -1, -1 ); + + TQPainter p( listBox()->viewport() ); + p.setClipRegion( r ); + + const TQColorGroup &cg = listBox()->tqcolorGroup(); + if ( erase ) + { + p.setPen( cg.base() ); + p.setBrush( cg.base() ); + p.drawRect( r ); + } + else + { + p.setBrush( cg.highlight().light( 120 ) ); + p.drawRect( r ); + + p.setPen( cg.highlight().dark( 140 ) ); + p.drawRect( r ); + } + + p.setPen( cg.foreground() ); + p.translate( r.x() - 1, r.y() - 1 ); + paintContents( &p ); +} + + +const TQPixmap &KJanusWidget::IconListItem::defaultPixmap() +{ + static TQPixmap *pix=0; + if( !pix ) + { + pix = new TQPixmap( 32, 32 ); + TQPainter p( pix ); + p.eraseRect( 0, 0, pix->width(), pix->height() ); + p.setPen( Qt::red ); + p.drawRect ( 0, 0, pix->width(), pix->height() ); + p.end(); + + TQBitmap mask( pix->width(), pix->height(), true ); + mask.fill( Qt::black ); + p.begin( &mask ); + p.setPen( Qt::white ); + p.drawRect ( 0, 0, pix->width(), pix->height() ); + p.end(); + + pix->setMask( mask ); + } + return *pix; +} + + +void KJanusWidget::IconListItem::paint( TQPainter *painter ) +{ + TQRect itemPaintRegion( listBox()->tqitemRect( this ) ); + TQRect r( 1, 1, itemPaintRegion.width() - 2, itemPaintRegion.height() - 2); + + if ( isSelected() ) + { + painter->eraseRect( r ); + + painter->save(); + painter->setPen( listBox()->tqcolorGroup().highlight().dark( 160 ) ); + painter->drawRect( r ); + painter->restore(); + } + + paintContents( painter ); +} + + +void KJanusWidget::IconListItem::paintContents( TQPainter *painter ) +{ + TQFontMetrics fm = painter->fontMetrics(); + int ht = fm.boundingRect( 0, 0, 0, 0, Qt::AlignCenter, text() ).height(); + int wp = mPixmap.width(); + int hp = mPixmap.height(); + painter->drawPixmap( (mMinimumWidth - wp) / 2, 5, mPixmap ); + + if( !text().isEmpty() ) + { + painter->drawText( 1, hp + 7, mMinimumWidth - 2, ht, Qt::AlignCenter, text() ); + } +} + +int KJanusWidget::IconListItem::height( const TQListBox *lb ) const +{ + if( text().isEmpty() ) + { + return mPixmap.height(); + } + else + { + int ht = lb->fontMetrics().boundingRect( 0, 0, 0, 0, Qt::AlignCenter, text() ).height(); + return (mPixmap.height() + ht + 10); + } +} + + +int KJanusWidget::IconListItem::width( const TQListBox *lb ) const +{ + int wt = lb->fontMetrics().boundingRect( 0, 0, 0, 0, Qt::AlignCenter, text() ).width() + 10; + int wp = mPixmap.width() + 10; + int w = QMAX( wt, wp ); + return QMAX( w, mMinimumWidth ); +} + + +void KJanusWidget::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + + +// 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 +// delete the node. +void KJanusWidget::removePage( TQWidget *page ) +{ + if (!d || !d->mPageToInt.contains(page)) + return; + + int index = d->mPageToInt[page]; + + if ( mFace == TreeList ) + { + TQMap<TQListViewItem*, TQWidget *>::Iterator i; + for( i = mTreeListToPageStack.begin(); i != mTreeListToPageStack.end(); ++i ) + if (i.data()==page) + { + delete i.key(); + mPageStack->removeWidget(page); + mTreeListToPageStack.remove(i); + d->mIntToTitle.remove(index); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + break; + } + } + else if ( mFace == IconList ) + { + TQMap<TQListBoxItem*, TQWidget *>::Iterator i; + for( i = mIconListToPageStack.begin(); i != mIconListToPageStack.end(); ++i ) + if (i.data()==page) + { + delete i.key(); + mPageStack->removeWidget(page); + mIconListToPageStack.remove(i); + d->mIntToTitle.remove(index); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + break; + } + } + else // Tabbed + { + mTabControl->removePage(page); + d->mPageToInt.remove(page); + d->mIntToPage.remove(index); + } +} + + +TQString KJanusWidget::pageTitle(int index) const +{ + if (!d || !d->mIntToTitle.contains(index)) + return TQString::null; + else + return d->mIntToTitle[index]; +} + + +TQWidget *KJanusWidget::pageWidget(int index) const +{ + if (!d || !d->mIntToPage.contains(index)) + return 0; + else + return d->mIntToPage[index]; +} + +#include "kjanuswidget.moc" |