• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Plasma

nativetabbar.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2007 Robert Knight <robertknight@gmail.com>
00003     Copyright 2008 Marco Martin <notmart@gmail.com>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 // Own
00022 #include "nativetabbar_p.h"
00023 
00024 // Qt
00025 #include <QIcon>
00026 #include <QMouseEvent>
00027 #include <QPainter>
00028 #include <QApplication>
00029 #include <QStyleOption>
00030 #include <QToolButton>
00031 
00032 #include <QGradient>
00033 #include <QLinearGradient>
00034 
00035 // KDE
00036 #include <kdebug.h>
00037 #include <kcolorutils.h>
00038 
00039 #include "plasma/plasma.h"
00040 #include "plasma/theme.h"
00041 #include "plasma/animator.h"
00042 #include "plasma/framesvg.h"
00043 #include "plasma/paintutils.h"
00044 
00045 //#include "private/style_p.h"
00046 
00047 namespace Plasma
00048 {
00049 
00050 class NativeTabBarPrivate
00051 {
00052 public:
00053     NativeTabBarPrivate(NativeTabBar *parent)
00054         : q(parent),
00055           backgroundSvg(0),
00056           buttonSvg(0),
00057           animationId(-1)
00058     {
00059     }
00060 
00061     ~NativeTabBarPrivate()
00062     {
00063         delete backgroundSvg;
00064         delete buttonSvg;
00065     }
00066 
00067     void syncBorders();
00068     void storeLastIndex();
00069 
00070     NativeTabBar *q;
00071     QTabBar::Shape shape; //used to keep track of shape() changes
00072     FrameSvg *backgroundSvg;
00073     qreal left, top, right, bottom;
00074     FrameSvg *buttonSvg;
00075     qreal buttonLeft, buttonTop, buttonRight, buttonBottom;
00076 
00077     int animationId;
00078 
00079     QRect currentAnimRect;
00080     int lastIndex[2];
00081     qreal animProgress;
00082 };
00083 
00084 void NativeTabBarPrivate::syncBorders()
00085 {
00086     backgroundSvg->getMargins(left, top, right, bottom);
00087     buttonSvg->getMargins(buttonLeft, buttonTop, buttonRight, buttonBottom);
00088 }
00089 
00090 void NativeTabBarPrivate::storeLastIndex()
00091 {
00092     // if first run
00093     if (lastIndex[0] == -1) {
00094         lastIndex[1] = q->currentIndex();
00095     }
00096     lastIndex[0] = lastIndex[1];
00097     lastIndex[1] = q->currentIndex();
00098 }
00099 
00100 NativeTabBar::NativeTabBar(QWidget *parent)
00101         : KTabBar(parent),
00102           d(new NativeTabBarPrivate(this))
00103 {
00104     d->backgroundSvg = new Plasma::FrameSvg();
00105     d->backgroundSvg->setImagePath("widgets/frame");
00106     d->backgroundSvg->setElementPrefix("sunken");
00107 
00108     d->buttonSvg = new Plasma::FrameSvg();
00109     d->buttonSvg->setImagePath("widgets/button");
00110     d->buttonSvg->setElementPrefix("normal");
00111 
00112     d->syncBorders();
00113 
00114     d->lastIndex[0] = -1;
00115     connect(this, SIGNAL(currentChanged(int)), this, SLOT(startAnimation()));
00116 
00117     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00118 }
00119 
00120 NativeTabBar::~NativeTabBar()
00121 {
00122     delete d;
00123 }
00124 
00125 QRect NativeTabBar::tabRect(int index) const
00126 {
00127     QRect rect = KTabBar::tabRect(index).translated(d->left, d->top);
00128 
00129     return rect;
00130 }
00131 
00132 int NativeTabBar::lastIndex() const
00133 {
00134     return d->lastIndex[0];
00135 }
00136 
00137 QSize NativeTabBar::tabSizeHint(int index) const
00138 {
00139     //return KTabBar::tabSizeHint(index);
00140     QSize hint = tabSize(index);
00141     int minwidth = 0;
00142     int minheight = 0;
00143     int maxwidth = 0;
00144 
00145     Shape s = shape();
00146     switch (s) {
00147         case RoundedSouth:
00148         case TriangularSouth:
00149         case RoundedNorth:
00150         case TriangularNorth:
00151             if (count() > 0) {
00152                 for (int i = count() - 1; i >= 0; i--) {
00153                     minwidth += tabSize(i).width();
00154                 }
00155 
00156                 if (minwidth < width() - d->left - d->right) {
00157                     hint.rwidth() += (width() - d->left - d->right - minwidth) / count();
00158                 }
00159             }
00160             break;
00161         case RoundedWest:
00162         case TriangularWest:
00163         case RoundedEast:
00164         case TriangularEast:
00165             if (count() > 0) {
00166                 for (int i = count() - 1; i >= 0; i--) {
00167                     minheight += tabSize(i).height();
00168                     if (tabSize(i).width() > maxwidth) {
00169                         maxwidth = tabSize(i).width();
00170                     }
00171                 }
00172 
00173                 if (minheight < height()) {
00174                     hint.rheight() += (height() - minheight) / count();
00175                 }
00176             }
00177             break;
00178     }
00179     return hint;
00180 }
00181 
00182 //FIXME: this shouldn't be necessary but it seems to return wring numbers the base implementation?
00183 QSize NativeTabBar::sizeHint() const
00184 {
00185     int width = 0;
00186     int height = 0;
00187 
00188     if (isVertical()) {
00189         for (int i = count() - 1; i >= 0; i--) {
00190              height += tabRect(i).height();
00191         }
00192 
00193         width = tabRect(0).width();
00194     } else {
00195         for (int i = count() - 1; i >= 0; i--) {
00196              width += tabRect(i).width();
00197         }
00198 
00199         height = tabRect(0).height();
00200     }
00201     return QSize(width + d->left + d->right, height + d->top + d->bottom);
00202 }
00203 
00204 void NativeTabBar::paintEvent(QPaintEvent *event)
00205 {
00206     if (!styleSheet().isNull()) {
00207         KTabBar::paintEvent(event);
00208         return;
00209     }
00210 
00211     QPainter painter(this);
00212     //int numTabs = count();
00213     //bool ltr = painter.layoutDirection() == Qt::LeftToRight; // Not yet used
00214 
00215     if (drawBase()) {
00216         d->backgroundSvg->paintFrame(&painter);
00217     }
00218 
00219     // Drawing Tabborders
00220     QRect movingRect;
00221 
00222     if (d->currentAnimRect.isNull()) {
00223         movingRect = tabRect(currentIndex());
00224     } else {
00225         movingRect = d->currentAnimRect;
00226     }
00227 
00228     //resizing here because in resizeevent the first time is invalid (still no tabs)
00229     d->buttonSvg->resizeFrame(movingRect.size());
00230     d->buttonSvg->paintFrame(&painter, movingRect.topLeft());
00231 
00232     QFontMetrics metrics(painter.font());
00233 
00234     for (int i = 0; i < count(); i++) {
00235         QRect rect = tabRect(i).adjusted(d->buttonLeft, d->buttonTop,
00236                                          -d->buttonRight, -d->buttonBottom);
00237         // draw tab icon
00238         QRect iconRect = QRect(rect.x(), rect.y(), iconSize().width(), iconSize().height());
00239 
00240         iconRect.moveCenter(QPoint(iconRect.center().x(), rect.center().y()));
00241         tabIcon(i).paint(&painter, iconRect);
00242 
00243         // draw tab text
00244         if (i == currentIndex() && d->animProgress == 1) {
00245             painter.setPen(Plasma::Theme::defaultTheme()->color(Theme::ButtonTextColor));
00246         } else {
00247             QColor color(Plasma::Theme::defaultTheme()->color(Theme::TextColor));
00248             if (!isTabEnabled(i)) {
00249                 color.setAlpha(140);
00250             }
00251 
00252             painter.setPen(color);
00253         }
00254         QRect textRect = rect;
00255 
00256         if (!tabIcon(i).isNull()) {
00257             textRect.setLeft(iconRect.right());
00258         }
00259 
00260         painter.setFont(Plasma::Theme::defaultTheme()->font(Plasma::Theme::DefaultFont));
00261         painter.drawText(textRect, Qt::AlignCenter | Qt::TextHideMnemonic, tabText(i));
00262     }
00263 
00264     QRect scrollButtonsRect;
00265     foreach (QObject *child, children()) {
00266         QToolButton *childWidget = qobject_cast<QToolButton *>(child);
00267         if (childWidget) {
00268             if (!childWidget->isVisible()) {
00269                 continue;
00270             }
00271 
00272             if (scrollButtonsRect.isValid()) {
00273                 scrollButtonsRect = scrollButtonsRect.united(childWidget->geometry());
00274             } else {
00275                 scrollButtonsRect = childWidget->geometry();
00276             }
00277         }
00278     }
00279 
00280     if (scrollButtonsRect.isValid()) {
00281         scrollButtonsRect.adjust(2, 4, -2, -4);
00282         painter.save();
00283 
00284         QColor background(Plasma::Theme::defaultTheme()->color(Theme::BackgroundColor));
00285         background.setAlphaF(0.75);
00286 
00287         painter.setRenderHint(QPainter::Antialiasing);
00288         painter.fillPath(PaintUtils::roundedRectangle(scrollButtonsRect, 5), background);
00289         painter.restore();
00290 
00291         QStyleOption so;
00292         so.initFrom(this);
00293         so.palette.setColor(QPalette::ButtonText,
00294                             Plasma::Theme::defaultTheme()->color(Theme::TextColor));
00295 
00296         so.rect = scrollButtonsRect.adjusted(0, 0, -scrollButtonsRect.width() / 2, 0);
00297         style()->drawPrimitive(QStyle::PE_IndicatorArrowLeft, &so, &painter, this);
00298 
00299         so.rect = scrollButtonsRect.adjusted(scrollButtonsRect.width() / 2, 0, 0, 0);
00300         style()->drawPrimitive(QStyle::PE_IndicatorArrowRight, &so, &painter, this);
00301     }
00302 }
00303 
00304 void NativeTabBar::resizeEvent(QResizeEvent *event)
00305 {
00306     KTabBar::resizeEvent(event);
00307     d->currentAnimRect = tabRect(currentIndex());
00308     d->backgroundSvg->resizeFrame(size());
00309 
00310     update();
00311 }
00312 
00313 void NativeTabBar::tabInserted(int index)
00314 {
00315     KTabBar::tabInserted(index);
00316     emit sizeHintChanged();
00317 }
00318 
00319 void NativeTabBar::tabRemoved(int index)
00320 {
00321     KTabBar::tabRemoved(index);
00322     emit sizeHintChanged();
00323 }
00324 
00325 void NativeTabBar::tabLayoutChange()
00326 {
00327     KTabBar::tabLayoutChange();
00328 
00329     if (shape() != d->shape) {
00330         d->shape = shape();
00331         emit shapeChanged(d->shape);
00332     }
00333 }
00334 
00335 void NativeTabBar::startAnimation()
00336 {
00337     d->storeLastIndex();
00338     Plasma::Animator::self()->customAnimation(
00339         10, 150, Plasma::Animator::EaseInOutCurve, this, "onValueChanged");
00340 }
00341 
00342 void NativeTabBar::onValueChanged(qreal value)
00343 {
00344     if ((d->animProgress = value) == 1.0) {
00345         animationFinished();
00346         return;
00347     }
00348 
00349     // animation rect
00350     QRect rect = tabRect(currentIndex());
00351     QRect lastRect = tabRect(lastIndex());
00352     int x = isHorizontal() ? (int)(lastRect.x() - value * (lastRect.x() - rect.x())) : rect.x();
00353     int y = isHorizontal() ? rect.y() : (int)(lastRect.y() - value * (lastRect.y() - rect.y()));
00354     QSizeF sz = lastRect.size() - value * (lastRect.size() - rect.size());
00355     d->currentAnimRect = QRect(x, y, (int)(sz.width()), (int)(sz.height()));
00356     update();
00357 }
00358 
00359 void NativeTabBar::animationFinished()
00360 {
00361     d->currentAnimRect = QRect();
00362     update();
00363 }
00364 
00365 bool NativeTabBar::isVertical() const
00366 {
00367     Shape s = shape();
00368     if(s == RoundedWest ||
00369        s == RoundedEast ||
00370        s == TriangularWest ||
00371        s == TriangularEast) {
00372         return true;
00373     }
00374     return false;
00375 }
00376 
00377 bool NativeTabBar::isHorizontal() const
00378 {
00379     return !isVertical();
00380 }
00381 
00382 QSize NativeTabBar::tabSize(int index) const
00383 {
00384     QSize hint;
00385     const QFontMetrics metrics(QApplication::font());
00386     const QSize textSize = metrics.size(Qt::TextHideMnemonic, tabText(index));
00387     hint.rwidth() = textSize.width() + iconSize().width();
00388     hint.rheight() = qMax(iconSize().height(), textSize.height());
00389     hint.rwidth() += d->buttonLeft + d->buttonRight;
00390     hint.rheight() += d->buttonTop + d->buttonBottom;
00391 
00392     if (isVertical()) {
00393         hint.rwidth() = qMax(hint.width(), int(minimumWidth() - d->left - d->right));
00394     } else {
00395         hint.rheight() = qMax(hint.height(), int(minimumHeight() - d->top - d->bottom));
00396     }
00397 
00398     return hint;
00399 }
00400 
00401 } // namespace Plasma
00402 
00403 #include "nativetabbar_p.moc"
00404 

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal