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

Plasma

tabbar.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2008 Marco Martin <notmart@gmail.com>
00003  *
00004  *   This program is free software; you can redistribute it and/or modify
00005  *   it under the terms of the GNU Library General Public License as
00006  *   published by the Free Software Foundation; either version 2, or
00007  *   (at your option) any later version.
00008  *
00009  *   This program is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details
00013  *
00014  *   You should have received a copy of the GNU Library General Public
00015  *   License along with this program; if not, write to the
00016  *   Free Software Foundation, Inc.,
00017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00018  */
00019 
00020 #include "tabbar.h"
00021 
00022 #include <QGraphicsLinearLayout>
00023 #include <QGraphicsLayoutItem>
00024 #include <QString>
00025 #include <QGraphicsScene>
00026 #include <QGraphicsProxyWidget>
00027 #include <QGraphicsSceneWheelEvent>
00028 #include <QIcon>
00029 #include <QStyleOption>
00030 #include <QPainter>
00031 
00032 #include <kdebug.h>
00033 
00034 #include <plasma/animator.h>
00035 #include <plasma/theme.h>
00036 
00037 #include "private/nativetabbar_p.h"
00038 
00039 namespace Plasma
00040 {
00041 
00042 class TabBarProxy : public QGraphicsProxyWidget
00043 {
00044 public:
00045     TabBarProxy(QGraphicsWidget *parent)
00046     : QGraphicsProxyWidget(parent)
00047     {
00048         native = new NativeTabBar();
00049         native->setAttribute(Qt::WA_NoSystemBackground);
00050         setWidget(native);
00051         setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00052     }
00053 
00054     void paint(QPainter *painter,
00055                const QStyleOptionGraphicsItem *option,
00056                QWidget *widget)
00057     {
00058         Q_UNUSED(option);
00059         Q_UNUSED(widget);
00060         //Don't paint the child widgets
00061         static_cast<NativeTabBar *>(QGraphicsProxyWidget::widget())->render(
00062             painter, QPoint(0, 0), QRegion(), 0);
00063     }
00064 
00065     NativeTabBar *native;
00066 };
00067 
00068 class TabBarPrivate
00069 {
00070 public:
00071     TabBarPrivate(TabBar *parent)
00072         : q(parent),
00073           tabProxy(0),
00074           currentIndex(0),
00075           tabWidgetMode(true),
00076           oldPage(0),
00077           newPage(0),
00078           oldPageAnimId(-1),
00079           newPageAnimId(-1),
00080           customFont(false)
00081     {
00082     }
00083 
00084     ~TabBarPrivate()
00085     {
00086     }
00087 
00088     void updateTabWidgetMode();
00089     void slidingCompleted(QGraphicsItem *item);
00090     void shapeChanged(const KTabBar::Shape shape);
00091     void setPalette();
00092 
00093     TabBar *q;
00094     TabBarProxy *tabProxy;
00095     QList<QGraphicsWidget *> pages;
00096     QGraphicsLinearLayout *mainLayout;
00097     QGraphicsLinearLayout *tabWidgetLayout;
00098     QGraphicsLinearLayout *tabBarLayout;
00099     int currentIndex;
00100     bool tabWidgetMode;
00101 
00102     QGraphicsWidget *oldPage;
00103     QGraphicsWidget *newPage;
00104     int oldPageAnimId;
00105     int newPageAnimId;
00106     bool customFont;
00107 };
00108 
00109 void TabBarPrivate::updateTabWidgetMode()
00110 {
00111     bool tabWidget = false;
00112 
00113     foreach (QGraphicsWidget *page, pages) {
00114         if (page->preferredSize() != QSize(0, 0)) {
00115             tabWidget = true;
00116             break;
00117         }
00118     }
00119 
00120     if (tabWidget != tabWidgetMode) {
00121         if (tabWidget) {
00122             mainLayout->removeAt(0);
00123             tabBarLayout->insertItem(1, tabProxy);
00124             mainLayout->addItem(tabWidgetLayout);
00125         } else {
00126             mainLayout->removeAt(0);
00127             tabBarLayout->removeAt(1);
00128             mainLayout->addItem(tabProxy);
00129         }
00130     }
00131 
00132     //always show the tabbar
00133     //FIXME: Qt BUG: calling show on a child of an hidden item it shows it anyways
00134     //so we avoid to call it if the parent is hidden
00135     if (!tabWidget && q->isVisible()) {
00136         q->setTabBarShown(true);
00137     }
00138 
00139     tabWidgetMode = tabWidget;
00140 }
00141 
00142 void TabBarPrivate::slidingCompleted(QGraphicsItem *item)
00143 {
00144     if (item == oldPage || item == newPage) {
00145         if (item == newPage) {
00146             tabWidgetLayout->addItem(newPage);
00147             newPageAnimId = -1;
00148             mainLayout->invalidate();
00149             emit q->currentChanged(currentIndex);
00150         } else {
00151             oldPageAnimId = -1;
00152             item->hide();
00153         }
00154         q->setFlags(0);
00155     }
00156 }
00157 
00158 void TabBarPrivate::shapeChanged(const QTabBar::Shape shape)
00159 {
00160     //FIXME: QGraphicsLinearLayout doesn't have setDirection, so for now
00161     // North is equal to south and East is equal to West
00162     switch (shape) {
00163     case QTabBar::RoundedWest:
00164     case QTabBar::TriangularWest:
00165 
00166     case QTabBar::RoundedEast:
00167     case QTabBar::TriangularEast:
00168         tabBarLayout->setOrientation(Qt::Vertical);
00169         tabWidgetLayout->setOrientation(Qt::Horizontal);
00170         tabWidgetLayout->itemAt(0)->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00171         if (tabWidgetLayout->count() > 1) {
00172             tabWidgetLayout->itemAt(1)->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00173         }
00174         tabProxy->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00175         break;
00176 
00177     case QTabBar::RoundedSouth:
00178     case QTabBar::TriangularSouth:
00179 
00180     case QTabBar::RoundedNorth:
00181     case QTabBar::TriangularNorth:
00182     default:
00183         tabBarLayout->setOrientation(Qt::Horizontal);
00184         tabWidgetLayout->setOrientation(Qt::Vertical);
00185         tabWidgetLayout->itemAt(0)->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
00186         if (tabWidgetLayout->count() > 1) {
00187             tabWidgetLayout->itemAt(1)->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00188         }
00189         tabProxy->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00190     }
00191     tabProxy->setPreferredSize(tabProxy->native->sizeHint());
00192 }
00193 
00194 void TabBarPrivate::setPalette()
00195 {
00196     QTabBar *native = q->nativeWidget();
00197     QColor color = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
00198     QPalette p = native->palette();
00199 
00200     p.setColor(QPalette::Normal, QPalette::Text, color);
00201     p.setColor(QPalette::Inactive, QPalette::Text, color);
00202     p.setColor(QPalette::Normal, QPalette::ButtonText, color);
00203     p.setColor(QPalette::Inactive, QPalette::ButtonText, color);
00204     p.setColor(QPalette::Normal, QPalette::Base, QColor(0,0,0,0));
00205     p.setColor(QPalette::Inactive, QPalette::Base, QColor(0,0,0,0));
00206     native->setPalette(p);
00207 
00208     if (!customFont) {
00209         q->nativeWidget()->setFont(Plasma::Theme::defaultTheme()->font(Plasma::Theme::DefaultFont));
00210     }
00211 }
00212 
00213 TabBar::TabBar(QGraphicsWidget *parent)
00214     : QGraphicsWidget(parent),
00215       d(new TabBarPrivate(this))
00216 {
00217     setContentsMargins(0,0,0,0);
00218     d->tabProxy = new TabBarProxy(this);
00219     d->tabWidgetLayout = new QGraphicsLinearLayout(Qt::Vertical);
00220     d->tabBarLayout = new QGraphicsLinearLayout(Qt::Horizontal);
00221     d->tabWidgetLayout->setContentsMargins(0,0,0,0);
00222 
00223     d->mainLayout = new QGraphicsLinearLayout(Qt::Horizontal);
00224     d->mainLayout->addItem(d->tabWidgetLayout);
00225 
00226     setLayout(d->mainLayout);
00227     d->mainLayout->setContentsMargins(0,0,0,0);
00228 
00229     d->tabWidgetLayout->addItem(d->tabBarLayout);
00230 
00231     //tabBar is centered, so a stretch at begin one at the end
00232     d->tabBarLayout->addStretch();
00233     d->tabBarLayout->addItem(d->tabProxy);
00234     d->tabBarLayout->addStretch();
00235     d->tabBarLayout->setContentsMargins(0,0,0,0);
00236     //d->tabBarLayout->setStretchFactor(d->tabProxy, 2);
00237 
00238     connect(d->tabProxy->native, SIGNAL(currentChanged(int)),
00239             this, SLOT(setCurrentIndex(int)));
00240     connect(d->tabProxy->native, SIGNAL(shapeChanged(QTabBar::Shape)),
00241             this, SLOT(shapeChanged(QTabBar::Shape)));
00242     connect(Plasma::Animator::self(), SIGNAL(movementFinished(QGraphicsItem*)),
00243             this, SLOT(slidingCompleted(QGraphicsItem*)));
00244     connect(Theme::defaultTheme(),SIGNAL(themeChanged()),this,SLOT(setPalette()));
00245 }
00246 
00247 TabBar::~TabBar()
00248 {
00249     delete d;
00250 }
00251 
00252 
00253 int TabBar::insertTab(int index, const QIcon &icon, const QString &label,
00254                       QGraphicsLayoutItem *content)
00255 {
00256     QGraphicsWidget *page = new QGraphicsWidget(this);
00257     page->setContentsMargins(0,0,0,0);
00258     page->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
00259     if (content) {
00260         if (content->isLayout()) {
00261             page->setLayout(static_cast<QGraphicsLayout *>(content));
00262         } else {
00263             QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, page);
00264             layout->setContentsMargins(0,0,0,0);
00265             layout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
00266             layout->addItem(content);
00267             page->setLayout(layout);
00268         }
00269     } else {
00270         page->setPreferredSize(0, 0);
00271     }
00272 
00273     d->pages.insert(qBound(0, index, d->pages.count()), page);
00274 
00275     if (d->pages.count() == 1) {
00276         d->tabWidgetLayout->addItem(page);
00277         page->setVisible(true);
00278         page->setEnabled(true);
00279     } else {
00280         page->setVisible(false);
00281         page->setEnabled(false);
00282     }
00283 
00284     d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00285     d->updateTabWidgetMode();
00286 
00287     int actualIndex = d->tabProxy->native->insertTab(index, icon, label);
00288     d->currentIndex = d->tabProxy->native->currentIndex();
00289     d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00290     d->updateTabWidgetMode();
00291     return actualIndex;
00292 }
00293 
00294 int TabBar::insertTab(int index, const QString &label, QGraphicsLayoutItem *content)
00295 {
00296     return insertTab(index, QIcon(), label, content);
00297 }
00298 
00299 int TabBar::addTab(const QIcon &icon, const QString &label, QGraphicsLayoutItem *content)
00300 {
00301     return insertTab(d->pages.count(), icon, label, content);
00302 }
00303 
00304 int TabBar::addTab(const QString &label, QGraphicsLayoutItem *content)
00305 {
00306     return insertTab(d->pages.count(), QIcon(), label, content);
00307 }
00308 
00309 int TabBar::currentIndex() const
00310 {
00311     return d->tabProxy->native->currentIndex();
00312 }
00313 
00314 void TabBar::resizeEvent(QGraphicsSceneResizeEvent * event)
00315 {
00316     if (!d->tabWidgetMode) {
00317         d->tabProxy->setMinimumSize(event->newSize().toSize());
00318         setMinimumSize(QSize(0, 0));
00319         setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00320     } else {
00321         d->tabProxy->native->setMinimumSize(QSize(0,0));
00322     }
00323 }
00324 
00325 void TabBar::setCurrentIndex(int index)
00326 {
00327     if (index >= d->tabProxy->native->count() ||
00328         d->tabProxy->native->count() <= 1 ||
00329         d->currentIndex == index) {
00330         return;
00331     }
00332 
00333     if (d->currentIndex >= 0) {
00334         d->oldPage = d->pages[d->currentIndex];
00335     } else {
00336         d->oldPage = 0;
00337     }
00338 
00339     d->tabWidgetLayout->removeItem(d->oldPage);
00340 
00341     if (index >= 0) {
00342         d->newPage = d->pages[index];
00343     } else {
00344         d->newPage = 0;
00345     }
00346 
00347     setFlags(QGraphicsItem::ItemClipsChildrenToShape);
00348 
00349     //if an animation was in rogress hide everything to avoid an inconsistent state
00350     if (d->newPageAnimId != -1 || d->oldPageAnimId != -1) {
00351         foreach (QGraphicsWidget *page, d->pages) {
00352             page->hide();
00353         }
00354         if (d->newPageAnimId != -1) {
00355             Animator::self()->stopItemMovement(d->newPageAnimId);
00356         }
00357         if (d->oldPageAnimId != -1) {
00358             Animator::self()->stopItemMovement(d->oldPageAnimId);
00359         }
00360     }
00361 
00362     if (d->newPage) {
00363         d->newPage->show();
00364         d->newPage->setEnabled(true);
00365     }
00366 
00367     if (d->oldPage) {
00368         d->oldPage->show();
00369         d->oldPage->setEnabled(false);
00370     }
00371 
00372     if (d->newPage && d->oldPage) {
00373         //FIXME: it seems necessary to resiz the thing 2 times to have effect
00374         d->newPage->resize(1,1);
00375         d->newPage->resize(d->oldPage->size());
00376 
00377         QRect beforeCurrentGeom(d->oldPage->geometry().toRect());
00378         beforeCurrentGeom.moveTopRight(beforeCurrentGeom.topLeft());
00379 
00380         if (index > d->currentIndex) {
00381             d->newPage->setPos(d->oldPage->geometry().topRight());
00382             d->newPageAnimId = Animator::self()->moveItem(
00383             d->newPage, Plasma::Animator::SlideOutMovement,
00384             d->oldPage->pos().toPoint());
00385             d->oldPageAnimId = Animator::self()->moveItem(
00386                 d->oldPage, Plasma::Animator::SlideOutMovement,
00387                 beforeCurrentGeom.topLeft());
00388         } else {
00389             d->newPage->setPos(beforeCurrentGeom.topLeft());
00390             d->newPageAnimId = Animator::self()->moveItem(
00391             d->newPage, Plasma::Animator::SlideOutMovement,
00392             d->oldPage->pos().toPoint());
00393             d->oldPageAnimId = Animator::self()->moveItem(
00394                 d->oldPage, Plasma::Animator::SlideOutMovement,
00395                 d->oldPage->geometry().topRight().toPoint());
00396         }
00397     } else {
00398         d->tabWidgetLayout->addItem(d->newPage);
00399     }
00400 
00401     d->currentIndex = index;
00402 
00403     d->tabProxy->native->setCurrentIndex(index);
00404 }
00405 
00406 int TabBar::count() const
00407 {
00408     return d->pages.count();
00409 }
00410 
00411 void TabBar::removeTab(int index)
00412 {
00413     if (index >= d->pages.count()) {
00414         return;
00415     }
00416 
00417     int oldCurrentIndex = d->tabProxy->native->currentIndex();
00418     d->tabProxy->native->removeTab(index);
00419     QGraphicsWidget *page = d->pages.takeAt(index);
00420 
00421     int currentIndex = d->tabProxy->native->currentIndex();
00422 
00423     if (oldCurrentIndex == index) {
00424         d->tabWidgetLayout->removeAt(1);
00425     }
00426 
00427     scene()->removeItem(page);
00428     page->deleteLater();
00429 
00430     if (oldCurrentIndex != currentIndex) {
00431         setCurrentIndex(currentIndex);
00432     }
00433 
00434     d->updateTabWidgetMode();
00435     d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00436 }
00437 
00438 QGraphicsLayoutItem *TabBar::takeTab(int index)
00439 {
00440     if (index >= d->pages.count()) {
00441         return 0;
00442     }
00443 
00444     int oldCurrentIndex = d->tabProxy->native->currentIndex();
00445     d->tabProxy->native->removeTab(index);
00446     QGraphicsWidget *page = d->pages.takeAt(index);
00447 
00448     int currentIndex = d->tabProxy->native->currentIndex();
00449 
00450     if (oldCurrentIndex == index) {
00451         d->tabWidgetLayout->removeAt(1);
00452     }
00453 
00454     QGraphicsLayoutItem *returnItem = 0;
00455     QGraphicsLayout *lay = page->layout();
00456     if (lay && lay->count() == 1) {
00457         returnItem = lay->itemAt(0);
00458         lay->removeAt(0);
00459     } else {
00460         returnItem = lay;
00461     }
00462 
00463     if (returnItem) {
00464         returnItem->setParentLayoutItem(0);
00465     }
00466 
00467     page->setLayout(0);
00468     scene()->removeItem(page);
00469     page->deleteLater();
00470 
00471     if (oldCurrentIndex != currentIndex) {
00472         setCurrentIndex(currentIndex);
00473     }
00474 
00475     d->updateTabWidgetMode();
00476     d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00477 
00478     return returnItem;
00479 }
00480 
00481 QGraphicsLayoutItem *TabBar::tabAt(int index)
00482 {
00483     if (index >= d->pages.count()) {
00484         return 0;
00485     }
00486 
00487     QGraphicsWidget *page = d->pages.value(index);
00488 
00489     QGraphicsLayoutItem *returnItem = 0;
00490     QGraphicsLayout *lay = page->layout();
00491     if (lay && lay->count() == 1) {
00492         returnItem = lay->itemAt(0);
00493     } else {
00494         returnItem = lay;
00495     }
00496 
00497     return returnItem;
00498 }
00499 
00500 void TabBar::setTabText(int index, const QString &label)
00501 {
00502     if (index >= d->pages.count()) {
00503         return;
00504     }
00505 
00506     d->tabProxy->native->setTabText(index, label);
00507 }
00508 
00509 QString TabBar::tabText(int index) const
00510 {
00511     return d->tabProxy->native->tabText(index);
00512 }
00513 
00514 void TabBar::setTabIcon(int index, const QIcon &icon)
00515 {
00516     d->tabProxy->native->setTabIcon(index, icon);
00517 }
00518 
00519 QIcon TabBar::tabIcon(int index) const
00520 {
00521     return d->tabProxy->native->tabIcon(index);
00522 }
00523 
00524 void TabBar::setTabBarShown(bool show)
00525 {
00526     if (!show && !d->tabWidgetMode) {
00527         return;
00528     }
00529 
00530     if (!show && d->tabProxy->isVisible()) {
00531         d->tabProxy->hide();
00532         d->tabBarLayout->removeItem(d->tabBarLayout);
00533     } else if (show && !d->tabProxy->isVisible()) {
00534         d->tabProxy->show();
00535         d->tabBarLayout->insertItem(0, d->tabBarLayout);
00536     }
00537 }
00538 
00539 bool TabBar::isTabBarShown() const
00540 {
00541     return d->tabProxy->isVisible();
00542 }
00543 
00544 void TabBar::setStyleSheet(const QString &stylesheet)
00545 {
00546     d->tabProxy->native->setStyleSheet(stylesheet);
00547 }
00548 
00549 QString TabBar::styleSheet() const
00550 {
00551     return d->tabProxy->native->styleSheet();
00552 }
00553 
00554 KTabBar *TabBar::nativeWidget() const
00555 {
00556     return d->tabProxy->native;
00557 }
00558 
00559 void TabBar::wheelEvent(QGraphicsSceneWheelEvent * event)
00560 {
00561     Q_UNUSED(event)
00562     //Still here for binary compatibility
00563 }
00564 
00565 void TabBar::changeEvent(QEvent *event)
00566 {
00567     if (event->type() == QEvent::FontChange) {
00568         d->customFont = true;
00569         nativeWidget()->setFont(font());
00570     }
00571 
00572     QGraphicsWidget::changeEvent(event);
00573 }
00574 
00575 } // namespace Plasma
00576 
00577 #include <tabbar.moc>
00578 

Plasma

Skip menu "Plasma"
  • Main Page
  • 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