22#include <QGraphicsLinearLayout>
23#include <QGraphicsLayoutItem>
24#include <QGraphicsProxyWidget>
25#include <QGraphicsScene>
26#include <QGraphicsSceneWheelEvent>
30#include <QParallelAnimationGroup>
32#include <QStyleOption>
38#include "private/nativetabbar_p.h"
39#include "private/themedwidgetinterface_p.h"
51 native =
new NativeTabBar();
52 native->setAttribute(Qt::WA_NoSystemBackground);
54 setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
57 void paint(QPainter *painter,
64 static_cast<NativeTabBar *
>(QGraphicsProxyWidget::widget())->render(
65 painter, QPoint(0, 0), QRegion(), 0);
71class TabBarPrivate :
public ThemedWidgetInterface<TabBar>
74 TabBarPrivate(TabBar *parent)
75 : ThemedWidgetInterface<TabBar>(parent),
89 void updateTabWidgetMode();
90 void slidingCompleted(QGraphicsItem *item);
91 void slidingNewPageCompleted();
92 void slidingOldPageCompleted();
93 void shapeChanged(
const KTabBar::Shape shape);
95 TabBarProxy *tabProxy;
96 QList<QGraphicsWidget *> pages;
98 QGraphicsLinearLayout *mainLayout;
99 QGraphicsLinearLayout *tabWidgetLayout;
100 QGraphicsLinearLayout *tabBarLayout;
104 QWeakPointer<QGraphicsWidget> oldPage;
105 QWeakPointer<QGraphicsWidget> newPage;
108 Animation *oldPageAnim;
109 Animation *newPageAnim;
110 QParallelAnimationGroup *animGroup;
112 QWeakPointer<QGraphicsWidget> firstPositionWidget;
113 QWeakPointer<QGraphicsWidget> lastPositionWidget;
116void TabBarPrivate::updateTabWidgetMode()
122 bool tabWidget =
false;
125 if (page->preferredSize() != QSize(0, 0)) {
131 if (tabWidget != tabWidgetMode) {
133 mainLayout->removeAt(0);
134 tabBarLayout->insertItem(1, tabProxy);
135 mainLayout->addItem(tabWidgetLayout);
137 mainLayout->removeAt(0);
138 tabBarLayout->removeAt(1);
139 mainLayout->addItem(tabProxy);
146 if (!tabWidget && q->isVisible()) {
147 q->setTabBarShown(
true);
150 tabWidgetMode = tabWidget;
151 if (!tabWidgetMode) {
152 q->setMinimumSize(QSize(0, 0));
153 q->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
155 tabProxy->native->setMinimumSize(QSize(0,0));
156 tabProxy->setMinimumSize(QSize(0,0));
160void TabBarPrivate::slidingNewPageCompleted()
163 tabWidgetLayout->addItem(newPage.data());
166 mainLayout->invalidate();
167 emit q->currentChanged(currentIndex);
172void TabBarPrivate::slidingOldPageCompleted()
183void TabBarPrivate::shapeChanged(
const QTabBar::Shape shape)
188 case QTabBar::RoundedWest:
189 case QTabBar::TriangularWest:
191 case QTabBar::RoundedEast:
192 case QTabBar::TriangularEast:
193 q->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
194 tabBarLayout->setOrientation(Qt::Vertical);
195 tabWidgetLayout->setOrientation(Qt::Horizontal);
196 tabWidgetLayout->itemAt(0)->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
197 if (tabWidgetLayout->count() > 1) {
198 tabWidgetLayout->itemAt(1)->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
200 tabProxy->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
203 case QTabBar::RoundedSouth:
204 case QTabBar::TriangularSouth:
206 case QTabBar::RoundedNorth:
207 case QTabBar::TriangularNorth:
209 q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
210 tabBarLayout->setOrientation(Qt::Horizontal);
211 tabWidgetLayout->setOrientation(Qt::Vertical);
212 tabWidgetLayout->itemAt(0)->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
213 if (tabWidgetLayout->count() > 1) {
214 tabWidgetLayout->itemAt(1)->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
216 tabProxy->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
218 tabProxy->setPreferredSize(tabProxy->native->sizeHint());
223 d(new TabBarPrivate(this))
225 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
226 setContentsMargins(0,0,0,0);
227 d->tabProxy =
new TabBarProxy(
this);
228 d->tabWidgetLayout =
new QGraphicsLinearLayout(Qt::Vertical);
229 d->tabBarLayout =
new QGraphicsLinearLayout(Qt::Horizontal);
230 d->tabWidgetLayout->setContentsMargins(0,0,0,0);
232 d->mainLayout =
new QGraphicsLinearLayout(Qt::Horizontal);
233 d->mainLayout->addItem(d->tabWidgetLayout);
235 setLayout(d->mainLayout);
236 d->mainLayout->setContentsMargins(0,0,0,0);
242 d->tabWidgetLayout->addItem(d->tabBarLayout);
243 d->tabWidgetLayout->addItem(d->emptyTabBarSpacer);
246 d->tabBarLayout->addStretch();
247 d->tabBarLayout->addItem(d->tabProxy);
248 d->tabBarLayout->addStretch();
249 d->tabBarLayout->setContentsMargins(0,0,0,0);
255 d->animGroup =
new QParallelAnimationGroup(
this);
257 d->animGroup->addAnimation(d->newPageAnim);
258 d->animGroup->addAnimation(d->oldPageAnim);
262 connect(d->tabProxy->native, SIGNAL(shapeChanged(QTabBar::Shape)),
263 this, SLOT(shapeChanged(QTabBar::Shape)));
264 connect(d->newPageAnim, SIGNAL(finished()),
this, SLOT(slidingNewPageCompleted()));
265 connect(d->oldPageAnim, SIGNAL(finished()),
this, SLOT(slidingOldPageCompleted()));
275int TabBar::insertTab(
int index,
const QIcon &icon,
const QString &label,
276 QGraphicsLayoutItem *content)
279 page->setContentsMargins(0,0,0,0);
280 page->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
282 if (content->isLayout()) {
285 QGraphicsLinearLayout *layout =
new QGraphicsLinearLayout(Qt::Vertical, page);
286 layout->setContentsMargins(0,0,0,0);
287 layout->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
288 layout->addItem(content);
289 page->setLayout(layout);
292 page->setPreferredSize(0, 0);
295 d->pages.insert(qBound(0, index, d->pages.count()), page);
297 if (d->pages.count() == 1) {
298 d->tabWidgetLayout->removeItem(d->emptyTabBarSpacer);
299 d->tabWidgetLayout->addItem(page);
300 page->setVisible(
true);
301 page->setEnabled(
true);
303 page->setVisible(
false);
304 page->setEnabled(
false);
307 d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
308 d->updateTabWidgetMode();
310 int actualIndex = d->tabProxy->native->insertTab(index, icon, label);
311 d->currentIndex = d->tabProxy->native->currentIndex();
312 d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
313 d->updateTabWidgetMode();
317int TabBar::insertTab(
int index,
const QString &label, QGraphicsLayoutItem *content)
319 return insertTab(index, QIcon(), label, content);
322int TabBar::addTab(
const QIcon &icon,
const QString &label, QGraphicsLayoutItem *content)
324 return insertTab(d->pages.count(), icon, label, content);
327int TabBar::addTab(
const QString &label, QGraphicsLayoutItem *content)
329 return insertTab(d->pages.count(), QIcon(), label, content);
332int TabBar::currentIndex()
const
334 return d->tabProxy->native->currentIndex();
337void TabBar::resizeEvent(QGraphicsSceneResizeEvent * event)
339 if (!d->tabWidgetMode) {
340 d->tabProxy->setMinimumSize(event->newSize().toSize());
341 setMinimumSize(QSize(0, 0));
342 setMinimumHeight(d->tabProxy->widget()->minimumSizeHint().height());
343 setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
345 setMinimumSize(QSize(-1, -1));
346 d->tabProxy->native->setMinimumSize(QSize(0,0));
350void TabBar::setCurrentIndex(
int index)
352 if (index >= d->pages.count() ||
353 d->pages.count() < 2 ||
354 d->currentIndex == index) {
358 d->oldPage = d->pages.value(d->currentIndex);
361 d->tabWidgetLayout->removeItem(d->oldPage.data());
365 d->newPage = d->pages.value(index);
368 setFlags(QGraphicsItem::ItemClipsChildrenToShape);
372 if (d->animGroup->state() != QAbstractAnimation::Stopped) {
376 d->animGroup->stop();
380 d->newPage.data()->show();
381 d->newPage.data()->setEnabled(
true);
385 d->oldPage.data()->show();
386 d->oldPage.data()->setEnabled(
false);
389 if (d->newPage && d->oldPage) {
391 d->newPage.data()->resize(1,1);
392 d->newPage.data()->resize(d->oldPage.data()->size());
394 QRect beforeCurrentGeom(d->oldPage.data()->geometry().toRect());
395 beforeCurrentGeom.moveTopRight(beforeCurrentGeom.topLeft());
397 if (index > d->currentIndex) {
398 d->newPage.data()->setPos(d->oldPage.data()->geometry().topRight());
400 d->newPageAnim->setProperty(
"distancePointF", QPointF(d->oldPage.data()->size().width(), 0));
401 d->newPageAnim->setTargetWidget(d->newPage.data());
404 d->oldPageAnim->setProperty(
"distancePointF", QPointF(beforeCurrentGeom.width(), 0));
405 d->oldPageAnim->setTargetWidget(d->oldPage.data());
407 d->animGroup->start();
409 d->newPage.data()->setPos(beforeCurrentGeom.topLeft());
411 d->newPageAnim->setProperty(
"distancePointF", QPointF(d->oldPage.data()->size().width(), 0));
412 d->newPageAnim->setTargetWidget(d->newPage.data());
415 d->oldPageAnim->setProperty(
"distancePointF",
416 QPointF(d->oldPage.data()->size().width(), 0));
417 d->oldPageAnim->setTargetWidget(d->oldPage.data());
419 d->animGroup->start();
421 }
else if (d->newPage) {
422 d->tabWidgetLayout->addItem(d->newPage.data());
425 d->currentIndex = index;
426 d->tabProxy->native->setCurrentIndex(index);
429int TabBar::count()
const
431 return d->pages.count();
434void TabBar::removeTab(
int index)
436 if (index >= d->pages.count() || index < 0) {
440 d->newPageAnim->stop();
441 d->oldPageAnim->stop();
443 int oldCurrentIndex = d->tabProxy->native->currentIndex();
444 d->tabProxy->native->removeTab(index);
446 d->currentIndex = oldCurrentIndex;
449 if (oldCurrentIndex == index) {
450 d->tabWidgetLayout->removeAt(1);
451 if (d->tabProxy->native->count() > 0) {
457 scene()->removeItem(page);
460 if (d->pages.count() > 0) {
461 d->updateTabWidgetMode();
463 d->tabWidgetLayout->addItem(d->emptyTabBarSpacer);
467QGraphicsLayoutItem *TabBar::takeTab(
int index)
469 if (index >= d->pages.count()) {
473 int oldCurrentIndex = d->tabProxy->native->currentIndex();
474 d->tabProxy->native->removeTab(index);
478 if (oldCurrentIndex == index) {
479 d->tabWidgetLayout->removeAt(1);
480 if (d->tabProxy->native->count() > 0) {
486 QGraphicsLayoutItem *returnItem = 0;
488 if (lay && lay->count() == 1) {
489 returnItem = lay->itemAt(0);
496 returnItem->setParentLayoutItem(0);
497 if (QGraphicsItem *item = returnItem->graphicsItem()) {
498 item->setParentItem(0);
503 scene()->removeItem(page);
510 d->updateTabWidgetMode();
511 d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
516QGraphicsLayoutItem *TabBar::tabAt(
int index)
518 if (index >= d->pages.count()) {
524 QGraphicsLayoutItem *returnItem = 0;
526 if (lay && lay->count() == 1) {
527 returnItem = lay->itemAt(0);
535void TabBar::setTabText(
int index,
const QString &label)
537 if (index >= d->pages.count()) {
541 d->tabProxy->native->setTabText(index, label);
544QString TabBar::tabText(
int index)
const
546 return d->tabProxy->native->tabText(index);
549void TabBar::setTabIcon(
int index,
const QIcon &icon)
551 d->tabProxy->native->setTabIcon(index, icon);
554QIcon TabBar::tabIcon(
int index)
const
556 return d->tabProxy->native->tabIcon(index);
559void TabBar::setTabBarShown(
bool show)
561 if (!show && !d->tabWidgetMode) {
564 if (d->tabBarShown == show) {
567 d->tabBarShown = show;
571 d->tabWidgetLayout->removeItem(d->tabBarLayout);
574 d->tabWidgetLayout->insertItem(0, d->tabBarLayout);
578bool TabBar::isTabBarShown()
const
580 return d->tabBarShown;
583void TabBar::setStyleSheet(
const QString &stylesheet)
585 d->tabProxy->native->setStyleSheet(stylesheet);
588QString TabBar::styleSheet()
const
590 return d->tabProxy->native->styleSheet();
593void TabBar::setTabHighlighted(
int index,
bool highlight)
595 d->tabProxy->native->setTabHighlighted(index, highlight);
598bool TabBar::isTabHighlighted(
int index)
const
600 return d->tabProxy->native->isTabHighlighted(index);
603KTabBar *TabBar::nativeWidget()
const
605 return d->tabProxy->native;
608void TabBar::wheelEvent(QGraphicsSceneWheelEvent * event)
614void TabBar::changeEvent(QEvent *event)
616 d->changeEvent(event);
617 QGraphicsWidget::changeEvent(event);
622 if (d->lastPositionWidget.data() == widget) {
626 if (d->firstPositionWidget) {
628 d->tabBarLayout->removeItem(widget);
629 scene()->removeItem(widget);
630 widget->deleteLater();
633 d->firstPositionWidget = widget;
635 widget->setParentItem(
this);
636 if (layoutDirection() == Qt::LeftToRight) {
637 d->tabBarLayout->insertItem(0, widget);
639 d->tabBarLayout->addItem(widget);
647 return d->firstPositionWidget.data();
652 if (d->lastPositionWidget.data() == widget) {
656 if (d->lastPositionWidget) {
658 d->tabBarLayout->removeItem(widget);
659 scene()->removeItem(widget);
660 widget->deleteLater();
663 d->lastPositionWidget = widget;
665 widget->setParentItem(
this);
666 if (layoutDirection() == Qt::LeftToRight) {
667 d->tabBarLayout->addItem(widget);
669 d->tabBarLayout->insertItem(0, widget);
676 return d->lastPositionWidget.data();
static Plasma::Animation * create(Animator::Animation type, QObject *parent=0)
Factory to build new animation objects.
void setCurrentIndex(int index)
Activate a given tab.
void currentChanged(int index)
Emitted when the active tab changes.
Q_INVOKABLE int insertTab(int index, const QIcon &icon, const QString &label, QGraphicsLayoutItem *content=0)
Adds a new tab in the desired position.
Namespace for everything in libplasma.