• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

kmultitabbar.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           kmultitabbar.cpp -  description
00003                              -------------------
00004     begin                :  2001
00005     copyright            : (C) 2001,2002,2003 by Joseph Wenninger <jowenn@kde.org>
00006  ***************************************************************************/
00007 
00008 /***************************************************************************
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Library General Public
00011     License as published by the Free Software Foundation; either
00012     version 2 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Library General Public License for more details.
00018 
00019     You should have received a copy of the GNU Library General Public License
00020     along with this library; see the file COPYING.LIB.  If not, write to
00021     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00022     Boston, MA 02110-1301, USA.
00023  ***************************************************************************/
00024 
00025 #include "kmultitabbar.h"
00026 #include "kmultitabbar_p.h"
00027 #include "kmultitabbar.moc"
00028 #include "kmultitabbar_p.moc"
00029 
00030 #include <QtGui/QActionEvent>
00031 #include <QtGui/QLayout>
00032 #include <QtGui/QPainter>
00033 #include <QtGui/QFontMetrics>
00034 #include <QtGui/QStyle>
00035 #include <QStyleOptionButton>
00036 
00037 #include <kiconloader.h>
00038 #include <kdebug.h>
00039 #include <QtGui/QApplication>
00040 #include <math.h>
00041 
00049 class KMultiTabBarPrivate
00050 {
00051 public:
00052     class KMultiTabBarInternal *m_internal;
00053     QBoxLayout *m_l;
00054     QFrame *m_btnTabSep;
00055     QList<KMultiTabBarButton*> m_buttons;
00056     KMultiTabBar::KMultiTabBarPosition m_position;
00057 };
00058 
00059 
00060 KMultiTabBarInternal::KMultiTabBarInternal(QWidget *parent, KMultiTabBar::KMultiTabBarPosition pos):QFrame(parent)
00061 {
00062     m_position = pos;
00063     if (pos == KMultiTabBar::Left || pos == KMultiTabBar::Right)
00064         mainLayout=new QVBoxLayout(this);
00065     else
00066         mainLayout=new QHBoxLayout(this);
00067     mainLayout->setMargin(0);
00068     mainLayout->setSpacing(0);
00069     mainLayout->addStretch();
00070     setFrameStyle(NoFrame);
00071     setBackgroundRole(QPalette::Background);
00072 }
00073 
00074 KMultiTabBarInternal::~KMultiTabBarInternal()
00075 {
00076     qDeleteAll(m_tabs);
00077     m_tabs.clear();
00078 }
00079 
00080 void KMultiTabBarInternal::setStyle(enum KMultiTabBar::KMultiTabBarStyle style)
00081 {
00082     m_style=style;
00083     for (int i=0;i<m_tabs.count();i++)
00084         m_tabs.at(i)->setStyle(m_style);
00085 
00086     updateGeometry();
00087 }
00088 
00089 void KMultiTabBarInternal::contentsMousePressEvent(QMouseEvent *ev)
00090 {
00091     ev->ignore();
00092 }
00093 
00094 void KMultiTabBarInternal::mousePressEvent(QMouseEvent *ev)
00095 {
00096     ev->ignore();
00097 }
00098 
00099 KMultiTabBarTab* KMultiTabBarInternal::tab(int id) const
00100 {
00101     QListIterator<KMultiTabBarTab*> it(m_tabs);
00102     while (it.hasNext()) {
00103         KMultiTabBarTab *tab = it.next();
00104         if (tab->id()==id) return tab;
00105     }
00106     return 0;
00107 }
00108 
00109 int KMultiTabBarInternal::appendTab(const QPixmap &pic, int id, const QString& text)
00110 {
00111     KMultiTabBarTab  *tab;
00112     m_tabs.append(tab= new KMultiTabBarTab(pic,text,id,this,m_position,m_style));
00113 
00114     // Insert before the stretch..
00115     mainLayout->insertWidget(m_tabs.size()-1, tab);
00116     tab->show();
00117     return 0;
00118 }
00119 
00120 void KMultiTabBarInternal::removeTab(int id)
00121 {
00122     for (int pos=0;pos<m_tabs.count();pos++)
00123     {
00124         if (m_tabs.at(pos)->id()==id)
00125         {
00126             // remove & delete the tab
00127             delete m_tabs.takeAt(pos);
00128             break;
00129         }
00130     }
00131 }
00132 
00133 void KMultiTabBarInternal::setPosition(enum KMultiTabBar::KMultiTabBarPosition pos)
00134 {
00135     m_position=pos;
00136     for (int i=0;i<m_tabs.count();i++)
00137         m_tabs.at(i)->setPosition(m_position);
00138     updateGeometry();
00139 }
00140 
00141 // KMultiTabBarButton
00143 
00144 KMultiTabBarButton::KMultiTabBarButton(const QPixmap& pic, const QString& text,
00145                                        int id, QWidget *parent)
00146     : QPushButton(QIcon(pic), text, parent), m_id(id), d(0)
00147 {
00148     connect(this,SIGNAL(clicked()),this,SLOT(slotClicked()));
00149     setFlat(true);
00150 
00151         // we can't see the focus, so don't take focus. #45557
00152         // If keyboard navigation is wanted, then only the bar should take focus,
00153         // and arrows could change the focused button; but generally, tabbars don't take focus anyway.
00154         setFocusPolicy(Qt::NoFocus);
00155 }
00156 
00157 KMultiTabBarButton::~KMultiTabBarButton()
00158 {
00159 }
00160 
00161 void KMultiTabBarButton::setText(const QString &text)
00162 {
00163     QPushButton::setText(text);
00164 }
00165 
00166 void KMultiTabBarButton::slotClicked()
00167 {
00168     updateGeometry();
00169     emit clicked(m_id);
00170 }
00171 
00172 int KMultiTabBarButton::id() const 
00173 {
00174     return m_id;
00175 }
00176 
00177 void KMultiTabBarButton::hideEvent( QHideEvent* he) {
00178     QPushButton::hideEvent(he);
00179     KMultiTabBar *tb=dynamic_cast<KMultiTabBar*>(parentWidget());
00180     if (tb) tb->updateSeparator();
00181 }
00182 
00183 void KMultiTabBarButton::showEvent( QShowEvent* he) {
00184     QPushButton::showEvent(he);
00185     KMultiTabBar *tb=dynamic_cast<KMultiTabBar*>(parentWidget());
00186     if (tb) tb->updateSeparator();
00187 }
00188 
00189 // KMultiTabBarTab
00191 
00192 KMultiTabBarTab::KMultiTabBarTab(const QPixmap& pic, const QString& text,
00193                                        int id, QWidget *parent,
00194                                        KMultiTabBar::KMultiTabBarPosition pos,
00195                                        KMultiTabBar::KMultiTabBarStyle style)
00196     : KMultiTabBarButton(pic, text, id, parent), m_style(style), d(0)
00197 {
00198     m_position=pos;
00199     setToolTip(text);   
00200     setCheckable(true);
00201     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00202      // shrink down to icon only, but prefer to show text if it's there
00203 }
00204 
00205 KMultiTabBarTab::~KMultiTabBarTab()
00206 {
00207 }
00208 
00209 void KMultiTabBarTab::setPosition(KMultiTabBar::KMultiTabBarPosition pos)
00210 {
00211     m_position=pos;
00212     updateGeometry();
00213 }
00214 
00215 void KMultiTabBarTab::setStyle(KMultiTabBar::KMultiTabBarStyle style)
00216 {
00217     m_style=style;
00218     updateGeometry();
00219 }
00220 
00221 QPixmap KMultiTabBarTab::iconPixmap() const
00222 {
00223     int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
00224     return icon().pixmap(iconSize);
00225 }
00226 
00227 void KMultiTabBarTab::initStyleOption(QStyleOptionToolButton* opt) const
00228 {
00229     opt->initFrom(this);
00230     
00231     // Setup icon..
00232     if (!icon().isNull()) {
00233         opt->iconSize = iconPixmap().size();
00234         opt->icon     = icon();
00235     }
00236         
00237     // Should we draw text?
00238     if (shouldDrawText())
00239         opt->text = text();
00240         
00241     if (underMouse())
00242         opt->state |= QStyle::State_AutoRaise | QStyle::State_MouseOver | QStyle::State_Raised;
00243         
00244     if (isChecked())
00245         opt->state |= QStyle::State_Sunken | QStyle::State_On;
00246     
00247     opt->font = font();
00248     opt->toolButtonStyle = shouldDrawText() ? Qt::ToolButtonTextBesideIcon : Qt::ToolButtonIconOnly;
00249     opt->subControls = QStyle::SC_ToolButton;
00250 }
00251 
00252 QSize KMultiTabBarTab::sizeHint() const
00253 {
00254     return computeSizeHint(shouldDrawText());
00255 }
00256 
00257 QSize KMultiTabBarTab::minimumSizeHint() const
00258 {
00259     return computeSizeHint(false);
00260 }
00261 
00262 void KMultiTabBarTab::computeMargins(int* hMargin, int* vMargin) const
00263 {
00264     // Unfortunately, QStyle does not give us enough information to figure out 
00265     // where to place things, so we try to reverse-engineer it
00266     QStyleOptionToolButton opt;
00267     initStyleOption(&opt);
00268 
00269     QPixmap iconPix = iconPixmap();
00270     QSize trialSize = iconPix.size();
00271     QSize expandSize = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, trialSize, this);
00272     
00273     *hMargin = (expandSize.width()  - trialSize.width())/2;
00274     *vMargin = (expandSize.height() - trialSize.height())/2;
00275 }
00276 
00277 QSize KMultiTabBarTab::computeSizeHint(bool withText) const
00278 {
00279     // Compute as horizontal first, then flip around if need be.    
00280     QStyleOptionToolButton opt;
00281     initStyleOption(&opt);
00282     
00283     int hMargin, vMargin;
00284     computeMargins(&hMargin, &vMargin);
00285     
00286     // Compute interior size, starting from pixmap..
00287     QPixmap iconPix = iconPixmap();
00288     QSize size = iconPix.size();
00289     
00290     // Always include text height in computation, to avoid resizing the minor direction
00291     // when expanding text..
00292     QSize textSize = fontMetrics().size(Qt::TextShowMnemonic, text());
00293     size.setHeight(qMax(size.height(), textSize.height()));
00294     
00295     // Pick margins for major/minor direction, depending on orientation
00296     int majorMargin = isVertical() ? vMargin : hMargin;
00297     int minorMargin = isVertical() ? hMargin : vMargin;
00298     
00299     size.setWidth (size.width()  + 2*majorMargin);
00300     size.setHeight(size.height() + 2*minorMargin);
00301 
00302     if (withText)
00303         // Add enough room for the text, and an extra major margin.
00304         size.setWidth(size.width() + textSize.width() + majorMargin);
00305 
00306     // flip time?
00307     if (isVertical())
00308         return QSize(size.height(), size.width());
00309     else
00310         return size;
00311 }
00312 
00313 void KMultiTabBarTab::setState(bool newState)
00314 {
00315     setChecked(newState);
00316     updateGeometry();
00317 }
00318 
00319 void KMultiTabBarTab::setIcon(const QString& icon)
00320 {
00321     QPixmap pic=SmallIcon(icon);
00322     setIcon(pic);
00323 }
00324 
00325 void KMultiTabBarTab::setIcon(const QPixmap& icon)
00326 {
00327     QPushButton::setIcon(icon);
00328 }
00329 
00330 bool KMultiTabBarTab::shouldDrawText() const
00331 {
00332     return (m_style==KMultiTabBar::KDEV3ICON) || isChecked();
00333 }
00334 
00335 bool KMultiTabBarTab::isVertical() const
00336 {
00337     return m_position==KMultiTabBar::Right || m_position==KMultiTabBar::Left;
00338 }
00339 
00340 void KMultiTabBarTab::paintEvent(QPaintEvent*) {
00341     QPainter painter(this);
00342     
00343     QStyleOptionToolButton opt;
00344     initStyleOption(&opt);
00345     
00346     // Paint bevel..
00347     if (underMouse() || isChecked())
00348         style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &painter);
00349         
00350     int hMargin, vMargin;
00351     computeMargins(&hMargin, &vMargin);
00352         
00353     // We first figure out how much room we have for the text, based on 
00354     // icon size and margin, try to fit in by eliding, and perhaps
00355     // give up on drawing the text entirely if we're too short on room
00356     QPixmap icon = iconPixmap();
00357     int textRoom = 0;
00358     int iconRoom = 0;
00359     
00360     QString t;
00361     if (shouldDrawText()) {
00362         if (isVertical()) {
00363             iconRoom = icon.height() + 2*vMargin;
00364             textRoom = height() - iconRoom - vMargin;
00365         } else {
00366             iconRoom = icon.width() + 2*hMargin;
00367             textRoom = width() - iconRoom - hMargin;
00368         }
00369         
00370         t = painter.fontMetrics().elidedText(text(), Qt::ElideRight, textRoom);
00371         
00372         // See whether anything is left. Qt will return either 
00373         // ... or the ellipsis unicode character, 0x2026
00374         if (t == QLatin1String("...") || t == QChar(0x2026))
00375             t.clear();
00376     }
00377     
00378     opt.text = t;
00379     
00380     // Label time.... Simple case: no text, so just plop down the icon right in the center
00381     // We only do this when the button never draws the text, to avoid jumps in icon position
00382     // when resizing
00383     if (!shouldDrawText()) {
00384         style()->drawItemPixmap(&painter, rect(), Qt::AlignCenter | Qt::AlignVCenter, icon);
00385         return;
00386     }
00387 
00388     // Now where the icon/text goes depends on text direction and tab position  
00389     QRect iconArea;
00390     QRect labelArea;
00391     
00392     bool bottomIcon = false;
00393     bool rtl = layoutDirection() == Qt::RightToLeft;
00394     if (isVertical()) {
00395         if (m_position == KMultiTabBar::Left && !rtl)
00396             bottomIcon = true;
00397         if (m_position == KMultiTabBar::Right && rtl)
00398             bottomIcon = true;
00399     }
00400     //alignFlags = Qt::AlignLeading | Qt::AlignVCenter;
00401 
00402     if (isVertical()) {
00403         if (bottomIcon) {
00404             labelArea = QRect(0, vMargin, width(), textRoom);
00405             iconArea  = QRect(0, vMargin + textRoom, width(), iconRoom);
00406         } else {
00407             labelArea = QRect(0, iconRoom, width(), textRoom);
00408             iconArea  = QRect(0, 0, width(), iconRoom);
00409         }
00410     } else {
00411         // Pretty simple --- depends only on RTL/LTR
00412         if (rtl) {
00413             labelArea = QRect(hMargin, 0, textRoom, height());
00414             iconArea  = QRect(hMargin + textRoom, 0, iconRoom, height());
00415         } else {
00416             labelArea = QRect(iconRoom, 0, textRoom, height());
00417             iconArea  = QRect(0, 0, iconRoom, height());
00418         }
00419     }
00420     
00421     style()->drawItemPixmap(&painter, iconArea, Qt::AlignCenter | Qt::AlignVCenter, icon);
00422     
00423     if (t.isEmpty())
00424         return;
00425 
00426     QRect labelPaintArea = labelArea;
00427 
00428     if (isVertical()) {
00429         // If we're vertical, we paint to a simple 0,0 origin rect, 
00430         // and get the transformations to get us in the right place
00431         labelPaintArea = QRect(0, 0, labelArea.height(), labelArea.width());
00432 
00433         QTransform tr;
00434         
00435         if (bottomIcon) {
00436             tr.translate(labelArea.x(), labelPaintArea.width() + labelArea.y());
00437             tr.rotate(-90);
00438         } else {
00439             tr.translate(labelPaintArea.height() + labelArea.x(), labelArea.y());
00440             tr.rotate(90);
00441         }
00442         painter.setTransform(tr);
00443     }
00444     
00445     style()->drawItemText(&painter, labelPaintArea, Qt::AlignLeading | Qt::AlignVCenter,
00446                           palette(), true, t, QPalette::ButtonText);
00447 }
00448 
00449 // KMultiTabBar
00451 
00452 KMultiTabBar::KMultiTabBar(KMultiTabBarPosition pos, QWidget *parent)
00453     : QWidget(parent),
00454     d(new KMultiTabBarPrivate)
00455 {
00456     if (pos == Left || pos == Right)
00457     {
00458         d->m_l=new QVBoxLayout(this);
00459         setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding/*, true*/);
00460     }
00461     else
00462     {
00463         d->m_l=new QHBoxLayout(this);
00464         setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed/*, true*/);
00465     }
00466     d->m_l->setMargin(0);
00467     d->m_l->setSpacing(0);
00468 
00469     d->m_internal=new KMultiTabBarInternal(this, pos);
00470     setPosition(pos);
00471     setStyle(VSNET);
00472     d->m_l->insertWidget(0,d->m_internal);
00473     d->m_l->insertWidget(0,d->m_btnTabSep=new QFrame(this));
00474     d->m_btnTabSep->setFixedHeight(4);
00475     d->m_btnTabSep->setFrameStyle(QFrame::Panel | QFrame::Sunken);
00476     d->m_btnTabSep->setLineWidth(2);
00477     d->m_btnTabSep->hide();
00478 
00479     updateGeometry();
00480 }
00481 
00482 KMultiTabBar::~KMultiTabBar()
00483 {
00484     qDeleteAll( d->m_buttons );
00485     d->m_buttons.clear();
00486     delete d;
00487 }
00488 
00489 int KMultiTabBar::appendButton(const QPixmap &pic, int id, QMenu *popup, const QString&)
00490 {
00491     KMultiTabBarButton *btn = new KMultiTabBarButton(pic, QString(), id, this);
00492     btn->setMenu(popup);
00493     d->m_buttons.append(btn);
00494     d->m_l->insertWidget(0,btn);
00495     btn->show();
00496     d->m_btnTabSep->show();
00497     return 0;
00498 }
00499 
00500 void KMultiTabBar::updateSeparator() {
00501     bool hideSep=true;
00502     QListIterator<KMultiTabBarButton*> it(d->m_buttons);
00503     while (it.hasNext()){
00504         if (it.next()->isVisibleTo(this)) {
00505             hideSep=false;
00506             break;
00507         }
00508     }
00509     if (hideSep)
00510         d->m_btnTabSep->hide();
00511     else 
00512         d->m_btnTabSep->show();
00513 }
00514 
00515 int KMultiTabBar::appendTab(const QPixmap &pic, int id, const QString& text)
00516 {
00517     d->m_internal->appendTab(pic,id,text);
00518     return 0;
00519 }
00520 
00521 KMultiTabBarButton* KMultiTabBar::button(int id) const
00522 {
00523     QListIterator<KMultiTabBarButton*> it(d->m_buttons);
00524     while ( it.hasNext() ) {
00525         KMultiTabBarButton *button = it.next();
00526         if ( button->id() == id )
00527             return button;
00528     }
00529     
00530     return 0;
00531 }
00532 
00533 KMultiTabBarTab* KMultiTabBar::tab(int id) const
00534 {
00535     return d->m_internal->tab(id);
00536 }
00537 
00538 void KMultiTabBar::removeButton(int id)
00539 {
00540     for (int pos=0;pos<d->m_buttons.count();pos++)
00541     {
00542         if (d->m_buttons.at(pos)->id()==id)
00543         {
00544             d->m_buttons.takeAt(pos)->deleteLater();
00545             break;
00546         }
00547     }
00548     
00549     if (d->m_buttons.count()==0)
00550         d->m_btnTabSep->hide();
00551 }
00552 
00553 void KMultiTabBar::removeTab(int id)
00554 {
00555     d->m_internal->removeTab(id);
00556 }
00557 
00558 void KMultiTabBar::setTab(int id,bool state)
00559 {
00560     KMultiTabBarTab *ttab=tab(id);
00561     if (ttab)
00562         ttab->setState(state);
00563 }
00564 
00565 bool KMultiTabBar::isTabRaised(int id) const
00566 {
00567     KMultiTabBarTab *ttab=tab(id);
00568     if (ttab)
00569         return ttab->isChecked();
00570 
00571     return false;
00572 }
00573 
00574 void KMultiTabBar::setStyle(KMultiTabBarStyle style)
00575 {
00576     d->m_internal->setStyle(style);
00577 }
00578 
00579 KMultiTabBar::KMultiTabBarStyle KMultiTabBar::tabStyle() const
00580 {
00581     return d->m_internal->m_style;
00582 }
00583 
00584 void KMultiTabBar::setPosition(KMultiTabBarPosition pos)
00585 {
00586     d->m_position=pos;
00587     d->m_internal->setPosition(pos);
00588 }
00589 
00590 KMultiTabBar::KMultiTabBarPosition KMultiTabBar::position() const
00591 {
00592     return d->m_position;
00593 }
00594 
00595 void KMultiTabBar::fontChange(const QFont& /* oldFont */)
00596 {
00597     updateGeometry();
00598 }
00599 
00600 // vim: ts=4 sw=4 noet
00601 // kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal