src/gui/styles/qs60style_simulated.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qs60style.h"
       
    43 #include "qs60style_p.h"
       
    44 #include "qfile.h"
       
    45 #include "qhash.h"
       
    46 #include "qapplication.h"
       
    47 #include "qpainter.h"
       
    48 #include "qpicture.h"
       
    49 #include "qstyleoption.h"
       
    50 #include "qtransform.h"
       
    51 #include "qlayout.h"
       
    52 #include "qpixmapcache.h"
       
    53 #include "qmetaobject.h"
       
    54 #include "qdebug.h"
       
    55 #include "qbuffer.h"
       
    56 #include "qdesktopwidget.h"
       
    57 
       
    58 #if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
       
    59 
       
    60 QT_BEGIN_NAMESPACE
       
    61 
       
    62 static const quint32 blobVersion = 1;
       
    63 static const int pictureSize = 256;
       
    64 
       
    65 #if defined(Q_CC_GNU)
       
    66 #if __GNUC__ >= 2
       
    67 #define __FUNCTION__ __func__
       
    68 #endif
       
    69 #endif
       
    70 
       
    71 
       
    72 bool saveThemeToBlob(const QString &themeBlob,
       
    73     const QHash<QString, QPicture> &partPictures,
       
    74     const QHash<QPair<QString, int>, QColor> &colors)
       
    75 {
       
    76     QFile blob(themeBlob);
       
    77     if (!blob.open(QIODevice::WriteOnly)) {
       
    78         qWarning() << __FUNCTION__ << ": Could not create blob: " << themeBlob;
       
    79         return false;
       
    80     }
       
    81 
       
    82     QByteArray data;
       
    83     QBuffer dataBuffer(&data);
       
    84     dataBuffer.open(QIODevice::WriteOnly);
       
    85     QDataStream dataOut(&dataBuffer);
       
    86 
       
    87     const int colorsCount = colors.count();
       
    88     dataOut << colorsCount;
       
    89     const QList<QPair<QString, int> > colorKeys = colors.keys();
       
    90     for (int i = 0; i < colorsCount; ++i) {
       
    91         const QPair<QString, int> &key = colorKeys.at(i);
       
    92         dataOut << key;
       
    93         const QColor color = colors.value(key);
       
    94         dataOut << color;
       
    95     }
       
    96 
       
    97     const int picturesCount = partPictures.count();
       
    98     dataOut << picturesCount;
       
    99     foreach (const QString &key, partPictures.keys()) {
       
   100         const QPicture picture = partPictures.value(key);
       
   101         dataOut << key;
       
   102         dataOut << picture;
       
   103     }
       
   104 
       
   105     QDataStream blobOut(&blob);
       
   106     blobOut << blobVersion;
       
   107     blobOut << qCompress(data);
       
   108     return blobOut.status() == QDataStream::Ok;
       
   109 }
       
   110 
       
   111 bool loadThemeFromBlob(const QString &themeBlob,
       
   112     QHash<QString, QPicture> &partPictures,
       
   113     QHash<QPair<QString, int>, QColor> &colors)
       
   114 {
       
   115     QFile blob(themeBlob);
       
   116     if (!blob.open(QIODevice::ReadOnly)) {
       
   117         qWarning() << __FUNCTION__ << ": Could not read blob: " << themeBlob;
       
   118         return false;
       
   119     }
       
   120     QDataStream blobIn(&blob);
       
   121 
       
   122     quint32 version;
       
   123     blobIn >> version;
       
   124 
       
   125     if (version != blobVersion) {
       
   126         qWarning() << __FUNCTION__ << ": Invalid blob version: " << version << " ...expected: " << blobVersion;
       
   127         return false;
       
   128     }
       
   129 
       
   130     QByteArray data;
       
   131     blobIn >> data;
       
   132     data = qUncompress(data);
       
   133     QBuffer dataBuffer(&data);
       
   134     dataBuffer.open(QIODevice::ReadOnly);
       
   135     QDataStream dataIn(&dataBuffer);
       
   136 
       
   137     int colorsCount;
       
   138     dataIn >> colorsCount;
       
   139     for (int i = 0; i < colorsCount; ++i) {
       
   140         QPair<QString, int> key;
       
   141         dataIn >> key;
       
   142         QColor value;
       
   143         dataIn >> value;
       
   144         colors.insert(key, value);
       
   145     }
       
   146 
       
   147     int picturesCount;
       
   148     dataIn >> picturesCount;
       
   149     for (int i = 0; i < picturesCount; ++i) {
       
   150         QString key;
       
   151         dataIn >> key;
       
   152         QPicture value;
       
   153         dataIn >> value;
       
   154         value.setBoundingRect(QRect(0, 0, pictureSize, pictureSize)); // Bug? The forced bounding rect was not deserialized.
       
   155         partPictures.insert(key, value);
       
   156     }
       
   157 
       
   158     if (dataIn.status() != QDataStream::Ok) {
       
   159         qWarning() << __FUNCTION__ << ": Invalid data blob: " << themeBlob;
       
   160         return false;
       
   161     }
       
   162     return true;
       
   163 }
       
   164 
       
   165 class QS60StyleModeSpecifics
       
   166 {
       
   167 public:
       
   168     static QPixmap skinnedGraphics(QS60StyleEnums::SkinParts stylepart,
       
   169         const QSize &size, QS60StylePrivate::SkinElementFlags flags);
       
   170     static QHash<QString, QPicture> m_partPictures;
       
   171     static QHash<QPair<QString , int>, QColor> m_colors;
       
   172 };
       
   173 QHash<QString, QPicture> QS60StyleModeSpecifics::m_partPictures;
       
   174 QHash<QPair<QString , int>, QColor> QS60StyleModeSpecifics::m_colors;
       
   175 
       
   176 QS60StylePrivate::QS60StylePrivate()
       
   177 {
       
   178     setCurrentLayout(0);
       
   179 }
       
   180 
       
   181 QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list,
       
   182     int index, const QStyleOption *option)
       
   183 {
       
   184     const QString listKey = QS60Style::colorListKeys().at(list);
       
   185     return QS60StylePrivate::stateColor(
       
   186         QS60StyleModeSpecifics::m_colors.value(QPair<QString, int>(listKey, index)),
       
   187         option
       
   188     );
       
   189 }
       
   190 
       
   191 QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, const QSize &size,
       
   192                                QS60StylePrivate::SkinElementFlags flags)
       
   193 {
       
   194     const QString partKey = QS60Style::partKeys().at(part);
       
   195     const QPicture partPicture = QS60StyleModeSpecifics::m_partPictures.value(partKey);
       
   196     QSize partSize(partPicture.boundingRect().size());
       
   197     if (flags & (SF_PointEast | SF_PointWest)) {
       
   198         const int temp = partSize.width();
       
   199         partSize.setWidth(partSize.height());
       
   200         partSize.setHeight(temp);
       
   201     }
       
   202     const qreal scaleX = size.width() / (qreal)partSize.width();
       
   203     const qreal scaleY = size.height() / (qreal)partSize.height();
       
   204 
       
   205     QImage partImage(size, QImage::Format_ARGB32);
       
   206     partImage.fill(Qt::transparent);
       
   207     QPainter resultPainter(&partImage);
       
   208     QTransform t;
       
   209 
       
   210     if (flags & SF_PointEast)
       
   211         t.translate(size.width(), 0);
       
   212     else if (flags & SF_PointSouth)
       
   213         t.translate(size.width(), size.height());
       
   214     else if (flags & SF_PointWest)
       
   215         t.translate(0, size.height());
       
   216 
       
   217     t.scale(scaleX, scaleY);
       
   218 
       
   219     if (flags & SF_PointEast)
       
   220         t.rotate(90);
       
   221     else if (flags & SF_PointSouth)
       
   222         t.rotate(180);
       
   223     else if (flags & SF_PointWest)
       
   224         t.rotate(270);
       
   225 
       
   226     resultPainter.setTransform(t, true);
       
   227     const_cast<QPicture *>(&partPicture)->play(&resultPainter);
       
   228     resultPainter.end();
       
   229 
       
   230     QPixmap result = QPixmap::fromImage(partImage);
       
   231     if (flags & SF_StateDisabled) {
       
   232         QStyleOption opt;
       
   233         QPalette *themePalette = QS60StylePrivate::themePalette();
       
   234         if (themePalette)
       
   235             opt.palette = *themePalette;
       
   236         result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt);
       
   237     }
       
   238 
       
   239     return result;
       
   240 }
       
   241 
       
   242 QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size,
       
   243     SkinElementFlags flags)
       
   244 {
       
   245     const QS60StyleEnums::SkinParts center =        m_frameElementsData[frame].center;
       
   246     const QS60StyleEnums::SkinParts topLeft =       QS60StyleEnums::SkinParts(center - 8);
       
   247     const QS60StyleEnums::SkinParts topRight =      QS60StyleEnums::SkinParts(center - 7);
       
   248     const QS60StyleEnums::SkinParts bottomLeft =    QS60StyleEnums::SkinParts(center - 6);
       
   249     const QS60StyleEnums::SkinParts bottomRight =   QS60StyleEnums::SkinParts(center - 5);
       
   250     const QS60StyleEnums::SkinParts top =           QS60StyleEnums::SkinParts(center - 4);
       
   251     const QS60StyleEnums::SkinParts bottom =        QS60StyleEnums::SkinParts(center - 3);
       
   252     const QS60StyleEnums::SkinParts left =          QS60StyleEnums::SkinParts(center - 2);
       
   253     const QS60StyleEnums::SkinParts right =         QS60StyleEnums::SkinParts(center - 1);
       
   254 
       
   255     // The size of topLeft defines all other sizes
       
   256     const QSize cornerSize(partSize(topLeft));
       
   257     // if frame is so small that corners would cover it completely, draw only center piece
       
   258     const bool drawOnlyCenter =
       
   259          2 * cornerSize.width() + 1 >= size.width() || 2 * cornerSize.height() + 1 >= size.height();
       
   260 
       
   261     const int cornerWidth = cornerSize.width();
       
   262     const int cornerHeight = cornerSize.height();
       
   263     const int rectWidth = size.width();
       
   264     const int rectHeight = size.height();
       
   265     const QRect rect(QPoint(), size);
       
   266 
       
   267     const QRect topLeftRect = QRect(rect.topLeft(), cornerSize);
       
   268     const QRect topRect = rect.adjusted(cornerWidth, 0, -cornerWidth, -(rectHeight - cornerHeight));
       
   269     const QRect topRightRect = topLeftRect.translated(rectWidth - cornerWidth, 0);
       
   270     const QRect rightRect = rect.adjusted(rectWidth - cornerWidth, cornerHeight, 0, -cornerHeight);
       
   271     const QRect bottomRightRect = topRightRect.translated(0, rectHeight - cornerHeight);
       
   272     const QRect bottomRect = topRect.translated(0, rectHeight - cornerHeight);
       
   273     const QRect bottomLeftRect = topLeftRect.translated(0, rectHeight - cornerHeight);
       
   274     const QRect leftRect = rightRect.translated(cornerWidth - rectWidth, 0);
       
   275     const QRect centerRect = drawOnlyCenter ? rect : rect.adjusted(cornerWidth, cornerWidth, -cornerWidth, -cornerWidth);
       
   276 
       
   277     QPixmap result(size);
       
   278     result.fill(Qt::transparent);
       
   279     QPainter painter(&result);
       
   280 
       
   281 #if 0
       
   282     painter.save();
       
   283     painter.setOpacity(.3);
       
   284     painter.fillRect(topLeftRect, Qt::red);
       
   285     painter.fillRect(topRect, Qt::green);
       
   286     painter.fillRect(topRightRect, Qt::blue);
       
   287     painter.fillRect(rightRect, Qt::green);
       
   288     painter.fillRect(bottomRightRect, Qt::red);
       
   289     painter.fillRect(bottomRect, Qt::blue);
       
   290     painter.fillRect(bottomLeftRect, Qt::green);
       
   291     painter.fillRect(leftRect, Qt::blue);
       
   292     painter.fillRect(centerRect, Qt::red);
       
   293     painter.restore();
       
   294 #else
       
   295     drawPart(topLeft, &painter, topLeftRect, flags);
       
   296     drawPart(top, &painter, topRect, flags);
       
   297     drawPart(topRight, &painter, topRightRect, flags);
       
   298     drawPart(right, &painter, rightRect, flags);
       
   299     drawPart(bottomRight, &painter, bottomRightRect, flags);
       
   300     drawPart(bottom, &painter, bottomRect, flags);
       
   301     drawPart(bottomLeft, &painter, bottomLeftRect, flags);
       
   302     drawPart(left, &painter, leftRect, flags);
       
   303     drawPart(center, &painter, centerRect, flags);
       
   304 #endif
       
   305 
       
   306     return result;
       
   307 }
       
   308 
       
   309 void QS60StylePrivate::setStyleProperty_specific(const char *name, const QVariant &value)
       
   310 {
       
   311     setStyleProperty(name, value);
       
   312 }
       
   313 
       
   314 QVariant QS60StylePrivate::styleProperty_specific(const char *name) const
       
   315 {
       
   316     return styleProperty(name);
       
   317 }
       
   318 
       
   319 QPixmap QS60StylePrivate::backgroundTexture()
       
   320 {
       
   321     if (!m_background) {
       
   322         const QSize size = QApplication::desktop()->screen()->size();
       
   323         QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen, size);
       
   324         m_background = new QPixmap(background);
       
   325     }
       
   326     return *m_background;
       
   327 }
       
   328 
       
   329 QSize QS60StylePrivate::naviPaneSize()
       
   330 {
       
   331     return QSize(0, 0);
       
   332 }
       
   333 
       
   334 bool QS60StylePrivate::isTouchSupported()
       
   335 {
       
   336 #ifdef QT_KEYPAD_NAVIGATION
       
   337     return !QApplication::keypadNavigationEnabled();
       
   338 #else
       
   339     return true;
       
   340 #endif
       
   341 }
       
   342 
       
   343 bool QS60StylePrivate::isToolBarBackground()
       
   344 {
       
   345     return true;
       
   346 }
       
   347 
       
   348 QFont QS60StylePrivate::s60Font_specific(QS60StyleEnums::FontCategories fontCategory, int pointSize)
       
   349 {
       
   350     QFont result;
       
   351     result.setPointSize(pointSize);
       
   352     switch (fontCategory) {
       
   353         case QS60StyleEnums::FC_Primary:
       
   354             result.setBold(true);
       
   355             break;
       
   356         case QS60StyleEnums::FC_Secondary:
       
   357         case QS60StyleEnums::FC_Title:
       
   358         case QS60StyleEnums::FC_PrimarySmall:
       
   359         case QS60StyleEnums::FC_Digital:
       
   360         case QS60StyleEnums::FC_Undefined:
       
   361         default:
       
   362             break;
       
   363     }
       
   364     return result;
       
   365 }
       
   366 
       
   367 /*!
       
   368   Constructs a QS60Style object.
       
   369 */
       
   370 QS60Style::QS60Style()
       
   371     : QCommonStyle(*new QS60StylePrivate)
       
   372 {
       
   373     const QString defaultBlob = QString::fromLatin1(":/trolltech/styles/s60style/images/defaults60theme.blob");
       
   374     if (QFile::exists(defaultBlob))
       
   375         loadS60ThemeFromBlob(defaultBlob);
       
   376 }
       
   377 
       
   378 Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, enumPartKeys, {
       
   379     const int enumIndex = QS60StyleEnums::staticMetaObject.indexOfEnumerator("SkinParts");
       
   380     Q_ASSERT(enumIndex >= 0);
       
   381     const QMetaEnum metaEnum = QS60StyleEnums::staticMetaObject.enumerator(enumIndex);
       
   382     for (int i = 0; i < metaEnum.keyCount(); ++i) {
       
   383         const QString enumKey = QString::fromLatin1(metaEnum.key(i));
       
   384         QString partKey;
       
   385         // Following loop does following conversions: "SP_QgnNoteInfo" to "qgn_note_info"...
       
   386         for (int charPosition = 3; charPosition < enumKey.length(); charPosition++) {
       
   387             if (charPosition > 3 && enumKey[charPosition].isUpper())
       
   388                 partKey.append(QChar::fromLatin1('_'));
       
   389             partKey.append(enumKey[charPosition].toLower());
       
   390         }
       
   391         x->append(partKey);
       
   392     }
       
   393 })
       
   394 
       
   395 QStringList QS60Style::partKeys()
       
   396 {
       
   397     return *enumPartKeys();
       
   398 }
       
   399 
       
   400 Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, enumColorListKeys, {
       
   401     const int enumIndex = QS60StyleEnums::staticMetaObject.indexOfEnumerator("ColorLists");
       
   402     Q_ASSERT(enumIndex >= 0);
       
   403     const QMetaEnum metaEnum = QS60StyleEnums::staticMetaObject.enumerator(enumIndex);
       
   404     for (int i = 0; i < metaEnum.keyCount(); i++) {
       
   405         const QString enumKey = QString::fromLatin1(metaEnum.key(i));
       
   406         // Following line does following conversions: CL_QsnTextColors to "text"...
       
   407         x->append(enumKey.mid(6, enumKey.length() - 12).toLower());
       
   408     }
       
   409 })
       
   410 
       
   411 QStringList QS60Style::colorListKeys()
       
   412 {
       
   413     return *enumColorListKeys();
       
   414 }
       
   415 
       
   416 void QS60Style::setS60Theme(const QHash<QString, QPicture> &parts,
       
   417     const QHash<QPair<QString , int>, QColor> &colors)
       
   418 {
       
   419     Q_D(QS60Style);
       
   420     QS60StyleModeSpecifics::m_partPictures = parts;
       
   421     QS60StyleModeSpecifics::m_colors = colors;
       
   422     d->clearCaches(QS60StylePrivate::CC_ThemeChange);
       
   423     d->setBackgroundTexture(qApp);
       
   424     d->setThemePalette(qApp);
       
   425 }
       
   426 
       
   427 bool QS60Style::loadS60ThemeFromBlob(const QString &blobFile)
       
   428 {
       
   429     QHash<QString, QPicture> partPictures;
       
   430     QHash<QPair<QString, int>, QColor> colors;
       
   431 
       
   432     if (!loadThemeFromBlob(blobFile, partPictures, colors))
       
   433         return false;
       
   434     setS60Theme(partPictures, colors);
       
   435     return true;
       
   436 }
       
   437 
       
   438 bool QS60Style::saveS60ThemeToBlob(const QString &blobFile) const
       
   439 {
       
   440     return saveThemeToBlob(blobFile,
       
   441         QS60StyleModeSpecifics::m_partPictures, QS60StyleModeSpecifics::m_colors);
       
   442 }
       
   443 
       
   444 QPoint qt_s60_fill_background_offset(const QWidget *targetWidget)
       
   445 {
       
   446     Q_UNUSED(targetWidget)
       
   447     return QPoint();
       
   448 }
       
   449 
       
   450 QT_END_NAMESPACE
       
   451 
       
   452 #endif // QT_NO_STYLE_S60 || QT_PLUGIN