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