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);
71 class 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;
116 void 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));
160 void TabBarPrivate::slidingNewPageCompleted()
163 tabWidgetLayout->addItem(newPage.data());
166 mainLayout->invalidate();
167 emit q->currentChanged(currentIndex);
172 void TabBarPrivate::slidingOldPageCompleted()
183 void 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);
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);
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);
230 d->tabWidgetLayout->setContentsMargins(0,0,0,0);
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()));
276 QGraphicsLayoutItem *content)
279 page->setContentsMargins(0,0,0,0);
280 page->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
282 if (content->isLayout()) {
283 page->setLayout(static_cast<QGraphicsLayout *>(content));
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();
319 return insertTab(index, QIcon(), label, content);
322 int TabBar::addTab(
const QIcon &icon,
const QString &label, QGraphicsLayoutItem *content)
324 return insertTab(d->pages.count(), icon, label, content);
329 return insertTab(d->pages.count(), QIcon(), label, content);
334 return d->tabProxy->native->currentIndex();
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));
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);
431 return d->pages.count();
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) {
452 setCurrentIndex(currentIndex >= oldCurrentIndex ? currentIndex + 1 : currentIndex);
457 scene()->removeItem(page);
460 if (d->pages.count() > 0) {
461 d->updateTabWidgetMode();
463 d->tabWidgetLayout->addItem(d->emptyTabBarSpacer);
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) {
481 setCurrentIndex(currentIndex >= oldCurrentIndex ? currentIndex + 1 : currentIndex);
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);
506 if (oldCurrentIndex != currentIndex) {
510 d->updateTabWidgetMode();
511 d->tabProxy->setPreferredSize(d->tabProxy->native->sizeHint());
518 if (index >= d->pages.count()) {
524 QGraphicsLayoutItem *returnItem = 0;
526 if (lay && lay->count() == 1) {
527 returnItem = lay->itemAt(0);
537 if (index >= d->pages.count()) {
541 d->tabProxy->native->setTabText(index, label);
546 return d->tabProxy->native->tabText(index);
551 d->tabProxy->native->setTabIcon(index, icon);
556 return d->tabProxy->native->tabIcon(index);
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);
580 return d->tabBarShown;
585 d->tabProxy->native->setStyleSheet(stylesheet);
590 return d->tabProxy->native->styleSheet();
595 d->tabProxy->native->setTabHighlighted(index, highlight);
600 return d->tabProxy->native->isTabHighlighted(index);
605 return d->tabProxy->native;
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();
681 #include <tabbar.moc>
void setLastPositionWidget(QGraphicsWidget *widget)
Set a widget to be displayed on one side of the TabBar, depending on the LayoutDirection and the Shap...
void setFirstPositionWidget(QGraphicsWidget *widget)
Set a widget to be displayed on one side of the TabBar, depending on the LayoutDirection and the Shap...
The applet is constrained horizontally, but can expand vertically.
Q_INVOKABLE void setTabText(int index, const QString &label)
Sets the text label of the given tab.
Q_INVOKABLE void setTabIcon(int index, const QIcon &icon)
Sets an icon for a given tab.
void setStyleSheet(const QString &stylesheet)
Sets the stylesheet used to control the visual display of this TabBar.
QString styleSheet() const
void currentChanged(int index)
Emitted when the active tab changes.
Q_INVOKABLE int addTab(const QIcon &icon, const QString &label, QGraphicsLayoutItem *content=0)
Adds a new tab in the last position.
Q_INVOKABLE void setTabHighlighted(int index, bool highlight)
Highlight the specified tab.
void setTabBarShown(bool show)
shows or hides the tabbar, used if you just want to display the pages, when the tabbar doesn't have c...
The applet is constrained vertically, but can expand horizontally.
void setCurrentIndex(int index)
Activate a given tab.
Q_INVOKABLE QGraphicsLayoutItem * takeTab(int index)
Removes a tab, the page is reparented to 0 and is returned.
Q_INVOKABLE QString tabText(int index) const
Q_INVOKABLE int insertTab(int index, const QIcon &icon, const QString &label, QGraphicsLayoutItem *content=0)
Adds a new tab in the desired position.
KTabBar * nativeWidget() const
Q_INVOKABLE bool isTabHighlighted(int index) const
Q_INVOKABLE void removeTab(int index)
Removes a tab, contents are deleted.
Q_INVOKABLE QIcon tabIcon(int index) const
void wheelEvent(QGraphicsSceneWheelEvent *event)
void resizeEvent(QGraphicsSceneResizeEvent *event)
QGraphicsWidget * lastPositionWidget() const
static Plasma::Animation * create(Animator::Animation type, QObject *parent=0)
Factory to build new animation objects.
TabBar(QGraphicsWidget *parent=0)
Constructs a new TabBar.
void changeEvent(QEvent *event)
QGraphicsWidget * firstPositionWidget() const
Q_INVOKABLE QGraphicsLayoutItem * tabAt(int index)
Returns the contents of a page.
bool isTabBarShown() const