controlpanelplugins/themeplugin/src/cpthemechanger_p.cpp
changeset 11 10d0dd0e43f1
child 12 624337f114fe
equal deleted inserted replaced
10:0a74be98a8bc 11:10d0dd0e43f1
       
     1 /*
       
     2 * Copyright (c) 2008-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:  Private implementation of the theme changer.
       
    15  *
       
    16 */
       
    17 
       
    18 #include "cpthemechanger.h"
       
    19 #include "cpthemechanger_p.h"
       
    20 #include <QStringList>
       
    21 #include <QSettings>
       
    22 #include <QFileSystemWatcher>
       
    23 #include <HbIcon.h>
       
    24 #include <hbinstance.h>
       
    25 #include "cpthemeclient_p.h"
       
    26 #include "cpthemecommon_p.h"
       
    27 #ifdef Q_OS_SYMBIAN
       
    28 #include "cpthemeclientsymbian_p.h"
       
    29 #else
       
    30 #include "cpthemeclientqt_p.h"
       
    31 #endif
       
    32 
       
    33 namespace {
       
    34 #if !defined(Q_OS_SYMBIAN)
       
    35     #include <stdio.h>
       
    36     static const char* KThemePathKey = "HB_THEMES_DIR";
       
    37 #endif
       
    38 
       
    39     static const char* KDefaultTheme = "hbdefault";
       
    40     static const char* KSettingsGroup = "hborbit";
       
    41     static const char* KSettingsCategory = "currenttheme";
       
    42     static const bool KDefaultPreviewAvailable = true;
       
    43 }
       
    44 
       
    45 CpThemeChangerPrivate::CpThemeChangerPrivate(CpThemeChanger* qq):
       
    46     q_ptr(qq),
       
    47     themeClient(CpThemeClient::global()),
       
    48     fileWatcher(new QFileSystemWatcher(qq)),
       
    49     model(this, qq)
       
    50 
       
    51 {
       
    52     Q_Q(CpThemeChanger);
       
    53 
       
    54     // Figure out where our themes are. This is platform-dependent,
       
    55     // but not worth breaking out into platform-private implementations
       
    56     // at the moment. Ideally, this would be given to us by the theme server,
       
    57     #ifdef Q_OS_WIN
       
    58     static char* _path=NULL;
       
    59     static size_t _size=0;
       
    60     _dupenv_s(&_path, &_size, KThemePathKey);
       
    61     themeRootPath = QString(_path);
       
    62     themeRootPathPostfix = QString();
       
    63     free(_path);
       
    64     #elif defined(Q_OS_SYMBIAN)
       
    65     themeRootPath = "c:\\resource\\hb";
       
    66     themeRootPathPostfix  = "resource\\hb";
       
    67     #elif defined(Q_OS_UNIX)
       
    68     themeRootPath = QString(getenv(KThemePathKey));
       
    69     themeRootPathPostfix = QString();
       
    70     #elif defined(Q_OS_MACX)
       
    71     themeRootPath = QDir::homePath() + '/' + "Library" + QString("hb");
       
    72     themeRootPathPostfix = QString();
       
    73     #else
       
    74     themeRootPath = "c:\\resource\\hb";
       
    75     themeRootPathPostfix = QString();
       
    76     #endif
       
    77 
       
    78     // Get our current state
       
    79     QSettings settings(QLatin1String(ORGANIZATION), QLatin1String(THEME_COMPONENT));
       
    80     mCurrentTheme.name = settings.value(KSettingsCategory).toString();
       
    81     updateThemeList(mCurrentTheme.name);
       
    82 
       
    83     // Watch for changes to the theme directory in flash.
       
    84     // This may change once we start offering a model.
       
    85     fileWatcher->addPath(themeRootPath+"/themes/");
       
    86     q->connect(fileWatcher, SIGNAL(directoryChanged(const QString&)),
       
    87                q, SLOT(_q_themeDirectoryChanged(const QString&)));
       
    88 
       
    89     // Connect to the theme server
       
    90     connectToServer();
       
    91 }
       
    92 
       
    93 CpThemeChangerPrivate::~CpThemeChangerPrivate()
       
    94 {
       
    95     themeClient->releaseInstance();
       
    96 }
       
    97 
       
    98 const CpThemeChanger::ThemeInfo& CpThemeChangerPrivate::currentTheme() const
       
    99 {
       
   100     return mCurrentTheme;
       
   101 }
       
   102 
       
   103 const QString& CpThemeChangerPrivate::currentThemeName() const
       
   104 {
       
   105     return mCurrentTheme.name.isEmpty() ? KDefaultTheme : mCurrentTheme.name;
       
   106 }
       
   107 
       
   108 void CpThemeChangerPrivate::updateThemeList(const QString& newThemeName)
       
   109 {
       
   110     if(!themeList.isEmpty()) {
       
   111         themeList.clear();
       
   112     }
       
   113 
       
   114     mCurrentTheme.name = newThemeName.isEmpty() ? KDefaultTheme : newThemeName;
       
   115 
       
   116     // Get the list of Drives here
       
   117     QStringList themesPathList;
       
   118 
       
   119 #if defined(Q_OS_WIN32)
       
   120     themesPathList << themeRootPath;
       
   121 #elif defined(Q_OS_SYMBIAN)
       
   122     QFileInfoList driveInfoList = QDir::drives();
       
   123     foreach (const QFileInfo &driveInfo, driveInfoList) {
       
   124         const QString drive = driveInfo.absolutePath();
       
   125         themesPathList << drive + themeRootPathPostfix;
       
   126     }
       
   127 #elif defined(Q_OS_UNIX)
       
   128     themesPathList << themeRootPath;
       
   129 #elif defined(Q_OS_MACX)
       
   130     themesPathList << themeRootPath;
       
   131 #endif
       
   132 
       
   133     foreach (const QString &path, themesPathList) {
       
   134         QDir themeDir;
       
   135         themeDir.setPath( path ) ;
       
   136         QStringList iconthemeslist;
       
   137         QStringList list = themeDir.entryList(QDir::AllDirs|QDir::NoDotAndDotDot,QDir::Name);
       
   138         CpThemeChanger::ThemeInfo nameIconPair;
       
   139 
       
   140         if(list.contains("themes",Qt::CaseSensitive )) {
       
   141             QDir root(themeDir.path());
       
   142             themeDir.setPath(root.path()+"/themes/icons/") ;
       
   143             iconthemeslist=themeDir.entryList(QDir::AllDirs|QDir::NoDotAndDotDot,QDir::Name);
       
   144             foreach(QString themefolder, iconthemeslist) {
       
   145                 QDir iconThemePath(root.path()+"/themes/icons/"+themefolder);
       
   146                 if(iconThemePath.exists("index.theme") &&
       
   147                    (iconThemePath.exists("scalable") || iconThemePath.exists("pixmap") )) {
       
   148                     QSettings iniSetting(iconThemePath.path()+"/index.theme",QSettings::IniFormat);
       
   149                     iniSetting.beginGroup("Icon Theme");
       
   150                     QString hidden = iniSetting.value("Hidden").toString();
       
   151                     QString name = iniSetting.value("Name").toString();
       
   152                     QString iconPath = iniSetting.value("PreviewIconPath").toString();
       
   153                     if (name.isEmpty()) {
       
   154                         continue;
       
   155                     }
       
   156                     if (!KDefaultPreviewAvailable && iconPath.isEmpty())
       
   157                     {
       
   158                         continue;
       
   159                     }
       
   160                     QString fullPathToIcon(iconThemePath.path() + iconPath);
       
   161                     // Don't treat this as a theme unless it's got a preview.
       
   162                     if (!QFileInfo(fullPathToIcon).exists() && !KDefaultPreviewAvailable) {
       
   163                         continue;
       
   164                     }
       
   165                     if(iconPath.isEmpty()){
       
   166                         
       
   167                         //if no preview graphics path specified,look for the background graphic.
       
   168                         //first look in /scalable folder.  if not there, look in pixmap folder.
       
   169                         if(QFileInfo(fullPathToIcon + "/scalable/qtg_graf_screen_bg_prt.svg").exists()){
       
   170                             nameIconPair.icon = HbIcon(fullPathToIcon + "/scalable/qtg_graf_screen_bg_prt.svg");
       
   171                         } else if(QFileInfo(fullPathToIcon + "/pixmap/qtg_graf_screen_bg_prt.png").exists()){
       
   172                             nameIconPair.icon = HbIcon(fullPathToIcon + "/pixmap/qtg_graf_screen_bg_prt.png");
       
   173                         } else{
       
   174                             nameIconPair.icon = HbIcon(":/image/themePreview.svg");
       
   175                         }
       
   176                     } else {
       
   177                         nameIconPair.icon = HbIcon(fullPathToIcon);
       
   178                     }
       
   179                     nameIconPair.name = name;
       
   180                     themeList.append(nameIconPair);
       
   181 
       
   182                     if (name == mCurrentTheme.name) {
       
   183                         mCurrentTheme = nameIconPair;
       
   184                     }
       
   185 
       
   186                     iniSetting.endGroup();
       
   187                     if((hidden == "true") ||( hidden == "")||(name!=themefolder) ) {
       
   188                         iconthemeslist.removeOne(themefolder);
       
   189                         if(!themeList.isEmpty()) {
       
   190                             themeList.removeLast();
       
   191                         }
       
   192                     }
       
   193                 } else {
       
   194                     iconthemeslist.removeOne(themefolder);
       
   195                     if(!themeList.isEmpty()) {
       
   196                         themeList.removeLast();
       
   197                     }
       
   198                 }
       
   199             }
       
   200         }
       
   201     }
       
   202     // Include default
       
   203     CpThemeChanger::ThemeInfo def;
       
   204     def.name = KDefaultTheme;
       
   205     def.icon = HbIcon(":/image/themePreview.svg");
       
   206     themeList.append(def);
       
   207     if (mCurrentTheme.name == KDefaultTheme)
       
   208     {
       
   209         mCurrentTheme = def;
       
   210     }
       
   211 
       
   212     // Sort the themes list
       
   213     qSort(themeList.begin(), themeList.end());
       
   214 }
       
   215 
       
   216 const QList<CpThemeChanger::ThemeInfo>& CpThemeChangerPrivate::themes() const
       
   217 {
       
   218     return themeList;
       
   219 }
       
   220 
       
   221 bool CpThemeChangerPrivate::connectToServer()
       
   222 {
       
   223     return themeClient->connectToServer();
       
   224 }
       
   225 
       
   226 /**
       
   227  * Indicate if the client is connected to the server
       
   228  */
       
   229 bool CpThemeChangerPrivate::isConnected() const
       
   230 {
       
   231     return themeClient->isConnected();
       
   232 }
       
   233 
       
   234 /**
       
   235  * Change a theme
       
   236  */
       
   237 bool CpThemeChangerPrivate::changeTheme(const QString& newTheme)
       
   238 {
       
   239     bool result = false;
       
   240     // Skip doing this if the request is for the current theme
       
   241     if (newTheme.isEmpty() || newTheme == mCurrentTheme.name) return result;
       
   242 
       
   243     // Make sure it's a valid theme name
       
   244     bool exists = false;
       
   245     QList<CpThemeChanger::ThemeInfo> themeList = themes();
       
   246     QList<CpThemeChanger::ThemeInfo>::const_iterator i;
       
   247     for (i = themeList.constBegin(); i != themeList.constEnd(); ++i) {
       
   248         if ( newTheme == i->name) {
       
   249             exists = true;
       
   250             break;
       
   251         }
       
   252     }
       
   253 
       
   254     if (exists) {
       
   255         result = themeClient->changeTheme(newTheme);
       
   256 		updateThemeList(newTheme);
       
   257 }
       
   258     return result;
       
   259 }
       
   260 
       
   261 void CpThemeChangerPrivate::_q_themeDirectoryChanged(const QString&)
       
   262 {
       
   263     updateThemeList();
       
   264 }
       
   265 
       
   266 /*
       
   267     HbThemeChangerModel provides an interface to the data contained in the
       
   268     HbThemeChanger using QAbstractListModel.
       
   269 */
       
   270 
       
   271 /*
       
   272     Constructor
       
   273 */
       
   274 HbThemeListModel::HbThemeListModel(CpThemeChangerPrivate *dd, QObject* parent)
       
   275     : QAbstractListModel(parent)
       
   276     , mThemeChangerPrivate(dd)
       
   277 {
       
   278     connect(dd->fileWatcher, SIGNAL(directoryChanged(const QString&)),
       
   279         this, SLOT(themeListChanged()));
       
   280 }
       
   281 
       
   282 /*
       
   283     Destructor
       
   284 */
       
   285 HbThemeListModel::~HbThemeListModel()
       
   286 {
       
   287 
       
   288 }
       
   289 
       
   290 /*
       
   291     Reimplemented from QAbstractListModel.
       
   292 */
       
   293 int HbThemeListModel::rowCount(const QModelIndex&) const
       
   294 {
       
   295     return mThemeChangerPrivate->themeList.size();
       
   296 }
       
   297 
       
   298 /*
       
   299     Reimplemented from QAbstractListModel.  Provides the data for Qt::DisplayRole and
       
   300     Qt::DecorationRole.
       
   301 */
       
   302 QVariant HbThemeListModel::data(const QModelIndex& index, int role) const
       
   303 {
       
   304     QVariant retVal = QVariant();
       
   305 
       
   306     if (index.isValid()) {
       
   307         switch (role) {
       
   308             case Qt::DisplayRole:
       
   309                 retVal = mThemeChangerPrivate->themeList.at(index.row()).name;
       
   310                 break;
       
   311 
       
   312             case Qt::DecorationRole:
       
   313                 retVal = mThemeChangerPrivate->themeList.at(index.row()).icon;
       
   314                 break;
       
   315 
       
   316         case Qt::SizeHintRole:
       
   317                 retVal = mThemeChangerPrivate->themeList.at(index.row()).icon.size();
       
   318                 break;
       
   319 
       
   320             default:
       
   321                 // do nothing
       
   322                 qt_noop();
       
   323         }
       
   324     }
       
   325 
       
   326     return retVal;
       
   327 }
       
   328 
       
   329 /*
       
   330     Responds appropriately when the underlying data in the theme changer is modified.
       
   331 
       
   332     Unfortunately the directory watcher from QFileWatcher only says when something changed
       
   333     not what changed.  Therefore the model is considered reset rather than having rows
       
   334     with dataChanged.
       
   335 */
       
   336 void HbThemeListModel::themeListChanged()
       
   337 {
       
   338     beginResetModel();
       
   339 
       
   340     mThemeChangerPrivate->themes();
       
   341 
       
   342     endResetModel();
       
   343 }
       
   344 
       
   345 // End of file