00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
00148
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
00194 d->tabBarLayout->addStretch();
00195 d->tabBarLayout->addItem(d->tabProxy);
00196 d->tabBarLayout->addStretch();
00197
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
00297
00298
00299 #ifdef USE_SLIDING_ANIMATION
00300 d->newPage->resize(d->oldPage->size());
00301
00302 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
00303
00304
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
00421
00422 if (d->tabProxy->native->underMouse()) {
00423
00424 if (event->delta() < 0) {
00425 int index = d->tabProxy->native->currentIndex();
00426
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 }
00452
00453 #include <tabbar.moc>
00454