From 58b92a951899f74b63048a36c451d3355c0c5a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20Meril=C3=A4?= Date: Fri, 18 Sep 2009 19:06:46 +0300 Subject: S60 native looking dialog support. Related to QTSSIXTY-63 "Make Qt dialogs look native" S60 dialog support: * Positioning according S60 rules: - in portrait dialogs at the bottom of the screen, - in landscape positioned in the center of the screen [unless device supports bottom softkeys], so that softkeys are not covered by the dialog * If dialog shows extension, then dialog is re-positioned * Dialog size: - in portrait screen wide dialog, height can change - in landscape width is the same size as width in portrait (some dialogs are maximized) * No push buttons or DialogButtonBoxes in internal qt dialogs (QWizard, QInputDialog, QFileDialog, QFontDialog, QColorDialog, QProgressDialog, QErrorMessage, QMessageBox), instead signals are remapped to softkeys. * Globally, dialogbuttonboxes are converted automatically to softkeys. OPEN: * Needs to be re-factored slightly after softkey API refactoring is finished. BUGS: QWizard layout switch is wonky - dialog is not re-sized correctly. QFontDialog will not fit into device screen (too much widgets in it). Some effort needed to be make it smaller. Cannot set one softkey at the time softkeys => Options menu and right softkey cannot be set separately [SoftKey re-factoring will help] Dialogs cannot get touch events to softkeys [SoftKey re-factoring will help] Reviewed-by: Alessandro Portale Reviewed-by: Jason Barron Reviewed-by: mread Reviewed-by: Shane Kearns --- src/gui/dialogs/qcolordialog.cpp | 140 +++++++++++++++++++- src/gui/dialogs/qdialog.cpp | 81 +++++++++++- src/gui/dialogs/qdialog.h | 8 +- src/gui/dialogs/qerrormessage.cpp | 45 ++++++- src/gui/dialogs/qfontdialog.cpp | 14 +- src/gui/dialogs/qmessagebox.cpp | 9 ++ src/gui/dialogs/qprogressdialog.cpp | 26 +++- src/gui/dialogs/qwizard.cpp | 74 +++++++++-- src/gui/widgets/qdialogbuttonbox.cpp | 142 +++++++++++++++++++++ .../auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp | 22 ++++ 10 files changed, 535 insertions(+), 26 deletions(-) diff --git a/src/gui/dialogs/qcolordialog.cpp b/src/gui/dialogs/qcolordialog.cpp index 1a3b297..a7df999 100644 --- a/src/gui/dialogs/qcolordialog.cpp +++ b/src/gui/dialogs/qcolordialog.cpp @@ -63,6 +63,10 @@ #include "qspinbox.h" #include "qdialogbuttonbox.h" +#ifdef Q_WS_S60 +#include "private/qt_s60_p.h" +#endif + QT_BEGIN_NAMESPACE //////////// QWellArray BEGIN @@ -1066,12 +1070,33 @@ QColorShower::QColorShower(QColorDialog *parent) QGridLayout *gl = new QGridLayout(this); gl->setMargin(gl->spacing()); lab = new QColorShowLabel(this); + +#ifdef Q_WS_S60 + QS60Data s60Data = QS60Data(); + const bool nonTouchUI = !s60Data.hasTouchscreen; +#endif + + #ifndef Q_WS_WINCE +#ifdef Q_WS_S60 + lab->setMinimumHeight(60); +#endif lab->setMinimumWidth(60); #else lab->setMinimumWidth(20); #endif + +// In S60, due to small screen and different screen layouts need to re-arrange the widgets. +// For QVGA screens only the comboboxes and color label are visible. +// For nHD screens only color and luminence pickers and color label are visible. +#ifndef Q_WS_S60 gl->addWidget(lab, 0, 0, -1, 1); +#else + if (nonTouchUI) + gl->addWidget(lab, 0, 0, 1, -1); + else + gl->addWidget(lab, 0, 0, -1, 1); +#endif connect(lab, SIGNAL(colorDropped(QRgb)), this, SIGNAL(newCol(QRgb))); connect(lab, SIGNAL(colorDropped(QRgb)), this, SLOT(setRgb(QRgb))); @@ -1082,8 +1107,18 @@ QColorShower::QColorShower(QColorDialog *parent) lblHue->setBuddy(hEd); #endif lblHue->setAlignment(Qt::AlignRight|Qt::AlignVCenter); +#ifndef Q_WS_S60 gl->addWidget(lblHue, 0, 1); gl->addWidget(hEd, 0, 2); +#else + if (nonTouchUI) { + gl->addWidget(lblHue, 1, 0); + gl->addWidget(hEd, 2, 0); + } else { + lblHue->hide(); + hEd->hide(); + } +#endif sEd = new QColSpinBox(this); lblSat = new QLabel(this); @@ -1091,8 +1126,18 @@ QColorShower::QColorShower(QColorDialog *parent) lblSat->setBuddy(sEd); #endif lblSat->setAlignment(Qt::AlignRight|Qt::AlignVCenter); +#ifndef Q_WS_S60 gl->addWidget(lblSat, 1, 1); gl->addWidget(sEd, 1, 2); +#else + if (nonTouchUI) { + gl->addWidget(lblSat, 1, 1); + gl->addWidget(sEd, 2, 1); + } else { + lblSat->hide(); + sEd->hide(); + } +#endif vEd = new QColSpinBox(this); lblVal = new QLabel(this); @@ -1100,8 +1145,18 @@ QColorShower::QColorShower(QColorDialog *parent) lblVal->setBuddy(vEd); #endif lblVal->setAlignment(Qt::AlignRight|Qt::AlignVCenter); +#ifndef Q_WS_S60 gl->addWidget(lblVal, 2, 1); gl->addWidget(vEd, 2, 2); +#else + if (nonTouchUI) { + gl->addWidget(lblVal, 1, 2); + gl->addWidget(vEd, 2, 2); + } else { + lblVal->hide(); + vEd->hide(); + } +#endif rEd = new QColSpinBox(this); lblRed = new QLabel(this); @@ -1109,8 +1164,18 @@ QColorShower::QColorShower(QColorDialog *parent) lblRed->setBuddy(rEd); #endif lblRed->setAlignment(Qt::AlignRight|Qt::AlignVCenter); +#ifndef Q_WS_S60 gl->addWidget(lblRed, 0, 3); gl->addWidget(rEd, 0, 4); +#else + if (nonTouchUI) { + gl->addWidget(lblRed, 3, 0); + gl->addWidget(rEd, 4, 0); + } else { + lblRed->hide(); + rEd->hide(); + } +#endif gEd = new QColSpinBox(this); lblGreen = new QLabel(this); @@ -1118,8 +1183,18 @@ QColorShower::QColorShower(QColorDialog *parent) lblGreen->setBuddy(gEd); #endif lblGreen->setAlignment(Qt::AlignRight|Qt::AlignVCenter); +#ifndef Q_WS_S60 gl->addWidget(lblGreen, 1, 3); gl->addWidget(gEd, 1, 4); +#else + if (nonTouchUI) { + gl->addWidget(lblGreen, 3, 1); + gl->addWidget(gEd, 4, 1); + } else { + lblGreen->hide(); + gEd->hide(); + } +#endif bEd = new QColSpinBox(this); lblBlue = new QLabel(this); @@ -1127,8 +1202,18 @@ QColorShower::QColorShower(QColorDialog *parent) lblBlue->setBuddy(bEd); #endif lblBlue->setAlignment(Qt::AlignRight|Qt::AlignVCenter); +#ifndef Q_WS_S60 gl->addWidget(lblBlue, 2, 3); gl->addWidget(bEd, 2, 4); +#else + if (nonTouchUI) { + gl->addWidget(lblBlue, 3, 2); + gl->addWidget(bEd, 4, 2); + } else { + lblBlue->hide(); + bEd->hide(); + } +#endif alphaEd = new QColSpinBox(this); alphaLab = new QLabel(this); @@ -1136,8 +1221,18 @@ QColorShower::QColorShower(QColorDialog *parent) alphaLab->setBuddy(alphaEd); #endif alphaLab->setAlignment(Qt::AlignRight|Qt::AlignVCenter); +#ifndef Q_WS_S60 gl->addWidget(alphaLab, 3, 1, 1, 3); gl->addWidget(alphaEd, 3, 4); +#else + if (nonTouchUI) { + gl->addWidget(alphaLab, 1, 3, 3, 1); + gl->addWidget(alphaEd, 4, 3); + } else { + alphaLab->hide(); + alphaEd->hide(); + } +#endif alphaEd->hide(); alphaLab->hide(); @@ -1369,7 +1464,7 @@ void QColorDialogPrivate::init(const QColor &initial) leftLay = 0; -#if defined(Q_WS_WINCE) +#if (defined(Q_WS_WINCE) || defined(Q_WS_S60)) smallDisplay = true; const int lumSpace = 20; #else @@ -1399,6 +1494,11 @@ void QColorDialogPrivate::init(const QColor &initial) } #endif +#if defined(Q_WS_S60) + QS60Data s60Data = QS60Data(); + const bool nonTouchUI = !s60Data.hasTouchscreen; +#endif + if (!smallDisplay) { standard = new QColorWell(q, 6, 8, stdrgb); lblBasicColors = new QLabel(q); @@ -1429,8 +1529,16 @@ void QColorDialogPrivate::init(const QColor &initial) leftLay->addWidget(addCusBt); } else { // better color picker size for small displays +#ifdef Q_WS_S60 + QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size(); + pWidth = pHeight = qMin(screenSize.width(), screenSize.height()); + pHeight -= 20; + if(screenSize.height() > screenSize.width()) + pWidth -= 20; +#else pWidth = 150; pHeight = 100; +#endif custom = 0; standard = 0; } @@ -1446,13 +1554,35 @@ void QColorDialogPrivate::init(const QColor &initial) cp = new QColorPicker(q); cp->setFrameStyle(QFrame::Panel + QFrame::Sunken); + +#if defined(Q_WS_S60) + if (!nonTouchUI) { + pickLay->addWidget(cp); + cLay->addSpacing(lumSpace); + } else { + cp->hide(); + } +#else cLay->addSpacing(lumSpace); cLay->addWidget(cp); +#endif cLay->addSpacing(lumSpace); lp = new QColorLuminancePicker(q); +#if defined(Q_WS_S60) + QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size(); + const int minDimension = qMin(screenSize.height(), screenSize.width()); + //set picker to be finger-usable + int pickerWidth = !nonTouchUI ? minDimension/9 : minDimension/12; + lp->setFixedWidth(pickerWidth); + if (!nonTouchUI) + pickLay->addWidget(lp); + else + lp->hide(); +#else lp->setFixedWidth(20); pickLay->addWidget(lp); +#endif QObject::connect(cp, SIGNAL(newCol(int,int)), lp, SLOT(setCol(int,int))); QObject::connect(lp, SIGNAL(newHsv(int,int,int)), q, SLOT(_q_newHsv(int,int,int))); @@ -1463,7 +1593,13 @@ void QColorDialogPrivate::init(const QColor &initial) QObject::connect(cs, SIGNAL(newCol(QRgb)), q, SLOT(_q_newColorTypedIn(QRgb))); QObject::connect(cs, SIGNAL(currentColorChanged(const QColor&)), q, SIGNAL(currentColorChanged(const QColor&))); +#if defined(Q_WS_S60) + if (!nonTouchUI) + pWidth -= cp->size().width(); + topLay->addWidget(cs); +#else rightLay->addWidget(cs); +#endif buttons = new QDialogButtonBox(q); mainLay->addWidget(buttons); @@ -1875,7 +2011,7 @@ void QColorDialog::done(int result) Q_D(QColorDialog); QDialog::done(result); if (result == Accepted) { - d->selectedQColor = d->currentQColor(); + d->selectedQColor = d->currentQColor(); emit colorSelected(d->selectedQColor); } else { d->selectedQColor = QColor(); diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index 40a5285..7df49fa 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -65,11 +65,19 @@ extern bool qt_wince_is_smartphone(); //is defined in qguifunctions_wce.cpp #elif defined(Q_WS_X11) # include "../kernel/qt_x11_p.h" #elif defined(Q_OS_SYMBIAN) -# include "qfiledialog.h" -# include "qmenubar.h" +# include "qfiledialog.h" +# include "qfontdialog.h" +# include "qcolordialog.h" +# include "qwizard.h" +# include "qmenubar.h" #endif + +#if defined(Q_WS_S60) +#include "private/qt_s60_p.h" +#endif + #ifndef SPI_GETSNAPTODEFBUTTON -# define SPI_GETSNAPTODEFBUTTON 95 +# define SPI_GETSNAPTODEFBUTTON 95 #endif QT_BEGIN_NAMESPACE @@ -370,7 +378,7 @@ void QDialogPrivate::resetModalitySetByOpen() resetModalityTo = -1; } -#ifdef Q_WS_WINCE +#if defined(Q_WS_WINCE) || defined(Q_WS_S60) #ifdef Q_WS_WINCE_WM void QDialogPrivate::_q_doneAction() { @@ -385,10 +393,15 @@ void QDialogPrivate::_q_doneAction() bool QDialog::event(QEvent *e) { bool result = QWidget::event(e); +#ifdef Q_WS_WINCE if (e->type() == QEvent::OkRequest) { accept(); result = true; } +#else + if ((e->type() == QEvent::StyleChange) || (e->type() == QEvent::Resize )) + adjustPosition(parentWidget()); +#endif return result; } #endif @@ -499,8 +512,9 @@ int QDialog::exec() menuBar = new QMenuBar(this); #endif - if (qobject_cast(this)) - showFullScreen(); + if (qobject_cast(this) || qobject_cast(this) || + qobject_cast(this) || qobject_cast(this)) + showMaximized(); else #endif // Q_OS_SYMBIAN @@ -816,6 +830,12 @@ void QDialog::adjustPosition(QWidget* w) return; #endif +#ifdef Q_WS_S60 + if (s60AdjustedPosition()) + //dialog has already been positioned + return; +#endif + QPoint p(0, 0); int extraw = 0, extrah = 0, scrn = 0; if (w) @@ -879,6 +899,44 @@ void QDialog::adjustPosition(QWidget* w) move(p); } +#if defined(Q_WS_S60) +/*! \internal */ +bool QDialog::s60AdjustedPosition() +{ + QPoint p; + const QSize mainAreaSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size(); + const int statusPaneHeight = (S60->screenHeightInPixels - mainAreaSize.height())>>1; + const bool doS60Positioning = !(isFullScreen()||isMaximized()); + if (doS60Positioning) { + // naive way to deduce screen orientation + if (S60->screenHeightInPixels > S60->screenWidthInPixels) { + p.setY(S60->screenHeightInPixels-height()-qt_TSize2QSize(S60->buttonGroupContainer()->Size()).height()); + p.setX(0); + } else { + const int scrollbarWidth = style()->pixelMetric(QStyle::PM_ScrollBarExtent); + TRect cbaRect = TRect(); + AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, cbaRect); + AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation(); + switch (cbaLocation) { + case AknLayoutUtils::EAknCbaLocationBottom: + p.setY(S60->screenHeightInPixels - height()-cbaRect.Height()); + p.setX((S60->screenWidthInPixels - width())>>1); + break; + case AknLayoutUtils::EAknCbaLocationRight: + p.setY((S60->screenHeightInPixels - height())>>1); + p.setX(qMax(0,S60->screenWidthInPixels-width()-scrollbarWidth-cbaRect.Width())); + break; + case AknLayoutUtils::EAknCbaLocationLeft: + p.setY((S60->screenHeightInPixels - height())>>1); + p.setX(qMax(0,scrollbarWidth+cbaRect.Width())); + break; + } + } + move(p); + } + return doS60Positioning; +} +#endif /*! \obsolete @@ -1038,8 +1096,17 @@ QSize QDialog::sizeHint() const return QSize(qMax(QWidget::sizeHint().width(), d->extension->sizeHint().width()), QWidget::sizeHint().height()); } - +#if defined(Q_WS_S60) + // if size is not fixed, try to adjust it according to S60 layoutting + if (minimumSize() != maximumSize()) { + // In S60, dialogs are always the width of screen (in portrait, regardless of current layout) + return QSize(qMax(S60->screenHeightInPixels, S60->screenWidthInPixels), QWidget::sizeHint().height()); + } else { + return QWidget::sizeHint(); + } +#else return QWidget::sizeHint(); +#endif //Q_WS_S60 } diff --git a/src/gui/dialogs/qdialog.h b/src/gui/dialogs/qdialog.h index 65aba06..694bff7 100644 --- a/src/gui/dialogs/qdialog.h +++ b/src/gui/dialogs/qdialog.h @@ -107,7 +107,7 @@ public Q_SLOTS: protected: QDialog(QDialogPrivate &, QWidget *parent, Qt::WindowFlags f = 0); -#ifdef Q_WS_WINCE +#if defined(Q_WS_WINCE) || defined(Q_WS_S60) bool event(QEvent *e); #endif void keyPressEvent(QKeyEvent *); @@ -119,11 +119,15 @@ protected: #endif bool eventFilter(QObject *, QEvent *); void adjustPosition(QWidget*); - private: Q_DECLARE_PRIVATE(QDialog) Q_DISABLE_COPY(QDialog) +#if defined(Q_WS_S60) + bool s60AdjustedPosition(); +#endif + + #ifdef Q_WS_WINCE_WM Q_PRIVATE_SLOT(d_func(), void _q_doneAction()) #endif diff --git a/src/gui/dialogs/qerrormessage.cpp b/src/gui/dialogs/qerrormessage.cpp index 37500bd..3fbfce7 100644 --- a/src/gui/dialogs/qerrormessage.cpp +++ b/src/gui/dialogs/qerrormessage.cpp @@ -68,6 +68,11 @@ extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp #include "qguifunctions_wince.h" #endif +#if defined(Q_WS_S60) +#include +#include "private/qt_s60_p.h" +#endif + QT_BEGIN_NAMESPACE class QErrorMessagePrivate : public QDialogPrivate @@ -86,6 +91,7 @@ public: bool nextPending(); void retranslateStrings(); + void enableSoftKey(bool enable); }; class QErrorMessageTextView : public QTextEdit @@ -124,8 +130,15 @@ QSize QErrorMessageTextView::sizeHint() const else return QSize(300, 100); #else + +#ifdef Q_WS_S60 + const int smallerDimension = qMin(S60->screenHeightInPixels, S60->screenWidthInPixels); + // In S60 layout data, error messages seem to be one third of the screen height (in portrait) minus two. + return QSize(smallerDimension, smallerDimension/3-2); +#else return QSize(250, 75); -#endif +#endif //Q_WS_S60 +#endif //Q_WS_WINCE } /*! @@ -239,7 +252,8 @@ QErrorMessage::QErrorMessage(QWidget * parent) d->again->setChecked(true); grid->addWidget(d->again, 1, 1, Qt::AlignTop); d->ok = new QPushButton(this); -#ifdef Q_WS_WINCE + +#if defined(Q_WS_WINCE) || defined(Q_WS_S60) d->ok->setFixedSize(0,0); #endif connect(d->ok, SIGNAL(clicked()), this, SLOT(accept())); @@ -272,6 +286,7 @@ QErrorMessage::~QErrorMessage() void QErrorMessage::done(int a) { Q_D(QErrorMessage); + d->enableSoftKey(false); if (!d->again->isChecked() && !d->currentMessage.isEmpty() && d->currentType.isEmpty()) { d->doNotShow.insert(d->currentMessage); } @@ -346,6 +361,10 @@ void QErrorMessage::showMessage(const QString &message) d->pending.enqueue(qMakePair(message,QString())); if (!isVisible() && d->nextPending()) show(); + +#ifdef Q_WS_S60 + d->enableSoftKey(true); +#endif } /*! @@ -370,6 +389,28 @@ void QErrorMessage::showMessage(const QString &message, const QString &type) d->pending.push_back(qMakePair(message,type)); if (!isVisible() && d->nextPending()) show(); + +#ifdef Q_WS_S60 + d->enableSoftKey(true); +#endif +} + +/*! \internal */ +void QErrorMessagePrivate::enableSoftKey(bool enable) +{ +#ifdef Q_WS_S60 + Q_Q(QErrorMessage); + if (enable) { + QAction *okAction = new QAction(ok->text(), q); + okAction->setSoftKeyRole(QAction::OkSoftKey); + QObject::connect(okAction, SIGNAL(triggered()), q, SLOT(accept())); + q->setSoftKey(okAction); + } else { + q->setSoftKey(0); + } +#else + Q_UNUSED(enable); +#endif } diff --git a/src/gui/dialogs/qfontdialog.cpp b/src/gui/dialogs/qfontdialog.cpp index bb53abe..ca882c5 100644 --- a/src/gui/dialogs/qfontdialog.cpp +++ b/src/gui/dialogs/qfontdialog.cpp @@ -65,6 +65,10 @@ #include #include +#if defined(Q_WS_S60) +#include +#endif + QT_BEGIN_NAMESPACE class QFontListView : public QListView @@ -312,6 +316,8 @@ void QFontDialogPrivate::init() #if defined(Q_WS_WINCE) q->resize(180, 120); +#elif defined(Q_WS_S60) + q->resize(QApplication::desktop()->availableGeometry(QCursor::pos()).size()); #else q->resize(500, 360); #endif // Q_WS_WINCE @@ -768,7 +774,11 @@ void QFontDialogPrivate::retranslateStrings() familyAccel->setText(QFontDialog::tr("&Font")); styleAccel->setText(QFontDialog::tr("Font st&yle")); sizeAccel->setText(QFontDialog::tr("&Size")); +#ifndef Q_WS_S60 + // Removed the title due to lack of screen estate in small S60 screen. + // The effects are descriptive without a title (strikeout, underline). effects->setTitle(QFontDialog::tr("Effects")); +#endif strikeout->setText(QFontDialog::tr("Stri&keout")); underline->setText(QFontDialog::tr("&Underline")); sample->setTitle(QFontDialog::tr("Sample")); @@ -792,7 +802,7 @@ void QFontDialog::changeEvent(QEvent *e) \property QFontDialog::currentFont \brief the current font of the dialog. -*/ +*/ /*! \since 4.5 @@ -816,7 +826,7 @@ void QFontDialog::setCurrentFont(const QFont &font) d->updateFamilies(); #ifdef Q_WS_MAC - if (d->delegate) + if (d->delegate) QFontDialogPrivate::setFont(d->delegate, font); #endif } diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index 6eae697..a318c43 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -310,6 +310,15 @@ void QMessageBoxPrivate::updateSize() } width = hardLimit; } +#ifdef Q_WS_S60 + // in S60 portait messageBoxes should always occupy maximum width + if (QApplication::desktop()->size().height() > QApplication::desktop()->size().width()){ + width = hardLimit; + } else { + // in landscape the messageBoxes should be of same width as in portrait + width = qMin(QApplication::desktop()->size().height(), hardLimit); + } +#endif } if (informativeLabel) { diff --git a/src/gui/dialogs/qprogressdialog.cpp b/src/gui/dialogs/qprogressdialog.cpp index cf2fae8..0a4c730 100644 --- a/src/gui/dialogs/qprogressdialog.cpp +++ b/src/gui/dialogs/qprogressdialog.cpp @@ -57,6 +57,11 @@ #include #include +#if defined(Q_WS_S60) +#include +#include +#endif + QT_BEGIN_NAMESPACE // If the operation is expected to take this long (as predicted by @@ -431,7 +436,16 @@ void QProgressDialog::setCancelButton(QPushButton *cancelButton) int h = qMax(isVisible() ? height() : 0, sizeHint().height()); resize(w, h); if (cancelButton) +#ifndef Q_WS_S60 cancelButton->show(); +#else + { + QAction *cancelAction = new QAction(cancelButton->text(), this); + cancelAction->setSoftKeyRole(QAction::CancelSoftKey); + QObject::connect(cancelAction, SIGNAL(triggered()), this, SIGNAL(canceled())); + setSoftKey(cancelAction); + } +#endif } /*! @@ -701,7 +715,14 @@ QSize QProgressDialog::sizeHint() const int h = margin * 2 + bh.height() + sh.height() + spacing; if (d->cancel) h += d->cancel->sizeHint().height() + spacing; +#ifdef Q_WS_S60 + if (QApplication::desktop()->size().height() > QApplication::desktop()->size().width()) + return QSize(qMax(QApplication::desktop()->size().width(), sh.width() + 2 * margin), h); + else + return QSize(qMax(QApplication::desktop()->size().height(), sh.width() + 2 * margin), h); +#else return QSize(qMax(200, sh.width() + 2 * margin), h); +#endif } /*!\reimp @@ -718,10 +739,11 @@ void QProgressDialog::resizeEvent(QResizeEvent *) void QProgressDialog::changeEvent(QEvent *ev) { Q_D(QProgressDialog); - if (ev->type() == QEvent::StyleChange) + if (ev->type() == QEvent::StyleChange) { d->layout(); - else if (ev->type() == QEvent::LanguageChange) + } else if (ev->type() == QEvent::LanguageChange) { d->retranslateStrings(); + } QDialog::changeEvent(ev); } diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp index f1744b0..055d0d4 100644 --- a/src/gui/dialogs/qwizard.cpp +++ b/src/gui/dialogs/qwizard.cpp @@ -75,6 +75,10 @@ extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp #include // for memset() +#ifdef Q_WS_S60 +#include "qaction.h" +#endif + QT_BEGIN_NAMESPACE // These fudge terms were needed a few places to obtain pixel-perfect results @@ -244,7 +248,7 @@ bool QWizardLayoutInfo::operator==(const QWizardLayoutInfo &other) return topLevelMarginLeft == other.topLevelMarginLeft && topLevelMarginRight == other.topLevelMarginRight && topLevelMarginTop == other.topLevelMarginTop - && topLevelMarginBottom == other.topLevelMarginBottom + && topLevelMarginBottom == other.topLevelMarginBottom && childMarginLeft == other.childMarginLeft && childMarginRight == other.childMarginRight && childMarginTop == other.childMarginTop @@ -328,7 +332,7 @@ bool QWizardHeader::vistaDisabled() const bool styleDisabled = false; QWizard *wiz = parentWidget() ? qobject_cast (parentWidget()->parentWidget()) : 0; if (wiz) { - // Designer dosen't support the Vista style for Wizards. This property is used to turn + // Designer dosen't support the Vista style for Wizards. This property is used to turn // off the Vista style. const QVariant v = wiz->property("_q_wizard_vista_off"); styleDisabled = v.isValid() && v.toBool(); @@ -634,9 +638,9 @@ static QString buttonDefaultText(int wstyle, int which, const QWizardPrivate *wi #endif const bool macStyle = (wstyle == QWizard::MacStyle); switch (which) { - case QWizard::BackButton: + case QWizard::BackButton: return macStyle ? QWizard::tr("Go Back") : QWizard::tr("< &Back"); - case QWizard::NextButton: + case QWizard::NextButton: if (macStyle) return QWizard::tr("Continue"); else @@ -959,12 +963,12 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info) if (modern) { mainLayout->setMargin(0); mainLayout->setSpacing(0); - pageVBoxLayout->setContentsMargins(deltaMarginLeft, deltaMarginTop, + pageVBoxLayout->setContentsMargins(deltaMarginLeft, deltaMarginTop, deltaMarginRight, deltaMarginBottom); - buttonLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop, + buttonLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop, info.topLevelMarginRight, info.topLevelMarginBottom); } else { - mainLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop, + mainLayout->setContentsMargins(info.topLevelMarginLeft, info.topLevelMarginTop, info.topLevelMarginRight, info.topLevelMarginBottom); mainLayout->setHorizontalSpacing(info.hspacing); mainLayout->setVerticalSpacing(info.vspacing); @@ -1212,7 +1216,7 @@ void QWizardPrivate::updateLayout() QSpacerItem *bottomSpacer = pageVBoxLayout->itemAt(pageVBoxLayout->count() - 1)->spacerItem(); Q_ASSERT(bottomSpacer); bottomSpacer->changeSize(0, 0, QSizePolicy::Ignored, expandPage ? QSizePolicy::Ignored : QSizePolicy::MinimumExpanding); - pageVBoxLayout->invalidate(); + pageVBoxLayout->invalidate(); } if (info.header) { @@ -1595,6 +1599,54 @@ void QWizardPrivate::_q_updateButtonStates() } #endif +#ifdef Q_WS_S60 + //FIXME: needs to considered later on, when we implement equivalent of Symbian OS's CleanPushResetAndDestroy + QList actionList; + QAbstractButton *wizardButton; + for (int i = QWizard::BackButton; i < QWizard::NButtons; ++i) { + wizardButton = btns[i]; + if (wizardButton && !wizardButton->testAttribute(Qt::WA_WState_Hidden)) { + wizardButton->hide(); + QAction *action = new QAction(wizardButton->text(), q); + QAction::SoftKeyRole softKeyRole; + switch(i) { + case QWizard::BackButton: + softKeyRole = QAction::PreviousSoftKey; + break; + case QWizard::NextButton: + softKeyRole = QAction::NextSoftKey; + break; + case QWizard::CommitButton: + softKeyRole = QAction::EndEditSoftKey; + break; + case QWizard::FinishButton: + softKeyRole = QAction::FinishSoftKey; + break; + case QWizard::CancelButton: + softKeyRole = QAction::CancelSoftKey; + break; + case QWizard::HelpButton: + softKeyRole = QAction::ViewSoftKey; + break; + case QWizard::CustomButton1: + softKeyRole = QAction::SelectSoftKey; + break; + case QWizard::CustomButton2: + softKeyRole = QAction::SelectSoftKey; + break; + case QWizard::CustomButton3: + softKeyRole = QAction::SelectSoftKey; + break; + } + action->setSoftKeyRole(softKeyRole); + QObject::connect(action, SIGNAL(triggered()), wizardButton, SIGNAL(clicked())); + actionList.append(action); + } + } + //FIXME: setup Options Menu if there are more than two actions (waiting for SoftKey refactoring) + q->setSoftKeys(actionList); +#endif + enableUpdates(); } @@ -2788,7 +2840,11 @@ QSize QWizard::sizeHint() const { Q_D(const QWizard); QSize result = d->mainLayout->totalSizeHint(); +#ifdef Q_WS_S60 + QSize extra(QApplication::desktop()->availableGeometry(QCursor::pos()).size()); +#else QSize extra(500, 360); +#endif if (d->wizStyle == MacStyle && d->current != -1) { QSize pixmap(currentPage()->pixmap(BackgroundPixmap).size()); extra.setWidth(616); @@ -3389,7 +3445,7 @@ bool QWizardPage::validatePage() changes. This ensures that QWizard updates the enabled or disabled state of its buttons. An example of the reimplementation is available \l{http://qt.nokia.com/doc/qq/qq22-qwizard.html#validatebeforeitstoolate} - {here}. + {here}. \sa completeChanged(), isFinalPage() */ diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp index ef0b7b2..5eac611 100644 --- a/src/gui/widgets/qdialogbuttonbox.cpp +++ b/src/gui/widgets/qdialogbuttonbox.cpp @@ -49,6 +49,14 @@ #include "qdialogbuttonbox.h" + +#ifdef Q_WS_S60 +#include +#include +#include +#endif + + QT_BEGIN_NAMESPACE /*! @@ -263,6 +271,9 @@ public: QList buttonLists[QDialogButtonBox::NRoles]; QHash standardButtonHash; +#ifdef Q_WS_S60 + QList softkeyActions; +#endif Qt::Orientation orientation; QDialogButtonBox::ButtonLayout layoutPolicy; @@ -282,6 +293,10 @@ public: void addButtonsToLayout(const QList &buttonList, bool reverse); void retranslateStrings(); const char *standardButtonText(QDialogButtonBox::StandardButton sbutton) const; +#ifdef Q_WS_S60 + void addSoftKeyAction(QAbstractButton *button, QDialogButtonBox::ButtonRole role); + void setSoftKeys(); +#endif }; QDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient) @@ -457,6 +472,18 @@ void QDialogButtonBoxPrivate::layoutButtons() if (center) buttonLayout->addStretch(); + +#ifdef Q_WS_S60 + QWidget *dialog = 0; + QWidget *p = q; + while (p && !p->isWindow()) { + p = p->parentWidget(); + if (dialog = qobject_cast(p)) + break; + } + if (dialog) + q->hide(); +#endif } QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardButton sbutton, @@ -540,6 +567,115 @@ void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBo layoutButtons(); } +/*! \internal */ +#ifdef Q_WS_S60 +void QDialogButtonBoxPrivate::addSoftKeyAction(QAbstractButton *button, QDialogButtonBox::ButtonRole role) +{ + Q_Q(QDialogButtonBox); + + QAction::SoftKeyRole softkeyRole; + QAction *buttonAction = new QAction(button->text(), q); + + switch (role) { + case ApplyRole: + case AcceptRole: + softkeyRole = QAction::OkSoftKey; + break; + case RejectRole: + softkeyRole = QAction::CancelSoftKey; + break; + case DestructiveRole: + softkeyRole = QAction::ExitSoftKey; + break; + case ActionRole: + case HelpRole: + softkeyRole = QAction::ViewSoftKey; //todo: uhh + break; + case YesRole: + softkeyRole = QAction::SelectSoftKey; + break; + case NoRole: + softkeyRole = QAction::DeselectSoftKey; + break; + case ResetRole: + softkeyRole = QAction::BackSoftKey; + break; + default: + break; + } + QObject::connect(buttonAction, SIGNAL(triggered()), button, SIGNAL(clicked())); + buttonAction->setSoftKeyRole(softkeyRole); + softkeyActions.append(buttonAction); +} + +/*! \internal */ +void QDialogButtonBoxPrivate::setSoftKeys() +{ + Q_Q(QDialogButtonBox); + + QDialog *dialog = 0; + QWidget *p = q; + while (p && !p->isWindow()) { + p = p->parentWidget(); + if ((dialog = qobject_cast(p))) + break; + } + if (dialog) { + softkeyActions.clear(); + const int buttonCount = q->buttons().count(); + for (int i=0; i< buttonCount; i++){ + QAbstractButton *button = q->buttons().at(i); + QDialogButtonBox::ButtonRole role = q->buttonRole(button); + addSoftKeyAction(button, role); + } + //Need to re-arrange softkeys, if there are too many actions. + if (softkeyActions.count() > 2){ + //FIXME- wait for Softkey API refactoring + /* + QAction *actionSoftKeyOption = new QAction(tr("Options"), this); + actionSoftKeyOption->setSoftKeyRole(QAction::OptionsSoftKey); + setSoftKey(actionSoftKeyOption); + + QMenuBar *menuBarOptions = new QMenuBar(q->parentWidget()); + menubarOptions->addActions(softkeyActions); + buttonLayout->setMenuBar(menuBar); + */ + //Set right softkey + softkeyActions.clear(); + QAction::SoftKeyRole softKeyAction; + QAbstractButton *lskButton; + QList &searchList = buttonLists[DestructiveRole]; + if (searchList.count() > 0){ + lskButton = searchList.at(0); + softKeyAction = QAction::ExitSoftKey; + } else { + searchList = buttonLists[RejectRole]; + if (searchList.count() > 0){ + lskButton = searchList.at(0); + softKeyAction = QAction::CancelSoftKey; + } else { + searchList = buttonLists[NoRole]; + if (searchList.count() > 0) { + lskButton = searchList.at(0); + softKeyAction = QAction::DeselectSoftKey; + } else { + //no good candidates, rely on SoftKey API + } + } + } + QAction *leftSoftKeyAction = new QAction(lskButton->text(), dialog); + leftSoftKeyAction->setSoftKeyRole(softKeyAction); + QObject::connect(leftSoftKeyAction, SIGNAL(triggered()), lskButton, SIGNAL(clicked())); + softkeyActions.append(leftSoftKeyAction); + dialog->setSoftKeys(softkeyActions); + } else { + dialog->setSoftKeys(softkeyActions); + } + } +} + +#endif + void QDialogButtonBoxPrivate::createStandardButtons(QDialogButtonBox::StandardButtons buttons) { uint i = QDialogButtonBox::FirstButton; @@ -1128,6 +1264,12 @@ bool QDialogButtonBox::event(QEvent *event) }else if (event->type() == QEvent::LanguageChange) { d->retranslateStrings(); } +#ifdef Q_WS_S60 + // Set the softkeys in polish, to avoid doing them several times, since each call causes flicker in the softkeys. + else if (event->type() == QEvent::Polish) { + d->setSoftKeys(); + } +#endif return QWidget::event(event); } diff --git a/tests/auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp b/tests/auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp index a1e0fc1..98eb7cb 100644 --- a/tests/auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp +++ b/tests/auto/qdialogbuttonbox/tst_qdialogbuttonbox.cpp @@ -109,6 +109,7 @@ private slots: void testSignalOrder(); void testDefaultButton_data(); void testDefaultButton(); + void testS60SoftKeys(); void task191642_default(); private: @@ -713,6 +714,27 @@ void tst_QDialogButtonBox::testDefaultButton_data() QTest::newRow("third accept explicit after add") << 0 << 2 << 2; } +void tst_QDialogButtonBox::testS60SoftKeys() +{ +#ifdef Q_WS_S60 + QDialog dialog(0); + QDialogButtonBox buttonBox(&dialog); + buttonBox.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + dialog.show(); + QList softKeys = dialog.softKeys(); + QCOMPARE( softKeys.count(), 2); + + QDialog dialog2(0); + QDialogButtonBox buttonBox2(&dialog2); + buttonBox2.setStandardButtons(QDialogButtonBox::Cancel); + dialog2.show(); + softKeys = dialog2.softKeys(); + QCOMPARE( softKeys.count(), 1); +#else + QSKIP(); +#endif +} + void tst_QDialogButtonBox::testDefaultButton() { QFETCH(int, whenToSetDefault); -- cgit v0.12