• Skip to content
  • Skip to link menu
KDE 4.2 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 
00152 KMultiTabBarButton::~KMultiTabBarButton()
00153 {
00154 }
00155 
00156 void KMultiTabBarButton::setText(const QString &text)
00157 {
00158     QPushButton::setText(text);
00159 }
00160 
00161 void KMultiTabBarButton::slotClicked()
00162 {
00163     updateGeometry();
00164     emit clicked(m_id);
00165 }
00166 
00167 int KMultiTabBarButton::id() const 
00168 {
00169     return m_id;
00170 }
00171 
00172 void KMultiTabBarButton::hideEvent( QHideEvent* he) {
00173     QPushButton::hideEvent(he);
00174     KMultiTabBar *tb=dynamic_cast<KMultiTabBar*>(parentWidget());
00175     if (tb) tb->updateSeparator();
00176 }
00177 
00178 void KMultiTabBarButton::showEvent( QShowEvent* he) {
00179     QPushButton::showEvent(he);
00180     KMultiTabBar *tb=dynamic_cast<KMultiTabBar*>(parentWidget());
00181     if (tb) tb->updateSeparator();
00182 }
00183 
00184 // KMultiTabBarTab
00186 
00187 KMultiTabBarTab::KMultiTabBarTab(const QPixmap& pic, const QString& text,
00188                                        int id, QWidget *parent,
00189                                        KMultiTabBar::KMultiTabBarPosition pos,
00190                                        KMultiTabBar::KMultiTabBarStyle style)
00191     : KMultiTabBarButton(pic, text, id, parent), m_style(style), d(0)
00192 {
00193     m_position=pos;
00194     setToolTip(text);   
00195     setCheckable(true);
00196     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00197      // shrink down to icon only, but prefer to show text if it's there
00198 }
00199 
00200 KMultiTabBarTab::~KMultiTabBarTab()
00201 {
00202 }
00203 
00204 void KMultiTabBarTab::setPosition(KMultiTabBar::KMultiTabBarPosition pos)
00205 {
00206     m_position=pos;
00207     updateGeometry();
00208 }
00209 
00210 void KMultiTabBarTab::setStyle(KMultiTabBar::KMultiTabBarStyle style)
00211 {
00212     m_style=style;
00213     updateGeometry();
00214 }
00215 
00216 QPixmap KMultiTabBarTab::iconPixmap() const
00217 {
00218     int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this);
00219     return icon().pixmap(iconSize);
00220 }
00221 
00222 void KMultiTabBarTab::initStyleOption(QStyleOptionToolButton* opt) const
00223 {
00224     opt->initFrom(this);
00225     
00226     // Setup icon..
00227     if (!icon().isNull()) {
00228         opt->iconSize = iconPixmap().size();
00229         opt->icon     = icon();
00230     }
00231         
00232     // Should we draw text?
00233     if (shouldDrawText())
00234         opt->text = text();
00235         
00236     if (underMouse())
00237         opt->state |= QStyle::State_AutoRaise | QStyle::State_MouseOver | QStyle::State_Raised;
00238         
00239     if (isChecked())
00240         opt->state |= QStyle::State_Sunken | QStyle::State_On;
00241     
00242     opt->font = font();
00243     opt->toolButtonStyle = shouldDrawText() ? Qt::ToolButtonTextBesideIcon : Qt::ToolButtonIconOnly;
00244     opt->subControls = QStyle::SC_ToolButton;
00245 }
00246 
00247 QSize KMultiTabBarTab::sizeHint() const
00248 {
00249     return computeSizeHint(shouldDrawText());
00250 }
00251 
00252 QSize KMultiTabBarTab::minimumSizeHint() const
00253 {
00254     return computeSizeHint(false);
00255 }
00256 
00257 void KMultiTabBarTab::computeMargins(int* hMargin, int* vMargin) const
00258 {
00259     // Unfortunately, QStyle does not give us enough information to figure out 
00260     // where to place things, so we try to reverse-engineer it
00261     QStyleOptionToolButton opt;
00262     initStyleOption(&opt);
00263 
00264     QPixmap iconPix = iconPixmap();
00265     QSize trialSize = iconPix.size();
00266     QSize expandSize = style()->sizeFromContents(QStyle::CT_ToolButton, &opt, trialSize, this);
00267     
00268     *hMargin = (expandSize.width()  - trialSize.width())/2;
00269     *vMargin = (expandSize.height() - trialSize.height())/2;
00270 }
00271 
00272 QSize KMultiTabBarTab::computeSizeHint(bool withText) const
00273 {
00274     // Compute as horizontal first, then flip around if need be.    
00275     QStyleOptionToolButton opt;
00276     initStyleOption(&opt);
00277     
00278     int hMargin, vMargin;
00279     computeMargins(&hMargin, &vMargin);
00280     
00281     // Compute interior size, starting from pixmap..
00282     QPixmap iconPix = iconPixmap();
00283     QSize size = iconPix.size();
00284     
00285     // Always include text height in computation, to avoid resizing the minor direction
00286     // when expanding text..
00287     QSize textSize = fontMetrics().size(Qt::TextShowMnemonic, text());
00288     size.setHeight(qMax(size.height(), textSize.height()));
00289     
00290     // Pick margins for major/minor direction, depending on orientation
00291     int majorMargin = isVertical() ? vMargin : hMargin;
00292     int minorMargin = isVertical() ? hMargin : vMargin;
00293     
00294     size.setWidth (size.width()  + 2*majorMargin);
00295     size.setHeight(size.height() + 2*minorMargin);
00296 
00297     if (withText)
00298         // Add enough room for the text, and an extra major margin.
00299         size.setWidth(size.width() + textSize.width() + majorMargin);
00300 
00301     // flip time?
00302     if (isVertical())
00303         return QSize(size.height(), size.width());
00304     else
00305         return size;
00306 }
00307 
00308 void KMultiTabBarTab::setState(bool newState)
00309 {
00310     setChecked(newState);
00311     updateGeometry();
00312 }
00313 
00314 void KMultiTabBarTab::setIcon(const QString& icon)
00315 {
00316     QPixmap pic=SmallIcon(icon);
00317     setIcon(pic);
00318 }
00319 
00320 void KMultiTabBarTab::setIcon(const QPixmap& icon)
00321 {
00322     QPushButton::setIcon(icon);
00323 }
00324 
00325 bool KMultiTabBarTab::shouldDrawText() const
00326 {
00327     return (m_style==KMultiTabBar::KDEV3ICON) || isChecked();
00328 }
00329 
00330 bool KMultiTabBarTab::isVertical() const
00331 {
00332     return m_position==KMultiTabBar::Right || m_position==KMultiTabBar::Left;
00333 }
00334 
00335 void KMultiTabBarTab::paintEvent(QPaintEvent*) {
00336     QPainter painter(this);
00337     
00338     QStyleOptionToolButton opt;
00339     initStyleOption(&opt);
00340     
00341     // Paint bevel..
00342     if (underMouse() || isChecked())
00343         style()->drawPrimitive(QStyle::PE_PanelButtonTool, &opt, &painter);
00344         
00345     int hMargin, vMargin;
00346     computeMargins(&hMargin, &vMargin);
00347         
00348     // We first figure out how much room we have for the text, based on 
00349     // icon size and margin, try to fit in by eliding, and perhaps
00350     // give up on drawing the text entirely if we're too short on room
00351     QPixmap icon = iconPixmap();
00352     int textRoom = 0;
00353     int iconRoom = 0;
00354     
00355     QString t;
00356     if (shouldDrawText()) {
00357         if (isVertical()) {
00358             iconRoom = icon.height() + 2*vMargin;
00359             textRoom = height() - iconRoom - vMargin;
00360         } else {
00361             iconRoom = icon.width() + 2*hMargin;
00362             textRoom = width() - iconRoom - hMargin;
00363         }
00364         
00365         t = painter.fontMetrics().elidedText(text(), Qt::ElideRight, textRoom);
00366         
00367         // See whether anything is left. Qt will return either 
00368         // ... or the ellipsis unicode character, 0x2026
00369         if (t == QLatin1String("...") || t == QChar(0x2026))
00370             t.clear();
00371     }
00372     
00373     opt.text = t;
00374     
00375     // Label time.... Simple case: no text, so just plop down the icon right in the center
00376     // We only do this when the button never draws the text, to avoid jumps in icon position
00377     // when resizing
00378     if (!shouldDrawText()) {
00379         style()->drawItemPixmap(&painter, rect(), Qt::AlignCenter | Qt::AlignVCenter, icon);
00380         return;
00381     }
00382 
00383     // Now where the icon/text goes depends on text direction and tab position  
00384     QRect iconArea;
00385     QRect labelArea;
00386     
00387     bool bottomIcon = false;
00388     bool rtl = layoutDirection() == Qt::RightToLeft;
00389     if (isVertical()) {
00390         if (m_position == KMultiTabBar::Left && !rtl)
00391             bottomIcon = true;
00392         if (m_position == KMultiTabBar::Right && rtl)
00393             bottomIcon = true;
00394     }
00395     //alignFlags = Qt::AlignLeading | Qt::AlignVCenter;
00396 
00397     if (isVertical()) {
00398         if (bottomIcon) {
00399             labelArea = QRect(0, vMargin, width(), textRoom);
00400             iconArea  = QRect(0, vMargin + textRoom, width(), iconRoom);
00401         } else {
00402             labelArea = QRect(0, iconRoom, width(), textRoom);
00403             iconArea  = QRect(0, 0, width(), iconRoom);
00404         }
00405     } else {
00406         // Pretty simple --- depends only on RTL/LTR
00407         if (rtl) {
00408             labelArea = QRect(hMargin, 0, textRoom, height());
00409             iconArea  = QRect(hMargin + textRoom, 0, iconRoom, height());
00410         } else {
00411             labelArea = QRect(iconRoom, 0, textRoom, height());
00412             iconArea  = QRect(0, 0, iconRoom, height());
00413         }
00414     }
00415     
00416     style()->drawItemPixmap(&painter, iconArea, Qt::AlignCenter | Qt::AlignVCenter, icon);
00417     
00418     if (t.isEmpty())
00419         return;
00420 
00421     QRect labelPaintArea = labelArea;
00422 
00423     if (isVertical()) {
00424         // If we're vertical, we paint to a simple 0,0 origin rect, 
00425         // and get the transformations to get us in the right place
00426         labelPaintArea = QRect(0, 0, labelArea.height(), labelArea.width());
00427 
00428         QTransform tr;
00429         
00430         if (bottomIcon) {
00431             tr.translate(labelArea.x(), labelPaintArea.width() + labelArea.y());
00432             tr.rotate(-90);
00433         } else {
00434             tr.translate(labelPaintArea.height() + labelArea.x(), labelArea.y());
00435             tr.rotate(90);
00436         }
00437         painter.setTransform(tr);
00438     }
00439     
00440     style()->drawItemText(&painter, labelPaintArea, Qt::AlignLeading | Qt::AlignVCenter,
00441                           palette(), true, t, QPalette::ButtonText);
00442 }
00443 
00444 // KMultiTabBar
00446 
00447 KMultiTabBar::KMultiTabBar(KMultiTabBarPosition pos, QWidget *parent)
00448     : QWidget(parent),
00449     d(new KMultiTabBarPrivate)
00450 {
00451     if (pos == Left || pos == Right)
00452     {
00453         d->m_l=new QVBoxLayout(this);
00454         setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding/*, true*/);
00455     }
00456     else
00457     {
00458         d->m_l=new QHBoxLayout(this);
00459         setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed/*, true*/);
00460     }
00461     d->m_l->setMargin(0);
00462     d->m_l->setSpacing(0);
00463 
00464     d->m_internal=new KMultiTabBarInternal(this, pos);
00465     setPosition(pos);
00466     setStyle(VSNET);
00467     d->m_l->insertWidget(0,d->m_internal);
00468     d->m_l->insertWidget(0,d->m_btnTabSep=new QFrame(this));
00469     d->m_btnTabSep->setFixedHeight(4);
00470     d->m_btnTabSep->setFrameStyle(QFrame::Panel | QFrame::Sunken);
00471     d->m_btnTabSep->setLineWidth(2);
00472     d->m_btnTabSep->hide();
00473 
00474     updateGeometry();
00475 }
00476 
00477 KMultiTabBar::~KMultiTabBar()
00478 {
00479     qDeleteAll( d->m_buttons );
00480     d->m_buttons.clear();
00481     delete d;
00482 }
00483 
00484 int KMultiTabBar::appendButton(const QPixmap &pic, int id, QMenu *popup, const QString&)
00485 {
00486     KMultiTabBarButton *btn = new KMultiTabBarButton(pic, QString(), id, this);
00487     btn->setMenu(popup);
00488     d->m_buttons.append(btn);
00489     d->m_l->insertWidget(0,btn);
00490     btn->show();
00491     d->m_btnTabSep->show();
00492     return 0;
00493 }
00494 
00495 void KMultiTabBar::updateSeparator() {
00496     bool hideSep=true;
00497     QListIterator<KMultiTabBarButton*> it(d->m_buttons);
00498     while (it.hasNext()){
00499         if (it.next()->isVisibleTo(this)) {
00500             hideSep=false;
00501             break;
00502         }
00503     }
00504     if (hideSep)
00505         d->m_btnTabSep->hide();
00506     else 
00507         d->m_btnTabSep->show();
00508 }
00509 
00510 int KMultiTabBar::appendTab(const QPixmap &pic, int id, const QString& text)
00511 {
00512     d->m_internal->appendTab(pic,id,text);
00513     return 0;
00514 }
00515 
00516 KMultiTabBarButton* KMultiTabBar::button(int id) const
00517 {
00518     QListIterator<KMultiTabBarButton*> it(d->m_buttons);
00519     while ( it.hasNext() ) {
00520         KMultiTabBarButton *button = it.next();
00521         if ( button->id() == id )
00522             return button;
00523     }
00524     
00525     return 0;
00526 }
00527 
00528 KMultiTabBarTab* KMultiTabBar::tab(int id) const
00529 {
00530     return d->m_internal->tab(id);
00531 }
00532 
00533 void KMultiTabBar::removeButton(int id)
00534 {
00535     for (int pos=0;pos<d->m_buttons.count();pos++)
00536     {
00537         if (d->m_buttons.at(pos)->id()==id)
00538         {
00539             d->m_buttons.takeAt(pos)->deleteLater();
00540             break;
00541         }
00542     }
00543     
00544     if (d->m_buttons.count()==0)
00545         d->m_btnTabSep->hide();
00546 }
00547 
00548 void KMultiTabBar::removeTab(int id)
00549 {
00550     d->m_internal->removeTab(id);
00551 }
00552 
00553 void KMultiTabBar::setTab(int id,bool state)
00554 {
00555     KMultiTabBarTab *ttab=tab(id);
00556     if (ttab)
00557         ttab->setState(state);
00558 }
00559 
00560 bool KMultiTabBar::isTabRaised(int id) const
00561 {
00562     KMultiTabBarTab *ttab=tab(id);
00563     if (ttab)
00564         return ttab->isChecked();
00565 
00566     return false;
00567 }
00568 
00569 void KMultiTabBar::setStyle(KMultiTabBarStyle style)
00570 {
00571     d->m_internal->setStyle(style);
00572 }
00573 
00574 KMultiTabBar::KMultiTabBarStyle KMultiTabBar::tabStyle() const
00575 {
00576     return d->m_internal->m_style;
00577 }
00578 
00579 void KMultiTabBar::setPosition(KMultiTabBarPosition pos)
00580 {
00581     d->m_position=pos;
00582     d->m_internal->setPosition(pos);
00583 }
00584 
00585 KMultiTabBar::KMultiTabBarPosition KMultiTabBar::position() const
00586 {
00587     return d->m_position;
00588 }
00589 
00590 void KMultiTabBar::fontChange(const QFont& /* oldFont */)
00591 {
00592     updateGeometry();
00593 }
00594 
00595 // vim: ts=4 sw=4 noet
00596 // 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
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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