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 tabWidgetMode(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 tabWidgetMode;
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 != tabWidgetMode) {
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
00129
00130
00131 if (!tabWidget && q->isVisible()) {
00132 q->setTabBarShown(true);
00133 }
00134
00135 tabWidgetMode = tabWidget;
00136 }
00137
00138 void TabBarPrivate::slidingCompleted(QGraphicsItem *item)
00139 {
00140 if (item == oldPage || item == newPage) {
00141 if (item == newPage) {
00142 tabWidgetLayout->addItem(newPage);
00143 newPageAnimId = -1;
00144 } else {
00145 oldPageAnimId = -1;
00146 item->hide();
00147 }
00148 q->setFlags(0);
00149 }
00150 }
00151
00152 void TabBarPrivate::shapeChanged(const QTabBar::Shape shape)
00153 {
00154
00155
00156 switch (shape) {
00157 case QTabBar::RoundedWest:
00158 case QTabBar::TriangularWest:
00159
00160 case QTabBar::RoundedEast:
00161 case QTabBar::TriangularEast:
00162 tabBarLayout->setOrientation(Qt::Vertical);
00163 tabWidgetLayout->setOrientation(Qt::Horizontal);
00164 tabWidgetLayout->itemAt(0)->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00165 if (tabWidgetLayout->count() > 1) {
00166 tabWidgetLayout->itemAt(1)->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00167 }
00168 tabProxy->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00169 break;
00170
00171 case QTabBar::RoundedSouth:
00172 case QTabBar::TriangularSouth:
00173
00174 case QTabBar::RoundedNorth:
00175 case QTabBar::TriangularNorth:
00176 default:
00177 tabBarLayout->setOrientation(Qt::Horizontal);
00178 tabWidgetLayout->setOrientation(Qt::Vertical);
00179 tabWidgetLayout->itemAt(0)->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
00180 if (tabWidgetLayout->count() > 1) {
00181 tabWidgetLayout->itemAt(1)->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00182 }
00183 tabProxy->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00184 }
00185 tabProxy->setPreferredSize(tabProxy->native->sizeHint());
00186 }
00187
00188 TabBar::TabBar(QGraphicsWidget *parent)
00189 : QGraphicsWidget(parent),
00190 d(new TabBarPrivate(this))
00191 {
00192 d->tabProxy = new TabBarProxy(this);
00193 d->tabWidgetLayout = new QGraphicsLinearLayout(Qt::Vertical);
00194 d->tabBarLayout = new QGraphicsLinearLayout(Qt::Horizontal);
00195
00196 d->mainLayout = new QGraphicsLinearLayout(Qt::Horizontal);
00197 d->mainLayout->addItem(d->tabWidgetLayout);
00198
00199 setLayout(d->mainLayout);
00200 d->mainLayout->setContentsMargins(0,0,0,0);
00201
00202 d->tabWidgetLayout->addItem(d->tabBarLayout);
00203
00204
00205 d->tabBarLayout->addStretch();
00206 d->tabBarLayout->addItem(d->tabProxy);
00207 d->tabBarLayout->addStretch();
00208
00209
00210 connect(d->tabProxy->native, SIGNAL(currentChanged(int)),
00211 this, SLOT(setCurrentIndex(int)));
00212 connect(d->tabProxy->native, SIGNAL(shapeChanged(QTabBar::Shape)),
00213 this, SLOT(shapeChanged(QTabBar::Shape)));
00214 connect(Plasma::Animator::self(), SIGNAL(movementFinished(QGraphicsItem*)),
00215 this, SLOT(slidingCompleted(QGraphicsItem*)));
00216 }
00217
00218 TabBar::~TabBar()
00219 {
00220 delete d;
00221 }
00222
00223
00224 int TabBar::insertTab(int index, const QIcon &icon, const QString &label,
00225 QGraphicsLayoutItem *content)
00226 {
00227 QGraphicsWidget *page = new QGraphicsWidget(this);
00228 page->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00229 if (content) {
00230 if (content->isLayout()) {
00231 page->setLayout(static_cast<QGraphicsLayout *>(content));
00232 } else {
00233 QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, page);
00234 layout->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00235 layout->addItem(content);
00236 page->setLayout(layout);
00237 }
00238 } else {
00239 page->setPreferredSize(0, 0);
00240 }
00241
00242 d->pages.insert(qBound(0, index, d->pages.count()), page);
00243
00244 if (d->pages.count() == 1) {
00245 d->tabWidgetLayout->addItem(page);
00246 page->setVisible(true);
00247 page->setEnabled(true);
00248 } else {
00249 page->setVisible(false);
00250 page->setEnabled(false);
00251 }
00252
00253 d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00254 d->updateTabWidgetMode();
00255
00256 int actualIndex = d->tabProxy->native->insertTab(index, icon, label);
00257 d->currentIndex = d->tabProxy->native->currentIndex();
00258 d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00259 d->updateTabWidgetMode();
00260 return actualIndex;
00261 }
00262
00263 int TabBar::insertTab(int index, const QString &label, QGraphicsLayoutItem *content)
00264 {
00265 return insertTab(index, QIcon(), label, content);
00266 }
00267
00268 int TabBar::addTab(const QIcon &icon, const QString &label, QGraphicsLayoutItem *content)
00269 {
00270 return insertTab(d->pages.count(), icon, label, content);
00271 }
00272
00273 int TabBar::addTab(const QString &label, QGraphicsLayoutItem *content)
00274 {
00275 return insertTab(d->pages.count(), QIcon(), label, content);
00276 }
00277
00278 int TabBar::currentIndex() const
00279 {
00280 return d->tabProxy->native->currentIndex();
00281 }
00282
00283 void TabBar::resizeEvent(QGraphicsSceneResizeEvent * event)
00284 {
00285 if (!d->tabWidgetMode) {
00286 d->tabProxy->setMinimumSize(event->newSize().toSize());
00287 setMinimumSize(QSize(0, 0));
00288 setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
00289 } else {
00290 d->tabProxy->native->setMinimumSize(QSize(0,0));
00291 }
00292 }
00293
00294 void TabBar::setCurrentIndex(int index)
00295 {
00296 if (index >= d->tabProxy->native->count() ||
00297 d->tabProxy->native->count() <= 1 ||
00298 d->currentIndex == index) {
00299 return;
00300 }
00301
00302 d->tabWidgetLayout->removeAt(1);
00303
00304 if (d->currentIndex >= 0) {
00305 d->oldPage = d->pages[d->currentIndex];
00306 } else {
00307 d->oldPage = 0;
00308 }
00309
00310 if (index >= 0) {
00311 d->newPage = d->pages[index];
00312 } else {
00313 d->newPage = 0;
00314 }
00315
00316 if (d->newPage && d->oldPage) {
00317 d->newPage->resize(d->oldPage->size());
00318 }
00319
00320 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
00321
00322
00323 if (d->newPageAnimId != -1 || d->oldPageAnimId != -1) {
00324 foreach (QGraphicsWidget *page, d->pages) {
00325 page->hide();
00326 }
00327 if (d->newPageAnimId != -1) {
00328 Animator::self()->stopItemMovement(d->newPageAnimId);
00329 }
00330 if (d->oldPageAnimId != -1) {
00331 Animator::self()->stopItemMovement(d->oldPageAnimId);
00332 }
00333 }
00334
00335 if (d->newPage) {
00336 d->newPage->show();
00337 d->newPage->setEnabled(true);
00338 }
00339
00340 if (d->oldPage) {
00341 d->oldPage->show();
00342 d->oldPage->setEnabled(false);
00343 }
00344
00345 if (d->newPage && d->oldPage) {
00346 QRect beforeCurrentGeom(d->oldPage->geometry().toRect());
00347 beforeCurrentGeom.moveTopRight(beforeCurrentGeom.topLeft());
00348
00349 d->newPageAnimId = Animator::self()->moveItem(
00350 d->newPage, Plasma::Animator::SlideOutMovement,
00351 d->oldPage->pos().toPoint());
00352 if (index > d->currentIndex) {
00353 d->newPage->setPos(d->oldPage->geometry().topRight());
00354 d->oldPageAnimId = Animator::self()->moveItem(
00355 d->oldPage, Plasma::Animator::SlideOutMovement,
00356 beforeCurrentGeom.topLeft());
00357 } else {
00358 d->newPage->setPos(beforeCurrentGeom.topLeft());
00359 d->oldPageAnimId = Animator::self()->moveItem(
00360 d->oldPage, Plasma::Animator::SlideOutMovement,
00361 d->oldPage->geometry().topRight().toPoint());
00362 }
00363 } else {
00364 d->tabWidgetLayout->addItem(d->newPage);
00365 }
00366
00367 d->currentIndex = index;
00368 emit currentChanged(index);
00369 d->tabProxy->native->setCurrentIndex(index);
00370 }
00371
00372 int TabBar::count() const
00373 {
00374 return d->pages.count();
00375 }
00376
00377 void TabBar::removeTab(int index)
00378 {
00379 if (index > d->pages.count()) {
00380 return;
00381 }
00382
00383 int oldCurrentIndex = d->tabProxy->native->currentIndex();
00384 d->tabProxy->native->removeTab(index);
00385 QGraphicsWidget *page = d->pages.takeAt(index);
00386
00387 int currentIndex = d->tabProxy->native->currentIndex();
00388
00389 if (oldCurrentIndex == index) {
00390 d->tabWidgetLayout->removeAt(1);
00391 }
00392
00393 scene()->removeItem(page);
00394 page->deleteLater();
00395
00396 if (oldCurrentIndex != currentIndex) {
00397 setCurrentIndex(currentIndex);
00398 }
00399
00400 d->updateTabWidgetMode();
00401 d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
00402 }
00403
00404 void TabBar::setTabText(int index, const QString &label)
00405 {
00406 if (index > d->pages.count()) {
00407 return;
00408 }
00409
00410 d->tabProxy->native->setTabText(index, label);
00411 }
00412
00413 QString TabBar::tabText(int index) const
00414 {
00415 return d->tabProxy->native->tabText(index);
00416 }
00417
00418 void TabBar::setTabIcon(int index, const QIcon &icon)
00419 {
00420 d->tabProxy->native->setTabIcon(index, icon);
00421 }
00422
00423 QIcon TabBar::tabIcon(int index) const
00424 {
00425 return d->tabProxy->native->tabIcon(index);
00426 }
00427
00428 void TabBar::setTabBarShown(bool show)
00429 {
00430 if (!show && !d->tabWidgetMode) {
00431 return;
00432 }
00433
00434 if (!show && d->tabProxy->isVisible()) {
00435 d->tabProxy->hide();
00436 d->tabBarLayout->removeItem(d->tabProxy);
00437 } else if (show && !d->tabProxy->isVisible()) {
00438 d->tabProxy->show();
00439 d->tabBarLayout->insertItem(0, d->tabProxy);
00440 }
00441 }
00442
00443 bool TabBar::isTabBarShown() const
00444 {
00445 return d->tabProxy->isVisible();
00446 }
00447
00448 void TabBar::setStyleSheet(const QString &stylesheet)
00449 {
00450 d->tabProxy->native->setStyleSheet(stylesheet);
00451 }
00452
00453 QString TabBar::styleSheet() const
00454 {
00455 return d->tabProxy->native->styleSheet();
00456 }
00457
00458 KTabBar *TabBar::nativeWidget() const
00459 {
00460 return d->tabProxy->native;
00461 }
00462
00463 void TabBar::wheelEvent(QGraphicsSceneWheelEvent * event)
00464 {
00465 Q_UNUSED(event)
00466
00467 }
00468
00469 }
00470
00471 #include <tabbar.moc>
00472