controlpanelplugins/themeplugin/src/cpthemechanger_p.cpp
branchGCC_SURGE
changeset 27 848a3adde87f
parent 16 8c9427577f2a
parent 25 19394c261aa5
equal deleted inserted replaced
16:8c9427577f2a 27:848a3adde87f
     1 /*
       
     2  * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3  * All rights reserved.
       
     4  * This component and the accompanying materials are made available
       
     5  * under the terms of "Eclipse Public License v1.0""
       
     6  * which accompanies this distribution, and is available
       
     7  * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8  *
       
     9  * Initial Contributors:
       
    10  * Nokia Corporation - initial contribution.
       
    11  *
       
    12  * Contributors:
       
    13  *
       
    14  * Description:  
       
    15  *   
       
    16  */
       
    17 
       
    18 #include "cpthemechanger.h"
       
    19 #include "cpthemechanger_p.h"
       
    20 #include <QStringList>
       
    21 #include <QSettings>
       
    22 #include <QFileSystemWatcher>
       
    23 #include <QPixmap>
       
    24 #include <QSizeF>
       
    25 #include <hbicon.h>
       
    26 #include <hbinstance.h>
       
    27 #include "cpthemeclient_p.h"
       
    28 #include "cpthemecommon_p.h"
       
    29 #ifdef Q_OS_SYMBIAN
       
    30 #include "cpthemeclientsymbian_p.h"
       
    31 #else
       
    32 #include "cpthemeclientqt_p.h"
       
    33 #endif
       
    34 
       
    35 namespace {
       
    36 #if !defined(Q_OS_SYMBIAN)
       
    37     #include <stdio.h>
       
    38     static const char* KThemePathKey = "HB_THEMES_DIR";
       
    39 #endif
       
    40 
       
    41     static const QString KDefaultTheme = "hbdefault";
       
    42     static const char* KSettingsCategory = "currenttheme";
       
    43    
       
    44 }
       
    45 
       
    46 CpThemeChangerPrivate::CpThemeChangerPrivate(CpThemeChanger* qq):
       
    47     q_ptr(qq),
       
    48     themeClient(CpThemeClient::global()),
       
    49     fileWatcher(new QFileSystemWatcher(qq)),
       
    50     model(this, qq)
       
    51 
       
    52 {
       
    53     Q_Q(CpThemeChanger);
       
    54 
       
    55     // Figure out where our themes are. This is platform-dependent,
       
    56     // but not worth breaking out into platform-private implementations
       
    57     // at the moment. Ideally, this would be given to us by the theme server,
       
    58     #ifdef Q_OS_WIN
       
    59     static char* _path=NULL;
       
    60     static size_t _size=0;
       
    61     _dupenv_s(&_path, &_size, KThemePathKey);
       
    62     themeRootPath = QString(_path);
       
    63     themeRootPathPostfix = QString();
       
    64     free(_path);
       
    65     #elif defined(Q_OS_SYMBIAN)
       
    66     themeRootPath = "c:\\resource\\hb";
       
    67     themeRootPathPostfix  = "resource\\hb";
       
    68     #elif defined(Q_OS_UNIX)
       
    69     themeRootPath = QString(getenv(KThemePathKey));
       
    70     themeRootPathPostfix = QString();
       
    71     #elif defined(Q_OS_MACX)
       
    72     themeRootPath = QDir::homePath() + '/' + "Library" + QString("hb");
       
    73     themeRootPathPostfix = QString();
       
    74     #else
       
    75     themeRootPath = "c:\\resource\\hb";
       
    76     themeRootPathPostfix = QString();
       
    77     #endif
       
    78 
       
    79     // Get our current state
       
    80     QSettings settings(QLatin1String(ORGANIZATION), QLatin1String(THEME_COMPONENT));
       
    81     mCurrentTheme.name = settings.value(KSettingsCategory).toString();
       
    82     updateThemeList(mCurrentTheme.name);
       
    83 
       
    84     // Watch for changes to the theme directory in flash.
       
    85     // This may change once we start offering a model.
       
    86     fileWatcher->addPath(themeRootPath+"/themes/");
       
    87     q->connect(fileWatcher, SIGNAL(directoryChanged(const QString&)),
       
    88                q, SLOT(_q_themeDirectoryChanged(const QString&)));
       
    89 
       
    90     // Connect to the theme server
       
    91     connectToServer();
       
    92 }
       
    93 
       
    94 CpThemeChangerPrivate::~CpThemeChangerPrivate()
       
    95 {
       
    96     themeClient->releaseInstance();
       
    97 }
       
    98 
       
    99 const CpThemeChanger::ThemeInfo& CpThemeChangerPrivate::currentTheme() const
       
   100 {
       
   101     return mCurrentTheme;
       
   102 }
       
   103 
       
   104 const QString& CpThemeChangerPrivate::currentThemeName() const
       
   105 {
       
   106     return mCurrentTheme.name.isEmpty() ? KDefaultTheme : mCurrentTheme.name;
       
   107 }
       
   108 
       
   109 int CpThemeChangerPrivate::indexOf(const CpThemeChanger::ThemeInfo& theme) const
       
   110 {
       
   111     return themeList.indexOf(theme);
       
   112 }
       
   113 
       
   114 void CpThemeChangerPrivate::updateThemeList(const QString& newThemeName)
       
   115 {
       
   116     if(!themeList.isEmpty()) {
       
   117         themeList.clear();
       
   118     }
       
   119 
       
   120     mCurrentTheme.name = newThemeName.isEmpty() ? KDefaultTheme : newThemeName;
       
   121 
       
   122     // Get the list of Drives here
       
   123     QStringList themesPathList;
       
   124 
       
   125 #if defined(Q_OS_WIN32)
       
   126     themesPathList << themeRootPath;
       
   127 #elif defined(Q_OS_SYMBIAN)
       
   128     QFileInfoList driveInfoList = QDir::drives();
       
   129     foreach (const QFileInfo &driveInfo, driveInfoList) {
       
   130         const QString drive = driveInfo.absolutePath();
       
   131         themesPathList << drive + themeRootPathPostfix;
       
   132     }
       
   133 #elif defined(Q_OS_UNIX)
       
   134     themesPathList << themeRootPath;
       
   135 #elif defined(Q_OS_MACX)
       
   136     themesPathList << themeRootPath;
       
   137 #endif
       
   138 
       
   139     foreach (const QString &path, themesPathList) {
       
   140         QDir themeDir;
       
   141         themeDir.setPath( path ) ;
       
   142         QStringList iconthemeslist;
       
   143         QStringList list = themeDir.entryList(QDir::AllDirs|QDir::NoDotAndDotDot,QDir::Name);
       
   144         CpThemeChanger::ThemeInfo nameIconPair;
       
   145 
       
   146         if(list.contains("themes",Qt::CaseSensitive )) {
       
   147             QDir root(themeDir.path());
       
   148             themeDir.setPath(root.path()+"/themes/icons/") ;
       
   149             iconthemeslist=themeDir.entryList(QDir::AllDirs|QDir::NoDotAndDotDot,QDir::Name);
       
   150             foreach(QString themefolder, iconthemeslist) {
       
   151                 QDir iconThemePath(root.path()+"/themes/icons/"+themefolder);
       
   152                 if(iconThemePath.exists("index.theme") &&
       
   153                    (iconThemePath.exists("scalable") || iconThemePath.exists("pixmap") )) {
       
   154                     QSettings iniSetting(iconThemePath.path()+"/index.theme",QSettings::IniFormat);
       
   155                     iniSetting.beginGroup("Icon Theme");
       
   156                     QString hidden = iniSetting.value("Hidden").toString();
       
   157                     QString name = iniSetting.value("Name").toString();
       
   158                     QString iconPath = iniSetting.value("PreviewThumbnailPath").toString();
       
   159                     QString previewPathPrt = iniSetting.value("PreviewIconPath_prt").toString();
       
   160                     QString previewPathLsc = iniSetting.value("PreviewIconPath_lsc").toString();
       
   161                     if (name.isEmpty()) {
       
   162                         continue;
       
   163                     }
       
   164                     
       
   165                     QString fullPathToIcon(iconThemePath.path() + iconPath);
       
   166                     
       
   167                     if(iconPath.isEmpty()|| !QFileInfo(fullPathToIcon).exists()){
       
   168                         
       
   169                         //Set thumbnail
       
   170                         if(QFileInfo(fullPathToIcon + "/scalable/qtg_graf_theme_preview_thumbnail.svg").exists()){
       
   171                             nameIconPair.icon = HbIcon(fullPathToIcon + "/scalable/qtg_graf_theme_preview_thumbnail.svg");
       
   172                         }else if(QFileInfo(fullPathToIcon + "/scalable/qtg_graf_screen_bg_prt.svg").exists()){
       
   173                             QPixmap px(fullPathToIcon + "/scalable/qtg_graf_screen_bg_prt.svg");
       
   174                             QIcon scaledIcon(px.scaled(QSize(64, 64)));
       
   175                             nameIconPair.icon = HbIcon(scaledIcon);
       
   176                             nameIconPair.icon.setIconName(fullPathToIcon + "/scalable/qtg_graf_screen_bg_prt.svg");
       
   177                            
       
   178                         } else if(QFileInfo(fullPathToIcon + "/pixmap/qtg_graf_screen_bg_prt.png").exists()){
       
   179                             QPixmap px(fullPathToIcon + "/pixmap/qtg_graf_screen_bg_prt.png");
       
   180                             QIcon scaledIcon(px.scaled(QSize(64, 64)));
       
   181                             nameIconPair.icon = HbIcon(scaledIcon);
       
   182                             nameIconPair.icon.setIconName(fullPathToIcon + "/scalable/qtg_graf_screen_bg_prt.png");
       
   183                           
       
   184                         } else{
       
   185                             nameIconPair.icon = HbIcon(":/image/themePreview.svg");
       
   186                         }
       
   187                     } else {
       
   188                         nameIconPair.icon = HbIcon(fullPathToIcon);
       
   189                     }
       
   190                     
       
   191                     //Portrait preview
       
   192                     QString fullPathToPreviewPrt = (iconThemePath.path() + previewPathPrt );
       
   193                     
       
   194                     if(previewPathPrt.isEmpty() || !QFileInfo(fullPathToPreviewPrt).exists()) {
       
   195                     
       
   196                         if(QFileInfo(fullPathToPreviewPrt + "/scalable/qtg_graf_theme_preview_prt.svg").exists()){
       
   197                             nameIconPair.portraitPreviewIcon = HbIcon(fullPathToPreviewPrt + "/scalable/qtg_graf_theme_preview_prt.svg");
       
   198                         }else if(QFileInfo(fullPathToPreviewPrt + "/scalable/qtg_graf_screen_bg_prt.svg").exists()){
       
   199                             nameIconPair.portraitPreviewIcon = HbIcon(fullPathToPreviewPrt + "/scalable/qtg_graf_screen_bg_prt.svg");
       
   200                         } else if(QFileInfo(fullPathToPreviewPrt + "/pixmap/qtg_graf_screen_bg_prt.png").exists()){
       
   201                             nameIconPair.portraitPreviewIcon = HbIcon(fullPathToPreviewPrt + "/pixmap/qtg_graf_screen_bg_prt.png");
       
   202                         } else{
       
   203                             nameIconPair.portraitPreviewIcon = HbIcon(":/image/themePreview.svg");
       
   204                         }
       
   205                     }
       
   206                     else {
       
   207                         nameIconPair.portraitPreviewIcon = HbIcon(fullPathToPreviewPrt);
       
   208                     }
       
   209                     
       
   210                     //Landscape preview
       
   211                     QString fullPathToPreviewLsc = (iconThemePath.path() + previewPathLsc );
       
   212                                     
       
   213                     if(previewPathLsc.isEmpty() || !QFileInfo(fullPathToPreviewLsc).exists()) {
       
   214                                 
       
   215                         if(QFileInfo(fullPathToPreviewLsc + "/scalable/qtg_graf_theme_preview_lsc.svg").exists()){
       
   216                             nameIconPair.landscapePreviewIcon = HbIcon(fullPathToPreviewLsc + "/scalable/qtg_graf_theme_preview_lsc.svg");
       
   217                         }else if(QFileInfo(fullPathToPreviewLsc + "/scalable/qtg_graf_screen_bg_lsc.svg").exists()){
       
   218                             nameIconPair.landscapePreviewIcon = HbIcon(fullPathToPreviewLsc + "/scalable/qtg_graf_screen_bg_lsc.svg");
       
   219                         } else if(QFileInfo(fullPathToPreviewLsc + "/pixmap/qtg_graf_screen_bg_lsc.png").exists()){
       
   220                             nameIconPair.landscapePreviewIcon = HbIcon(fullPathToPreviewLsc + "/pixmap/qtg_graf_screen_bg_lsc.png");
       
   221                         } else{
       
   222                             nameIconPair.landscapePreviewIcon = HbIcon(":/image/themePreview.svg");
       
   223                         }
       
   224                     }
       
   225                     else {
       
   226                         nameIconPair.landscapePreviewIcon = HbIcon(fullPathToPreviewLsc);
       
   227                     }
       
   228                 
       
   229                     nameIconPair.name = name;
       
   230                                         
       
   231                     themeList.append(nameIconPair);
       
   232 
       
   233                     if (name == mCurrentTheme.name) {
       
   234                         mCurrentTheme = nameIconPair;
       
   235                     }
       
   236 
       
   237                     iniSetting.endGroup();
       
   238                     if((hidden == "true") ||( hidden == "")||(name!=themefolder) ) {
       
   239                         iconthemeslist.removeOne(themefolder);
       
   240                         if(!themeList.isEmpty()) {
       
   241                             themeList.removeLast();
       
   242                         }
       
   243                     }
       
   244                 } else {
       
   245                     iconthemeslist.removeOne(themefolder);
       
   246                     if(!themeList.isEmpty()) {
       
   247                         themeList.removeLast();
       
   248                     }
       
   249                 }
       
   250             }
       
   251         }
       
   252     }
       
   253     
       
   254     if (mCurrentTheme.name == KDefaultTheme)
       
   255     {
       
   256         // Include default
       
   257          CpThemeChanger::ThemeInfo def;
       
   258          def.name = KDefaultTheme;
       
   259          def.icon = HbIcon(":/image/themePreview.svg");
       
   260          themeList.append(def);
       
   261   
       
   262          mCurrentTheme = def;
       
   263     }
       
   264 
       
   265 }
       
   266 
       
   267 const QList<CpThemeChanger::ThemeInfo>& CpThemeChangerPrivate::themes() const
       
   268 {
       
   269    return themeList;
       
   270 }
       
   271 
       
   272 bool CpThemeChangerPrivate::connectToServer()
       
   273 {
       
   274     return themeClient->connectToServer();
       
   275 }
       
   276 
       
   277 /**
       
   278  * Indicate if the client is connected to the server
       
   279  */
       
   280 bool CpThemeChangerPrivate::isConnected() const
       
   281 {
       
   282     return themeClient->isConnected();
       
   283 }
       
   284 
       
   285 /**
       
   286  * Change a theme
       
   287  */
       
   288 bool CpThemeChangerPrivate::changeTheme(const QString& newTheme)
       
   289 {
       
   290     bool result = false;
       
   291     // Skip doing this if the request is for the current theme
       
   292     if (newTheme.isEmpty() || newTheme == mCurrentTheme.name) return result;
       
   293 
       
   294     // Make sure it's a valid theme name
       
   295     bool exists = false;
       
   296     QList<CpThemeChanger::ThemeInfo> themeList = themes();
       
   297     QList<CpThemeChanger::ThemeInfo>::const_iterator i;
       
   298     for (i = themeList.constBegin(); i != themeList.constEnd(); ++i) {
       
   299         if ( newTheme == i->name) {
       
   300             exists = true;
       
   301             break;
       
   302         }
       
   303     }
       
   304 
       
   305     if (exists) {
       
   306         result = themeClient->changeTheme(newTheme);
       
   307 		updateThemeList(newTheme);
       
   308     }
       
   309     return result;
       
   310 }
       
   311 
       
   312 void CpThemeChangerPrivate::_q_themeDirectoryChanged(const QString&)
       
   313 {
       
   314     updateThemeList();
       
   315 }
       
   316 
       
   317 /*
       
   318     HbThemeChangerModel provides an interface to the data contained in the
       
   319     HbThemeChanger using QAbstractListModel.
       
   320 */
       
   321 
       
   322 /*
       
   323     Constructor
       
   324 */
       
   325 HbThemeListModel::HbThemeListModel(CpThemeChangerPrivate *dd, QObject* parent)
       
   326     : QAbstractListModel(parent)
       
   327     , mThemeChangerPrivate(dd)
       
   328 {
       
   329     connect(dd->fileWatcher, SIGNAL(directoryChanged(const QString&)),
       
   330         this, SLOT(themeListChanged()));
       
   331 }
       
   332 
       
   333 /*
       
   334     Destructor
       
   335 */
       
   336 HbThemeListModel::~HbThemeListModel()
       
   337 {
       
   338 
       
   339 }
       
   340 
       
   341 /*
       
   342     Reimplemented from QAbstractListModel.
       
   343 */
       
   344 int HbThemeListModel::rowCount(const QModelIndex&) const
       
   345 {
       
   346     return mThemeChangerPrivate->themeList.size();
       
   347 }
       
   348 
       
   349 /*
       
   350     Reimplemented from QAbstractListModel.  Provides the data for Qt::DisplayRole and
       
   351     Qt::DecorationRole.
       
   352 */
       
   353 QVariant HbThemeListModel::data(const QModelIndex& index, int role) const
       
   354 {
       
   355     QVariant retVal = QVariant();
       
   356 
       
   357     if (index.isValid()) {
       
   358         switch (role) {
       
   359             case Qt::DisplayRole:
       
   360                 retVal = mThemeChangerPrivate->themeList.at(index.row()).name;
       
   361                 break;
       
   362 
       
   363             case Qt::DecorationRole:
       
   364                 retVal = mThemeChangerPrivate->themeList.at(index.row()).icon;
       
   365                 break;
       
   366 
       
   367         case Qt::SizeHintRole:
       
   368                 retVal = mThemeChangerPrivate->themeList.at(index.row()).icon.size();
       
   369                 break;
       
   370         case CpThemeChanger::PortraitPreviewRole:
       
   371                 retVal = mThemeChangerPrivate->themeList.at(index.row()).portraitPreviewIcon;
       
   372                 break;
       
   373         case CpThemeChanger::LandscapePreviewRole:
       
   374                 retVal = mThemeChangerPrivate->themeList.at(index.row()).landscapePreviewIcon;
       
   375 
       
   376             default:
       
   377                 // do nothing
       
   378                 qt_noop();
       
   379         }
       
   380     }
       
   381 
       
   382     return retVal;
       
   383 }
       
   384 
       
   385 /*
       
   386     Responds appropriately when the underlying data in the theme changer is modified.
       
   387 
       
   388     Unfortunately the directory watcher from QFileWatcher only says when something changed
       
   389     not what changed.  Therefore the model is considered reset rather than having rows
       
   390     with dataChanged.
       
   391 */
       
   392 void HbThemeListModel::themeListChanged()
       
   393 {
       
   394     beginResetModel();
       
   395 
       
   396     mThemeChangerPrivate->themes();
       
   397 
       
   398     endResetModel();
       
   399 }
       
   400 
       
   401 // End of file