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 #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
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
00133
00134
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
00161
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
00232 d->tabBarLayout->addStretch();
00233 d->tabBarLayout->addItem(d->tabProxy);
00234 d->tabBarLayout->addStretch();
00235 d->tabBarLayout->setContentsMargins(0,0,0,0);
00236
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
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
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
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 }
00576
00577 #include <tabbar.moc>
00578