• Skip to content
  • Skip to link menu
KDE 4.2 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 
00036 #include "private/nativetabbar_p.h"
00037 
00038 namespace Plasma
00039 {
00040 
00041 class TabBarProxy : public QGraphicsProxyWidget
00042 {
00043 public:
00044     TabBarProxy(QGraphicsWidget *parent)
00045     : QGraphicsProxyWidget(parent)
00046     {
00047         native = new NativeTabBar();
00048         native->setAttribute(Qt::WA_NoSystemBackground);
00049         setWidget(native);
00050         setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00051     }
00052 
00053     void paint(QPainter *painter,
00054                const QStyleOptionGraphicsItem *option,
00055                QWidget *widget)
00056     {
00057         Q_UNUSED(option);
00058         Q_UNUSED(widget);
00059         //Don't paint the child widgets
00060         static_cast<NativeTabBar *>(QGraphicsProxyWidget::widget())->render(
00061             painter, QPoint(0, 0), QRegion(), 0);
00062     }
00063 
00064     NativeTabBar *native;
00065 };
00066 
00067 class TabBarPrivate
00068 {
00069 public:
00070     TabBarPrivate(TabBar *parent)
00071         : q(parent),
00072           tabProxy(0),
00073           currentIndex(0),
00074           isTabWidget(true),
00075           oldPage(0),
00076           newPage(0),
00077           oldPageAnimId(-1),
00078           newPageAnimId(-1)
00079     {
00080     }
00081 
00082     ~TabBarPrivate()
00083     {
00084     }
00085 
00086     void updateTabWidgetMode();
00087     void slidingCompleted(QGraphicsItem *item);
00088     void shapeChanged(const KTabBar::Shape shape);
00089 
00090     TabBar *q;
00091     TabBarProxy *tabProxy;
00092     QList<QGraphicsWidget *> pages;
00093     QGraphicsLinearLayout *mainLayout;
00094     QGraphicsLinearLayout *tabWidgetLayout;
00095     QGraphicsLinearLayout *tabBarLayout;
00096     int currentIndex;
00097     bool isTabWidget;
00098 
00099     QGraphicsWidget *oldPage;
00100     QGraphicsWidget *newPage;
00101     int oldPageAnimId;
00102     int newPageAnimId;
00103 };
00104 
00105 void TabBarPrivate::updateTabWidgetMode()
00106 {
00107     bool tabWidget = false;
00108 
00109     foreach (QGraphicsWidget *page, pages) {
00110         if (page->preferredSize() != QSize(0, 0)) {
00111             tabWidget = true;
00112             break;
00113         }
00114     }
00115 
00116     if (tabWidget != isTabWidget) {
00117         if (tabWidget) {
00118             mainLayout->removeAt(0);
00119             tabBarLayout->insertItem(1, tabProxy);
00120             mainLayout->addItem(tabWidgetLayout);
00121         } else {
00122             mainLayout->removeAt(0);
00123             tabBarLayout->removeAt(1);
00124             mainLayout->addItem(tabProxy);
00125         }
00126     }
00127 
00128     isTabWidget = tabWidget;
00129 }
00130 
00131 void TabBarPrivate::slidingCompleted(QGraphicsItem *item)
00132 {
00133     if (item == oldPage || item == newPage) {
00134         if (item == newPage) {
00135             tabWidgetLayout->addItem(newPage);
00136             newPageAnimId = -1;
00137         } else {
00138             oldPageAnimId = -1;
00139             item->hide();
00140         }
00141         q->setFlags(0);
00142     }
00143 }
00144 
00145 void TabBarPrivate::shapeChanged(const QTabBar::Shape shape)
00146 {
00147     //FIXME: QGraphicsLinearLayout doesn't have setDirection, so for now
00148     // North is equal to south and East is equal to West
00149     switch (shape) {
00150     case QTabBar::RoundedWest:
00151     case QTabBar::TriangularWest:
00152 
00153     case QTabBar::RoundedEast:
00154     case QTabBar::TriangularEast:
00155         tabBarLayout->setOrientation(Qt::Vertical);
00156         tabWidgetLayout->setOrientation(Qt::Horizontal);
00157         tabWidgetLayout->itemAt(0)->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00158         tabWidgetLayout->itemAt(1)->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00159         tabProxy->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00160         break;
00161 
00162     case QTabBar::RoundedSouth:
00163     case QTabBar::TriangularSouth:
00164 
00165     case QTabBar::RoundedNorth:
00166     case QTabBar::TriangularNorth:
00167     default:
00168         tabBarLayout->setOrientation(Qt::Horizontal);
00169         tabWidgetLayout->setOrientation(Qt::Vertical);
00170         tabWidgetLayout->itemAt(0)->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00171         tabWidgetLayout->itemAt(1)->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00172         tabProxy->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00173     }
00174     tabProxy->setPreferredSize(tabProxy->native->sizeHint());
00175 }
00176 
00177 TabBar::TabBar(QGraphicsWidget *parent)
00178     : QGraphicsWidget(parent),
00179       d(new TabBarPrivate(this))
00180 {
00181     d->tabProxy = new TabBarProxy(this);
00182     d->tabWidgetLayout = new QGraphicsLinearLayout(Qt::Vertical);
00183     d->tabBarLayout = new QGraphicsLinearLayout(Qt::Horizontal);
00184 
00185     d->mainLayout = new QGraphicsLinearLayout(Qt::Horizontal);
00186     d->mainLayout->addItem(d->tabWidgetLayout);
00187 
00188     setLayout(d->mainLayout);
00189     d->mainLayout->setContentsMargins(0,0,0,0);
00190 
00191     d->tabWidgetLayout->addItem(d->tabBarLayout);
00192 
00193     //tabBar is centered, so a stretch at begin one at the end
00194     d->tabBarLayout->addStretch();
00195     d->tabBarLayout->addItem(d->tabProxy);
00196     d->tabBarLayout->addStretch();
00197     //d->tabBarLayout->setStretchFactor(d->tabProxy, 2);
00198 
00199     connect(d->tabProxy->native, SIGNAL(currentChanged(int)),
00200             this, SLOT(setCurrentIndex(int)));
00201     connect(d->tabProxy->native, SIGNAL(shapeChanged(QTabBar::Shape)),
00202             this, SLOT(shapeChanged(QTabBar::Shape)));
00203     connect(Plasma::Animator::self(), SIGNAL(movementFinished(QGraphicsItem*)),
00204             this, SLOT(slidingCompleted(QGraphicsItem*)));
00205 }
00206 
00207 TabBar::~TabBar()
00208 {
00209     delete d;
00210 }
00211 
00212 
00213 int TabBar::insertTab(int index, const QIcon &icon, const QString &label,
00214                       QGraphicsLayoutItem *content)
00215 {
00216     QGraphicsWidget *page = new QGraphicsWidget(this);
00217     page->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00218     if (content) {
00219         if (content->isLayout()) {
00220             page->setLayout(static_cast<QGraphicsLayout *>(content));
00221         } else {
00222             QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, page);
00223             layout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00224             layout->addItem(content);
00225             page->setLayout(layout);
00226         }
00227     } else {
00228         page->setPreferredSize(0, 0);
00229     }
00230 
00231     d->pages.insert(qBound(0, index, d->pages.count()), page);
00232 
00233     if (d->pages.count() == 1) {
00234         d->tabWidgetLayout->addItem(page);
00235         page->setVisible(true);
00236         page->setEnabled(true);
00237     } else {
00238         page->setVisible(false);
00239         page->setEnabled(false);
00240     }
00241 
00242     d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00243     d->updateTabWidgetMode();
00244 
00245     int actualIndex = d->tabProxy->native->insertTab(index, icon, label);
00246     d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00247     d->updateTabWidgetMode();
00248     return actualIndex;
00249 }
00250 
00251 int TabBar::insertTab(int index, const QString &label, QGraphicsLayoutItem *content)
00252 {
00253     return insertTab(index, QIcon(), label, content);
00254 }
00255 
00256 int TabBar::addTab(const QIcon &icon, const QString &label, QGraphicsLayoutItem *content)
00257 {
00258     return insertTab(d->pages.count(), icon, label, content);
00259 }
00260 
00261 int TabBar::addTab(const QString &label, QGraphicsLayoutItem *content)
00262 {
00263     return insertTab(d->pages.count(), QIcon(), label, content);
00264 }
00265 
00266 int TabBar::currentIndex() const
00267 {
00268     return d->tabProxy->native->currentIndex();
00269 }
00270 
00271 void TabBar::resizeEvent(QGraphicsSceneResizeEvent * event)
00272 {
00273     if (!d->isTabWidget) {
00274         d->tabProxy->native->setMinimumSize(contentsRect().size().toSize());
00275     } else {
00276         d->tabProxy->native->setMinimumSize(QSize(0,0));
00277     }
00278 
00279     setMaximumSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX);
00280     setMinimumSize(0, 0);
00281 }
00282 
00283 void TabBar::setCurrentIndex(int index)
00284 {
00285     if (index > d->tabProxy->native->count() ||
00286         d->tabProxy->native->count() <= 1 ||
00287         d->currentIndex == index) {
00288         return;
00289     }
00290 
00291     d->tabWidgetLayout->removeAt(1);
00292 
00293     d->oldPage = d->pages[d->currentIndex];
00294     d->newPage = d->pages[index];
00295 
00296 //FIXME: this part should be enabled again once
00297 //http://trolltech.com/developer/task-tracker/index_html?id=220488
00298 //get fixed
00299 #ifdef USE_SLIDING_ANIMATION
00300     d->newPage->resize(d->oldPage->size());
00301 
00302     setFlags(QGraphicsItem::ItemClipsChildrenToShape);
00303 
00304     //if an animation was in rogress hide everything to avoid an inconsistent state
00305     if (d->newPageAnimId != -1 || d->oldPageAnimId != -1) {
00306         foreach (QGraphicsWidget *page, d->pages) {
00307             page->hide();
00308         }
00309         if (d->newPageAnimId != -1) {
00310             Animator::self()->stopItemMovement(d->newPageAnimId);
00311         }
00312         if (d->oldPageAnimId != -1) {
00313             Animator::self()->stopItemMovement(d->oldPageAnimId);
00314         }
00315     }
00316 
00317     d->oldPage->show();
00318     d->newPage->show();
00319     d->newPage->setEnabled(true);
00320 
00321     d->oldPage->setEnabled(false);
00322 
00323     QRect beforeCurrentGeom(d->oldPage->geometry().toRect());
00324     beforeCurrentGeom.moveTopRight(beforeCurrentGeom.topLeft());
00325 
00326     d->newPageAnimId = Animator::self()->moveItem(
00327         d->newPage, Plasma::Animator::SlideOutMovement,
00328         d->oldPage->pos().toPoint());
00329     if (index > d->currentIndex) {
00330         d->newPage->setPos(d->oldPage->geometry().topRight());
00331         d->oldPageAnimId = Animator::self()->moveItem(
00332             d->oldPage, Plasma::Animator::SlideOutMovement,
00333             beforeCurrentGeom.topLeft());
00334     } else {
00335         d->newPage->setPos(beforeCurrentGeom.topLeft());
00336         d->oldPageAnimId = Animator::self()->moveItem(
00337             d->oldPage, Plasma::Animator::SlideOutMovement,
00338             d->oldPage->geometry().topRight().toPoint());
00339     }
00340 #else
00341     d->tabWidgetLayout->addItem(d->pages[index]);
00342     d->oldPage->hide();
00343     d->newPage->show();
00344     d->newPage->setEnabled(true);
00345     d->oldPage->setEnabled(false);
00346 #endif
00347     d->currentIndex = index;
00348     emit currentChanged(index);
00349     d->tabProxy->native->setCurrentIndex(index);
00350 }
00351 
00352 int TabBar::count() const
00353 {
00354     return d->pages.count();
00355 }
00356 
00357 void TabBar::removeTab(int index)
00358 {
00359     if (index > d->pages.count()) {
00360         return;
00361     }
00362 
00363     int currentIndex = d->tabProxy->native->currentIndex();
00364 
00365     d->tabProxy->native->removeTab(index);
00366     QGraphicsWidget *page = d->pages.takeAt(index);
00367 
00368     if (index == currentIndex) {
00369         setCurrentIndex(currentIndex);
00370     }
00371 
00372     scene()->removeItem(page);
00373     page->deleteLater();
00374 
00375     d->updateTabWidgetMode();
00376     d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00377 }
00378 
00379 void TabBar::setTabText(int index, const QString &label)
00380 {
00381     if (index > d->pages.count()) {
00382         return;
00383     }
00384 
00385     d->tabProxy->native->setTabText(index, label);
00386 }
00387 
00388 QString TabBar::tabText(int index) const
00389 {
00390     return d->tabProxy->native->tabText(index);
00391 }
00392 
00393 void TabBar::setTabIcon(int index, const QIcon &icon)
00394 {
00395     d->tabProxy->native->setTabIcon(index, icon);
00396 }
00397 
00398 QIcon TabBar::tabIcon(int index) const
00399 {
00400     return d->tabProxy->native->tabIcon(index);
00401 }
00402 
00403 void TabBar::setStyleSheet(const QString &stylesheet)
00404 {
00405     d->tabProxy->native->setStyleSheet(stylesheet);
00406 }
00407 
00408 QString TabBar::styleSheet() const
00409 {
00410     return d->tabProxy->native->styleSheet();
00411 }
00412 
00413 KTabBar *TabBar::nativeWidget() const
00414 {
00415     return d->tabProxy->native;
00416 }
00417 
00418 void TabBar::wheelEvent(QGraphicsSceneWheelEvent * event)
00419 {
00420     //FIXME: probably this would make more sense in NativeTabBar, but it works only here
00421 
00422     if (d->tabProxy->native->underMouse()) {
00423         //Cycle tabs with the circular array tecnique
00424         if (event->delta() < 0) {
00425             int index = d->tabProxy->native->currentIndex();
00426             //search for an enabled tab
00427             for (int i = 0; i < d->tabProxy->native->count()-1; ++i) {
00428                 index = (index + 1) % d->tabProxy->native->count();
00429                 if (d->tabProxy->native->isTabEnabled(index)) {
00430                     break;
00431                 }
00432             }
00433 
00434             d->tabProxy->native->setCurrentIndex(index);
00435         } else {
00436             int index = d->tabProxy->native->currentIndex();
00437             for (int i = 0; i < d->tabProxy->native->count()-1; ++i) {
00438                 index = (d->tabProxy->native->count() + index -1) % d->tabProxy->native->count();
00439                 if (d->tabProxy->native->isTabEnabled(index)) {
00440                     break;
00441                 }
00442             }
00443 
00444             d->tabProxy->native->setCurrentIndex(index);
00445         }
00446     } else {
00447         QGraphicsWidget::wheelEvent(event);
00448     }
00449 }
00450 
00451 } // namespace Plasma
00452 
00453 #include <tabbar.moc>
00454 

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
  • 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