src/hbwidgets/widgets/hbdatetimepicker_p.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbwidgets/widgets/hbdatetimepicker_p.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,1582 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (developer.feedback@nokia.com)
+**
+** This file is part of the HbWidgets module of the UI Extensions for Mobile.
+**
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at developer.feedback@nokia.com.
+**
+****************************************************************************/
+
+#include "hbdatetimepicker_p.h"
+#include "hbdatetimepicker.h"
+#include "hbstyleoption.h"
+#include "hbfeaturemanager_p.h"
+
+//TODO:remove frameitem dependency
+#include "hbframeitem.h"
+
+#include <QStringListModel>
+#include <QGraphicsLinearLayout>
+#include <QModelIndex>
+#include <QDate>
+#include <QLocale>
+#include <QDebug>
+#include <QStringListModel>
+#include <QPointer>
+
+#define HBDATETIMEPICKER_DEBUG
+
+//////////HbDateTimeParser - Implementaion may change in future.//////////////
+
+static inline int countRepeat(const QString &str, int index, int maxCount)
+{
+    int count = 1;
+    const QChar ch(str.at(index));
+    const int max = qMin(index + maxCount, str.size());
+    while (index + count < max && str.at(index + count) == ch) {
+        ++count;
+    }
+    return count;
+}
+
+static QString unquote(const QString &str)
+{
+    const QChar quote(QLatin1Char('\''));
+    const QChar slash(QLatin1Char('\\'));
+    const QChar zero(QLatin1Char('0'));
+    QString ret;
+    QChar status(zero);
+    const int max = str.size();
+    for (int i=0; i<max; ++i) { 
+        if (str.at(i) == quote) {
+            if (status != quote) {
+                status = quote;
+            } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
+                ret[ret.size() - 1] = quote;
+            } else {
+                status = zero;
+            }
+        } else {
+            ret += str.at(i);
+        }
+    }
+    return ret;
+}
+
+static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
+{
+    QString str(string.mid(from, size));
+    if (lastQuote >= from)
+        str = unquote(str);
+    list->append(str);
+}
+
+bool HbDateTimeParser::parseFormat(const QString &format)
+{
+    const QLatin1Char quote('\'');
+    const QLatin1Char slash('\\');
+    const QLatin1Char zero('0');
+
+    if (format == mDisplayFormat && !format.isEmpty()) {
+        return true;
+    }
+
+    QVector<SectionNode> newSectionNodes;
+    Sections newDisplay = 0;
+    QStringList newSeparators;
+    int i, index = 0;
+    int add = 0;
+    QChar status(zero);
+    const int max = format.size();
+    int lastQuote = -1;
+    for (i = 0; i<max; ++i) {
+        if (format.at(i) == quote) {
+            lastQuote = i;
+            ++add;
+            if (status != quote) {
+                status = quote;
+            } else if (format.at(i - 1) != slash) {
+                status = zero;
+            }
+        } else if (status != quote) {
+            const char sect = format.at(i).toLatin1();
+            switch (sect) {
+            case 'H':
+            case 'h':
+                {
+                    const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
+                    const SectionNode sn = { hour, i - add, countRepeat(format, i, 2) };
+                    newSectionNodes.append(sn);
+                    appendSeparator(&newSeparators, format, index, i - index, lastQuote);
+                    i += sn.count - 1;
+                    index = i + 1;
+                    newDisplay |= hour;
+                }
+                break;
+            case 'm':
+                {
+                    const SectionNode sn = { MinuteSection, i - add, countRepeat(format, i, 2) };
+                    newSectionNodes.append(sn);
+                    appendSeparator(&newSeparators, format, index, i - index, lastQuote);
+                    i += sn.count - 1;
+                    index = i + 1;
+                    newDisplay |= MinuteSection;
+                }
+                break;
+            case 's':
+                {
+                    const SectionNode sn = { SecondSection, i - add, countRepeat(format, i, 2) };
+                    newSectionNodes.append(sn);
+                    appendSeparator(&newSeparators, format, index, i - index, lastQuote);
+                    i += sn.count - 1;
+                    index = i + 1;
+                    newDisplay |= SecondSection;
+                }
+                break;
+
+            case 'z':
+                {
+                    const SectionNode sn = { MSecSection, i - add, countRepeat(format, i, 3) < 3 ? 1 : 3 };
+                    newSectionNodes.append(sn);
+                    appendSeparator(&newSeparators, format, index, i - index, lastQuote);
+                    i += sn.count - 1;
+                    index = i + 1;
+                    newDisplay |= MSecSection;
+                }
+                break;
+            case 'A':
+            case 'a':
+                {
+                    const bool cap = (sect == 'A');
+                    const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0) };
+                    newSectionNodes.append(sn);
+                    appendSeparator(&newSeparators, format, index, i - index, lastQuote);
+                    newDisplay |= AmPmSection;
+                    if (i + 1 < format.size()
+                        && format.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
+                            ++i;
+                    }
+                    index = i + 1;
+                }
+                break;
+            case 'y':
+                {
+                    const int repeat = countRepeat(format, i, 4);
+                    if (repeat >= 2) {
+                        const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
+                            i - add, repeat == 4 ? 4 : 2 };
+                        newSectionNodes.append(sn);
+                        appendSeparator(&newSeparators, format, index, i - index, lastQuote);
+                        i += sn.count - 1;
+                        index = i + 1;
+                        newDisplay |= sn.type;
+                    }
+                }
+                break;
+            case 'M':
+                {
+                    const SectionNode sn = { MonthSection, i - add, countRepeat(format, i, 4) };
+                    newSectionNodes.append(sn);
+                    newSeparators.append(unquote(format.mid(index, i - index)));
+                    i += sn.count - 1;
+                    index = i + 1;
+                    newDisplay |= MonthSection;
+                }
+                break;
+            case 'd':
+                {
+                    const int repeat = countRepeat(format, i, 4);
+                    const SectionNode sn = { repeat >= 3 ? DayOfWeekSection : DaySection, i - add, repeat };
+                    newSectionNodes.append(sn);
+                    appendSeparator(&newSeparators, format, index, i - index, lastQuote);
+                    i += sn.count - 1;
+                    index = i + 1;
+                    newDisplay |= sn.type;
+                }
+                break;
+
+            default:
+                break;
+            }
+        }
+    }
+
+    if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
+        const int max = newSectionNodes.size();
+        for (int i=0; i<max; ++i) {
+            SectionNode &node = newSectionNodes[i];
+            if (node.type == Hour12Section)
+                node.type = Hour24Section;
+        }
+    }
+
+    if (index < format.size()) {
+        appendSeparator(&newSeparators, format, index, index - max, lastQuote);
+    } else {
+        newSeparators.append(QString());
+    }
+
+    mDisplayFormat = format;
+    mSeparators = newSeparators;
+    mSectionNodes = newSectionNodes;
+    mDisplaySections = newDisplay;
+    
+    return true;
+}
+
+int HbDateTimeParser::sectionSize(int sectionIndex) const
+{
+    if (sectionIndex < 0)
+        return 0;
+
+    if (sectionIndex >= mSectionNodes.size()) {
+        qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
+        return -1;
+    }
+    if (sectionIndex == mSectionNodes.size() - 1) {
+        return mDisplayFormat.size() - sectionPos(sectionIndex) - mSeparators.last().size();
+    } else {
+        return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
+            - mSeparators.at(sectionIndex + 1).size();
+    }
+}
+
+int HbDateTimeParser::sectionPos(int sectionIndex) const
+{
+    return sectionPos(sectionNode(sectionIndex));
+}
+
+int HbDateTimeParser::sectionPos(const SectionNode &sn) const
+{
+    if (sn.pos == -1) {
+        return -1;
+    }
+
+    return sn.pos;
+}
+
+const HbDateTimeParser::SectionNode &HbDateTimeParser::sectionNode(int sectionIndex) const
+{
+    return mSectionNodes.at(sectionIndex);
+}
+/////////////////////////////////////////////////
+
+
+HbDateTimePickerPrivate::HbDateTimePickerPrivate()
+:HbWidgetPrivate()
+    ,mDayPicker(0)
+    ,mMonthPicker(0)
+    ,mYearPicker(0)
+    ,mHourPicker(0)
+    ,mMinutePicker(0)
+    ,mSecondPicker(0)
+    ,mAmPmPicker(0)
+    ,mDayModel(0)
+    ,mMonthModel(0)
+    ,mYearModel(0)
+    ,mHourModel(0)
+    ,mMinuteModel(0)
+    ,mSecondModel(0)
+    ,mAmPmModel(0)
+    ,mYearOffset(-1)
+    ,mMonthOffset(-1)
+    ,mDayOffset(-1)
+    ,mHourOffset(-1)
+    ,mMinuteOffset(-1)
+    ,mSecondOffset(-1)
+    ,mDateTime(QDateTime::currentDateTime())
+    ,mDateTimeMode(QVariant::Date) //default is date mode
+    ,mLayout(0)         
+    //,mFormat() //set the format again in init()
+    //,mDisplaySecions() //is blank by default
+    ,mParser()
+    ,mYearFormat()
+    ,mMonthFormat()
+    ,mDayFormat()
+    ,mHourFormat()
+    ,mMinuteFormat()
+    ,mSecondFormat() 
+    ,mIs24HourFormat(false)
+    ,mIsTwoDigitYearFormat(false)
+    ,mBackground(0)
+    ,mFrame(0)
+    ,mContent(0)
+{
+    mMinimumDate = HBDATETIMEPICKER_DATETIME_MIN;
+    mMaximumDate = HBDATETIMEPICKER_DATETIME_MAX;
+    mDateTime = mMinimumDate;
+}
+
+HbDateTimePickerPrivate::~HbDateTimePickerPrivate()
+{
+    QGraphicsLayoutItem *item;
+    foreach(item,mDividers)
+    {
+        mLayout->removeItem(item);
+        delete item;
+    }
+}
+
+/*
+   called only once. while the widget is constructing.
+*/
+
+void HbDateTimePickerPrivate::init(QVariant::Type dateTimeMode)
+{
+    Q_Q(HbDateTimePicker);
+
+    //create base content widget which contains the tumble views
+    mContent=new HbWidget(q);
+    mLayout = new QGraphicsLinearLayout(Qt::Horizontal);
+    mLayout->setSpacing(0);
+    mLayout->setContentsMargins(0,0,0,0);
+    mContent->setLayout(mLayout);
+    q->style()->setItemName(mContent,"content");
+
+    mDateTimeMode = dateTimeMode;
+
+    //read the format from locale
+    mFormat = localeDateTimeFormat(dateTimeMode);
+
+    //parse the format and set the sections in order
+    parseDisplayFormat(mFormat);
+
+    mDividers.clear();
+
+    //create the dividers used in rearrangeTumbleViews
+    createPrimitives();
+
+    //recreate and rearrange depending on the format
+    rearrangeTumbleViews();
+}
+
+/*!
+  \internal
+
+  Getting the format from the local settings.
+*/
+QString HbDateTimePickerPrivate::localeDateTimeFormat(const QVariant::Type &dateTimeMode)
+{
+    if(dateTimeMode == QVariant::Date) {
+        return mLocale.dateFormat(QLocale::ShortFormat);
+    } else if(dateTimeMode == QVariant::Time) {
+        return mLocale.timeFormat(QLocale::ShortFormat);
+    }
+    return mLocale.dateTimeFormat(QLocale::ShortFormat);
+}
+
+bool HbDateTimePickerPrivate::isFormatValid(const QString &newDisplayFormat)
+{
+    if(newDisplayFormat == mFormat) {
+        return false;
+    }
+    return true;
+}
+
+/* 
+   this will reset the display sections and re add them in order
+   mentioned in the display format passed. this also sets the mIs24HourFormat var.
+*/
+void HbDateTimePickerPrivate::parseDisplayFormat(const QString &format)
+{
+    if(mParser.parseFormat(format)) {
+        for(int i=0;i<mParser.mSectionNodes.count();++i) {
+            switch(mParser.mSectionNodes[i].type) {
+                case HbDateTimeParser::DaySection:
+                case HbDateTimeParser::DayOfWeekSection:
+                    mDayFormat = QString(mParser.mSectionNodes[i].count,'d');
+                    break;
+
+                case HbDateTimeParser::MonthSection:
+                    mMonthFormat = QString(mParser.mSectionNodes[i].count,'M');
+                    break;
+
+                case HbDateTimeParser::YearSection:
+                    mIsTwoDigitYearFormat = false;
+                    mYearFormat = QString(mParser.mSectionNodes[i].count,'y');
+                    break;
+
+                case HbDateTimeParser::YearSection2Digits:
+                    mIsTwoDigitYearFormat = true;
+                    mYearFormat = QString(mParser.mSectionNodes[i].count,'y');
+                    break;
+
+                case HbDateTimeParser::SecondSection:
+                    mSecondFormat = QString(mParser.mSectionNodes[i].count,'s');
+                    break;
+
+                case HbDateTimeParser::MinuteSection:
+                    mMinuteFormat = QString(mParser.mSectionNodes[i].count,'m');
+                    break;
+
+                case HbDateTimeParser::Hour12Section:
+                    mIs24HourFormat = false;
+                    mHourFormat = QString(mParser.mSectionNodes[i].count,'h');
+                    break;
+
+                case HbDateTimeParser::Hour24Section:
+                    mIs24HourFormat = true;
+                    mHourFormat = QString(mParser.mSectionNodes[i].count,'h');
+                    break;
+
+                default:
+                    break;
+                    /*case HbDateTimeParser::DayOfWeekSection: not supported */
+            }
+        }
+    }
+}
+
+/*
+   this is called whenever the setDisplayFormat changes.
+   function deletes all tumbleviews which currently exist and
+   it creates the ones which are required and makes the connections.
+*/
+void HbDateTimePickerPrivate::rearrangeTumbleViews()
+{                  
+    Q_Q(HbDateTimePicker);
+
+    deleteAndNull(mYearPicker);
+    deleteAndNull(mMonthPicker);
+    deleteAndNull(mDayPicker);
+    deleteAndNull(mHourPicker);
+    deleteAndNull(mMinutePicker);
+    deleteAndNull(mSecondPicker);
+    deleteAndNull(mAmPmPicker);
+
+    deleteAndNull(mYearModel);
+    deleteAndNull(mDayModel);
+    deleteAndNull(mMonthModel);
+    deleteAndNull(mHourModel);
+    deleteAndNull(mMinuteModel);
+    deleteAndNull(mSecondModel);
+    deleteAndNull(mAmPmModel);
+
+    mYearOffset = -1;
+    mMonthOffset = -1;
+    mDayOffset = -1;
+    mHourOffset = -1;
+    mMinuteOffset = -1;
+    mSecondOffset = -1;
+
+    createDividers();
+
+    //divider stuff
+    //TODO: improve the divider addition and removal
+    foreach(QGraphicsItem *item, mDividers) {
+        HbFrameItem *fame = qgraphicsitem_cast<HbFrameItem *>(item);
+        Q_ASSERT(fame); // WRONG USE OF PRIMITIVES - Please fix it
+        mLayout->removeItem(fame);
+        fame->setVisible(false);
+    }
+
+
+    //TODO: improve the divider addition and removal
+    bool hasSeparator = mParser.mSectionNodes.count() > 1;
+
+    for(int i=0;i<mParser.mSectionNodes.count();i++) {
+
+        if(hasSeparator && (mLayout->count()>0)) {
+            //TODO: improve the divider addition and removal
+            HbFrameItem *f=static_cast<HbFrameItem*>(mDividers.at(i - 1));
+            if(f) {
+                f->setVisible(true);
+            }
+            mLayout->addItem(mDividers.at(i - 1));
+        }
+
+        switch(mParser.mSectionNodes[i].type) {
+            case HbDateTimeParser::AmPmSection:
+                mAmPmPicker = new HbTumbleView(q);
+                mAmPmModel = new QStringListModel(q);
+                mAmPmPicker->setModel(mAmPmModel);
+                mLayout->addItem(mAmPmPicker);
+                break;
+            case HbDateTimeParser::DaySection:
+            case HbDateTimeParser::DayOfWeekSection:
+                mDayPicker = new HbTumbleView(q);
+                mDayModel = new QStringListModel(q);
+                mDayPicker->setModel(mDayModel);
+                mLayout->addItem(mDayPicker);
+                break;
+            case HbDateTimeParser::MonthSection:
+                mMonthPicker = new HbTumbleView(q);
+                mMonthModel = new QStringListModel(q);
+                mMonthPicker->setModel(mMonthModel);
+                mLayout->addItem(mMonthPicker);
+                break;
+            case HbDateTimeParser::YearSection:
+            case HbDateTimeParser::YearSection2Digits:
+                mYearPicker = new HbTumbleView(q);
+                mYearModel = new QStringListModel(q);
+                mYearPicker->setModel(mYearModel);
+                mLayout->addItem(mYearPicker);
+                break;
+            case HbDateTimeParser::SecondSection:
+                mSecondPicker = new HbTumbleView(q);
+                mSecondModel = new QStringListModel(q);
+                mSecondPicker->setModel(mSecondModel);
+                mLayout->addItem(mSecondPicker);
+                break;
+            case HbDateTimeParser::MinuteSection:
+                mMinutePicker = new HbTumbleView(q);
+                mMinuteModel = new QStringListModel(q);
+                mMinutePicker->setModel(mMinuteModel);
+                mLayout->addItem(mMinutePicker);
+                break;
+            case HbDateTimeParser::Hour12Section:
+            case HbDateTimeParser::Hour24Section:
+                mHourPicker = new HbTumbleView(q);
+                mHourModel = new QStringListModel(q);
+                mHourPicker->setModel(mHourModel);
+                mLayout->addItem(mHourPicker);
+                break;
+            default:break;
+        }
+    }
+    setRanges();
+    makeConnections();
+    syncVisualDate();
+ //TODO:what to do with current date, should reset ?
+}
+
+void HbDateTimePickerPrivate::makeConnections()
+{
+    Q_Q(HbDateTimePicker);
+    bool b=false;
+    if(mYearPicker) {
+        b=QObject::connect(mYearPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_yearChanged(int)));
+        Q_ASSERT(b);
+    }
+    if(mMonthPicker) {
+        b=QObject::connect(mMonthPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_monthChanged(int)));
+        Q_ASSERT(b);
+    }
+    if(mDayPicker) {
+        b=QObject::connect(mDayPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_dayChanged(int)));
+        Q_ASSERT(b);
+    }
+    if(mHourPicker) {
+        b=QObject::connect(mHourPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_hoursChanged(int)));
+        Q_ASSERT(b);
+    }
+    if(mMinutePicker) {
+        b=QObject::connect(mMinutePicker,SIGNAL(itemSelected(int)),q,SLOT(_q_minutesChanged(int)));
+        Q_ASSERT(b);
+    }
+    if(mSecondPicker) {
+        b=QObject::connect(mSecondPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_secondsChanged(int)));
+        Q_ASSERT(b);
+    }
+    if(mAmPmPicker) {
+        b=QObject::connect(mAmPmPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_ampmChanged(int)));
+        Q_ASSERT(b);
+    }
+    Q_UNUSED(b);
+}
+void HbDateTimePickerPrivate::removeConnections()
+{
+    Q_Q(HbDateTimePicker);    
+    if(mYearPicker) {
+        QObject::disconnect(mYearPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_yearChanged(int)));
+    }
+    if(mMonthPicker) {
+        QObject::disconnect(mMonthPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_monthChanged(int)));
+    }
+    if(mDayPicker) {
+        QObject::disconnect(mDayPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_dayChanged(int)));
+    }
+    if(mHourPicker) {
+        QObject::disconnect(mHourPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_hoursChanged(int)));
+    }
+    if(mMinutePicker) {
+        QObject::disconnect(mMinutePicker,SIGNAL(itemSelected(int)),q,SLOT(_q_minutesChanged(int)));
+    }
+    if(mSecondPicker) {
+        QObject::disconnect(mSecondPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_secondsChanged(int)));
+    }
+    if(mAmPmPicker) {
+        QObject::disconnect(mAmPmPicker,SIGNAL(itemSelected(int)),q,SLOT(_q_ampmChanged(int)));
+    }
+}
+
+
+void HbDateTimePickerPrivate::setRanges() 
+{
+    if(mIsTwoDigitYearFormat) {
+        mYearOffset = mMinimumDate.date().year()%100;
+        setYearRange(mMinimumDate.date().year()%100,mMaximumDate.date().year()%100); 
+    } else {
+        mYearOffset = mMinimumDate.date().year();
+        setYearRange(mMinimumDate.date().year(),mMaximumDate.date().year()); 
+    }
+
+    mMonthOffset = 1;
+    setMonthRange(1,12);//default all months
+
+    mDayOffset = 1;
+    setDayRange(1,31);//default all days
+
+    mHourOffset = 0;
+    setHourRange(0,23);
+
+    mMinuteOffset = 0;
+    setMinuteRange(0,59);
+
+    mSecondOffset = 0;
+    setSecondRange(0,59);
+
+    setAmPm();
+}
+
+void HbDateTimePickerPrivate::syncVisualDate()
+{
+    //no matter how good this is written , there always seems to be a gap
+    //between visual and actual selected data. creating syncup with visual.
+
+    int y=1,m=1,d=1,h=0,n=0,s=0;
+
+    if(mYearPicker) {
+        y = mYearOffset+mYearPicker->selected();
+    }
+    if(mMonthPicker) {
+        m = mMonthOffset+mMonthPicker->selected();
+    }
+    if(mDayPicker) {
+        d = mDayOffset +mDayPicker->selected();
+    }
+
+    if(mHourPicker) {
+        h=mHourOffset+mHourPicker->selected();
+    }
+
+    if(mMinutePicker) {
+        n=mMinuteOffset+mMinutePicker->selected();
+    }
+    if(mSecondPicker) {
+        s=mSecondOffset+mSecondPicker->selected();
+    }
+    QDateTime dt(QDate(y,m,d),QTime(h,n,s));
+    if(dt.isValid()) {
+        mDateTime = dt;
+    }
+}
+
+void HbDateTimePickerPrivate::emitDateChange()
+{
+    Q_Q(HbDateTimePicker);
+
+    emit q->dateChanged(mDateTime.date());
+    emit q->dateTimeChanged(mDateTime);
+}
+
+void HbDateTimePickerPrivate::emitTimeChange()
+{
+    Q_Q(HbDateTimePicker);
+
+    emit q->timeChanged(mDateTime.time());
+    emit q->dateTimeChanged(mDateTime);
+
+}
+void HbDateTimePickerPrivate::emitDateTimeChange()
+{
+    Q_Q(HbDateTimePicker);
+
+    emit q->dateChanged(mDateTime.date());
+    emit q->timeChanged(mDateTime.time());
+    emit q->dateTimeChanged(mDateTime);
+
+}
+
+
+void HbDateTimePickerPrivate::setDateTimeRange(const QDateTime &startdt,
+        const QDateTime &enddt)
+{
+    Q_Q(HbDateTimePicker);
+    QDateTime start(startdt);
+    QDateTime end(enddt);
+    if(start.isValid() && end.isValid()) {
+
+        removeConnections();
+
+        //change the date range
+        if(start.date() > end.date()) {
+            end.setDate(start.date());
+        }
+        if(mIsTwoDigitYearFormat) {
+            setYearRange(start.date().year()%100,end.date().year()%100);
+        } else {
+            setYearRange(start.date().year(),end.date().year());
+        }
+
+        //change the time range
+        if(start.time() > end.time()) {
+            end.setTime(start.time());
+        }
+        setHourRange(start.time().hour(),end.time().hour());
+
+        mMinimumDate = start;
+        mMaximumDate = end;
+
+        //scroll to the clamped date
+        bool dirty=false;
+        if(mDateTime < mMinimumDate) {
+            dirty = true;
+            mDateTime = mMinimumDate;
+        } else if(mDateTime > mMaximumDate) {
+            dirty = true;
+            mDateTime = mMaximumDate;
+        }
+        if(dirty) {
+            setDateTime(mDateTime);
+            //force the year change so month range gets set appropriately
+            //TODO:fix after modularization of entire code
+        }
+
+        if(mYearPicker) {
+            _q_yearChanged(mYearPicker->selected());
+        }
+
+        //force the hour change so minute range gets set appropriately
+        if(mHourPicker) {
+            _q_hoursChanged(mHourPicker->selected());
+        }
+
+        //emit the changes
+        emit q->dateChanged(mDateTime.date());
+        emit q->timeChanged(mDateTime.time());
+        emit q->dateTimeChanged(mDateTime);          
+
+        makeConnections();
+    }
+}
+void HbDateTimePickerPrivate::setDateTime(const QDateTime &newDate)
+{
+    QDateTime newDateTime(newDate);
+    //TODO: validity and bounds check for selected
+    if(newDateTime.isValid()) {
+
+        //update the mem var
+        if(newDateTime.date() < mMinimumDate.date()) {
+            newDateTime.setDate(mMinimumDate.date());
+        } else if(newDateTime.date() > mMaximumDate.date()) {
+            newDateTime.setDate(mMaximumDate.date());
+        }
+
+        if(newDateTime.time() < mMinimumDate.time()) {
+            newDateTime.setTime(mMinimumDate.time());
+        }else if(newDateTime.time() > mMaximumDate.time()) {
+            newDateTime.setTime(mMaximumDate.time());
+        }
+
+        //set the selections
+        if(mYearPicker) {
+#ifdef HBDATETIMEPICKER_DEBUG
+            qDebug() << "setDateTime: yearOffset=" << mYearOffset;
+#endif
+            if(mIsTwoDigitYearFormat) {
+                mYearPicker->setSelected((newDateTime.date().year()%100)-mYearOffset);
+            } else {
+                mYearPicker->setSelected(newDateTime.date().year()-mYearOffset);
+            }
+        }
+        if(mMonthPicker) {
+            mMonthPicker->setSelected(newDateTime.date().month()-mMonthOffset);
+        }
+        if(mDayPicker) {
+            mDayPicker->setSelected(newDateTime.date().day()-mDayOffset);
+        }
+        if(mHourPicker) {
+            mHourPicker->setSelected(newDateTime.time().hour()-mHourOffset);
+        }
+        if(mMinutePicker) {
+            mMinutePicker->setSelected(newDateTime.time().minute()-mMinuteOffset);
+        }
+        if(mSecondPicker) {
+#ifdef HBDATETIMEPICKER_DEBUG
+            qDebug() << "setDateTime before: secondOffset=" << mSecondOffset << " time=" << newDateTime.time();
+#endif
+            mSecondPicker->setSelected(newDateTime.time().second()-mSecondOffset);
+#ifdef HBDATETIMEPICKER_DEBUG
+            qDebug() << "setDateTime after: secondOffset=" << mSecondOffset << " time=" << newDateTime.time();
+#endif
+        }
+        mDateTime = newDateTime;
+
+    }
+}
+void HbDateTimePickerPrivate::setMinimumDateTime(const QDateTime &newMinDateTime)
+{
+    setDateTimeRange(newMinDateTime,mMaximumDate);
+}
+void HbDateTimePickerPrivate::setMaximumDateTime(const QDateTime &newMaxDateTime)
+{
+    setDateTimeRange(mMinimumDate,newMaxDateTime);
+}
+
+
+void HbDateTimePickerPrivate::setYearRange(int start,int end)
+{
+    if(!mYearPicker) {
+        return;
+    }
+    //calculate the index it should be after resize
+    //the currentIndex gets reset after the resize and gets set to 0
+    //to work around that issue this is added
+    int newIndex = mYearPicker->selected()-(start-mYearOffset);
+    if(newIndex < 0) {
+        newIndex = 0;
+    }
+    if(newIndex > (end-start)) {
+        newIndex = end-start;
+    }
+
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "setyear range (" << start << "," << end << ")" ;
+#endif
+
+
+
+    resizeModel(mYearModel, mYearOffset, 
+        mYearOffset+mYearModel->rowCount()-1, start, 
+        end, &HbDateTimePickerPrivate::localeYear);
+
+    mYearOffset = start;
+
+    mYearPicker->setSelected(newIndex);
+}
+
+void HbDateTimePickerPrivate::setMonthRange(int start,int end)
+{
+    if(!mMonthPicker) {
+        return;
+    }
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "setMonthRange: " << start << " ," << end;
+#endif
+    //calculate the index it should be after resize
+    //the currentIndex gets reset after the resize and gets set to 0
+    //to work around that issue this is added
+    int newIndex = mMonthPicker->selected()-(start-mMonthOffset);
+    if(newIndex < 0) {
+        newIndex = 0;
+    }
+    if(newIndex > (end-start)) {
+        newIndex = end-start;
+    }
+    resizeModel(mMonthModel,
+            mMonthOffset,mMonthOffset+mMonthModel->rowCount()-1,
+            start,end,
+            &HbDateTimePickerPrivate::localeMonth);
+    mMonthOffset = start;
+
+    mMonthPicker->setSelected(newIndex);
+
+    //check if current month is valid
+    if(mDateTime.date().month() < start) {
+        mDateTime.setDate(QDate(mDateTime.date().year(),start,mDateTime.date().day()));
+    }
+    else if(mDateTime.date().month() > end) {
+        mDateTime.setDate(QDate(mDateTime.date().year(),end,mDateTime.date().day()));
+    }
+}
+
+
+void HbDateTimePickerPrivate::setDayRange(int start,int end)
+{
+    if(!mDayPicker) {
+        return;
+    }
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "setDayRange: " << start << " ," << end;
+#endif
+    //calculate the index it should be after resize
+    //the currentIndex gets reset after the resize and gets set to 0
+    //to work around that issue this is added
+    int newIndex = mDayPicker->selected()-(start-mDayOffset);
+    if(newIndex < 0) {
+        newIndex = 0;
+    }
+    if(newIndex > (end-start)) {
+        newIndex = end-start;
+    }
+
+    resizeModel(mDayModel,
+            mDayOffset,mDayOffset+mDayModel->rowCount()-1,
+            start,end,
+            &HbDateTimePickerPrivate::localeDay);
+    mDayOffset = start;
+
+    mDayPicker->setSelected(newIndex);
+
+
+    //check if current day is valid
+    if(mDateTime.date().day() < start) {
+        mDateTime.setDate(QDate(mDateTime.date().year(),mDateTime.date().month(),start));
+    }
+    else if(mDateTime.date().day() > end) {
+        mDateTime.setDate(QDate(mDateTime.date().year(),mDateTime.date().month(),end));
+    }
+}
+
+void HbDateTimePickerPrivate::setHourRange(int start,int end)
+{
+    
+    if(!mHourPicker) {
+        return;
+    }
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "setHourRange: " << start << " ," << end;
+#endif
+    //calculate the index it should be after resize
+    //the currentIndex gets reset after the resize and gets set to 0
+    //to work around that issue this is added
+    int newIndex = mHourPicker->selected()-(start-mHourOffset);
+    if(newIndex < 0) {
+        newIndex = 0;
+    }
+    if(newIndex > (end-start)) {
+        newIndex = end-start;
+    }
+
+    resizeModel(mHourModel,
+            mHourOffset,mHourOffset+mHourModel->rowCount()-1,
+            start,end,
+            &HbDateTimePickerPrivate::localeHour);
+    mHourOffset = start;
+
+    mHourPicker->setSelected(newIndex);
+
+    //check if hour is valid
+    if(mDateTime.time().hour() < start) {
+        mDateTime.setTime(QTime(start,mDateTime.time().minute(),mDateTime.time().second()));
+    }
+    else if(mDateTime.time().hour() > end) {
+        mDateTime.setTime(QTime(end,mDateTime.time().minute(),mDateTime.time().second()));
+    }
+}
+void HbDateTimePickerPrivate::setMinuteRange(int start,int end)
+{
+    
+    if(!mMinutePicker) {
+        return;
+    }
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "setMinuteRange: " << start << " ," << end;
+#endif
+    //calculate the index it should be after resize
+    //the currentIndex gets reset after the resize and gets set to 0
+    //to work around that issue this is added
+    int newIndex = mMinutePicker->selected()-(start-mMinuteOffset);
+    if(newIndex < 0) {
+        newIndex = 0;
+    }
+    if(newIndex > (end-start)) {
+        newIndex = end-start;
+    }
+
+    resizeModel(mMinuteModel,
+            mMinuteOffset,mMinuteOffset+mMinuteModel->rowCount()-1,
+            start,end,
+            &HbDateTimePickerPrivate::localeMinute);
+    mMinuteOffset = start;
+
+    mMinutePicker->setSelected(newIndex);
+
+    //check if minute is valid
+    if(mDateTime.time().minute() < start) {
+        mDateTime.setTime(QTime(mDateTime.time().hour(),start,mDateTime.time().second()));
+    }
+    else if(mDateTime.time().minute() > end) {
+        mDateTime.setTime(QTime(mDateTime.time().hour(),end,mDateTime.time().second()));
+    }
+}
+void HbDateTimePickerPrivate::setSecondRange(int start,int end)
+{
+    
+    if(!mSecondPicker) {
+        return;
+    }
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "setSecondRange: " << start << " ," << end;
+#endif
+    //calculate the index it should be after resize
+    //the currentIndex gets reset after the resize and gets set to 0
+    //to work around that issue this is added
+    int newIndex = mSecondPicker->selected()-(start-mSecondOffset);
+    if(newIndex < 0) {
+        newIndex = 0;
+    }
+    if(newIndex > (end-start)) {
+        newIndex = end-start;
+    }
+
+    resizeModel(mSecondModel,
+            mSecondOffset,mSecondOffset+mSecondModel->rowCount()-1,
+            start,end,
+            &HbDateTimePickerPrivate::localeSecond);
+    mSecondOffset = start;
+
+    mSecondPicker->setSelected(newIndex);
+
+    //check if second is valid
+    if(mDateTime.time().second() < start) {
+        mDateTime.setTime(QTime(mDateTime.time().hour(),mDateTime.time().minute(),start));
+    }
+    else if(mDateTime.time().second() > end) {
+        mDateTime.setTime(QTime(mDateTime.time().hour(),mDateTime.time().minute(),end));
+    }
+}
+
+void HbDateTimePickerPrivate::setAmPm()
+{
+    if(!mAmPmPicker) {
+        return;
+    }
+    //TODO: check if range has both am and pm
+    QStringList amList;
+    amList << localeAmPm(true) << localeAmPm(false);
+    mAmPmModel->setStringList(amList);
+}
+
+QString HbDateTimePickerPrivate::localeYear(int year)
+{
+    //TODO:locale and format stuff
+    if(mIsTwoDigitYearFormat) {
+        return mLocale.toString(QDate(1900+year,1,1),mYearFormat);//year 00 is invalid
+    }
+    return mLocale.toString(QDate(year,1,1),mYearFormat);
+}
+
+QString HbDateTimePickerPrivate::localeMonth(int month)
+{
+    return mLocale.toString(QDate(2000,month,1),mMonthFormat);
+
+}
+QString HbDateTimePickerPrivate::localeDay(int day)
+{
+    return mLocale.toString(QDate(2000,1,day),mDayFormat);
+}
+
+QString HbDateTimePickerPrivate::localeHour(int hour)
+{
+    if(mIs24HourFormat) {
+        return mLocale.toString(QTime(hour,0,0),mHourFormat);
+    } 
+
+    QString hourStr=mLocale.toString(QTime(hour,0,0),QString("%1:%2").arg(mHourFormat).arg("ap"));
+    QStringList hourAm=hourStr.split(":");
+    if(hourAm.count() > 1) {
+        return hourAm.at(0);
+    }
+    return QString("Format Err");
+}
+
+QString HbDateTimePickerPrivate::localeMinute(int minute)
+{
+    return mLocale.toString(QTime(0,minute,0),mMinuteFormat);
+}
+
+QString HbDateTimePickerPrivate::localeSecond(int second)
+{
+    return mLocale.toString(QTime(0,0,second),mSecondFormat);
+}
+
+QString HbDateTimePickerPrivate::localeAmPm(bool isAm)
+{
+    QString text = isAm ? mLocale.amText() : mLocale.pmText();
+#ifdef HB_TEXT_MEASUREMENT_UTILITY
+    if ( HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) {
+        text.append(QChar(LOC_TEST_START));
+        text.append("qtl_datetimepicker_popup_ampm_sec");
+        text.append(QChar(LOC_TEST_END));
+    }
+#endif
+    return text;
+}
+
+
+/* there are seven different models for seven pickers. insertion and removal
+   to each of the models to resize them its the same logic. but to populate the
+   data need the appropriate locale and format converted data. which is passed
+   as a function pointer instead of creating seven different QStringListModel derived
+   model classes with one interface/virtual fuction specialization.
+*/
+void HbDateTimePickerPrivate::resizeModel(QStringListModel *model,
+            int oldStart, int oldEnd,
+            int newStart, int newEnd,
+            QString (HbDateTimePickerPrivate::*localeFunc)(int))
+{
+    //if row count is zero, then insert from newEnd to newStart
+    if((model->rowCount() == 0) && (newEnd-newStart>=0)) {
+        //initialize condition
+        model->insertRows(0,newEnd-newStart+1);
+        for(int i=0;i<=newEnd-newStart;i++) {
+            QModelIndex index=model->index(i,0);
+            if(index.isValid()) {
+                //model->setData(index,(this->*localeFunc)(i+newStart));//TODO:add a readable typedef
+                QString text = (this->*localeFunc)(i+newStart);
+#ifdef HB_TEXT_MEASUREMENT_UTILITY
+                if ( localeFunc == &HbDateTimePickerPrivate::localeMonth &&
+                    HbFeatureManager::instance()->featureStatus( HbFeatureManager::TextMeasurement ) ) {
+                    text.append(QChar(LOC_TEST_START));
+                    text.append("qtl_datetimepicker_popup_month_sec");
+                    text.append(QChar(LOC_TEST_END));
+                }
+#endif
+                model->setData(index,text);//TODO:add a readable typedef
+            }
+        }
+        return;
+    }
+
+    if(newStart < oldStart) {
+        model->insertRows(0,oldStart-newStart);
+        for(int i=0;i<oldStart-newStart;++i) {
+            QModelIndex index=model->index(i,0);
+            if(index.isValid()) {
+                model->setData(index,(this->*localeFunc)(i+newStart));
+            }
+        }
+    }
+    if(newEnd > oldEnd) {
+        int rowCount = model->rowCount(); 
+        model->insertRows(rowCount,newEnd-oldEnd);
+        for(int i=0;i<newEnd-oldEnd;++i) {
+            QModelIndex index=model->index(rowCount+i,0);
+            if(index.isValid()) {
+                model->setData(index,(this->*localeFunc)(oldEnd+i+1));
+            }
+        }
+    }
+
+    if(newStart > oldStart) {
+        model->removeRows(0,newStart-oldStart);
+    }
+
+    if(oldEnd > newEnd) {
+        model->removeRows((model->rowCount()-(oldEnd-newEnd)),oldEnd-newEnd);
+    }
+}
+
+void HbDateTimePickerPrivate::createPrimitives()
+{
+    Q_Q(HbDateTimePicker);
+    if(!mBackground) {
+        mBackground = q->style()->createPrimitive(HbStyle::P_DateTimePicker_background,q);
+        q->style()->setItemName(mBackground,"background");
+    }
+    if(!mFrame) {
+        mFrame = q->style()->createPrimitive(HbStyle::P_DateTimePicker_frame,q);
+        q->style()->setItemName(mFrame,"frame");
+    }
+    createDividers();
+}
+
+void HbDateTimePickerPrivate::createDividers()
+{
+    Q_Q(HbDateTimePicker);
+    
+    if( mParser.mSectionNodes.count() == mDividers.count() ){
+        return;
+    }
+
+    if( mParser.mSectionNodes.count() < mDividers.count() ){
+        for( int i = mParser.mSectionNodes.count() - 1; i > mDividers.count(); i--)
+        {
+            QPointer<QGraphicsWidget> item = mDividers.at(i);
+            mDividers.removeAt(i);
+            delete item;
+        }
+
+        return;
+    }
+    else if( mParser.mSectionNodes.count() > mDividers.count() ){
+
+        for(int i = mDividers.count();i < mParser.mSectionNodes.count(); i++) { //TODO: optimally create when required
+            QGraphicsItem *item=q->style()->createPrimitive(HbStyle::P_DateTimePicker_separator, mContent);
+            Q_ASSERT(item->isWidget());
+            q->style()->setItemName(item,"separator");
+            mDividers.append(static_cast<QGraphicsWidget *>(item));
+        }
+    }
+}
+
+void HbDateTimePickerPrivate::updateDividers()
+{
+    /*Q_Q(HbDateTimePicker);
+    HbStyleOption option;
+    q->initStyleOption(&option);
+    for(int i=0;i<qMin(mDividers.count(),mDividerIndex);i++) {
+        q->style()->updatePrimitive((QGraphicsItem*)mDividers.at(i),HbStyle::P_DateTimePicker_separator,&option);
+    }*/
+
+    //TODO: improve the divider addition and removal
+
+    //using the style update primitive crashes. need to investigate why
+
+}
+
+void HbDateTimePickerPrivate::_q_dayChanged(int index)
+{
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "_q_dayChanged:" << index;
+#endif
+    QDate newDate(mDateTime.date().year(),mDateTime.date().month(),index+mDayOffset);
+    if(newDate.isValid()) {
+        mDateTime.setDate(newDate);
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "dayChange:currentDate:" << mDateTime;
+#endif
+    }
+    else {
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "got invalid day change:" << index;
+#endif
+        return;
+    }
+
+    emitDateChange();
+
+    Q_UNUSED(index);
+}
+
+void HbDateTimePickerPrivate::_q_monthChanged(int index)
+{
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "_q_monthChanged:" << index;
+#endif
+    QDate newDate(mDateTime.date());
+    if(mMonthOffset >= 0) {
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "month: before:" << newDate << " ,off-ind:" << newDate.month()-mMonthOffset << "-" << index;
+#endif
+        newDate = newDate.addMonths(index+mMonthOffset-newDate.month());
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "month: after:" << newDate;
+#endif
+    }else {
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "month: before else:" << newDate;
+#endif
+        newDate = newDate.addMonths(index);
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "month: after else:" << newDate;
+#endif
+    }
+    if(newDate.isValid()) {
+        mDateTime.setDate(newDate);
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "monthChange:currentDate:" << mDateTime << " ind:" << index;
+#endif
+    }
+    else {
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "got invalid month change:" << index;
+        qDebug() << "got invalid month change:" << mMonthOffset;
+#endif
+        return;
+    }
+
+    //check if day range changed
+    if(mDayPicker) {
+        int start=mDayOffset;
+        int end=mDayOffset+mDayModel->rowCount()-1;
+        if(isMinimumYear() && isMinimumMonth()) {
+            start = mMinimumDate.date().day();
+        } else {
+            start = 1;
+        }
+        if(isMaximumYear() && isMaximumMonth()) {
+            end = mMaximumDate.date().day();
+        } else {
+            end = mDateTime.date().daysInMonth();
+        }
+
+        //set if dayrange changed
+        if((start != mDayOffset)
+                ||(end !=mDayOffset+mDayModel->rowCount()-1)) {
+            setDayRange(start,end);
+        }
+    }
+
+    emitDateChange();
+}
+
+void HbDateTimePickerPrivate::_q_yearChanged(int index)
+{
+    qDebug() << "_q_yearChanged:" << index;
+    //Q_Q(HbDateTimePicker);
+    QDate newDate(mDateTime.date());
+    if(mIsTwoDigitYearFormat) {
+        newDate = newDate.addYears(index+mYearOffset-(newDate.year()%100));
+    }
+    else {
+        newDate = newDate.addYears(index+mYearOffset-newDate.year());
+    }
+    if(newDate.isValid()) {
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "yearChange:currentDate before:" << mDateTime << " ind:" << index << " yeOff:" << mYearOffset;
+#endif
+        mDateTime.setDate(newDate);
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "yearChange:currentDate:" << mDateTime << " ind:" << index;
+#endif
+    }
+    else {
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "got invalid month change:" << index;
+        qDebug() << "got invalid month change:" << mMonthOffset;
+#endif
+        return;
+    }
+
+    //check if month range changed
+    int start=0,end=0;
+    if(mMonthPicker) {
+        start=mMonthOffset;
+        end=start+mMonthModel->rowCount()-1;
+        if(isMinimumYear())  {
+            start = mMinimumDate.date().month();
+        } else {
+            start = 1;
+        }
+
+        if(isMaximumYear()) {
+            end = mMaximumDate.date().month();
+        } else {
+            end = 12;
+        }
+
+        //set if range changed
+        if((start != mMonthOffset)
+                || (end != mMonthModel->rowCount()-1)) {
+            setMonthRange(start,end);
+        }
+
+    }
+    
+    //check if day range changed
+    if(mDayPicker) {
+        int start=mDayOffset;
+        int end=mDayOffset+mDayModel->rowCount()-1;
+        if(isMinimumYear() && isMinimumMonth()) {
+            start = mMinimumDate.date().day();
+        } else {
+            start = 1;
+        }
+        if(isMaximumYear() && isMaximumMonth()) {
+            end = mMaximumDate.date().day();
+        } else {
+            end = mDateTime.date().daysInMonth();
+        }
+
+        //set if dayrange changed
+        if((start != mDayOffset)
+                ||(end !=mDayOffset+mDayModel->rowCount()-1)) {
+            setDayRange(start,end);
+        }
+    }
+
+    emitDateChange();
+
+}
+
+void HbDateTimePickerPrivate::_q_hoursChanged(int index)
+{
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "_q_hoursChanged:" << index;
+#endif
+    QTime newTime(mHourOffset+index,mDateTime.time().minute(),mDateTime.time().second());
+    if(newTime.isValid()) {
+        mDateTime.setTime(newTime);
+    }
+    else {
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "got invalid hour change:" << index;
+        qDebug() << "got invalid hour change offset:" << mHourOffset;
+#endif
+        return;
+    }
+
+    //check if minute range changed
+    int start=0,end=0;
+    if(mMinutePicker) {
+        start=mMinuteOffset;
+        end=start+mMinuteModel->rowCount()-1;
+        if(isMinimumHour())  {
+            start = mMinimumDate.time().minute();
+        } else {
+            start = 0;
+        }
+        if(isMaximumHour()) {
+            end = mMaximumDate.time().minute();
+        } else {
+            end = 59;
+        }
+
+        //set if range changed
+        if((start != mMinuteOffset)
+                || (end != start+mMinuteModel->rowCount()-1)) {
+            setMinuteRange(start,end);
+        }
+
+    }
+    
+    //check if seconds range changed
+    if(mSecondPicker) {
+        start=mSecondOffset;
+        end=mSecondOffset+mSecondModel->rowCount()-1;
+        if(isMinimumHour() && isMinimumMinute()) {
+            start = mMinimumDate.time().second();
+        } else {
+            start = 0;
+        }
+        if(isMaximumHour() && isMaximumMinute()) {
+            end = mMaximumDate.time().second();
+        } else {
+            end = 59;
+        }
+
+        //set if seconds range changed
+        if((start != mSecondOffset)
+                ||(end !=mSecondOffset+mSecondModel->rowCount()-1)) {
+            setSecondRange(start,end);
+        }
+    }
+
+    //check if am or pm and scroll to respective time
+    if((!mIs24HourFormat) && mAmPmPicker) {
+        if(mAmPmPicker->selected() == 0) {
+            //is AM
+            if(mDateTime.time().hour() > 11) {
+                mAmPmPicker->setSelected(1);
+            }
+        } else if(mAmPmPicker->selected() == 1) {
+            //is PM
+            if(mDateTime.time().hour() < 12) {
+                mAmPmPicker->setSelected(0);
+            }
+        }
+    }
+
+    emitTimeChange();
+}
+
+void HbDateTimePickerPrivate::_q_minutesChanged(int index)
+{
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "_q_minutesChanged:" << index;
+#endif
+    QTime newTime(mDateTime.time().hour(),mMinuteOffset+index,mDateTime.time().second());
+    if(newTime.isValid()) {
+        mDateTime.setTime(newTime);
+    }
+    else {
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "got invalid minute change:" << index;
+        qDebug() << "got invalid minute change offset:" << mMinuteOffset;
+#endif
+        return;
+    }
+
+    int start,end;
+    //check if seconds range changed
+    if(mSecondPicker) {
+        start=mSecondOffset;
+        end=mSecondOffset+mSecondModel->rowCount()-1;
+        if(isMinimumHour() && isMinimumMinute()) {
+            start = mMinimumDate.time().second();
+        } else {
+            start = 0;
+        }
+        if(isMaximumHour() && isMaximumMinute()) {
+            end = mMaximumDate.time().second();
+        } else {
+            end = 59;
+        }
+
+        //set if seconds range changed
+        if((start != mSecondOffset)
+                ||(end !=mSecondOffset+mSecondModel->rowCount()-1)) {
+            setSecondRange(start,end);
+        }
+    }
+
+    emitTimeChange();
+}
+
+void HbDateTimePickerPrivate::_q_secondsChanged(int index)
+{
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "_q_secondsChanged:" << index;
+#endif
+    QTime newTime(mDateTime.time().hour(),mDateTime.time().minute(),mSecondOffset+index);
+    if(newTime.isValid()) {
+        mDateTime.setTime(newTime);
+    }
+    else {
+#ifdef HBDATETIMEPICKER_DEBUG
+        qDebug() << "got invalid second change:" << index;
+        qDebug() << "got invalid second change offset:" << mSecondOffset;
+#endif
+        return;
+    }
+
+
+    emitTimeChange();
+}
+
+void HbDateTimePickerPrivate::_q_ampmChanged(int index)
+{
+    
+#ifdef HBDATETIMEPICKER_DEBUG
+    qDebug() << "_q_ampmChanged:" << index;
+#endif
+    if(index == 0) {
+        //AM is chosen 
+        QTime newTime(mDateTime.time().hour()-12,mDateTime.time().minute(),mDateTime.time().second());
+        if(newTime.isValid()) {
+            if(newTime >= mMinimumDate.time()) {
+                mDateTime.setTime(newTime);
+                if(mHourPicker) {
+                    mHourPicker->setSelected(newTime.hour()-mHourOffset);
+                }
+                emitTimeChange();
+            }else {
+                mAmPmPicker->setSelected(1);//invalid so scrollback
+            }
+
+        }  
+    } else if(index == 1) {
+        //PM is chosen
+        QTime newTime(mDateTime.time().hour()+12,mDateTime.time().minute(),mDateTime.time().second());
+        if(newTime.isValid()) {
+            if(newTime <= mMaximumDate.time()) {
+                mDateTime.setTime(newTime);
+                if(mHourPicker) {
+                    mHourPicker->setSelected(newTime.hour()-mHourOffset);
+                } 
+                emitTimeChange();
+            } else { 
+                mAmPmPicker->setSelected(0);//invalid so scrollback
+            }
+        } 
+    }
+}