src/hbwidgets/widgets/hbdatetimepicker_p.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 03 May 2010 12:48:33 +0300
changeset 1 f7ac710697a9
parent 0 16d8024aca5e
child 2 06ff229162e9
permissions -rw-r--r--
Revision: 201015 Kit: 201018

/****************************************************************************
**
** 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)
    ,mIntervals()
    ,mHighlight(0)
{
    mMinimumDate = HBDATETIMEPICKER_DATETIME_MIN;
    mMaximumDate = HBDATETIMEPICKER_DATETIME_MAX;
    mDateTime = mMinimumDate;
}

HbDateTimePickerPrivate::~HbDateTimePickerPrivate()
{
}

/*
   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(1);
    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);

    //create primitives
    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;

    QPointer<HbTumbleView> lastAdded;

    for(int i=0;i<mParser.mSectionNodes.count();i++) {
        switch(mParser.mSectionNodes[i].type) {
            case HbDateTimeParser::AmPmSection:
                mAmPmPicker = new HbTumbleView(q);
                mAmPmModel = new QStringListModel(q);
                mAmPmPicker->setModel(mAmPmModel);
                //mAmPmPicker->setLoopingEnabled(true);
                mLayout->addItem(mAmPmPicker);
                mAmPmPicker->primitive("highlight")->hide();
                mAmPmPicker->primitive("separator")->show();
                lastAdded = mAmPmPicker;
                break;

            case HbDateTimeParser::DaySection:
            case HbDateTimeParser::DayOfWeekSection:
                mDayPicker = new HbTumbleView(q);
                mDayModel = new QStringListModel(q);
                mDayPicker->setModel(mDayModel);
                //mDayPicker->setLoopingEnabled(true);
                mLayout->addItem(mDayPicker);
                mDayPicker->primitive("highlight")->hide();
                mDayPicker->primitive("separator")->show();
                lastAdded = mDayPicker;
                break;

            case HbDateTimeParser::MonthSection:
                mMonthPicker = new HbTumbleView(q);
                mMonthModel = new QStringListModel(q);
                mMonthPicker->setModel(mMonthModel);
                //mMonthPicker->setLoopingEnabled(true);
                mLayout->addItem(mMonthPicker);
                mMonthPicker->primitive("highlight")->hide();
                mMonthPicker->primitive("separator")->show();
                lastAdded = mMonthPicker;
                break;

            case HbDateTimeParser::YearSection:
            case HbDateTimeParser::YearSection2Digits:
                mYearPicker = new HbTumbleView(q);
                mYearModel = new QStringListModel(q);
                mYearPicker->setModel(mYearModel);
                //mYearPicker->setLoopingEnabled(true);
                mLayout->addItem(mYearPicker);
                mYearPicker->primitive("highlight")->hide();
                mYearPicker->primitive("separator")->show();
                lastAdded = mYearPicker;
                break;

            case HbDateTimeParser::SecondSection:
                mSecondPicker = new HbTumbleView(q);
                mSecondModel = new QStringListModel(q);
                mSecondPicker->setModel(mSecondModel);
                //mSecondPicker->setLoopingEnabled(false);
                mLayout->addItem(mSecondPicker);
                mSecondPicker->primitive("highlight")->hide();
                mSecondPicker->primitive("separator")->show();
                lastAdded = mSecondPicker;
                break;

            case HbDateTimeParser::MinuteSection:
                mMinutePicker = new HbTumbleView(q);
                mMinuteModel = new QStringListModel(q);
                mMinutePicker->setModel(mMinuteModel);
                //mMinutePicker->setLoopingEnabled(false);
                mLayout->addItem(mMinutePicker);
                mMinutePicker->primitive("highlight")->hide();
                mMinutePicker->primitive("separator")->show();
                lastAdded = mMinutePicker;
                break;

            case HbDateTimeParser::Hour12Section:
            case HbDateTimeParser::Hour24Section:
                mHourPicker = new HbTumbleView(q);
                mHourModel = new QStringListModel(q);
                mHourPicker->setModel(mHourModel);
                //mHourPicker->setLoopingEnabled(true);
                mLayout->addItem(mHourPicker);
                mHourPicker->primitive("highlight")->hide();
                mHourPicker->primitive("separator")->show();
                lastAdded = mHourPicker;
                break;

            default:
                break;
        }
    }

    //For the last added tumble view, hide the separator.
    if(lastAdded){
        lastAdded->primitive("separator")->hide();
    }

    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
        }
        if(mAmPmPicker){
            if(newDate.time().hour() >= 12){
                mAmPmPicker->setSelected(1);
            }
            else{
                mAmPmPicker->setSelected(0);
            }
        }

        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, mIntervals[QDateTimeEdit::MinuteSection]);
    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), int interval)
{
    if(interval > 1){
        model->removeRows(0, model->rowCount());
    }

    if((model->rowCount() == 0) && (newEnd-newStart>=0)) {
        //initialize condition

        for(int i=0;i<=newEnd-newStart;i++) {
            //model->setData(index,(this->*localeFunc)(i+newStart));//TODO:add a readable typedef
            QString text;

            if(interval > 1){
                if(((newStart + interval) * i) <= newEnd){
                    model->insertRow(i);
                    text = (this->*localeFunc)(!((newStart + interval)*i) ? newStart : (newStart + interval)*i);
                }
                else{
                    break;
                }
            }
            else{
                model->insertRow(i);
                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
            QModelIndex index=model->index(i,0);
            if(index.isValid()) {
                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");
    }

    if(!mHighlight){
        mHighlight = q->style()->createPrimitive(HbStyle::P_TumbleView_highlight,q);
        q->style()->setItemName(mHighlight,"highlight");
    }
}

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(),mLocale.toInt(mMinuteModel->index(mMinuteOffset+index,0).data().toString()),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
            }
        } 
    }
}