screensaver/snsrplugins/snsrbigclockscreensaverplugin/snsrindicators/src/snsrindicatormodel.cpp
changeset 97 66b5fe3c07fd
child 98 e6f74eb7f69f
equal deleted inserted replaced
95:32e56106abf2 97:66b5fe3c07fd
       
     1 /*
       
     2 * Copyright (c) 2010 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:  Model for handling indicator data.
       
    15 *
       
    16 */
       
    17 
       
    18 #include <qglobal.h>
       
    19 #ifdef Q_OS_SYMBIAN
       
    20 #include <xqsettingsmanager.h>
       
    21 #include <xqsettingskey.h>
       
    22 #include <coreapplicationuissdkcrkeys.h>
       
    23 #endif //Q_OS_SYMBIAN
       
    24 
       
    25 #include "snsrindicatormodel.h"
       
    26 #include "snsrindicatorinfo.h"
       
    27 
       
    28 /*!
       
    29     \class SnsrIndicatorModel
       
    30     \ingroup group_snsrbigclockscreensaverplugin
       
    31     \brief Model for handling indicator data.
       
    32  */
       
    33 
       
    34 // TODO: what is the final type string of silent indicator?
       
    35 // workaround solution: assume that it contains
       
    36 // substring "silence" like in the demo app provided by the team.
       
    37 const char *gSilentIndicatorTypeString = "silence";
       
    38 const char *gOfflineIndicatorTypeString = "offline";
       
    39 
       
    40 
       
    41 /*!
       
    42     Constructs a new SnsrIndicatorModel
       
    43     \param parent Parent object.
       
    44  */
       
    45 SnsrIndicatorModel::SnsrIndicatorModel(QObject *parent): QObject(parent),
       
    46     mOfflineStateOn(false)
       
    47 {   
       
    48     initializeOfflineModeIndication();
       
    49 }
       
    50 
       
    51 /*!
       
    52     Destructs the class.
       
    53  */
       
    54 SnsrIndicatorModel::~SnsrIndicatorModel()
       
    55 {
       
    56      mNotificationIndicators.clear();
       
    57      mSettingIndicators.clear();
       
    58      mIndicatorsToShow.clear();
       
    59 #ifdef Q_OS_SYMBIAN
       
    60      if (mSettingsManager && mOfflineKey) {
       
    61          mSettingsManager->stopMonitoring(*mOfflineKey);
       
    62      }
       
    63      delete mOfflineKey;
       
    64 #endif //Q_OS_SYMBIAN
       
    65 }
       
    66 
       
    67 /*!
       
    68     If there are already some active indicators when screensaver is
       
    69     launched, then this method is called.
       
    70     Indicators that are gonna be shown by the screensaver are
       
    71     added to the model. 
       
    72     \param activeIndicators Active universal indicators in 
       
    73     chronological order according to their arrival time.
       
    74  */
       
    75 void SnsrIndicatorModel::handleActiveIndicators(
       
    76     const QList<HbIndicatorInterface*> &activeIndicators)
       
    77 {
       
    78     mNotificationIndicators.clear();
       
    79     mSettingIndicators.clear();
       
    80     
       
    81     bool addedAny(false);
       
    82     
       
    83     for (int i = 0; i < activeIndicators.size(); ++i) {
       
    84         HbIndicatorInterface* activatedIndicator = activeIndicators.at(i);
       
    85         SnsrIndicatorInfo indicatorInfo;
       
    86         if (activatedIndicator 
       
    87             && showIndicatorInScreensaver(*activatedIndicator,indicatorInfo)) {
       
    88             addIndicator(indicatorInfo);
       
    89             connectToIndicatorsUpdateSignal(*activatedIndicator);
       
    90             addedAny = true;
       
    91         }
       
    92     }
       
    93     
       
    94     // Send signal only once if there were any such indicators that
       
    95     // screensaver is supposed to show (=added to the model).
       
    96     if (addedAny) {
       
    97         emitChangeSignal();
       
    98     }
       
    99 }
       
   100 
       
   101 /*!
       
   102     Called when some universal indicator gets activated.
       
   103     \param activatedIndicator Activated universal indicator
       
   104  */
       
   105 void SnsrIndicatorModel::handleActivatedIndicator(
       
   106     HbIndicatorInterface *activatedIndicator)
       
   107 {
       
   108     SnsrIndicatorInfo indicatorInfo;
       
   109     if (activatedIndicator
       
   110         && showIndicatorInScreensaver(*activatedIndicator,indicatorInfo)) {
       
   111         if (addIndicator(indicatorInfo)) {
       
   112             connectToIndicatorsUpdateSignal(*activatedIndicator);
       
   113             emitChangeSignal();
       
   114         }
       
   115     }
       
   116 }
       
   117 
       
   118 /*!
       
   119     Called when some universal indicator gets deactivated.
       
   120     \param deactivatedIndicator Deactivated universal indicator
       
   121  */
       
   122 void SnsrIndicatorModel::handleDeactivatedIndicator(
       
   123     HbIndicatorInterface *deactivatedIndicator)
       
   124 {
       
   125     if (deactivatedIndicator) {
       
   126         SnsrIndicatorInfo indicatorInfo(
       
   127             deactivatedIndicator->indicatorType(), 
       
   128             deactivatedIndicator->indicatorData(HbIndicatorInterface::MonoDecorationNameRole).toString(),
       
   129             deactivatedIndicator->category());
       
   130         
       
   131         if (findAndRemoveIndicator(indicatorInfo)) {
       
   132             emitChangeSignal();
       
   133         }
       
   134     }
       
   135 }
       
   136 
       
   137 /*!
       
   138     Called when some universal indicator updates its data by
       
   139     emitting dataChanged signal. 
       
   140     We listen to this signal because at least the silent indicator plugin demo 
       
   141     uses this method to inform the clients when it gets deactivated/activated 
       
   142     once it has been activated once by setting its icon path to empty/valid string.
       
   143     Don't know if this is going to be the final solution as it's unconventional (?) 
       
   144     but let's be prepared also to this kind of approach. 
       
   145  */
       
   146 void SnsrIndicatorModel::handleUpdatedIndicator()
       
   147 {
       
   148     HbIndicatorInterface* indicator =
       
   149         qobject_cast<HbIndicatorInterface*>(sender());
       
   150     if (!indicator) {
       
   151         return;
       
   152     }
       
   153     
       
   154     // If indicator's icon path was set to empty string, then treat it
       
   155     // like it were deactivated. And if not empty, then it's active again.
       
   156     if (indicator->indicatorData(
       
   157             HbIndicatorInterface::MonoDecorationNameRole).toString().isEmpty()) {
       
   158         handleDeactivatedIndicator(indicator);
       
   159     }
       
   160     else {
       
   161         handleActivatedIndicator(indicator);
       
   162     }
       
   163     
       
   164 }
       
   165 
       
   166 /*!
       
   167     Sends a signal with a list of all currently active indicators.
       
   168     No signal is sent if there are no active indicators currently.
       
   169  */
       
   170 void SnsrIndicatorModel::initializeIndicatorWidget()
       
   171 {
       
   172     getCurrentOfflineState(); // update status to be on the safe side
       
   173     
       
   174     if ( anyActiveIndicators() ) {
       
   175         emitChangeSignal();
       
   176     }
       
   177 }
       
   178 
       
   179 #ifdef Q_OS_SYMBIAN 
       
   180 /*!
       
   181     listens airplane repository key.
       
   182  */
       
   183 void SnsrIndicatorModel::offlineValueChanged( const XQSettingsKey &key, const QVariant &value )
       
   184 {
       
   185     bool previousState(mOfflineStateOn);
       
   186     switch ( key.key() ) {
       
   187         case KCoreAppUIsNetworkConnectionAllowed:
       
   188              if(value.toInt() == ECoreAppUIsNetworkConnectionNotAllowed &&
       
   189                 value.isValid())
       
   190                  {
       
   191                  mOfflineStateOn = true;                     
       
   192                  }
       
   193              else
       
   194                  {
       
   195                  mOfflineStateOn = false; 
       
   196                  }            
       
   197              if (previousState != mOfflineStateOn) {
       
   198                  emitChangeSignal();
       
   199              }
       
   200              break;
       
   201         default:
       
   202             break;
       
   203 
       
   204         }
       
   205 }
       
   206 #endif //Q_OS_SYMBIAN
       
   207 
       
   208 /*!
       
   209     Add the indicator into this model. Handle here the order in which
       
   210     indicators are shown in screensaver: notification indicators should be
       
   211     shown in the same order as shown in statusbar, that is in reversed
       
   212     chronological order. Silent indicator should always be the right-most one.
       
   213     /retval true if indicator was added (not found already in the listings)
       
   214  */
       
   215 bool SnsrIndicatorModel::addIndicator(const SnsrIndicatorInfo &indicatorInfo)
       
   216 {
       
   217     // To be on the safe side, check that the indicator doesn't already
       
   218     // exists in the active indicator listings.
       
   219     bool added(false);
       
   220     
       
   221     // Use prepend to keep the list in reversed chronological order
       
   222     if (indicatorInfo.category == HbIndicatorInterface::NotificationCategory
       
   223         && !isIndicatorAlreadyAdded(indicatorInfo)) {
       
   224         mNotificationIndicators.prepend(indicatorInfo);
       
   225         added = true;
       
   226     }
       
   227     else if (indicatorInfo.category == HbIndicatorInterface::SettingCategory
       
   228              && !isIndicatorAlreadyAdded(indicatorInfo)) {
       
   229         mSettingIndicators.append(indicatorInfo);
       
   230         added = true;
       
   231     }
       
   232     
       
   233     return added;
       
   234 }
       
   235 
       
   236 /*!
       
   237     Check whether the indicator is already added in the active 
       
   238     indicator listing.
       
   239     /retval true if indicator is already added; false if not.
       
   240  */
       
   241 bool SnsrIndicatorModel::isIndicatorAlreadyAdded(const SnsrIndicatorInfo &indicatorInfo) const
       
   242 {
       
   243     bool alreadyExits(false);
       
   244     
       
   245     const QList<SnsrIndicatorInfo> &indicatorList = 
       
   246         indicatorInfo.category == HbIndicatorInterface::NotificationCategory 
       
   247         ? mNotificationIndicators : mSettingIndicators;
       
   248     
       
   249     for (int i = 0; i < indicatorList.size(); ++i) {
       
   250         if (indicatorList.at(i).type == indicatorInfo.type) {
       
   251             alreadyExits = true;
       
   252             break;
       
   253         }
       
   254     }
       
   255     return alreadyExits;
       
   256 }
       
   257 
       
   258 /*!
       
   259    Remove indicator if it can be found.
       
   260    /retval true if the indicator was removed
       
   261  */
       
   262 bool SnsrIndicatorModel::findAndRemoveIndicator(const SnsrIndicatorInfo &indicatorInfo)
       
   263 {
       
   264     bool removed(false);
       
   265     int index(-1);
       
   266     QList<SnsrIndicatorInfo> &indicatorList = 
       
   267         indicatorInfo.category == HbIndicatorInterface::NotificationCategory 
       
   268         ? mNotificationIndicators : mSettingIndicators;
       
   269     
       
   270     for (int i = 0; i < indicatorList.size(); ++i) {
       
   271         if (indicatorList.at(i).type == indicatorInfo.type) {
       
   272             index = i;
       
   273             break;
       
   274         }
       
   275     }
       
   276     if (index >= 0) {
       
   277         indicatorList.removeAt(index);
       
   278         removed = true;
       
   279     }
       
   280     return removed;
       
   281 }
       
   282 
       
   283 /*!
       
   284    Check whether to show the indicator in screensaver or not.
       
   285    Icon path is asked with HbIndicatorInterface::MonoDecorationNameRole 
       
   286    which refers to the indicator icons shown also in the statusbar:
       
   287    only 4 Notification indicators has premission to publish data with
       
   288    that role. As those 4 are the ones wanted also by screensaver, no
       
   289    extra checks are needed.
       
   290    From the Setting category one should show only Silent indicator.
       
   291    No indicators are shown from the Progress category.
       
   292    If indicator should be shown by screensaver, indicator info is
       
   293    packaged and returned within the parameter.
       
   294    
       
   295    /retval true if the indicator should be shown in screensaver
       
   296  */
       
   297 bool SnsrIndicatorModel::showIndicatorInScreensaver(
       
   298         const HbIndicatorInterface &indicatorInterface, SnsrIndicatorInfo &indicatorInfo)
       
   299 {
       
   300     bool show(false);
       
   301     // all indicators shown by screensaver must have valid status bar icon path
       
   302     QString iconPath = 
       
   303             indicatorInterface.indicatorData(HbIndicatorInterface::MonoDecorationNameRole).toString();
       
   304     QString typeString = indicatorInterface.indicatorType();
       
   305     HbIndicatorInterface::Category category = indicatorInterface.category();
       
   306     
       
   307     if (category == HbIndicatorInterface::NotificationCategory
       
   308         && !iconPath.isEmpty()) {
       
   309         // only 4 indicators of this category has permission to publish status bar
       
   310         // icon path->we should show all of them->no additional checks are neeeded.
       
   311         show = true;
       
   312     }
       
   313     else if (category == HbIndicatorInterface::SettingCategory
       
   314              && !iconPath.isEmpty()
       
   315              // TODO: what is the type string of silent indicator? 
       
   316              // workaround solution: assume that it contains
       
   317              // substring "silence" like in the demo app.
       
   318              // && type == gSilentIndicatorTypeString ) { 
       
   319              && typeString.contains(gSilentIndicatorTypeString, Qt::CaseInsensitive)) {  
       
   320         show = true;
       
   321     }
       
   322     else { // e.g. no Progress category indicators are shown
       
   323         show = false;
       
   324     }
       
   325  
       
   326     // package indicator data into indicatorInfo parameter
       
   327     indicatorInfo.type = typeString;
       
   328     indicatorInfo.iconPath = iconPath;
       
   329     indicatorInfo.category = category;
       
   330         
       
   331     return show;
       
   332 }
       
   333 
       
   334 /*!
       
   335    Start listening to indicator's dataChanged signals.
       
   336    /parameter indicator whose dataChanged signal we want to listen
       
   337  */
       
   338 void SnsrIndicatorModel::connectToIndicatorsUpdateSignal(const HbIndicatorInterface &indicatorInterface)
       
   339 {
       
   340     // Connect to silent indicator's dataChanged signal as it seems to 
       
   341     // use unconventional method (demo at least) to inform when
       
   342     // it's get deactivated/activated: dataChanged signal is emitted and
       
   343     // icon path is set to empty string/valid string.
       
   344     // It's assumed that we don't need to listen to other indicators
       
   345     // as we are not interested e.g. when primary/secondary texts change etc.
       
   346     
       
   347     // NOTE: do NOT disconnect the indicator signal anywhere explicitly here
       
   348     // or we won't get activation/deactivation messages.
       
   349     if (indicatorInterface.indicatorType().contains(gSilentIndicatorTypeString, Qt::CaseInsensitive)) {
       
   350         QObject::connect( &indicatorInterface, SIGNAL(dataChanged()),
       
   351                           this, SLOT(handleUpdatedIndicator()));
       
   352     }
       
   353 }
       
   354 
       
   355 /*!
       
   356    Check whether there is any active indicator currently.
       
   357    /retval true if there is at least one indicator to show
       
   358  */
       
   359 bool SnsrIndicatorModel::anyActiveIndicators() const
       
   360 {
       
   361   bool any(false);
       
   362   if ( mNotificationIndicators.size() != 0 
       
   363       || mSettingIndicators.size() != 0 
       
   364       || mOfflineStateOn ) {
       
   365       any = true;
       
   366   }
       
   367   return any;
       
   368 }
       
   369 
       
   370 /*!
       
   371     Send appropriate signal so that UI widget can update itself.
       
   372  */
       
   373 void SnsrIndicatorModel::emitChangeSignal()
       
   374 {   
       
   375     if (anyActiveIndicators()) {   
       
   376         updateIndicatorsToShowList();
       
   377         emit indicatorsUpdated(mIndicatorsToShow);
       
   378     }
       
   379     else {
       
   380         mIndicatorsToShow.clear();
       
   381         emit allIndicatorsDeactivated();
       
   382     }
       
   383 }
       
   384 
       
   385 /*!
       
   386    Updates the list that contains all the indicators that
       
   387    should be shown in UI. List should contain active indicators
       
   388    in this order: 
       
   389    offline + notification indicators + settings indicators.
       
   390    This is the list that will be sent to the widget.
       
   391  */
       
   392 void SnsrIndicatorModel::updateIndicatorsToShowList()
       
   393 {
       
   394     mIndicatorsToShow.clear();
       
   395     
       
   396     if (mOfflineStateOn) {
       
   397         mIndicatorsToShow.append(mOfflineIndicatorInfo);
       
   398     }
       
   399     mIndicatorsToShow.append(mNotificationIndicators);
       
   400     mIndicatorsToShow.append(mSettingIndicators);
       
   401 }
       
   402 
       
   403 /*!
       
   404  * Reads the airplanemode repository value and starts monitoring it.
       
   405  * if the value is 1, offline indicator is shown.
       
   406  */
       
   407 void SnsrIndicatorModel::initializeOfflineModeIndication()
       
   408 {
       
   409 #ifdef Q_OS_SYMBIAN
       
   410     mOfflineIndicatorInfo = SnsrIndicatorInfo(
       
   411         gOfflineIndicatorTypeString,
       
   412         QLatin1String("qtg_mono_offline"),
       
   413         HbIndicatorInterface::NotificationCategory);
       
   414     
       
   415     mSettingsManager = new XQSettingsManager(this);
       
   416     //connect to offlineValueChanged slot so we get information if the value is changed while screensaver is on
       
   417     connect(mSettingsManager, SIGNAL(valueChanged(XQSettingsKey, QVariant)),
       
   418             this, SLOT(offlineValueChanged( const XQSettingsKey, const QVariant)));
       
   419     mOfflineKey = new XQSettingsKey(XQSettingsKey::TargetCentralRepository, 
       
   420                                     KCRUidCoreApplicationUIs.iUid, 
       
   421                                     KCoreAppUIsNetworkConnectionAllowed);
       
   422     if(mSettingsManager->readItemValue(*mOfflineKey).toInt() == ECoreAppUIsNetworkConnectionNotAllowed)
       
   423         {
       
   424         mOfflineStateOn = true;
       
   425         } 
       
   426     mSettingsManager->startMonitoring(*mOfflineKey);
       
   427 #else
       
   428     mOfflineStateOn = false;
       
   429 #endif //Q_OS_SYMBIAN
       
   430 }
       
   431 
       
   432 /*!
       
   433     Get current offline status.
       
   434  */
       
   435 void SnsrIndicatorModel::getCurrentOfflineState()
       
   436 {
       
   437 #ifdef Q_OS_SYMBIAN
       
   438     if(mSettingsManager->readItemValue(*mOfflineKey).toInt() == ECoreAppUIsNetworkConnectionNotAllowed) {
       
   439         mOfflineStateOn = true;
       
   440     }
       
   441     else {
       
   442        mOfflineStateOn = false;
       
   443     }
       
   444 #else
       
   445     mOfflineStateOn = false;
       
   446 #endif //Q_OS_SYMBIAN
       
   447 }
       
   448