src/hbwidgets/widgets/hbdatetimepicker_p.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbWidgets module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include "hbdatetimepicker_p.h"
       
    27 #include "hbdatetimepicker.h"
       
    28 #include "hbstyleoption.h"
       
    29 #include "hbfeaturemanager_p.h"
       
    30 
       
    31 //TODO:remove frameitem dependency
       
    32 #include "hbframeitem.h"
       
    33 
       
    34 #include <QStringListModel>
       
    35 #include <QGraphicsLinearLayout>
       
    36 #include <QModelIndex>
       
    37 #include <QDate>
       
    38 #include <QLocale>
       
    39 #include <QDebug>
       
    40 #include <QStringListModel>
       
    41 #include <QPointer>
       
    42 
       
    43 #define HBDATETIMEPICKER_DEBUG
       
    44 
       
    45 //////////HbDateTimeParser - Implementaion may change in future.//////////////
       
    46 
       
    47 static inline int countRepeat(const QString &str, int index, int maxCount)
       
    48 {
       
    49     int count = 1;
       
    50     const QChar ch(str.at(index));
       
    51     const int max = qMin(index + maxCount, str.size());
       
    52     while (index + count < max && str.at(index + count) == ch) {
       
    53         ++count;
       
    54     }
       
    55     return count;
       
    56 }
       
    57 
       
    58 static QString unquote(const QString &str)
       
    59 {
       
    60     const QChar quote(QLatin1Char('\''));
       
    61     const QChar slash(QLatin1Char('\\'));
       
    62     const QChar zero(QLatin1Char('0'));
       
    63     QString ret;
       
    64     QChar status(zero);
       
    65     const int max = str.size();
       
    66     for (int i=0; i<max; ++i) { 
       
    67         if (str.at(i) == quote) {
       
    68             if (status != quote) {
       
    69                 status = quote;
       
    70             } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
       
    71                 ret[ret.size() - 1] = quote;
       
    72             } else {
       
    73                 status = zero;
       
    74             }
       
    75         } else {
       
    76             ret += str.at(i);
       
    77         }
       
    78     }
       
    79     return ret;
       
    80 }
       
    81 
       
    82 static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
       
    83 {
       
    84     QString str(string.mid(from, size));
       
    85     if (lastQuote >= from)
       
    86         str = unquote(str);
       
    87     list->append(str);
       
    88 }
       
    89 
       
    90 bool HbDateTimeParser::parseFormat(const QString &format)
       
    91 {
       
    92     const QLatin1Char quote('\'');
       
    93     const QLatin1Char slash('\\');
       
    94     const QLatin1Char zero('0');
       
    95 
       
    96     if (format == mDisplayFormat && !format.isEmpty()) {
       
    97         return true;
       
    98     }
       
    99 
       
   100     QVector<SectionNode> newSectionNodes;
       
   101     Sections newDisplay = 0;
       
   102     QStringList newSeparators;
       
   103     int i, index = 0;
       
   104     int add = 0;
       
   105     QChar status(zero);
       
   106     const int max = format.size();
       
   107     int lastQuote = -1;
       
   108     for (i = 0; i<max; ++i) {
       
   109         if (format.at(i) == quote) {
       
   110             lastQuote = i;
       
   111             ++add;
       
   112             if (status != quote) {
       
   113                 status = quote;
       
   114             } else if (format.at(i - 1) != slash) {
       
   115                 status = zero;
       
   116             }
       
   117         } else if (status != quote) {
       
   118             const char sect = format.at(i).toLatin1();
       
   119             switch (sect) {
       
   120             case 'H':
       
   121             case 'h':
       
   122                 {
       
   123                     const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
       
   124                     const SectionNode sn = { hour, i - add, countRepeat(format, i, 2) };
       
   125                     newSectionNodes.append(sn);
       
   126                     appendSeparator(&newSeparators, format, index, i - index, lastQuote);
       
   127                     i += sn.count - 1;
       
   128                     index = i + 1;
       
   129                     newDisplay |= hour;
       
   130                 }
       
   131                 break;
       
   132             case 'm':
       
   133                 {
       
   134                     const SectionNode sn = { MinuteSection, i - add, countRepeat(format, i, 2) };
       
   135                     newSectionNodes.append(sn);
       
   136                     appendSeparator(&newSeparators, format, index, i - index, lastQuote);
       
   137                     i += sn.count - 1;
       
   138                     index = i + 1;
       
   139                     newDisplay |= MinuteSection;
       
   140                 }
       
   141                 break;
       
   142             case 's':
       
   143                 {
       
   144                     const SectionNode sn = { SecondSection, i - add, countRepeat(format, i, 2) };
       
   145                     newSectionNodes.append(sn);
       
   146                     appendSeparator(&newSeparators, format, index, i - index, lastQuote);
       
   147                     i += sn.count - 1;
       
   148                     index = i + 1;
       
   149                     newDisplay |= SecondSection;
       
   150                 }
       
   151                 break;
       
   152 
       
   153             case 'z':
       
   154                 {
       
   155                     const SectionNode sn = { MSecSection, i - add, countRepeat(format, i, 3) < 3 ? 1 : 3 };
       
   156                     newSectionNodes.append(sn);
       
   157                     appendSeparator(&newSeparators, format, index, i - index, lastQuote);
       
   158                     i += sn.count - 1;
       
   159                     index = i + 1;
       
   160                     newDisplay |= MSecSection;
       
   161                 }
       
   162                 break;
       
   163             case 'A':
       
   164             case 'a':
       
   165                 {
       
   166                     const bool cap = (sect == 'A');
       
   167                     const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0) };
       
   168                     newSectionNodes.append(sn);
       
   169                     appendSeparator(&newSeparators, format, index, i - index, lastQuote);
       
   170                     newDisplay |= AmPmSection;
       
   171                     if (i + 1 < format.size()
       
   172                         && format.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
       
   173                             ++i;
       
   174                     }
       
   175                     index = i + 1;
       
   176                 }
       
   177                 break;
       
   178             case 'y':
       
   179                 {
       
   180                     const int repeat = countRepeat(format, i, 4);
       
   181                     if (repeat >= 2) {
       
   182                         const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
       
   183                             i - add, repeat == 4 ? 4 : 2 };
       
   184                         newSectionNodes.append(sn);
       
   185                         appendSeparator(&newSeparators, format, index, i - index, lastQuote);
       
   186                         i += sn.count - 1;
       
   187                         index = i + 1;
       
   188                         newDisplay |= sn.type;
       
   189                     }
       
   190                 }
       
   191                 break;
       
   192             case 'M':
       
   193                 {
       
   194                     const SectionNode sn = { MonthSection, i - add, countRepeat(format, i, 4) };
       
   195                     newSectionNodes.append(sn);
       
   196                     newSeparators.append(unquote(format.mid(index, i - index)));
       
   197                     i += sn.count - 1;
       
   198                     index = i + 1;
       
   199                     newDisplay |= MonthSection;
       
   200                 }
       
   201                 break;
       
   202             case 'd':
       
   203                 {
       
   204                     const int repeat = countRepeat(format, i, 4);
       
   205                     const SectionNode sn = { repeat >= 3 ? DayOfWeekSection : DaySection, i - add, repeat };
       
   206                     newSectionNodes.append(sn);
       
   207                     appendSeparator(&newSeparators, format, index, i - index, lastQuote);
       
   208                     i += sn.count - 1;
       
   209                     index = i + 1;
       
   210                     newDisplay |= sn.type;
       
   211                 }
       
   212                 break;
       
   213 
       
   214             default:
       
   215                 break;
       
   216             }
       
   217         }
       
   218     }
       
   219 
       
   220     if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
       
   221         const int max = newSectionNodes.size();
       
   222         for (int i=0; i<max; ++i) {
       
   223             SectionNode &node = newSectionNodes[i];
       
   224             if (node.type == Hour12Section)
       
   225                 node.type = Hour24Section;
       
   226         }
       
   227     }
       
   228 
       
   229     if (index < format.size()) {
       
   230         appendSeparator(&newSeparators, format, index, index - max, lastQuote);
       
   231     } else {
       
   232         newSeparators.append(QString());
       
   233     }
       
   234 
       
   235     mDisplayFormat = format;
       
   236     mSeparators = newSeparators;
       
   237     mSectionNodes = newSectionNodes;
       
   238     mDisplaySections = newDisplay;
       
   239     
       
   240     return true;
       
   241 }
       
   242 
       
   243 int HbDateTimeParser::sectionSize(int sectionIndex) const
       
   244 {
       
   245     if (sectionIndex < 0)
       
   246         return 0;
       
   247 
       
   248     if (sectionIndex >= mSectionNodes.size()) {
       
   249         qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
       
   250         return -1;
       
   251     }
       
   252     if (sectionIndex == mSectionNodes.size() - 1) {
       
   253         return mDisplayFormat.size() - sectionPos(sectionIndex) - mSeparators.last().size();
       
   254     } else {
       
   255         return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
       
   256             - mSeparators.at(sectionIndex + 1).size();
       
   257     }
       
   258 }
       
   259 
       
   260 int HbDateTimeParser::sectionPos(int sectionIndex) const
       
   261 {
       
   262     return sectionPos(sectionNode(sectionIndex));
       
   263 }
       
   264 
       
   265 int HbDateTimeParser::sectionPos(const SectionNode &sn) const
       
   266 {
       
   267     if (sn.pos == -1) {
       
   268         return -1;
       
   269     }
       
   270 
       
   271     return sn.pos;
       
   272 }
       
   273 
       
   274 const HbDateTimeParser::SectionNode &HbDateTimeParser::sectionNode(int sectionIndex) const
       
   275 {
       
   276     return mSectionNodes.at(sectionIndex);
       
   277 }
       
   278 /////////////////////////////////////////////////
       
   279 
       
   280 
       
   281 HbDateTimePickerPrivate::HbDateTimePickerPrivate()
       
   282 :HbWidgetPrivate()
       
   283     ,mDayPicker(0)
       
   284     ,mMonthPicker(0)
       
   285     ,mYearPicker(0)
       
   286     ,mHourPicker(0)
       
   287     ,mMinutePicker(0)
       
   288     ,mSecondPicker(0)
       
   289     ,mAmPmPicker(0)
       
   290     ,mDayModel(0)
       
   291     ,mMonthModel(0)
       
   292     ,mYearModel(0)
       
   293     ,mHourModel(0)
       
   294     ,mMinuteModel(0)
       
   295     ,mSecondModel(0)
       
   296     ,mAmPmModel(0)
       
   297     ,mYearOffset(-1)
       
   298     ,mMonthOffset(-1)
       
   299     ,mDayOffset(-1)
       
   300     ,mHourOffset(-1)
       
   301     ,mMinuteOffset(-1)
       
   302     ,mSecondOffset(-1)
       
   303     ,mDateTime(QDateTime::currentDateTime())
       
   304     ,mDateTimeMode(QVariant::Date) //default is date mode
       
   305     ,mLayout(0)         
       
   306     //,mFormat() //set the format again in init()
       
   307     //,mDisplaySecions() //is blank by default
       
   308     ,mParser()
       
   309     ,mYearFormat()
       
   310     ,mMonthFormat()
       
   311     ,mDayFormat()
       
   312     ,mHourFormat()
       
   313     ,mMinuteFormat()
       
   314     ,mSecondFormat() 
       
   315     ,mIs24HourFormat(false)
       
   316     ,mIsTwoDigitYearFormat(false)
       
   317     ,mBackground(0)
       
   318     ,mFrame(0)
       
   319     ,mContent(0)
       
   320 {
       
   321     mMinimumDate = HBDATETIMEPICKER_DATETIME_MIN;
       
   322     mMaximumDate = HBDATETIMEPICKER_DATETIME_MAX;
       
   323     mDateTime = mMinimumDate;
       
   324 }
       
   325 
       
   326 HbDateTimePickerPrivate::~HbDateTimePickerPrivate()
       
   327 {
       
   328     QGraphicsLayoutItem *item;
       
   329     foreach(item,mDividers)
       
   330     {
       
   331         mLayout->removeItem(item);
       
   332         delete item;
       
   333     }
       
   334 }
       
   335 
       
   336 /*
       
   337    called only once. while the widget is constructing.
       
   338 */
       
   339 
       
   340 void HbDateTimePickerPrivate::init(QVariant::Type dateTimeMode)
       
   341 {
       
   342     Q_Q(HbDateTimePicker);
       
   343 
       
   344     //create base content widget which contains the tumble views
       
   345     mContent=new HbWidget(q);
       
   346     mLayout = new QGraphicsLinearLayout(Qt::Horizontal);
       
   347     mLayout->setSpacing(0);
       
   348     mLayout->setContentsMargins(0,0,0,0);
       
   349     mContent->setLayout(mLayout);
       
   350     q->style()->setItemName(mContent,"content");
       
   351 
       
   352     mDateTimeMode = dateTimeMode;
       
   353 
       
   354     //read the format from locale
       
   355     mFormat = localeDateTimeFormat(dateTimeMode);
       
   356 
       
   357     //parse the format and set the sections in order
       
   358     parseDisplayFormat(mFormat);
       
   359 
       
   360     mDividers.clear();
       
   361 
       
   362     //create the dividers used in rearrangeTumbleViews
       
   363     createPrimitives();
       
   364 
       
   365     //recreate and rearrange depending on the format
       
   366     rearrangeTumbleViews();
       
   367 }
       
   368 
       
   369 /*!
       
   370   \internal
       
   371 
       
   372   Getting the format from the local settings.
       
   373 */
       
   374 QString HbDateTimePickerPrivate::localeDateTimeFormat(const QVariant::Type &dateTimeMode)
       
   375 {
       
   376     if(dateTimeMode == QVariant::Date) {
       
   377         return mLocale.dateFormat(QLocale::ShortFormat);
       
   378     } else if(dateTimeMode == QVariant::Time) {
       
   379         return mLocale.timeFormat(QLocale::ShortFormat);
       
   380     }
       
   381     return mLocale.dateTimeFormat(QLocale::ShortFormat);
       
   382 }
       
   383 
       
   384 bool HbDateTimePickerPrivate::isFormatValid(const QString &newDisplayFormat)
       
   385 {
       
   386     if(newDisplayFormat == mFormat) {
       
   387         return false;
       
   388     }
       
   389     return true;
       
   390 }
       
   391 
       
   392 /* 
       
   393    this will reset the display sections and re add them in order
       
   394    mentioned in the display format passed. this also sets the mIs24HourFormat var.
       
   395 */
       
   396 void HbDateTimePickerPrivate::parseDisplayFormat(const QString &format)
       
   397 {
       
   398     if(mParser.parseFormat(format)) {
       
   399         for(int i=0;i<mParser.mSectionNodes.count();++i) {
       
   400             switch(mParser.mSectionNodes[i].type) {
       
   401                 case HbDateTimeParser::DaySection:
       
   402                 case HbDateTimeParser::DayOfWeekSection:
       
   403                     mDayFormat = QString(mParser.mSectionNodes[i].count,'d');
       
   404                     break;
       
   405 
       
   406                 case HbDateTimeParser::MonthSection:
       
   407                     mMonthFormat = QString(mParser.mSectionNodes[i].count,'M');
       
   408                     break;
       
   409 
       
   410                 case HbDateTimeParser::YearSection:
       
   411                     mIsTwoDigitYearFormat = false;
       
   412                     mYearFormat = QString(mParser.mSectionNodes[i].count,'y');
       
   413                     break;
       
   414 
       
   415                 case HbDateTimeParser::YearSection2Digits:
       
   416                     mIsTwoDigitYearFormat = true;
       
   417                     mYearFormat = QString(mParser.mSectionNodes[i].count,'y');
       
   418                     break;
       
   419 
       
   420                 case HbDateTimeParser::SecondSection:
       
   421                     mSecondFormat = QString(mParser.mSectionNodes[i].count,'s');
       
   422                     break;
       
   423 
       
   424                 case HbDateTimeParser::MinuteSection:
       
   425                     mMinuteFormat = QString(mParser.mSectionNodes[i].count,'m');
       
   426                     break;
       
   427 
       
   428                 case HbDateTimeParser::Hour12Section:
       
   429                     mIs24HourFormat = false;
       
   430                     mHourFormat = QString(mParser.mSectionNodes[i].count,'h');
       
   431                     break;
       
   432 
       
   433                 case HbDateTimeParser::Hour24Section:
       
   434                     mIs24HourFormat = true;
       
   435                     mHourFormat = QString(mParser.mSectionNodes[i].count,'h');
       
   436                     break;
       
   437 
       
   438                 default:
       
   439                     break;
       
   440                     /*case HbDateTimeParser::DayOfWeekSection: not supported */
       
   441             }
       
   442         }
       
   443     }
       
   444 }
       
   445 
       
   446 /*
       
   447    this is called whenever the setDisplayFormat changes.
       
   448    function deletes all tumbleviews which currently exist and
       
   449    it creates the ones which are required and makes the connections.
       
   450 */
       
   451 void HbDateTimePickerPrivate::rearrangeTumbleViews()
       
   452 {                  
       
   453     Q_Q(HbDateTimePicker);
       
   454 
       
   455     deleteAndNull(mYearPicker);
       
   456     deleteAndNull(mMonthPicker);
       
   457     deleteAndNull(mDayPicker);
       
   458     deleteAndNull(mHourPicker);
       
   459     deleteAndNull(mMinutePicker);
       
   460     deleteAndNull(mSecondPicker);
       
   461     deleteAndNull(mAmPmPicker);
       
   462 
       
   463     deleteAndNull(mYearModel);
       
   464     deleteAndNull(mDayModel);
       
   465     deleteAndNull(mMonthModel);
       
   466     deleteAndNull(mHourModel);
       
   467     deleteAndNull(mMinuteModel);
       
   468     deleteAndNull(mSecondModel);
       
   469     deleteAndNull(mAmPmModel);
       
   470 
       
   471     mYearOffset = -1;
       
   472     mMonthOffset = -1;
       
   473     mDayOffset = -1;
       
   474     mHourOffset = -1;
       
   475     mMinuteOffset = -1;
       
   476     mSecondOffset = -1;
       
   477 
       
   478     createDividers();
       
   479 
       
   480     //divider stuff
       
   481     //TODO: improve the divider addition and removal
       
   482     foreach(QGraphicsItem *item, mDividers) {
       
   483         HbFrameItem *fame = qgraphicsitem_cast<HbFrameItem *>(item);
       
   484         Q_ASSERT(fame); // WRONG USE OF PRIMITIVES - Please fix it
       
   485         mLayout->removeItem(fame);
       
   486         fame->setVisible(false);
       
   487     }
       
   488 
       
   489 
       
   490     //TODO: improve the divider addition and removal
       
   491     bool hasSeparator = mParser.mSectionNodes.count() > 1;
       
   492 
       
   493     for(int i=0;i<mParser.mSectionNodes.count();i++) {
       
   494 
       
   495         if(hasSeparator && (mLayout->count()>0)) {
       
   496             //TODO: improve the divider addition and removal
       
   497             HbFrameItem *f=static_cast<HbFrameItem*>(mDividers.at(i - 1));
       
   498             if(f) {
       
   499                 f->setVisible(true);
       
   500             }
       
   501             mLayout->addItem(mDividers.at(i - 1));
       
   502         }
       
   503 
       
   504         switch(mParser.mSectionNodes[i].type) {
       
   505             case HbDateTimeParser::AmPmSection:
       
   506                 mAmPmPicker = new HbTumbleView(q);
       
   507                 mAmPmModel = new QStringListModel(q);
       
   508                 mAmPmPicker->setModel(mAmPmModel);
       
   509                 mLayout->addItem(mAmPmPicker);
       
   510                 break;
       
   511             case HbDateTimeParser::DaySection:
       
   512             case HbDateTimeParser::DayOfWeekSection:
       
   513                 mDayPicker = new HbTumbleView(q);
       
   514                 mDayModel = new QStringListModel(q);
       
   515                 mDayPicker->setModel(mDayModel);
       
   516                 mLayout->addItem(mDayPicker);
       
   517                 break;
       
   518             case HbDateTimeParser::MonthSection:
       
   519                 mMonthPicker = new HbTumbleView(q);
       
   520                 mMonthModel = new QStringListModel(q);
       
   521                 mMonthPicker->setModel(mMonthModel);
       
   522                 mLayout->addItem(mMonthPicker);
       
   523                 break;
       
   524             case HbDateTimeParser::YearSection:
       
   525             case HbDateTimeParser::YearSection2Digits:
       
   526                 mYearPicker = new HbTumbleView(q);
       
   527                 mYearModel = new QStringListModel(q);
       
   528                 mYearPicker->setModel(mYearModel);
       
   529                 mLayout->addItem(mYearPicker);
       
   530                 break;
       
   531             case HbDateTimeParser::SecondSection:
       
   532                 mSecondPicker = new HbTumbleView(q);
       
   533                 mSecondModel = new QStringListModel(q);
       
   534                 mSecondPicker->setModel(mSecondModel);
       
   535                 mLayout->addItem(mSecondPicker);
       
   536                 break;
       
   537             case HbDateTimeParser::MinuteSection:
       
   538                 mMinutePicker = new HbTumbleView(q);
       
   539                 mMinuteModel = new QStringListModel(q);
       
   540                 mMinutePicker->setModel(mMinuteModel);
       
   541                 mLayout->addItem(mMinutePicker);
       
   542                 break;
       
   543             case HbDateTimeParser::Hour12Section:
       
   544             case HbDateTimeParser::Hour24Section:
       
   545                 mHourPicker = new HbTumbleView(q);
       
   546                 mHourModel = new QStringListModel(q);
       
   547                 mHourPicker->setModel(mHourModel);
       
   548                 mLayout->addItem(mHourPicker);
       
   549                 break;
       
   550             default:break;
       
   551         }
       
   552     }
       
   553     setRanges();
       
   554     makeConnections();
       
   555     syncVisualDate();
       
   556  //TODO:what to do with current date, should reset ?
       
   557 }
       
   558 
       
   559 void HbDateTimePickerPrivate::makeConnections()
       
   560 {
       
   561     Q_Q(HbDateTimePicker);
       
   562     bool b=false;
       
   563     if(mYearPicker) {
       
   564         b=QObject::connect(mYearPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_yearChanged(int)));
       
   565         Q_ASSERT(b);
       
   566     }
       
   567     if(mMonthPicker) {
       
   568         b=QObject::connect(mMonthPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_monthChanged(int)));
       
   569         Q_ASSERT(b);
       
   570     }
       
   571     if(mDayPicker) {
       
   572         b=QObject::connect(mDayPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_dayChanged(int)));
       
   573         Q_ASSERT(b);
       
   574     }
       
   575     if(mHourPicker) {
       
   576         b=QObject::connect(mHourPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_hoursChanged(int)));
       
   577         Q_ASSERT(b);
       
   578     }
       
   579     if(mMinutePicker) {
       
   580         b=QObject::connect(mMinutePicker,SIGNAL(itemSelected(int)),q,SLOT(_q_minutesChanged(int)));
       
   581         Q_ASSERT(b);
       
   582     }
       
   583     if(mSecondPicker) {
       
   584         b=QObject::connect(mSecondPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_secondsChanged(int)));
       
   585         Q_ASSERT(b);
       
   586     }
       
   587     if(mAmPmPicker) {
       
   588         b=QObject::connect(mAmPmPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_ampmChanged(int)));
       
   589         Q_ASSERT(b);
       
   590     }
       
   591     Q_UNUSED(b);
       
   592 }
       
   593 void HbDateTimePickerPrivate::removeConnections()
       
   594 {
       
   595     Q_Q(HbDateTimePicker);    
       
   596     if(mYearPicker) {
       
   597         QObject::disconnect(mYearPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_yearChanged(int)));
       
   598     }
       
   599     if(mMonthPicker) {
       
   600         QObject::disconnect(mMonthPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_monthChanged(int)));
       
   601     }
       
   602     if(mDayPicker) {
       
   603         QObject::disconnect(mDayPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_dayChanged(int)));
       
   604     }
       
   605     if(mHourPicker) {
       
   606         QObject::disconnect(mHourPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_hoursChanged(int)));
       
   607     }
       
   608     if(mMinutePicker) {
       
   609         QObject::disconnect(mMinutePicker,SIGNAL(itemSelected(int)),q,SLOT(_q_minutesChanged(int)));
       
   610     }
       
   611     if(mSecondPicker) {
       
   612         QObject::disconnect(mSecondPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_secondsChanged(int)));
       
   613     }
       
   614     if(mAmPmPicker) {
       
   615         QObject::disconnect(mAmPmPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_ampmChanged(int)));
       
   616     }
       
   617 }
       
   618 
       
   619 
       
   620 void HbDateTimePickerPrivate::setRanges() 
       
   621 {
       
   622     if(mIsTwoDigitYearFormat) {
       
   623         mYearOffset = mMinimumDate.date().year()%100;
       
   624         setYearRange(mMinimumDate.date().year()%100,mMaximumDate.date().year()%100); 
       
   625     } else {
       
   626         mYearOffset = mMinimumDate.date().year();
       
   627         setYearRange(mMinimumDate.date().year(),mMaximumDate.date().year()); 
       
   628     }
       
   629 
       
   630     mMonthOffset = 1;
       
   631     setMonthRange(1,12);//default all months
       
   632 
       
   633     mDayOffset = 1;
       
   634     setDayRange(1,31);//default all days
       
   635 
       
   636     mHourOffset = 0;
       
   637     setHourRange(0,23);
       
   638 
       
   639     mMinuteOffset = 0;
       
   640     setMinuteRange(0,59);
       
   641 
       
   642     mSecondOffset = 0;
       
   643     setSecondRange(0,59);
       
   644 
       
   645     setAmPm();
       
   646 }
       
   647 
       
   648 void HbDateTimePickerPrivate::syncVisualDate()
       
   649 {
       
   650     //no matter how good this is written , there always seems to be a gap
       
   651     //between visual and actual selected data. creating syncup with visual.
       
   652 
       
   653     int y=1,m=1,d=1,h=0,n=0,s=0;
       
   654 
       
   655     if(mYearPicker) {
       
   656         y = mYearOffset+mYearPicker->selected();
       
   657     }
       
   658     if(mMonthPicker) {
       
   659         m = mMonthOffset+mMonthPicker->selected();
       
   660     }
       
   661     if(mDayPicker) {
       
   662         d = mDayOffset +mDayPicker->selected();
       
   663     }
       
   664 
       
   665     if(mHourPicker) {
       
   666         h=mHourOffset+mHourPicker->selected();
       
   667     }
       
   668 
       
   669     if(mMinutePicker) {
       
   670         n=mMinuteOffset+mMinutePicker->selected();
       
   671     }
       
   672     if(mSecondPicker) {
       
   673         s=mSecondOffset+mSecondPicker->selected();
       
   674     }
       
   675     QDateTime dt(QDate(y,m,d),QTime(h,n,s));
       
   676     if(dt.isValid()) {
       
   677         mDateTime = dt;
       
   678     }
       
   679 }
       
   680 
       
   681 void HbDateTimePickerPrivate::emitDateChange()
       
   682 {
       
   683     Q_Q(HbDateTimePicker);
       
   684 
       
   685     emit q->dateChanged(mDateTime.date());
       
   686     emit q->dateTimeChanged(mDateTime);
       
   687 }
       
   688 
       
   689 void HbDateTimePickerPrivate::emitTimeChange()
       
   690 {
       
   691     Q_Q(HbDateTimePicker);
       
   692 
       
   693     emit q->timeChanged(mDateTime.time());
       
   694     emit q->dateTimeChanged(mDateTime);
       
   695 
       
   696 }
       
   697 void HbDateTimePickerPrivate::emitDateTimeChange()
       
   698 {
       
   699     Q_Q(HbDateTimePicker);
       
   700 
       
   701     emit q->dateChanged(mDateTime.date());
       
   702     emit q->timeChanged(mDateTime.time());
       
   703     emit q->dateTimeChanged(mDateTime);
       
   704 
       
   705 }
       
   706 
       
   707 
       
   708 void HbDateTimePickerPrivate::setDateTimeRange(const QDateTime &startdt,
       
   709         const QDateTime &enddt)
       
   710 {
       
   711     Q_Q(HbDateTimePicker);
       
   712     QDateTime start(startdt);
       
   713     QDateTime end(enddt);
       
   714     if(start.isValid() && end.isValid()) {
       
   715 
       
   716         removeConnections();
       
   717 
       
   718         //change the date range
       
   719         if(start.date() > end.date()) {
       
   720             end.setDate(start.date());
       
   721         }
       
   722         if(mIsTwoDigitYearFormat) {
       
   723             setYearRange(start.date().year()%100,end.date().year()%100);
       
   724         } else {
       
   725             setYearRange(start.date().year(),end.date().year());
       
   726         }
       
   727 
       
   728         //change the time range
       
   729         if(start.time() > end.time()) {
       
   730             end.setTime(start.time());
       
   731         }
       
   732         setHourRange(start.time().hour(),end.time().hour());
       
   733 
       
   734         mMinimumDate = start;
       
   735         mMaximumDate = end;
       
   736 
       
   737         //scroll to the clamped date
       
   738         bool dirty=false;
       
   739         if(mDateTime < mMinimumDate) {
       
   740             dirty = true;
       
   741             mDateTime = mMinimumDate;
       
   742         } else if(mDateTime > mMaximumDate) {
       
   743             dirty = true;
       
   744             mDateTime = mMaximumDate;
       
   745         }
       
   746         if(dirty) {
       
   747             setDateTime(mDateTime);
       
   748             //force the year change so month range gets set appropriately
       
   749             //TODO:fix after modularization of entire code
       
   750         }
       
   751 
       
   752         if(mYearPicker) {
       
   753             _q_yearChanged(mYearPicker->selected());
       
   754         }
       
   755 
       
   756         //force the hour change so minute range gets set appropriately
       
   757         if(mHourPicker) {
       
   758             _q_hoursChanged(mHourPicker->selected());
       
   759         }
       
   760 
       
   761         //emit the changes
       
   762         emit q->dateChanged(mDateTime.date());
       
   763         emit q->timeChanged(mDateTime.time());
       
   764         emit q->dateTimeChanged(mDateTime);          
       
   765 
       
   766         makeConnections();
       
   767     }
       
   768 }
       
   769 void HbDateTimePickerPrivate::setDateTime(const QDateTime &newDate)
       
   770 {
       
   771     QDateTime newDateTime(newDate);
       
   772     //TODO: validity and bounds check for selected
       
   773     if(newDateTime.isValid()) {
       
   774 
       
   775         //update the mem var
       
   776         if(newDateTime.date() < mMinimumDate.date()) {
       
   777             newDateTime.setDate(mMinimumDate.date());
       
   778         } else if(newDateTime.date() > mMaximumDate.date()) {
       
   779             newDateTime.setDate(mMaximumDate.date());
       
   780         }
       
   781 
       
   782         if(newDateTime.time() < mMinimumDate.time()) {
       
   783             newDateTime.setTime(mMinimumDate.time());
       
   784         }else if(newDateTime.time() > mMaximumDate.time()) {
       
   785             newDateTime.setTime(mMaximumDate.time());
       
   786         }
       
   787 
       
   788         //set the selections
       
   789         if(mYearPicker) {
       
   790 #ifdef HBDATETIMEPICKER_DEBUG
       
   791             qDebug() << "setDateTime: yearOffset=" << mYearOffset;
       
   792 #endif
       
   793             if(mIsTwoDigitYearFormat) {
       
   794                 mYearPicker->setSelected((newDateTime.date().year()%100)-mYearOffset);
       
   795             } else {
       
   796                 mYearPicker->setSelected(newDateTime.date().year()-mYearOffset);
       
   797             }
       
   798         }
       
   799         if(mMonthPicker) {
       
   800             mMonthPicker->setSelected(newDateTime.date().month()-mMonthOffset);
       
   801         }
       
   802         if(mDayPicker) {
       
   803             mDayPicker->setSelected(newDateTime.date().day()-mDayOffset);
       
   804         }
       
   805         if(mHourPicker) {
       
   806             mHourPicker->setSelected(newDateTime.time().hour()-mHourOffset);
       
   807         }
       
   808         if(mMinutePicker) {
       
   809             mMinutePicker->setSelected(newDateTime.time().minute()-mMinuteOffset);
       
   810         }
       
   811         if(mSecondPicker) {
       
   812 #ifdef HBDATETIMEPICKER_DEBUG
       
   813             qDebug() << "setDateTime before: secondOffset=" << mSecondOffset << " time=" << newDateTime.time();
       
   814 #endif
       
   815             mSecondPicker->setSelected(newDateTime.time().second()-mSecondOffset);
       
   816 #ifdef HBDATETIMEPICKER_DEBUG
       
   817             qDebug() << "setDateTime after: secondOffset=" << mSecondOffset << " time=" << newDateTime.time();
       
   818 #endif
       
   819         }
       
   820         mDateTime = newDateTime;
       
   821 
       
   822     }
       
   823 }
       
   824 void HbDateTimePickerPrivate::setMinimumDateTime(const QDateTime &newMinDateTime)
       
   825 {
       
   826     setDateTimeRange(newMinDateTime,mMaximumDate);
       
   827 }
       
   828 void HbDateTimePickerPrivate::setMaximumDateTime(const QDateTime &newMaxDateTime)
       
   829 {
       
   830     setDateTimeRange(mMinimumDate,newMaxDateTime);
       
   831 }
       
   832 
       
   833 
       
   834 void HbDateTimePickerPrivate::setYearRange(int start,int end)
       
   835 {
       
   836     if(!mYearPicker) {
       
   837         return;
       
   838     }
       
   839     //calculate the index it should be after resize
       
   840     //the currentIndex gets reset after the resize and gets set to 0
       
   841     //to work around that issue this is added
       
   842     int newIndex = mYearPicker->selected()-(start-mYearOffset);
       
   843     if(newIndex < 0) {
       
   844         newIndex = 0;
       
   845     }
       
   846     if(newIndex > (end-start)) {
       
   847         newIndex = end-start;
       
   848     }
       
   849 
       
   850 #ifdef HBDATETIMEPICKER_DEBUG
       
   851     qDebug() << "setyear range (" << start << "," << end << ")" ;
       
   852 #endif
       
   853 
       
   854 
       
   855 
       
   856     resizeModel(mYearModel, mYearOffset, 
       
   857         mYearOffset+mYearModel->rowCount()-1, start, 
       
   858         end, &HbDateTimePickerPrivate::localeYear);
       
   859 
       
   860     mYearOffset = start;
       
   861 
       
   862     mYearPicker->setSelected(newIndex);
       
   863 }
       
   864 
       
   865 void HbDateTimePickerPrivate::setMonthRange(int start,int end)
       
   866 {
       
   867     if(!mMonthPicker) {
       
   868         return;
       
   869     }
       
   870 #ifdef HBDATETIMEPICKER_DEBUG
       
   871     qDebug() << "setMonthRange: " << start << " ," << end;
       
   872 #endif
       
   873     //calculate the index it should be after resize
       
   874     //the currentIndex gets reset after the resize and gets set to 0
       
   875     //to work around that issue this is added
       
   876     int newIndex = mMonthPicker->selected()-(start-mMonthOffset);
       
   877     if(newIndex < 0) {
       
   878         newIndex = 0;
       
   879     }
       
   880     if(newIndex > (end-start)) {
       
   881         newIndex = end-start;
       
   882     }
       
   883     resizeModel(mMonthModel,
       
   884             mMonthOffset,mMonthOffset+mMonthModel->rowCount()-1,
       
   885             start,end,
       
   886             &HbDateTimePickerPrivate::localeMonth);
       
   887     mMonthOffset = start;
       
   888 
       
   889     mMonthPicker->setSelected(newIndex);
       
   890 
       
   891     //check if current month is valid
       
   892     if(mDateTime.date().month() < start) {
       
   893         mDateTime.setDate(QDate(mDateTime.date().year(),start,mDateTime.date().day()));
       
   894     }
       
   895     else if(mDateTime.date().month() > end) {
       
   896         mDateTime.setDate(QDate(mDateTime.date().year(),end,mDateTime.date().day()));
       
   897     }
       
   898 }
       
   899 
       
   900 
       
   901 void HbDateTimePickerPrivate::setDayRange(int start,int end)
       
   902 {
       
   903     if(!mDayPicker) {
       
   904         return;
       
   905     }
       
   906 #ifdef HBDATETIMEPICKER_DEBUG
       
   907     qDebug() << "setDayRange: " << start << " ," << end;
       
   908 #endif
       
   909     //calculate the index it should be after resize
       
   910     //the currentIndex gets reset after the resize and gets set to 0
       
   911     //to work around that issue this is added
       
   912     int newIndex = mDayPicker->selected()-(start-mDayOffset);
       
   913     if(newIndex < 0) {
       
   914         newIndex = 0;
       
   915     }
       
   916     if(newIndex > (end-start)) {
       
   917         newIndex = end-start;
       
   918     }
       
   919 
       
   920     resizeModel(mDayModel,
       
   921             mDayOffset,mDayOffset+mDayModel->rowCount()-1,
       
   922             start,end,
       
   923             &HbDateTimePickerPrivate::localeDay);
       
   924     mDayOffset = start;
       
   925 
       
   926     mDayPicker->setSelected(newIndex);
       
   927 
       
   928 
       
   929     //check if current day is valid
       
   930     if(mDateTime.date().day() < start) {
       
   931         mDateTime.setDate(QDate(mDateTime.date().year(),mDateTime.date().month(),start));
       
   932     }
       
   933     else if(mDateTime.date().day() > end) {
       
   934         mDateTime.setDate(QDate(mDateTime.date().year(),mDateTime.date().month(),end));
       
   935     }
       
   936 }
       
   937 
       
   938 void HbDateTimePickerPrivate::setHourRange(int start,int end)
       
   939 {
       
   940     
       
   941     if(!mHourPicker) {
       
   942         return;
       
   943     }
       
   944 #ifdef HBDATETIMEPICKER_DEBUG
       
   945     qDebug() << "setHourRange: " << start << " ," << end;
       
   946 #endif
       
   947     //calculate the index it should be after resize
       
   948     //the currentIndex gets reset after the resize and gets set to 0
       
   949     //to work around that issue this is added
       
   950     int newIndex = mHourPicker->selected()-(start-mHourOffset);
       
   951     if(newIndex < 0) {
       
   952         newIndex = 0;
       
   953     }
       
   954     if(newIndex > (end-start)) {
       
   955         newIndex = end-start;
       
   956     }
       
   957 
       
   958     resizeModel(mHourModel,
       
   959             mHourOffset,mHourOffset+mHourModel->rowCount()-1,
       
   960             start,end,
       
   961             &HbDateTimePickerPrivate::localeHour);
       
   962     mHourOffset = start;
       
   963 
       
   964     mHourPicker->setSelected(newIndex);
       
   965 
       
   966     //check if hour is valid
       
   967     if(mDateTime.time().hour() < start) {
       
   968         mDateTime.setTime(QTime(start,mDateTime.time().minute(),mDateTime.time().second()));
       
   969     }
       
   970     else if(mDateTime.time().hour() > end) {
       
   971         mDateTime.setTime(QTime(end,mDateTime.time().minute(),mDateTime.time().second()));
       
   972     }
       
   973 }
       
   974 void HbDateTimePickerPrivate::setMinuteRange(int start,int end)
       
   975 {
       
   976     
       
   977     if(!mMinutePicker) {
       
   978         return;
       
   979     }
       
   980 #ifdef HBDATETIMEPICKER_DEBUG
       
   981     qDebug() << "setMinuteRange: " << start << " ," << end;
       
   982 #endif
       
   983     //calculate the index it should be after resize
       
   984     //the currentIndex gets reset after the resize and gets set to 0
       
   985     //to work around that issue this is added
       
   986     int newIndex = mMinutePicker->selected()-(start-mMinuteOffset);
       
   987     if(newIndex < 0) {
       
   988         newIndex = 0;
       
   989     }
       
   990     if(newIndex > (end-start)) {
       
   991         newIndex = end-start;
       
   992     }
       
   993 
       
   994     resizeModel(mMinuteModel,
       
   995             mMinuteOffset,mMinuteOffset+mMinuteModel->rowCount()-1,
       
   996             start,end,
       
   997             &HbDateTimePickerPrivate::localeMinute);
       
   998     mMinuteOffset = start;
       
   999 
       
  1000     mMinutePicker->setSelected(newIndex);
       
  1001 
       
  1002     //check if minute is valid
       
  1003     if(mDateTime.time().minute() < start) {
       
  1004         mDateTime.setTime(QTime(mDateTime.time().hour(),start,mDateTime.time().second()));
       
  1005     }
       
  1006     else if(mDateTime.time().minute() > end) {
       
  1007         mDateTime.setTime(QTime(mDateTime.time().hour(),end,mDateTime.time().second()));
       
  1008     }
       
  1009 }
       
  1010 void HbDateTimePickerPrivate::setSecondRange(int start,int end)
       
  1011 {
       
  1012     
       
  1013     if(!mSecondPicker) {
       
  1014         return;
       
  1015     }
       
  1016 #ifdef HBDATETIMEPICKER_DEBUG
       
  1017     qDebug() << "setSecondRange: " << start << " ," << end;
       
  1018 #endif
       
  1019     //calculate the index it should be after resize
       
  1020     //the currentIndex gets reset after the resize and gets set to 0
       
  1021     //to work around that issue this is added
       
  1022     int newIndex = mSecondPicker->selected()-(start-mSecondOffset);
       
  1023     if(newIndex < 0) {
       
  1024         newIndex = 0;
       
  1025     }
       
  1026     if(newIndex > (end-start)) {
       
  1027         newIndex = end-start;
       
  1028     }
       
  1029 
       
  1030     resizeModel(mSecondModel,
       
  1031             mSecondOffset,mSecondOffset+mSecondModel->rowCount()-1,
       
  1032             start,end,
       
  1033             &HbDateTimePickerPrivate::localeSecond);
       
  1034     mSecondOffset = start;
       
  1035 
       
  1036     mSecondPicker->setSelected(newIndex);
       
  1037 
       
  1038     //check if second is valid
       
  1039     if(mDateTime.time().second() < start) {
       
  1040         mDateTime.setTime(QTime(mDateTime.time().hour(),mDateTime.time().minute(),start));
       
  1041     }
       
  1042     else if(mDateTime.time().second() > end) {
       
  1043         mDateTime.setTime(QTime(mDateTime.time().hour(),mDateTime.time().minute(),end));
       
  1044     }
       
  1045 }
       
  1046 
       
  1047 void HbDateTimePickerPrivate::setAmPm()
       
  1048 {
       
  1049     if(!mAmPmPicker) {
       
  1050         return;
       
  1051     }
       
  1052     //TODO: check if range has both am and pm
       
  1053     QStringList amList;
       
  1054     amList << localeAmPm(true) << localeAmPm(false);
       
  1055     mAmPmModel->setStringList(amList);
       
  1056 }
       
  1057 
       
  1058 QString HbDateTimePickerPrivate::localeYear(int year)
       
  1059 {
       
  1060     //TODO:locale and format stuff
       
  1061     if(mIsTwoDigitYearFormat) {
       
  1062         return mLocale.toString(QDate(1900+year,1,1),mYearFormat);//year 00 is invalid
       
  1063     }
       
  1064     return mLocale.toString(QDate(year,1,1),mYearFormat);
       
  1065 }
       
  1066 
       
  1067 QString HbDateTimePickerPrivate::localeMonth(int month)
       
  1068 {
       
  1069     return mLocale.toString(QDate(2000,month,1),mMonthFormat);
       
  1070 
       
  1071 }
       
  1072 QString HbDateTimePickerPrivate::localeDay(int day)
       
  1073 {
       
  1074     return mLocale.toString(QDate(2000,1,day),mDayFormat);
       
  1075 }
       
  1076 
       
  1077 QString HbDateTimePickerPrivate::localeHour(int hour)
       
  1078 {
       
  1079     if(mIs24HourFormat) {
       
  1080         return mLocale.toString(QTime(hour,0,0),mHourFormat);
       
  1081     } 
       
  1082 
       
  1083     QString hourStr=mLocale.toString(QTime(hour,0,0),QString("%1:%2").arg(mHourFormat).arg("ap"));
       
  1084     QStringList hourAm=hourStr.split(":");
       
  1085     if(hourAm.count() > 1) {
       
  1086         return hourAm.at(0);
       
  1087     }
       
  1088     return QString("Format Err");
       
  1089 }
       
  1090 
       
  1091 QString HbDateTimePickerPrivate::localeMinute(int minute)
       
  1092 {
       
  1093     return mLocale.toString(QTime(0,minute,0),mMinuteFormat);
       
  1094 }
       
  1095 
       
  1096 QString HbDateTimePickerPrivate::localeSecond(int second)
       
  1097 {
       
  1098     return mLocale.toString(QTime(0,0,second),mSecondFormat);
       
  1099 }
       
  1100 
       
  1101 QString HbDateTimePickerPrivate::localeAmPm(bool isAm)
       
  1102 {
       
  1103     QString text = isAm ? mLocale.amText() : mLocale.pmText();
       
  1104 #ifdef HB_TEXT_MEASUREMENT_UTILITY
       
  1105     if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) {
       
  1106         text.append(QChar(LOC_TEST_START));
       
  1107         text.append("qtl_datetimepicker_popup_ampm_sec");
       
  1108         text.append(QChar(LOC_TEST_END));
       
  1109     }
       
  1110 #endif
       
  1111     return text;
       
  1112 }
       
  1113 
       
  1114 
       
  1115 /* there are seven different models for seven pickers. insertion and removal
       
  1116    to each of the models to resize them its the same logic. but to populate the
       
  1117    data need the appropriate locale and format converted data. which is passed
       
  1118    as a function pointer instead of creating seven different QStringListModel derived
       
  1119    model classes with one interface/virtual fuction specialization.
       
  1120 */
       
  1121 void HbDateTimePickerPrivate::resizeModel(QStringListModel *model,
       
  1122             int oldStart, int oldEnd,
       
  1123             int newStart, int newEnd,
       
  1124             QString (HbDateTimePickerPrivate::*localeFunc)(int))
       
  1125 {
       
  1126     //if row count is zero, then insert from newEnd to newStart
       
  1127     if((model->rowCount() == 0) && (newEnd-newStart>=0)) {
       
  1128         //initialize condition
       
  1129         model->insertRows(0,newEnd-newStart+1);
       
  1130         for(int i=0;i<=newEnd-newStart;i++) {
       
  1131             QModelIndex index=model->index(i,0);
       
  1132             if(index.isValid()) {
       
  1133                 //model->setData(index,(this->*localeFunc)(i+newStart));//TODO:add a readable typedef
       
  1134                 QString text = (this->*localeFunc)(i+newStart);
       
  1135 #ifdef HB_TEXT_MEASUREMENT_UTILITY
       
  1136                 if ( localeFunc == &HbDateTimePickerPrivate::localeMonth &&
       
  1137                     HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) {
       
  1138                     text.append(QChar(LOC_TEST_START));
       
  1139                     text.append("qtl_datetimepicker_popup_month_sec");
       
  1140                     text.append(QChar(LOC_TEST_END));
       
  1141                 }
       
  1142 #endif
       
  1143                 model->setData(index,text);//TODO:add a readable typedef
       
  1144             }
       
  1145         }
       
  1146         return;
       
  1147     }
       
  1148 
       
  1149     if(newStart < oldStart) {
       
  1150         model->insertRows(0,oldStart-newStart);
       
  1151         for(int i=0;i<oldStart-newStart;++i) {
       
  1152             QModelIndex index=model->index(i,0);
       
  1153             if(index.isValid()) {
       
  1154                 model->setData(index,(this->*localeFunc)(i+newStart));
       
  1155             }
       
  1156         }
       
  1157     }
       
  1158     if(newEnd > oldEnd) {
       
  1159         int rowCount = model->rowCount(); 
       
  1160         model->insertRows(rowCount,newEnd-oldEnd);
       
  1161         for(int i=0;i<newEnd-oldEnd;++i) {
       
  1162             QModelIndex index=model->index(rowCount+i,0);
       
  1163             if(index.isValid()) {
       
  1164                 model->setData(index,(this->*localeFunc)(oldEnd+i+1));
       
  1165             }
       
  1166         }
       
  1167     }
       
  1168 
       
  1169     if(newStart > oldStart) {
       
  1170         model->removeRows(0,newStart-oldStart);
       
  1171     }
       
  1172 
       
  1173     if(oldEnd > newEnd) {
       
  1174         model->removeRows((model->rowCount()-(oldEnd-newEnd)),oldEnd-newEnd);
       
  1175     }
       
  1176 }
       
  1177 
       
  1178 void HbDateTimePickerPrivate::createPrimitives()
       
  1179 {
       
  1180     Q_Q(HbDateTimePicker);
       
  1181     if(!mBackground) {
       
  1182         mBackground = q->style()->createPrimitive(HbStyle::P_DateTimePicker_background,q);
       
  1183         q->style()->setItemName(mBackground,"background");
       
  1184     }
       
  1185     if(!mFrame) {
       
  1186         mFrame = q->style()->createPrimitive(HbStyle::P_DateTimePicker_frame,q);
       
  1187         q->style()->setItemName(mFrame,"frame");
       
  1188     }
       
  1189     createDividers();
       
  1190 }
       
  1191 
       
  1192 void HbDateTimePickerPrivate::createDividers()
       
  1193 {
       
  1194     Q_Q(HbDateTimePicker);
       
  1195     
       
  1196     if( mParser.mSectionNodes.count() == mDividers.count() ){
       
  1197         return;
       
  1198     }
       
  1199 
       
  1200     if( mParser.mSectionNodes.count() < mDividers.count() ){
       
  1201         for( int i = mParser.mSectionNodes.count() - 1; i > mDividers.count(); i--)
       
  1202         {
       
  1203             QPointer<QGraphicsWidget> item = mDividers.at(i);
       
  1204             mDividers.removeAt(i);
       
  1205             delete item;
       
  1206         }
       
  1207 
       
  1208         return;
       
  1209     }
       
  1210     else if( mParser.mSectionNodes.count() > mDividers.count() ){
       
  1211 
       
  1212         for(int i = mDividers.count();i < mParser.mSectionNodes.count(); i++) { //TODO: optimally create when required
       
  1213             QGraphicsItem *item=q->style()->createPrimitive(HbStyle::P_DateTimePicker_separator, mContent);
       
  1214             Q_ASSERT(item->isWidget());
       
  1215             q->style()->setItemName(item,"separator");
       
  1216             mDividers.append(static_cast<QGraphicsWidget *>(item));
       
  1217         }
       
  1218     }
       
  1219 }
       
  1220 
       
  1221 void HbDateTimePickerPrivate::updateDividers()
       
  1222 {
       
  1223     /*Q_Q(HbDateTimePicker);
       
  1224     HbStyleOption option;
       
  1225     q->initStyleOption(&option);
       
  1226     for(int i=0;i<qMin(mDividers.count(),mDividerIndex);i++) {
       
  1227         q->style()->updatePrimitive((QGraphicsItem*)mDividers.at(i),HbStyle::P_DateTimePicker_separator,&option);
       
  1228     }*/
       
  1229 
       
  1230     //TODO: improve the divider addition and removal
       
  1231 
       
  1232     //using the style update primitive crashes. need to investigate why
       
  1233 
       
  1234 }
       
  1235 
       
  1236 void HbDateTimePickerPrivate::_q_dayChanged(int index)
       
  1237 {
       
  1238 #ifdef HBDATETIMEPICKER_DEBUG
       
  1239     qDebug() << "_q_dayChanged:" << index;
       
  1240 #endif
       
  1241     QDate newDate(mDateTime.date().year(),mDateTime.date().month(),index+mDayOffset);
       
  1242     if(newDate.isValid()) {
       
  1243         mDateTime.setDate(newDate);
       
  1244 #ifdef HBDATETIMEPICKER_DEBUG
       
  1245         qDebug() << "dayChange:currentDate:" << mDateTime;
       
  1246 #endif
       
  1247     }
       
  1248     else {
       
  1249 #ifdef HBDATETIMEPICKER_DEBUG
       
  1250         qDebug() << "got invalid day change:" << index;
       
  1251 #endif
       
  1252         return;
       
  1253     }
       
  1254 
       
  1255     emitDateChange();
       
  1256 
       
  1257     Q_UNUSED(index);
       
  1258 }
       
  1259 
       
  1260 void HbDateTimePickerPrivate::_q_monthChanged(int index)
       
  1261 {
       
  1262 #ifdef HBDATETIMEPICKER_DEBUG
       
  1263     qDebug() << "_q_monthChanged:" << index;
       
  1264 #endif
       
  1265     QDate newDate(mDateTime.date());
       
  1266     if(mMonthOffset >= 0) {
       
  1267 #ifdef HBDATETIMEPICKER_DEBUG
       
  1268         qDebug() << "month: before:" << newDate << " ,off-ind:" << newDate.month()-mMonthOffset << "-" << index;
       
  1269 #endif
       
  1270         newDate = newDate.addMonths(index+mMonthOffset-newDate.month());
       
  1271 #ifdef HBDATETIMEPICKER_DEBUG
       
  1272         qDebug() << "month: after:" << newDate;
       
  1273 #endif
       
  1274     }else {
       
  1275 #ifdef HBDATETIMEPICKER_DEBUG
       
  1276         qDebug() << "month: before else:" << newDate;
       
  1277 #endif
       
  1278         newDate = newDate.addMonths(index);
       
  1279 #ifdef HBDATETIMEPICKER_DEBUG
       
  1280         qDebug() << "month: after else:" << newDate;
       
  1281 #endif
       
  1282     }
       
  1283     if(newDate.isValid()) {
       
  1284         mDateTime.setDate(newDate);
       
  1285 #ifdef HBDATETIMEPICKER_DEBUG
       
  1286         qDebug() << "monthChange:currentDate:" << mDateTime << " ind:" << index;
       
  1287 #endif
       
  1288     }
       
  1289     else {
       
  1290 #ifdef HBDATETIMEPICKER_DEBUG
       
  1291         qDebug() << "got invalid month change:" << index;
       
  1292         qDebug() << "got invalid month change:" << mMonthOffset;
       
  1293 #endif
       
  1294         return;
       
  1295     }
       
  1296 
       
  1297     //check if day range changed
       
  1298     if(mDayPicker) {
       
  1299         int start=mDayOffset;
       
  1300         int end=mDayOffset+mDayModel->rowCount()-1;
       
  1301         if(isMinimumYear() && isMinimumMonth()) {
       
  1302             start = mMinimumDate.date().day();
       
  1303         } else {
       
  1304             start = 1;
       
  1305         }
       
  1306         if(isMaximumYear() && isMaximumMonth()) {
       
  1307             end = mMaximumDate.date().day();
       
  1308         } else {
       
  1309             end = mDateTime.date().daysInMonth();
       
  1310         }
       
  1311 
       
  1312         //set if dayrange changed
       
  1313         if((start != mDayOffset)
       
  1314                 ||(end !=mDayOffset+mDayModel->rowCount()-1)) {
       
  1315             setDayRange(start,end);
       
  1316         }
       
  1317     }
       
  1318 
       
  1319     emitDateChange();
       
  1320 }
       
  1321 
       
  1322 void HbDateTimePickerPrivate::_q_yearChanged(int index)
       
  1323 {
       
  1324     qDebug() << "_q_yearChanged:" << index;
       
  1325     //Q_Q(HbDateTimePicker);
       
  1326     QDate newDate(mDateTime.date());
       
  1327     if(mIsTwoDigitYearFormat) {
       
  1328         newDate = newDate.addYears(index+mYearOffset-(newDate.year()%100));
       
  1329     }
       
  1330     else {
       
  1331         newDate = newDate.addYears(index+mYearOffset-newDate.year());
       
  1332     }
       
  1333     if(newDate.isValid()) {
       
  1334 #ifdef HBDATETIMEPICKER_DEBUG
       
  1335         qDebug() << "yearChange:currentDate before:" << mDateTime << " ind:" << index << " yeOff:" << mYearOffset;
       
  1336 #endif
       
  1337         mDateTime.setDate(newDate);
       
  1338 #ifdef HBDATETIMEPICKER_DEBUG
       
  1339         qDebug() << "yearChange:currentDate:" << mDateTime << " ind:" << index;
       
  1340 #endif
       
  1341     }
       
  1342     else {
       
  1343 #ifdef HBDATETIMEPICKER_DEBUG
       
  1344         qDebug() << "got invalid month change:" << index;
       
  1345         qDebug() << "got invalid month change:" << mMonthOffset;
       
  1346 #endif
       
  1347         return;
       
  1348     }
       
  1349 
       
  1350     //check if month range changed
       
  1351     int start=0,end=0;
       
  1352     if(mMonthPicker) {
       
  1353         start=mMonthOffset;
       
  1354         end=start+mMonthModel->rowCount()-1;
       
  1355         if(isMinimumYear())  {
       
  1356             start = mMinimumDate.date().month();
       
  1357         } else {
       
  1358             start = 1;
       
  1359         }
       
  1360 
       
  1361         if(isMaximumYear()) {
       
  1362             end = mMaximumDate.date().month();
       
  1363         } else {
       
  1364             end = 12;
       
  1365         }
       
  1366 
       
  1367         //set if range changed
       
  1368         if((start != mMonthOffset)
       
  1369                 || (end != mMonthModel->rowCount()-1)) {
       
  1370             setMonthRange(start,end);
       
  1371         }
       
  1372 
       
  1373     }
       
  1374     
       
  1375     //check if day range changed
       
  1376     if(mDayPicker) {
       
  1377         int start=mDayOffset;
       
  1378         int end=mDayOffset+mDayModel->rowCount()-1;
       
  1379         if(isMinimumYear() && isMinimumMonth()) {
       
  1380             start = mMinimumDate.date().day();
       
  1381         } else {
       
  1382             start = 1;
       
  1383         }
       
  1384         if(isMaximumYear() && isMaximumMonth()) {
       
  1385             end = mMaximumDate.date().day();
       
  1386         } else {
       
  1387             end = mDateTime.date().daysInMonth();
       
  1388         }
       
  1389 
       
  1390         //set if dayrange changed
       
  1391         if((start != mDayOffset)
       
  1392                 ||(end !=mDayOffset+mDayModel->rowCount()-1)) {
       
  1393             setDayRange(start,end);
       
  1394         }
       
  1395     }
       
  1396 
       
  1397     emitDateChange();
       
  1398 
       
  1399 }
       
  1400 
       
  1401 void HbDateTimePickerPrivate::_q_hoursChanged(int index)
       
  1402 {
       
  1403 #ifdef HBDATETIMEPICKER_DEBUG
       
  1404     qDebug() << "_q_hoursChanged:" << index;
       
  1405 #endif
       
  1406     QTime newTime(mHourOffset+index,mDateTime.time().minute(),mDateTime.time().second());
       
  1407     if(newTime.isValid()) {
       
  1408         mDateTime.setTime(newTime);
       
  1409     }
       
  1410     else {
       
  1411 #ifdef HBDATETIMEPICKER_DEBUG
       
  1412         qDebug() << "got invalid hour change:" << index;
       
  1413         qDebug() << "got invalid hour change offset:" << mHourOffset;
       
  1414 #endif
       
  1415         return;
       
  1416     }
       
  1417 
       
  1418     //check if minute range changed
       
  1419     int start=0,end=0;
       
  1420     if(mMinutePicker) {
       
  1421         start=mMinuteOffset;
       
  1422         end=start+mMinuteModel->rowCount()-1;
       
  1423         if(isMinimumHour())  {
       
  1424             start = mMinimumDate.time().minute();
       
  1425         } else {
       
  1426             start = 0;
       
  1427         }
       
  1428         if(isMaximumHour()) {
       
  1429             end = mMaximumDate.time().minute();
       
  1430         } else {
       
  1431             end = 59;
       
  1432         }
       
  1433 
       
  1434         //set if range changed
       
  1435         if((start != mMinuteOffset)
       
  1436                 || (end != start+mMinuteModel->rowCount()-1)) {
       
  1437             setMinuteRange(start,end);
       
  1438         }
       
  1439 
       
  1440     }
       
  1441     
       
  1442     //check if seconds range changed
       
  1443     if(mSecondPicker) {
       
  1444         start=mSecondOffset;
       
  1445         end=mSecondOffset+mSecondModel->rowCount()-1;
       
  1446         if(isMinimumHour() && isMinimumMinute()) {
       
  1447             start = mMinimumDate.time().second();
       
  1448         } else {
       
  1449             start = 0;
       
  1450         }
       
  1451         if(isMaximumHour() && isMaximumMinute()) {
       
  1452             end = mMaximumDate.time().second();
       
  1453         } else {
       
  1454             end = 59;
       
  1455         }
       
  1456 
       
  1457         //set if seconds range changed
       
  1458         if((start != mSecondOffset)
       
  1459                 ||(end !=mSecondOffset+mSecondModel->rowCount()-1)) {
       
  1460             setSecondRange(start,end);
       
  1461         }
       
  1462     }
       
  1463 
       
  1464     //check if am or pm and scroll to respective time
       
  1465     if((!mIs24HourFormat) && mAmPmPicker) {
       
  1466         if(mAmPmPicker->selected() == 0) {
       
  1467             //is AM
       
  1468             if(mDateTime.time().hour() > 11) {
       
  1469                 mAmPmPicker->setSelected(1);
       
  1470             }
       
  1471         } else if(mAmPmPicker->selected() == 1) {
       
  1472             //is PM
       
  1473             if(mDateTime.time().hour() < 12) {
       
  1474                 mAmPmPicker->setSelected(0);
       
  1475             }
       
  1476         }
       
  1477     }
       
  1478 
       
  1479     emitTimeChange();
       
  1480 }
       
  1481 
       
  1482 void HbDateTimePickerPrivate::_q_minutesChanged(int index)
       
  1483 {
       
  1484 #ifdef HBDATETIMEPICKER_DEBUG
       
  1485     qDebug() << "_q_minutesChanged:" << index;
       
  1486 #endif
       
  1487     QTime newTime(mDateTime.time().hour(),mMinuteOffset+index,mDateTime.time().second());
       
  1488     if(newTime.isValid()) {
       
  1489         mDateTime.setTime(newTime);
       
  1490     }
       
  1491     else {
       
  1492 #ifdef HBDATETIMEPICKER_DEBUG
       
  1493         qDebug() << "got invalid minute change:" << index;
       
  1494         qDebug() << "got invalid minute change offset:" << mMinuteOffset;
       
  1495 #endif
       
  1496         return;
       
  1497     }
       
  1498 
       
  1499     int start,end;
       
  1500     //check if seconds range changed
       
  1501     if(mSecondPicker) {
       
  1502         start=mSecondOffset;
       
  1503         end=mSecondOffset+mSecondModel->rowCount()-1;
       
  1504         if(isMinimumHour() && isMinimumMinute()) {
       
  1505             start = mMinimumDate.time().second();
       
  1506         } else {
       
  1507             start = 0;
       
  1508         }
       
  1509         if(isMaximumHour() && isMaximumMinute()) {
       
  1510             end = mMaximumDate.time().second();
       
  1511         } else {
       
  1512             end = 59;
       
  1513         }
       
  1514 
       
  1515         //set if seconds range changed
       
  1516         if((start != mSecondOffset)
       
  1517                 ||(end !=mSecondOffset+mSecondModel->rowCount()-1)) {
       
  1518             setSecondRange(start,end);
       
  1519         }
       
  1520     }
       
  1521 
       
  1522     emitTimeChange();
       
  1523 }
       
  1524 
       
  1525 void HbDateTimePickerPrivate::_q_secondsChanged(int index)
       
  1526 {
       
  1527 #ifdef HBDATETIMEPICKER_DEBUG
       
  1528     qDebug() << "_q_secondsChanged:" << index;
       
  1529 #endif
       
  1530     QTime newTime(mDateTime.time().hour(),mDateTime.time().minute(),mSecondOffset+index);
       
  1531     if(newTime.isValid()) {
       
  1532         mDateTime.setTime(newTime);
       
  1533     }
       
  1534     else {
       
  1535 #ifdef HBDATETIMEPICKER_DEBUG
       
  1536         qDebug() << "got invalid second change:" << index;
       
  1537         qDebug() << "got invalid second change offset:" << mSecondOffset;
       
  1538 #endif
       
  1539         return;
       
  1540     }
       
  1541 
       
  1542 
       
  1543     emitTimeChange();
       
  1544 }
       
  1545 
       
  1546 void HbDateTimePickerPrivate::_q_ampmChanged(int index)
       
  1547 {
       
  1548     
       
  1549 #ifdef HBDATETIMEPICKER_DEBUG
       
  1550     qDebug() << "_q_ampmChanged:" << index;
       
  1551 #endif
       
  1552     if(index == 0) {
       
  1553         //AM is chosen 
       
  1554         QTime newTime(mDateTime.time().hour()-12,mDateTime.time().minute(),mDateTime.time().second());
       
  1555         if(newTime.isValid()) {
       
  1556             if(newTime >= mMinimumDate.time()) {
       
  1557                 mDateTime.setTime(newTime);
       
  1558                 if(mHourPicker) {
       
  1559                     mHourPicker->setSelected(newTime.hour()-mHourOffset);
       
  1560                 }
       
  1561                 emitTimeChange();
       
  1562             }else {
       
  1563                 mAmPmPicker->setSelected(1);//invalid so scrollback
       
  1564             }
       
  1565 
       
  1566         }  
       
  1567     } else if(index == 1) {
       
  1568         //PM is chosen
       
  1569         QTime newTime(mDateTime.time().hour()+12,mDateTime.time().minute(),mDateTime.time().second());
       
  1570         if(newTime.isValid()) {
       
  1571             if(newTime <= mMaximumDate.time()) {
       
  1572                 mDateTime.setTime(newTime);
       
  1573                 if(mHourPicker) {
       
  1574                     mHourPicker->setSelected(newTime.hour()-mHourOffset);
       
  1575                 } 
       
  1576                 emitTimeChange();
       
  1577             } else { 
       
  1578                 mAmPmPicker->setSelected(0);//invalid so scrollback
       
  1579             }
       
  1580         } 
       
  1581     }
       
  1582 }