diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2009-09-29 04:09:01 (GMT) |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2009-09-29 04:09:01 (GMT) |
commit | 575ad2c60482b279f828cfa87186b5fbb10f76c6 (patch) | |
tree | 101df52cd4b769dc8d10ef60714f25d819636e70 /src/gui | |
parent | a913e326409062bbc1cad4d5898181c7b81cba23 (diff) | |
parent | 638f46a96b68d21137c4903c68015752ebdf58dc (diff) | |
download | Qt-575ad2c60482b279f828cfa87186b5fbb10f76c6.zip Qt-575ad2c60482b279f828cfa87186b5fbb10f76c6.tar.gz Qt-575ad2c60482b279f828cfa87186b5fbb10f76c6.tar.bz2 |
Merge branch '4.6' of git@scm.dev.nokia.troll.no:qt/qt into kinetic-declarativeui
Conflicts:
configure.exe
mkspecs/features/qt.prf
Diffstat (limited to 'src/gui')
163 files changed, 3533 insertions, 1989 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<QFileDialog *>(this)) - showFullScreen(); + if (qobject_cast<QFileDialog *>(this) || qobject_cast<QFontDialog *>(this) || + qobject_cast<QColorDialog *>(this) || qobject_cast<QWizard *>(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..436ef94 100644 --- a/src/gui/dialogs/qerrormessage.cpp +++ b/src/gui/dialogs/qerrormessage.cpp @@ -68,6 +68,13 @@ extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp #include "qguifunctions_wince.h" #endif +#if defined(QT_SOFTKEYS_ENABLED) +#include <qaction.h> +#ifdef Q_WS_S60 +#include "private/qt_s60_p.h" +#endif +#endif + QT_BEGIN_NAMESPACE class QErrorMessagePrivate : public QDialogPrivate @@ -78,6 +85,9 @@ public: QCheckBox * again; QTextEdit * errors; QLabel * icon; +#ifdef QT_SOFTKEYS_ENABLED + QAction *okAction; +#endif QQueue<QPair<QString, QString> > pending; QSet<QString> doNotShow; QSet<QString> doNotShowType; @@ -124,8 +134,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 } /*! @@ -228,6 +245,12 @@ QErrorMessage::QErrorMessage(QWidget * parent) Q_D(QErrorMessage); QGridLayout * grid = new QGridLayout(this); d->icon = new QLabel(this); +#ifdef QT_SOFTKEYS_ENABLED + d->okAction = new QAction(this); + d->okAction->setSoftKeyRole(QAction::PositiveSoftKey); + connect(d->okAction, SIGNAL(triggered()), this, SLOT(accept())); + addAction(d->okAction); +#endif #ifndef QT_NO_MESSAGEBOX d->icon->setPixmap(QMessageBox::standardIcon(QMessageBox::Information)); d->icon->setAlignment(Qt::AlignHCenter | Qt::AlignTop); @@ -239,7 +262,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())); @@ -372,7 +396,6 @@ void QErrorMessage::showMessage(const QString &message, const QString &type) show(); } - /*! \reimp */ @@ -389,6 +412,9 @@ void QErrorMessagePrivate::retranslateStrings() { again->setText(QErrorMessage::tr("&Show this message again")); ok->setText(QErrorMessage::tr("&OK")); +#ifdef QT_SOFTKEYS_ENABLED + okAction->setText(ok->text()); +#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 <private/qdialog_p.h> #include <private/qfont_p.h> +#if defined(Q_WS_S60) +#include <QtGui/qdesktopwidget.h> +#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/qnspanelproxy_mac.mm b/src/gui/dialogs/qnspanelproxy_mac.mm index 97ad287..4f6ff90 100644 --- a/src/gui/dialogs/qnspanelproxy_mac.mm +++ b/src/gui/dialogs/qnspanelproxy_mac.mm @@ -144,14 +144,21 @@ void macStartIntercept(SEL originalSel, SEL fakeSel, Class baseClass, Class prox #endif { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + // The following code replaces the _implementation_ for the selector we want to hack + // (originalSel) with the implementation found in proxyClass. Then it creates + // a new 'backup' method inside baseClass containing the old, original, + // implementation (fakeSel). You can let the proxy implementation of originalSel + // call fakeSel if needed (similar approach to calling a super class implementation). + // fakeSel must also be implemented in proxyClass, as the signature is used + // as template for the method one we add into baseClass. + // NB: You will typically never create any instances of proxyClass; we use it + // only for stealing its contents and put it into baseClass. Method originalMethod = class_getInstanceMethod(baseClass, originalSel); Method newMethod = class_getInstanceMethod(proxyClass, originalSel); Method fakeMethod = class_getInstanceMethod(proxyClass, fakeSel); - IMP originalCtorImp = method_setImplementation(originalMethod, - method_getImplementation(newMethod)); - class_addMethod(baseClass, fakeSel, originalCtorImp, - method_getTypeEncoding(fakeMethod)); + IMP originalImp = method_setImplementation(originalMethod, method_getImplementation(newMethod)); + class_addMethod(baseClass, fakeSel, originalImp, method_getTypeEncoding(fakeMethod)); #endif } } diff --git a/src/gui/dialogs/qprintdialog_win.cpp b/src/gui/dialogs/qprintdialog_win.cpp index 1a3d2de..f66c27f 100644 --- a/src/gui/dialogs/qprintdialog_win.cpp +++ b/src/gui/dialogs/qprintdialog_win.cpp @@ -131,8 +131,8 @@ static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWidget *parent, if (d->ep->printToFile) pd->Flags |= PD_PRINTTOFILE; - Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); - pd->hwndOwner = parent ? parent->winId() : 0; + Q_ASSERT(parent != 0 && parent->testAttribute(Qt::WA_WState_Created)); + pd->hwndOwner = parent->winId(); pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage()); pd->lpPageRanges[0].nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1; pd->nCopies = d->ep->num_copies; @@ -212,6 +212,10 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally() else parent = QApplication::activeWindow(); + // If there is no window, fall back to the print dialog itself + if (parent == 0) + parent = q; + QWidget modal_widget; modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); modal_widget.setParent(parent, Qt::Window); diff --git a/src/gui/dialogs/qprogressdialog.cpp b/src/gui/dialogs/qprogressdialog.cpp index cf2fae8..5fb10bf 100644 --- a/src/gui/dialogs/qprogressdialog.cpp +++ b/src/gui/dialogs/qprogressdialog.cpp @@ -57,6 +57,14 @@ #include <private/qdialog_p.h> #include <limits.h> +#if defined(QT_SOFTKEYS_ENABLED) +#include <qaction.h> +#endif +#ifdef Q_WS_S60 +#include <QtGui/qdesktopwidget.h> +#endif + + QT_BEGIN_NAMESPACE // If the operation is expected to take this long (as predicted by @@ -77,6 +85,9 @@ public: #ifndef QT_NO_SHORTCUT escapeShortcut(0), #endif +#ifdef QT_SOFTKEYS_ENABLED + cancelAction(0), +#endif useDefaultCancelText(false) { } @@ -103,6 +114,9 @@ public: #ifndef QT_NO_SHORTCUT QShortcut *escapeShortcut; #endif +#ifdef QT_SOFTKEYS_ENABLED + QAction *cancelAction; +#endif bool useDefaultCancelText; QPointer<QObject> receiverToDisconnectOnClose; QByteArray memberToDisconnectOnClose; @@ -410,6 +424,10 @@ void QProgressDialog::setCancelButton(QPushButton *cancelButton) { Q_D(QProgressDialog); delete d->cancel; +#ifdef QT_SOFTKEYS_ENABLED + delete d->cancelAction; + d->cancelAction = 0; +#endif d->cancel = cancelButton; if (cancelButton) { if (cancelButton->parentWidget() == this) { @@ -431,7 +449,16 @@ void QProgressDialog::setCancelButton(QPushButton *cancelButton) int h = qMax(isVisible() ? height() : 0, sizeHint().height()); resize(w, h); if (cancelButton) +#if !defined(QT_SOFTKEYS_ENABLED) cancelButton->show(); +#else + { + d->cancelAction = new QAction(cancelButton->text(), this); + d->cancelAction->setSoftKeyRole(QAction::NegativeSoftKey); + connect(d->cancelAction, SIGNAL(triggered()), this, SIGNAL(canceled())); + addAction(d->cancelAction); + } +#endif } /*! @@ -448,10 +475,14 @@ void QProgressDialog::setCancelButtonText(const QString &cancelButtonText) d->useDefaultCancelText = false; if (!cancelButtonText.isNull()) { - if (d->cancel) + if (d->cancel) { d->cancel->setText(cancelButtonText); - else +#ifdef QT_SOFTKEYS_ENABLED + d->cancelAction->setText(cancelButtonText); +#endif + } else { setCancelButton(new QPushButton(cancelButtonText, this)); + } } else { setCancelButton(0); } @@ -701,7 +732,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 +756,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..0f6d353 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 <string.h> // for memset() +#ifdef QT_SOFTKEYS_ENABLED +#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 <QWizard *>(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(); @@ -523,8 +527,12 @@ public: , maximumWidth(QWIDGETSIZE_MAX) , maximumHeight(QWIDGETSIZE_MAX) { - for (int i = 0; i < QWizard::NButtons; ++i) + for (int i = 0; i < QWizard::NButtons; ++i) { btns[i] = 0; +#ifdef QT_SOFTKEYS_ENABLED + softKeys[i] = 0; +#endif + } #if !defined(QT_NO_STYLE_WINDOWSVISTA) if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) @@ -609,6 +617,9 @@ public: QLabel *titleLabel; QLabel *subTitleLabel; QWizardRuler *bottomRuler; +#ifdef QT_SOFTKEYS_ENABLED + mutable QAction *softKeys[QWizard::NButtons]; +#endif QVBoxLayout *pageVBoxLayout; QHBoxLayout *buttonLayout; @@ -634,9 +645,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 +970,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 +1223,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) { @@ -1327,6 +1338,29 @@ bool QWizardPrivate::ensureButton(QWizard::WizardButton which) const #endif if (which < QWizard::NStandardButtons) pushButton->setText(buttonDefaultText(wizStyle, which, this)); + +#ifdef QT_SOFTKEYS_ENABLED + QAction *softKey = new QAction(pushButton->text(), antiFlickerWidget); + QAction::SoftKeyRole softKeyRole; + switch(which) { + case QWizard::NextButton: + case QWizard::FinishButton: + case QWizard::CancelButton: + softKeyRole = QAction::NegativeSoftKey; + break; + case QWizard::BackButton: + case QWizard::CommitButton: + case QWizard::HelpButton: + case QWizard::CustomButton1: + case QWizard::CustomButton2: + case QWizard::CustomButton3: + default: + softKeyRole = QAction::PositiveSoftKey; + break; + } + softKey->setSoftKeyRole(softKeyRole); + softKeys[which] = softKey; +#endif connectButton(which); } return true; @@ -1340,6 +1374,10 @@ void QWizardPrivate::connectButton(QWizard::WizardButton which) const } else { QObject::connect(btns[which], SIGNAL(clicked()), q, SLOT(_q_emitCustomButtonClicked())); } + +#ifdef QT_SOFTKEYS_ENABLED + QObject::connect(softKeys[which], SIGNAL(triggered()), btns[which], SIGNAL(clicked())); +#endif } void QWizardPrivate::updateButtonTexts() @@ -1353,6 +1391,9 @@ void QWizardPrivate::updateButtonTexts() btns[i]->setText(buttonCustomTexts.value(i)); else if (i < QWizard::NStandardButtons) btns[i]->setText(buttonDefaultText(wizStyle, i, this)); +#ifdef QT_SOFTKEYS_ENABLED + softKeys[i]->setText(btns[i]->text()); +#endif } } } @@ -1595,6 +1636,19 @@ void QWizardPrivate::_q_updateButtonStates() } #endif +#ifdef QT_SOFTKEYS_ENABLED + QAbstractButton *wizardButton; + for (int i = 0; i < QWizard::NButtons; ++i) { + wizardButton = btns[i]; + if (wizardButton && !wizardButton->testAttribute(Qt::WA_WState_Hidden)) { + wizardButton->hide(); + q->addAction(softKeys[i]); + } else { + q->removeAction(softKeys[i]); + } + } +#endif + enableUpdates(); } @@ -2788,7 +2842,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 +3447,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/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index ee87323..eee9bbf 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -777,7 +777,7 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou A blur effect blurs the source. This effect is useful for reducing details, such as when the source loses focus and you want to draw attention to other elements. The level of detail can be modified using the setBlurRadius() - function. + function. Use setBlurHint() to choose the quality or performance blur hints. By default, the blur radius is 5 pixels. @@ -795,7 +795,7 @@ QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent) { Q_D(QGraphicsBlurEffect); - d->filter->setQuality(Qt::SmoothTransformation); + d->filter->setBlurHint(QPixmapBlurFilter::PerformanceHint); } /*! @@ -839,6 +839,54 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) */ /*! + \enum QGraphicsBlurEffect::BlurHint + + \since 4.6 + + This enum describes the hint of a blur graphics effect. + + \value PerformanceHint Using this value hints that performance is the + most important factor, at the potential cost of lower quality. + + \value QualityHint Using this value hints that a higher quality blur is + preferred over a fast blur. +*/ + +/*! + \property QGraphicsBlurEffect::blurHint + \brief the blur hint of the effect. + + Use the PerformanceHint blur hint to say that you want a faster blur, + and the QualityHint blur hint to say that you prefer a higher quality blur. + + When animating the blur radius it's recommended to use the PerformanceHint. + + By default, the blur hint is PerformanceHint. +*/ +QGraphicsBlurEffect::BlurHint QGraphicsBlurEffect::blurHint() const +{ + Q_D(const QGraphicsBlurEffect); + return BlurHint(d->filter->blurHint()); +} + +void QGraphicsBlurEffect::setBlurHint(QGraphicsBlurEffect::BlurHint hint) +{ + Q_D(QGraphicsBlurEffect); + if (BlurHint(d->filter->blurHint()) == hint) + return; + + d->filter->setBlurHint(QPixmapBlurFilter::BlurHint(hint)); + emit blurHintChanged(hint); +} + +/*! + \fn void QGraphicsBlurEffect::blurHintChanged(QGraphicsBlurEffect::BlurHint hint) + + This signal is emitted whenever the effect's blur hint changes. + The \a hint parameter holds the effect's new blur hint. +*/ + +/*! \reimp */ QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 5062826..c256381 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -224,18 +224,27 @@ class Q_GUI_EXPORT QGraphicsBlurEffect: public QGraphicsEffect { Q_OBJECT Q_PROPERTY(int blurRadius READ blurRadius WRITE setBlurRadius NOTIFY blurRadiusChanged) + Q_PROPERTY(BlurHint blurHint READ blurHint WRITE setBlurHint NOTIFY blurHintChanged) public: + enum BlurHint { + PerformanceHint, + QualityHint + }; + QGraphicsBlurEffect(QObject *parent = 0); ~QGraphicsBlurEffect(); QRectF boundingRectFor(const QRectF &rect) const; int blurRadius() const; + BlurHint blurHint() const; public Q_SLOTS: void setBlurRadius(int blurRadius); + void setBlurHint(BlurHint blurHint); Q_SIGNALS: void blurRadiusChanged(int blurRadius); + void blurHintChanged(BlurHint blurHint); protected: void draw(QPainter *painter, QGraphicsEffectSource *source); diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 222524e..840b9d6 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -47,21 +47,31 @@ QT_BEGIN_NAMESPACE +// Current GL and VG contexts. These are used to determine if +// we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent(). +// If a background thread modifies the value, the worst that will +// happen is a redundant eglMakeCurrent() in the foreground thread. +static QEglContext * volatile currentGLContext = 0; +static QEglContext * volatile currentVGContext = 0; + QEglContext::QEglContext() : apiType(QEgl::OpenGL) , dpy(EGL_NO_DISPLAY) , ctx(EGL_NO_CONTEXT) - , surf(EGL_NO_SURFACE) , cfg(0) - , share(false) + , currentSurface(EGL_NO_SURFACE) , current(false) - , reserved(0) { } QEglContext::~QEglContext() { destroy(); + + if (currentGLContext == this) + currentGLContext = 0; + if (currentVGContext == this) + currentVGContext = 0; } bool QEglContext::isValid() const @@ -69,11 +79,6 @@ bool QEglContext::isValid() const return (ctx != EGL_NO_CONTEXT); } -bool QEglContext::isSharing() const -{ - return share; -} - bool QEglContext::isCurrent() const { return current; @@ -148,7 +153,7 @@ bool QEglContext::chooseConfig } // Create the EGLContext. -bool QEglContext::createContext(QEglContext *shareContext) +bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties) { // We need to select the correct API before calling eglCreateContext(). #ifdef EGL_OPENGL_ES_API @@ -162,6 +167,8 @@ bool QEglContext::createContext(QEglContext *shareContext) // Create a new context for the configuration. QEglProperties contextProps; + if (properties) + contextProps = *properties; #if defined(QT_OPENGL_ES_2) if (apiType == QEgl::OpenGL) contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2); @@ -182,31 +189,17 @@ bool QEglContext::createContext(QEglContext *shareContext) return false; } } - share = (shareContext != 0); return true; } -// Recreate the surface for a paint device because the native id has changed. -bool QEglContext::recreateSurface(QPaintDevice *device) -{ - // Bail out if the surface has not been created for the first time yet. - if (surf == EGL_NO_SURFACE) - return true; - - // Destroy the old surface. - eglDestroySurface(dpy, surf); - surf = EGL_NO_SURFACE; - - // Create a new one. - return createSurface(device); -} - -// Destroy the EGL surface object. -void QEglContext::destroySurface() +// Destroy an EGL surface object. If it was current on this context +// then call doneCurrent() for it first. +void QEglContext::destroySurface(EGLSurface surface) { - if (surf != EGL_NO_SURFACE) { - eglDestroySurface(dpy, surf); - surf = EGL_NO_SURFACE; + if (surface != EGL_NO_SURFACE) { + if (surface == currentSurface) + doneCurrent(); + eglDestroySurface(dpy, surface); } } @@ -217,21 +210,28 @@ void QEglContext::destroy() eglDestroyContext(dpy, ctx); dpy = EGL_NO_DISPLAY; ctx = EGL_NO_CONTEXT; - surf = EGL_NO_SURFACE; cfg = 0; - share = false; } -bool QEglContext::makeCurrent() +bool QEglContext::makeCurrent(EGLSurface surface) { if (ctx == EGL_NO_CONTEXT) { qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current"; return false; } + // If lazyDoneCurrent() was called on the surface, then we may be able + // to assume that it is still current within the thread. + if (surface == currentSurface && currentContext(apiType) == this) { + current = true; + return true; + } + current = true; + currentSurface = surface; + setCurrentContext(apiType, this); - bool ok = eglMakeCurrent(dpy, surf, surf, ctx); + bool ok = eglMakeCurrent(dpy, surface, surface, ctx); if (!ok) qWarning() << "QEglContext::makeCurrent():" << errorString(eglGetError()); return ok; @@ -245,6 +245,8 @@ bool QEglContext::doneCurrent() return false; current = false; + currentSurface = EGL_NO_SURFACE; + setCurrentContext(apiType, 0); // We need to select the correct API before calling eglMakeCurrent() // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG @@ -264,12 +266,23 @@ bool QEglContext::doneCurrent() return ok; } -bool QEglContext::swapBuffers() +// Act as though doneCurrent() was called, but keep the context +// and the surface active for the moment. This allows makeCurrent() +// to skip a call to eglMakeCurrent() if we are using the same +// surface as the last set of painting operations. We leave the +// currentContext() pointer as-is for now. +bool QEglContext::lazyDoneCurrent() +{ + current = false; + return true; +} + +bool QEglContext::swapBuffers(EGLSurface surface) { if(ctx == EGL_NO_CONTEXT) return false; - bool ok = eglSwapBuffers(dpy, surf); + bool ok = eglSwapBuffers(dpy, surface); if (!ok) qWarning() << "QEglContext::swapBuffers():" << errorString(eglGetError()); return ok; @@ -305,15 +318,6 @@ void QEglContext::waitClient() #endif } -// Query the actual size of the EGL surface. -QSize QEglContext::surfaceSize() const -{ - int w, h; - eglQuerySurface(dpy, surf, EGL_WIDTH, &w); - eglQuerySurface(dpy, surf, EGL_HEIGHT, &h); - return QSize(w, h); -} - // Query the value of a configuration attribute. bool QEglContext::configAttrib(int name, EGLint *value) const { @@ -411,4 +415,20 @@ bool QEglContext::hasExtension(const char* extensionName) return extensions().contains(QLatin1String(extensionName)); } +QEglContext *QEglContext::currentContext(QEgl::API api) +{ + if (api == QEgl::OpenGL) + return currentGLContext; + else + return currentVGContext; +} + +void QEglContext::setCurrentContext(QEgl::API api, QEglContext *context) +{ + if (api == QEgl::OpenGL) + currentGLContext = context; + else + currentVGContext = context; +} + QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index 366bd9e..dc399da 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -80,7 +80,6 @@ public: ~QEglContext(); bool isValid() const; - bool isSharing() const; bool isCurrent() const; QEgl::API api() const { return apiType; } @@ -88,22 +87,20 @@ public: bool openDisplay(QPaintDevice *device); bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat); - bool createContext(QEglContext *shareContext = 0); - bool createSurface(QPaintDevice *device, const QEglProperties *properties = 0); - bool recreateSurface(QPaintDevice *device); - void destroySurface(); + bool createContext(QEglContext *shareContext = 0, const QEglProperties *properties = 0); + EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0); + void destroySurface(EGLSurface surface); void destroy(); - bool makeCurrent(); + bool makeCurrent(EGLSurface surface); bool doneCurrent(); - bool swapBuffers(); + bool lazyDoneCurrent(); + bool swapBuffers(EGLSurface surface); void waitNative(); void waitClient(); - QSize surfaceSize() const; - bool configAttrib(int name, EGLint *value) const; static void clearError() { eglGetError(); } @@ -111,10 +108,12 @@ public: static QString errorString(EGLint code); EGLDisplay display() const { return dpy; } + EGLContext context() const { return ctx; } - EGLSurface surface() const { return surf; } - void setSurface(EGLSurface surface) { surf = surface; } + void setContext(EGLContext context) { ctx = context; } + EGLConfig config() const { return cfg; } + void setConfig(EGLConfig config) { cfg = config; } QEglProperties configProperties(EGLConfig cfg = 0) const; @@ -129,13 +128,14 @@ private: QEgl::API apiType; EGLDisplay dpy; EGLContext ctx; - EGLSurface surf; EGLConfig cfg; - bool share; + EGLSurface currentSurface; bool current; - void *reserved; // For extension data in future versions. static EGLDisplay getDisplay(QPaintDevice *device); + + static QEglContext *currentContext(QEgl::API api); + static void setCurrentContext(QEgl::API api, QEglContext *context); }; QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_qws.cpp b/src/gui/egl/qegl_qws.cpp index 2754589..590b666 100644 --- a/src/gui/egl/qegl_qws.cpp +++ b/src/gui/egl/qegl_qws.cpp @@ -57,11 +57,11 @@ QT_BEGIN_NAMESPACE // We don't have QGLScreen to create EGL surfaces for us, // so surface creation needs to be done in QtOpenGL or // QtOpenVG for Qt/Embedded. -bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { Q_UNUSED(device); Q_UNUSED(properties); - return false; + return EGL_NO_SURFACE; } EGLDisplay QEglContext::getDisplay(QPaintDevice *device) diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp index fa0b5cb..2101f0b 100644 --- a/src/gui/egl/qegl_symbian.cpp +++ b/src/gui/egl/qegl_symbian.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE -bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { // Create the native drawable for the paint device. int devType = device->devType(); @@ -67,7 +67,7 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop } if (!ok) { qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); - return false; + return EGL_NO_SURFACE; } // Create the EGL surface to draw into, based on the native drawable. @@ -76,15 +76,14 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop props = properties->properties(); else props = 0; + EGLSurface surf; if (devType == QInternal::Widget) surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0); else surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, 0); - if (surf == EGL_NO_SURFACE) { + if (surf == EGL_NO_SURFACE) qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); - return false; - } - return true; + return surf; } EGLDisplay QEglContext::getDisplay(QPaintDevice *device) diff --git a/src/gui/egl/qegl_wince.cpp b/src/gui/egl/qegl_wince.cpp index e07d748..bf07f85 100644 --- a/src/gui/egl/qegl_wince.cpp +++ b/src/gui/egl/qegl_wince.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE -bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { // Create the native drawable for the paint device. int devType = device->devType(); @@ -67,7 +67,7 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop } if (!ok) { qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); - return false; + return EGL_NO_SURFACE; } // Create the EGL surface to draw into, based on the native drawable. @@ -76,15 +76,15 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop props = properties->properties(); else props = 0; + EGLSurface surf; if (devType == QInternal::Widget) surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props); else surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, props); if (surf == EGL_NO_SURFACE) { qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); - return false; } - return true; + return surf; } EGLDisplay QEglContext::getDisplay(QPaintDevice *device) diff --git a/src/gui/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp index 5f34f8e..9d556a8 100644 --- a/src/gui/egl/qegl_x11.cpp +++ b/src/gui/egl/qegl_x11.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE -bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) +EGLSurface QEglContext::createSurface(QPaintDevice *device, const QEglProperties *properties) { // Create the native drawable for the paint device. int devType = device->devType(); @@ -72,7 +72,7 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop } if (!ok) { qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); - return false; + return EGL_NO_SURFACE; } // Create the EGL surface to draw into, based on the native drawable. @@ -81,6 +81,7 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop props = properties->properties(); else props = 0; + EGLSurface surf; if (devType == QInternal::Widget) surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, props); else @@ -88,9 +89,8 @@ bool QEglContext::createSurface(QPaintDevice *device, const QEglProperties *prop if (surf == EGL_NO_SURFACE) { qWarning() << "QEglContext::createSurface(): Unable to create EGL surface:" << errorString(eglGetError()); - return false; } - return true; + return surf; } EGLDisplay QEglContext::getDisplay(QPaintDevice *device) diff --git a/src/gui/embedded/directfb.pri b/src/gui/embedded/directfb.pri index 43ff0c7..fa4dd68 100644 --- a/src/gui/embedded/directfb.pri +++ b/src/gui/embedded/directfb.pri @@ -14,7 +14,7 @@ #DEFINES += QT_NO_DIRECTFB_KEYBOARD #DEFINES += QT_DIRECTFB_TIMING #DEFINES += QT_NO_DIRECTFB_OPAQUE_DETECTION -#DIRECTFB_DRAWINGOPERATIONS=DRAW_RECTS|DRAW_LINES|DRAW_IMAGE|DRAW_PIXMAP|DRAW_TILED_PIXMAP|STROKE_PATH|DRAW_PATH|DRAW_POINTS|DRAW_ELLIPSE|DRAW_POLYGON|DRAW_TEXT|FILL_PATH|FILL_RECT|DRAW_COLORSPANS +#DIRECTFB_DRAWINGOPERATIONS=DRAW_RECTS|DRAW_LINES|DRAW_IMAGE|DRAW_PIXMAP|DRAW_TILED_PIXMAP|STROKE_PATH|DRAW_PATH|DRAW_POINTS|DRAW_ELLIPSE|DRAW_POLYGON|DRAW_TEXT|FILL_PATH|FILL_RECT|DRAW_COLORSPANS|DRAW_ROUNDED_RECT #DEFINES += \"QT_DIRECTFB_WARN_ON_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\" #DEFINES += \"QT_DIRECTFB_DISABLE_RASTERFALLBACKS=$$DIRECTFB_DRAWINGOPERATIONS\" diff --git a/src/gui/embedded/qscreenmulti_qws.cpp b/src/gui/embedded/qscreenmulti_qws.cpp index beeb6aa..3a23ca2 100644 --- a/src/gui/embedded/qscreenmulti_qws.cpp +++ b/src/gui/embedded/qscreenmulti_qws.cpp @@ -46,6 +46,7 @@ #include <qlist.h> #include <qstringlist.h> #include <qwidget.h> +#include <qdebug.h> QT_BEGIN_NAMESPACE @@ -230,6 +231,9 @@ bool QMultiScreen::connect(const QString &displaySpec) QStringList specs = dSpec.split(QLatin1Char(' '), QString::SkipEmptyParts); foreach (QString spec, specs) { const int id = getDisplayId(spec); + if (spec.startsWith("vnc:", Qt::CaseInsensitive)) { + spec.append(":noDisablePainting"); + } const QPoint offset = filterDisplayOffset(spec); QScreen *s = qt_get_screen(id, spec.toLatin1().constData()); s->setOffset(offset); diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 7041d58..49aabf5 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -542,7 +542,7 @@ static bool simplifySequentialChunk(Graph<AnchorVertex, AnchorData> *graph, void QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) { static bool noSimplification = !qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); - if (noSimplification) + if (noSimplification || items.isEmpty()) return; if (graphSimplified[orientation]) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 81eeb39..c3934c7 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -982,12 +982,10 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) QGraphicsItem *p = newParent; while (p) { if (p->flags() & QGraphicsItem::ItemIsFocusScope) { - // ### We really want the parent's focus scope item to point - // to this item's focusItem... - if (q_ptr->flags() & QGraphicsItem::ItemIsFocusScope) - p->d_ptr->focusScopeItem = q_ptr; - else - p->d_ptr->focusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem; + p->d_ptr->focusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem; + // ### The below line might not make sense... + if (subFocusItem) + subFocusItem->d_ptr->clearSubFocus(); break; } p = p->d_ptr->parent; @@ -1481,6 +1479,7 @@ QList<QGraphicsItem *> QGraphicsItem::children() const */ QList<QGraphicsItem *> QGraphicsItem::childItems() const { + const_cast<QGraphicsItem *>(this)->d_ptr->ensureSortedChildren(); return d_ptr->children; } @@ -2812,15 +2811,12 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim if (scene && scene->focusItem() == f) return; - // Update the child focus chain. - setSubFocus(); - // Update focus scope item ptr. QGraphicsItem *p = parent; while (p) { if (p->flags() & QGraphicsItem::ItemIsFocusScope) { p->d_ptr->focusScopeItem = q_ptr; - if (!q_ptr->isActive()) + if (!q_ptr->isActive() || !p->focusItem()) return; break; } @@ -2830,10 +2826,11 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim if (climb) { while (f->d_ptr->focusScopeItem && f->d_ptr->focusScopeItem->isVisible()) f = f->d_ptr->focusScopeItem; - if (f != q_ptr) - f->d_ptr->setSubFocus(); } + // Update the child focus chain. + f->d_ptr->setSubFocus(); + // Update the scene's focus item. if (scene) { QGraphicsItem *p = q_ptr->panel(); @@ -2858,13 +2855,15 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim void QGraphicsItem::clearFocus() { // Pass focus to the closest parent focus scope. - QGraphicsItem *p = d_ptr->parent; - while (p) { - if (p->flags() & ItemIsFocusScope) { - p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false); - return; + if (!d_ptr->inDestructor) { + QGraphicsItem *p = d_ptr->parent; + while (p) { + if (p->flags() & ItemIsFocusScope) { + p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false); + return; + } + p = p->d_ptr->parent; } - p = p->d_ptr->parent; } // Invisible items with focus must explicitly clear subfocus. @@ -4050,6 +4049,82 @@ void QGraphicsItem::setZValue(qreal z) } /*! + \internal + + Ensures that the list of children is sorted by insertion order, and that + the siblingIndexes are packed (no gaps), and start at 0. + + ### This function is almost identical to + QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes(). +*/ +void QGraphicsItemPrivate::ensureSequentialSiblingIndex() +{ + if (!sequentialOrdering) { + qSort(children.begin(), children.end(), insertionOrder); + sequentialOrdering = 1; + needSortChildren = 1; + } + if (holesInSiblingIndex) { + holesInSiblingIndex = 0; + for (int i = 0; i < children.size(); ++i) + children[i]->d_ptr->siblingIndex = i; + } +} + +/*! + \since 4.6 + + Stacks this item before \a sibling, which must be a sibling item (i.e., the + two items must share the same parent item, or must both be toplevel items). + The \a sibling must have the same Z value as this item, otherwise calling + this function will have no effect. + + By default, all items are stacked by insertion order (i.e., the first item + you add is drawn before the next item you add). If two items' Z values are + different, then the item with the highest Z value is drawn on top. When the + Z values are the same, the insertion order will decide the stacking order. + + \sa setZValue(), ItemStacksBehindParent +*/ +void QGraphicsItem::stackBefore(const QGraphicsItem *sibling) +{ + if (sibling == this) + return; + if (!sibling || d_ptr->parent != sibling->parentItem()) { + qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling); + return; + } + QList<QGraphicsItem *> *siblings = d_ptr->parent + ? &d_ptr->parent->d_ptr->children + : (d_ptr->scene ? &d_ptr->scene->d_func()->topLevelItems : 0); + if (!siblings) { + qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling); + return; + } + + // First, make sure that the sibling indexes have no holes. This also + // marks the children list for sorting. + if (d_ptr->parent) + d_ptr->parent->d_ptr->ensureSequentialSiblingIndex(); + else + d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes(); + + // Only move items with the same Z value, and that need moving. + int siblingIndex = sibling->d_ptr->siblingIndex; + int myIndex = d_ptr->siblingIndex; + if (myIndex >= siblingIndex && d_ptr->z == sibling->d_ptr->z) { + siblings->move(myIndex, siblingIndex); + // Fixup the insertion ordering. + for (int i = 0; i < siblings->size(); ++i) { + int &index = siblings->at(i)->d_ptr->siblingIndex; + if (i != siblingIndex && index >= siblingIndex && index <= myIndex) + ++index; + } + d_ptr->siblingIndex = siblingIndex; + } +} + +/*! Returns the bounding rect of this item's descendants (i.e., its children, their children, etc.) in local coordinates. The rectangle will contain all descendants after they have been mapped @@ -4755,20 +4830,36 @@ void QGraphicsItemPrivate::resolveDepth() /*! \internal + + ### This function is almost identical to + QGraphicsScenePrivate::registerTopLevelItem(). */ void QGraphicsItemPrivate::addChild(QGraphicsItem *child) { - needSortChildren = 1; + // Remove all holes from the sibling index list. Now the max index + // number is equal to the size of the children list. + ensureSequentialSiblingIndex(); + needSortChildren = 1; // ### maybe 0 child->d_ptr->siblingIndex = children.size(); children.append(child); } /*! \internal + + ### This function is almost identical to + QGraphicsScenePrivate::unregisterTopLevelItem(). */ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) { - children.removeOne(child); + // When removing elements in the middle of the children list, + // there will be a "gap" in the list of sibling indexes (0,1,3,4). + if (!holesInSiblingIndex) + holesInSiblingIndex = child->d_ptr->siblingIndex != children.size() - 1; + if (sequentialOrdering && !holesInSiblingIndex) + children.removeAt(child->d_ptr->siblingIndex); + else + children.removeOne(child); // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because // the child is not guaranteed to be at the index after the list is sorted. // (see ensureSortedChildren()). @@ -5075,46 +5166,6 @@ void QGraphicsItem::update(const QRectF &rect) } /*! - \internal - - Scrolls \a rect in \a pix by \a dx, \a dy. - - ### This can be done much more efficiently by using XCopyArea on X11 with - the same dst and src, and through moving pixels in the raster engine. It - can probably also be done much better on the other paint engines. -*/ -void _q_scrollPixmap(QPixmap *pix, const QRect &rect, int dx, int dy) -{ -#if 0 - QPainter painter(pix); - painter.setClipRect(rect); - painter.drawPixmap(rect.translated(dx, dy), *pix, rect); - painter.end(); -#elif defined Q_WS_X11 - GC gc = XCreateGC(X11->display, pix->handle(), 0, 0); - - XRectangle xrect; - xrect.x = rect.x(); - xrect.y = rect.y(); - xrect.width = rect.width(); - xrect.height = rect.height(); - XSetClipRectangles(X11->display, gc, 0, 0, &xrect, 1, YXBanded); - - XCopyArea(X11->display, pix->handle(), pix->handle(), gc, - rect.x(), rect.y(), rect.width(), rect.height(), - rect.x()+dx, rect.y()+dy); - XFreeGC(X11->display, gc); -#else - QPixmap newPix = *pix; - QPainter painter(&newPix); - painter.setClipRect(rect); - painter.drawPixmap(rect.translated(dx, dy), *pix, rect); - painter.end(); - *pix = newPix; -#endif -} - -/*! \since 4.4 Scrolls the contents of \a rect by \a dx, \a dy. If \a rect is a null rect (the default), the item's bounding rect is scrolled. @@ -5154,7 +5205,7 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) QRectF br = boundingRect().adjusted(-adjust, -adjust, adjust, adjust); QRect irect = rect.toRect().translated(-br.x(), -br.y()); - _q_scrollPixmap(&pix, irect, dx, dy); + pix.scroll(dx, dy, irect); QPixmapCache::replace(c->key, pix); @@ -6993,10 +7044,12 @@ void QGraphicsItem::prepareGeometryChange() if (d_ptr->inSetPosHelper) return; - if (d_ptr->flags & ItemClipsChildrenToShape) + if (d_ptr->flags & ItemClipsChildrenToShape + || d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { d_ptr->invalidateCachedClipPathRecursively(); - else + } else { d_ptr->invalidateCachedClipPath(); + } } /*! diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 665f33f..99d2e12 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -294,14 +294,15 @@ public: QPointF transformOriginPoint() const; void setTransformOriginPoint(const QPointF &origin); - inline void setTransformOriginPoint(qreal x, qreal y) - { setTransformOriginPoint(QPointF(x,y)); } + inline void setTransformOriginPoint(qreal ax, qreal ay) + { setTransformOriginPoint(QPointF(ax,ay)); } virtual void advance(int phase); // Stacking order qreal zValue() const; void setZValue(qreal z); + void stackBefore(const QGraphicsItem *sibling); // Hit test virtual QRectF boundingRect() const = 0; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index fd2ff34..3feccdc 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -153,7 +153,7 @@ public: dirtyClipPath(1), emptyClipPath(0), inSetPosHelper(0), - needSortChildren(1), + needSortChildren(1), // ### can be 0 by default? allChildrenDirty(0), fullUpdatePending(0), flags(0), @@ -174,6 +174,8 @@ public: mouseSetsFocus(1), explicitActivate(0), wantsActive(0), + holesInSiblingIndex(0), + sequentialOrdering(1), globalStackingOrder(-1), q_ptr(0) { @@ -421,6 +423,8 @@ public: inline QTransform transformToParent() const; inline void ensureSortedChildren(); + static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b); + void ensureSequentialSiblingIndex(); QPainterPath cachedClipPath; QRectF childrenBoundingRect; @@ -493,6 +497,8 @@ public: // New 32 bits quint32 explicitActivate : 1; quint32 wantsActive : 1; + quint32 holesInSiblingIndex : 1; + quint32 sequentialOrdering : 1; // Optional stacking order int globalStackingOrder; @@ -646,14 +652,32 @@ inline QTransform QGraphicsItemPrivate::transformToParent() const return matrix; } +/*! + \internal +*/ inline void QGraphicsItemPrivate::ensureSortedChildren() { if (needSortChildren) { qSort(children.begin(), children.end(), qt_notclosestLeaf); needSortChildren = 0; + sequentialOrdering = 1; + for (int i = 0; i < children.size(); ++i) { + if (children[i]->d_ptr->siblingIndex != i) { + sequentialOrdering = 0; + break; + } + } } } +/*! + \internal +*/ +inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem *b) +{ + return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex; +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp index 0e4df71..2e9a30c 100644 --- a/src/gui/graphicsview/qgraphicslayout.cpp +++ b/src/gui/graphicsview/qgraphicslayout.cpp @@ -419,6 +419,26 @@ void QGraphicsLayout::widgetEvent(QEvent *e) \sa itemAt(), count() */ +/*! + \since 4.6 + + This function is a convenience function provided for custom layouts, and will go through + all items in the layout and reparent their graphics items to the closest QGraphicsWidget + ancestor of the layout. + + If \a layoutItem is already in a different layout, it will be removed from that layout. + + If custom layouts want special behaviour they can ignore to use this function, and implement + their own behaviour. + + \sa graphicsItem() + */ +void QGraphicsLayout::addChildLayoutItem(QGraphicsLayoutItem *layoutItem) +{ + Q_D(QGraphicsLayout); + d->addChildLayoutItem(layoutItem); +} + QT_END_NAMESPACE #endif //QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h index e872980..e214a62 100644 --- a/src/gui/graphicsview/qgraphicslayout.h +++ b/src/gui/graphicsview/qgraphicslayout.h @@ -78,6 +78,7 @@ public: protected: QGraphicsLayout(QGraphicsLayoutPrivate &, QGraphicsLayoutItem *); + void addChildLayoutItem(QGraphicsLayoutItem *layoutItem); private: Q_DISABLE_COPY(QGraphicsLayout) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index f6e0aaf..4b74b67 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -283,6 +283,8 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() processDirtyItemsEmitted(false), selectionChanging(0), needSortTopLevelItems(true), + holesInTopLevelSiblingIndex(false), + topLevelSequentialOrdering(true), stickyFocus(false), hasFocus(false), focusItem(0), @@ -379,24 +381,36 @@ void QGraphicsScenePrivate::_q_emitUpdated() /*! \internal + + ### This function is almost identical to QGraphicsItemPrivate::addChild(). */ void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item) { - needSortTopLevelItems = true; + item->d_ptr->ensureSequentialSiblingIndex(); + needSortTopLevelItems = true; // ### maybe false item->d_ptr->siblingIndex = topLevelItems.size(); topLevelItems.append(item); } /*! \internal + + ### This function is almost identical to QGraphicsItemPrivate::removeChild(). */ void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) { - topLevelItems.removeOne(item); + if (!holesInTopLevelSiblingIndex) + holesInTopLevelSiblingIndex = item->d_ptr->siblingIndex != topLevelItems.size() - 1; + if (topLevelSequentialOrdering && !holesInTopLevelSiblingIndex) + topLevelItems.removeAt(item->d_ptr->siblingIndex); + else + topLevelItems.removeOne(item); // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because // the item is not guaranteed to be at the index after the list is sorted // (see ensureSortedTopLevelItems()). item->d_ptr->siblingIndex = -1; + if (topLevelSequentialOrdering) + topLevelSequentialOrdering = !holesInTopLevelSiblingIndex; } /*! @@ -925,19 +939,19 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre Q_Q(const QGraphicsScene); QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0; if (!view) - return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, QTransform()); + return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform()); const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1)); if (!view->isTransformed()) - return q->items(pointRect, Qt::IntersectsItemShape, Qt::AscendingOrder); + return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder); const QTransform viewTransform = view->viewportTransform(); if (viewTransform.type() <= QTransform::TxScale) { return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape, - Qt::AscendingOrder, viewTransform); + Qt::DescendingOrder, viewTransform); } return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape, - Qt::AscendingOrder, viewTransform); + Qt::DescendingOrder, viewTransform); } /*! @@ -1239,6 +1253,29 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou /*! \internal + Ensures that the list of toplevels is sorted by insertion order, and that + the siblingIndexes are packed (no gaps), and start at 0. + + ### This function is almost identical to + QGraphicsItemPrivate::ensureSequentialSiblingIndex(). +*/ +void QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes() +{ + if (!topLevelSequentialOrdering) { + qSort(topLevelItems.begin(), topLevelItems.end(), QGraphicsItemPrivate::insertionOrder); + topLevelSequentialOrdering = true; + needSortTopLevelItems = 1; + } + if (holesInTopLevelSiblingIndex) { + holesInTopLevelSiblingIndex = 0; + for (int i = 0; i < topLevelItems.size(); ++i) + topLevelItems[i]->d_ptr->siblingIndex = i; + } +} + +/*! + \internal + Set the font and propagate the changes if the font is different from the current font. */ @@ -1584,7 +1621,7 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) d->indexMethod = method; - QList<QGraphicsItem *> oldItems = d->index->items(Qt::AscendingOrder); + QList<QGraphicsItem *> oldItems = d->index->items(Qt::DescendingOrder); delete d->index; if (method == BspTreeIndex) d->index = new QGraphicsSceneBspTreeIndex(this); @@ -1693,7 +1730,7 @@ QRectF QGraphicsScene::itemsBoundingRect() const QList<QGraphicsItem *> QGraphicsScene::items() const { Q_D(const QGraphicsScene); - return d->index->items(Qt::AscendingOrder); + return d->index->items(Qt::DescendingOrder); } /*! @@ -1724,7 +1761,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const { Q_D(const QGraphicsScene); - return d->index->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder); + return d->index->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder); } /*! @@ -1746,7 +1783,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->index->items(rectangle, mode, Qt::AscendingOrder); + return d->index->items(rectangle, mode, Qt::DescendingOrder); } /*! @@ -1794,7 +1831,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSe QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->index->items(polygon, mode, Qt::AscendingOrder); + return d->index->items(polygon, mode, Qt::DescendingOrder); } /*! @@ -1816,7 +1853,7 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->index->items(path, mode, Qt::AscendingOrder); + return d->index->items(path, mode, Qt::DescendingOrder); } /*! @@ -1928,7 +1965,7 @@ QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item, // Does not support ItemIgnoresTransformations. QList<QGraphicsItem *> tmp; - foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder)) { + foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::DescendingOrder)) { if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) tmp << itemInVicinity; } @@ -1972,7 +2009,7 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const { QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape, - Qt::AscendingOrder, deviceTransform); + Qt::DescendingOrder, deviceTransform); return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); } @@ -2127,7 +2164,7 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectio bool changed = false; // Set all items in path to selected. - foreach (QGraphicsItem *item, items(path, mode, Qt::AscendingOrder, deviceTransform)) { + foreach (QGraphicsItem *item, items(path, mode, Qt::DescendingOrder, deviceTransform)) { if (item->flags() & QGraphicsItem::ItemIsSelectable) { if (!item->isSelected()) changed = true; @@ -2434,17 +2471,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Ensure that newly added items that have subfocus set, gain // focus automatically if there isn't a focus item already. - if (!d->focusItem) { - if (item->focusItem() == item && item != d->lastFocusItem) { - QGraphicsItem *fi = item->focusItem() ? item->focusItem() : item->focusScopeItem(); - if (fi) { - QGraphicsItem *fsi; - while ((fsi = fi->focusScopeItem()) && fsi->isVisible()) - fi = fsi; - fi->setFocus(); - } - } - } + if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item) + item->focusItem()->setFocus(); d->updateInputMethodSensitivityInViews(); } @@ -4380,7 +4408,7 @@ void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const if (viewTransform) exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect); } - const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::DescendingOrder); + const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::AscendingOrder); for (int i = 0; i < tli.size(); ++i) drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget); } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 3b03624..46917ce 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -111,6 +111,9 @@ public: QList<QGraphicsItem *> unpolishedItems; QList<QGraphicsItem *> topLevelItems; bool needSortTopLevelItems; + bool holesInTopLevelSiblingIndex; + bool topLevelSequentialOrdering; + QMap<QGraphicsItem *, QPointF> movingItemsInitialPositions; void registerTopLevelItem(QGraphicsItem *item); void unregisterTopLevelItem(QGraphicsItem *item); @@ -255,6 +258,8 @@ public: } } + void ensureSequentialTopLevelSiblingIndexes(); + QStyle *style; QFont font; void setFont_helper(const QFont &font); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 7c46144..e21183a 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -480,23 +480,23 @@ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList<QGraphicsItem *> *itemLi return; if (onlyTopLevelItems) { - if (order == Qt::AscendingOrder) + if (order == Qt::DescendingOrder) qSort(itemList->begin(), itemList->end(), qt_closestLeaf); - else if (order == Qt::DescendingOrder) + else if (order == Qt::AscendingOrder) qSort(itemList->begin(), itemList->end(), qt_notclosestLeaf); return; } if (sortCacheEnabled) { - if (order == Qt::AscendingOrder) { + if (order == Qt::DescendingOrder) { qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); - } else if (order == Qt::DescendingOrder) { + } else if (order == Qt::AscendingOrder) { qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); } } else { - if (order == Qt::AscendingOrder) { + if (order == Qt::DescendingOrder) { qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); - } else if (order == Qt::DescendingOrder) { + } else if (order == Qt::AscendingOrder) { qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); } } @@ -605,7 +605,7 @@ QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::estimateTopLevelItems(const Q } /*! - \fn QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; + \fn QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const; Return all items in the BSP index and sort them using \a order. */ diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index cf85ba8..0a86bb7 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -81,7 +81,7 @@ public: QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const; QList<QGraphicsItem *> estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const; - QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::AscendingOrder) const; + QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const; int bspTreeDepth(); void setBspTreeDepth(int depth); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index e01ad10..f0404fd 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -265,12 +265,13 @@ bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item, /*! \internal + This function returns the items in ascending order. */ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, QGraphicsSceneIndexIntersector *intersector, QList<QGraphicsItem *> *items, const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, + Qt::ItemSelectionMode mode, qreal parentOpacity) const { Q_ASSERT(item); @@ -326,7 +327,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; recursive_items_helper(child, exposeRect, intersector, items, viewTransform, - mode, order, opacity); + mode, opacity); } } @@ -343,7 +344,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; recursive_items_helper(child, exposeRect, intersector, items, viewTransform, - mode, order, opacity); + mode, opacity); } } } @@ -542,7 +543,7 @@ QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF & Q_UNUSED(rect); QGraphicsScenePrivate *scened = d->scene->d_func(); scened->ensureSortedTopLevelItems(); - if (order == Qt::AscendingOrder) { + if (order == Qt::DescendingOrder) { QList<QGraphicsItem *> sorted; for (int i = scened->topLevelItems.size() - 1; i >= 0; --i) sorted << scened->topLevelItems.at(i); @@ -552,7 +553,7 @@ QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF & } /*! - \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const + \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const This pure virtual function all items in the index and sort them using \a order. diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index ab7b38c..adebfde 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -88,7 +88,7 @@ public: QGraphicsScene *scene() const; - virtual QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; + virtual QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const = 0; virtual QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; virtual QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode, @@ -138,7 +138,7 @@ public: void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, QGraphicsSceneIndexIntersector *intersector, QList<QGraphicsItem *> *items, const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; + Qt::ItemSelectionMode mode, qreal parentOpacity = 1.0) const; inline void items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector, QList<QGraphicsItem *> *items, const QTransform &viewTransform, Qt::ItemSelectionMode mode, Qt::SortOrder order) const; @@ -154,10 +154,10 @@ inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphi Qt::ItemSelectionMode mode, Qt::SortOrder order) const { Q_Q(const QGraphicsSceneIndex); - const QList<QGraphicsItem *> tli = q->estimateTopLevelItems(rect, Qt::DescendingOrder); + const QList<QGraphicsItem *> tli = q->estimateTopLevelItems(rect, Qt::AscendingOrder); for (int i = 0; i < tli.size(); ++i) - recursive_items_helper(tli.at(i), rect, intersector, items, viewTransform, mode, order); - if (order == Qt::AscendingOrder) { + recursive_items_helper(tli.at(i), rect, intersector, items, viewTransform, mode); + if (order == Qt::DescendingOrder) { const int n = items->size(); for (int i = 0; i < n / 2; ++i) items->swap(i, n - i - 1); diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp index 70fed64..d6faf05 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -62,7 +62,7 @@ */ /*! - \fn QList<QGraphicsItem *> QGraphicsSceneLinearIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; + \fn QList<QGraphicsItem *> QGraphicsSceneLinearIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const; Return all items in the index and sort them using \a order. */ diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index 4c4aa9f..0aaee14 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -76,7 +76,7 @@ public: QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene) { } - QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::AscendingOrder) const + QList<QGraphicsItem *> items(Qt::SortOrder order = Qt::DescendingOrder) const { Q_UNUSED(order); return m_items; } virtual QList<QGraphicsItem *> estimateItems(const QRectF &rect, Qt::SortOrder order) const diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index b0829c5..98b2c9c 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -971,7 +971,7 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg *allItems = true; // All items are guaranteed within the exposed region. - return scene->items(Qt::DescendingOrder); + return scene->items(Qt::AscendingOrder); } // Step 2) If the expose region is a simple rect and the view is only @@ -981,7 +981,7 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg if (simpleRectLookup) { return scene->items(exposedRegionSceneBounds, Qt::IntersectsItemBoundingRect, - Qt::DescendingOrder, viewTransform); + Qt::AscendingOrder, viewTransform); } // If the region is complex or the view has a complex transform, adjust @@ -993,7 +993,7 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion))); return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect, - Qt::DescendingOrder, viewTransform); + Qt::AscendingOrder, viewTransform); } /*! @@ -2055,13 +2055,13 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const QTransform xinv = viewportTransform().inverted(); return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)), Qt::IntersectsItemShape, - Qt::AscendingOrder, + Qt::DescendingOrder, viewportTransform()); } // Use the polygon version return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1), Qt::IntersectsItemShape, - Qt::AscendingOrder, + Qt::DescendingOrder, viewportTransform()); } @@ -2089,7 +2089,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelection Q_D(const QGraphicsView); if (!d->scene) return QList<QGraphicsItem *>(); - return d->scene->items(mapToScene(rect), mode, Qt::AscendingOrder, viewportTransform()); + return d->scene->items(mapToScene(rect), mode, Qt::DescendingOrder, viewportTransform()); } /*! @@ -2117,7 +2117,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSel Q_D(const QGraphicsView); if (!d->scene) return QList<QGraphicsItem *>(); - return d->scene->items(mapToScene(polygon), mode, Qt::AscendingOrder, viewportTransform()); + return d->scene->items(mapToScene(polygon), mode, Qt::DescendingOrder, viewportTransform()); } /*! @@ -2137,7 +2137,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSe Q_D(const QGraphicsView); if (!d->scene) return QList<QGraphicsItem *>(); - return d->scene->items(mapToScene(path), mode, Qt::AscendingOrder, viewportTransform()); + return d->scene->items(mapToScene(path), mode, Qt::DescendingOrder, viewportTransform()); } /*! diff --git a/src/gui/graphicsview/qsimplex_p.cpp b/src/gui/graphicsview/qsimplex_p.cpp index e3a991e..1ba24a3 100644 --- a/src/gui/graphicsview/qsimplex_p.cpp +++ b/src/gui/graphicsview/qsimplex_p.cpp @@ -48,6 +48,32 @@ QT_BEGIN_NAMESPACE +/*! + \class QSimplex + + The QSimplex class is a Linear Programming problem solver based on the two-phase + simplex method. + + It takes a set of QSimplexConstraints as its restrictive constraints and an + additional QSimplexConstraint as its objective function. Then methods to maximize + and minimize the problem solution are provided. + + The two-phase simplex method is based on the following steps: + First phase: + 1.a) Modify the original, complex, and possibly not feasible problem, into a new, + easy to solve problem. + 1.b) Set as the objective of the new problem, a feasible solution for the original + complex problem. + 1.c) Run simplex to optimize the modified problem and check whether a solution for + the original problem exists. + + Second phase: + 2.a) Go back to the original problem with the feasibl (but not optimal) solution + found in the first phase. + 2.b) Set the original objective. + 3.c) Run simplex to optimize the original problem towards its optimal solution. +*/ + QSimplex::QSimplex() : objective(0), rows(0), columns(0), firstArtificial(0), matrix(0) { } @@ -84,15 +110,31 @@ void QSimplex::clearDataStructures() objective = 0; } +/*! + Sets the new constraints in the simplex solver and returns whether the problem + is feasible. + + This method sets the new constraints, normalizes them, creates the simplex matrix + and runs the first simplex phase. +*/ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) { + //////////////////////////// + // Reset to initial state // + //////////////////////////// clearDataStructures(); if (newConstraints.isEmpty()) return true; // we are ok with no constraints constraints = newConstraints; - // Set Variables direct mapping + /////////////////////////////////////// + // Prepare variables and constraints // + /////////////////////////////////////// + + // Set Variables direct mapping. + // "variables" is a list that provides a stable, indexed list of all variables + // used in this problem. QSet<QSimplexVariable *> variablesSet; for (int i = 0; i < constraints.size(); ++i) variablesSet += \ @@ -100,12 +142,25 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) variables = variablesSet.toList(); // Set Variables reverse mapping + // We also need to be able to find the index for a given variable, to do that + // we store in each variable its index. for (int i = 0; i < variables.size(); ++i) { // The variable "0" goes at the column "1", etc... variables[i]->index = i + 1; } // Normalize Constraints + // In this step, we prepare the constraints in two ways: + // Firstly, we modify all constraints of type "LessOrEqual" or "MoreOrEqual" + // by the adding slack or surplus variables and making them "Equal" constraints. + // Secondly, we need every single constraint to have a direct, easy feasible + // solution. Constraints that have slack variables are already easy to solve, + // to all the others we add artificial variables. + // + // At the end we modify the constraints as follows: + // - LessOrEqual: SLACK variable is added. + // - Equal: ARTIFICIAL variable is added. + // - More or Equal: ARTIFICIAL and SURPLUS variables are added. int variableIndex = variables.size(); QList <QSimplexVariable *> artificialList; @@ -138,12 +193,18 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) } } + // All original, slack and surplus have already had its index set + // at this point. We now set the index of the artificial variables + // as to ensure they are at the end of the variable list and therefore + // can be easily removed at the end of this method. firstArtificial = variableIndex + 1; for (int i = 0; i < artificialList.size(); ++i) artificialList[i]->index = ++variableIndex; artificialList.clear(); - // Matrix + ///////////////////////////// + // Fill the Simplex matrix // + ///////////////////////////// // One for each variable plus the Basic and BFS columns (first and last) columns = variableIndex + 2; @@ -188,24 +249,61 @@ bool QSimplex::setConstraints(const QList<QSimplexConstraint *> newConstraints) setValueAt(i, columns - 1, c->constant); } - // Set temporary objective: -1 * sum_of_artificial_vars + // Set objective for the first-phase Simplex. + // Z = -1 * sum_of_artificial_vars for (int j = firstArtificial; j < columns - 1; ++j) setValueAt(0, j, 1.0); // Maximize our objective (artificial vars go to zero) solveMaxHelper(); + // If there is a solution where the sum of all artificial + // variables is zero, then all of them can be removed and yet + // we will have a feasible (but not optimal) solution for the + // original problem. + // Otherwise, we clean up our structures and report there is + // no feasible solution. if (valueAt(0, columns - 1) != 0.0) { qWarning() << "QSimplex: No feasible solution!"; clearDataStructures(); return false; } - // Remove artificial variables + // Remove artificial variables. We already have a feasible + // solution for the first problem, thus we don't need them + // anymore. clearColumns(firstArtificial, columns - 2); + + #ifdef QT_DEBUG + // Ensure that at the end of the simplex each row should either: + // - Have a positive value on the column associated to its variable, or + // - Have zero values in all columns. + // + // This avoids a regression where restrictions would be lost + // due to randomness in the pivotRowForColumn method. + for (int i = 1; i < rows; ++i) { + int variableIndex = valueAt(i, 0); + if (valueAt(i, variableIndex) > 0) + continue; + + for (int j = 1; j < columns; ++j) { + Q_ASSERT(valueAt(i, j) == 0); + } + } + #endif + return true; } +/*! + \internal + + Run simplex on the current matrix with the current objective. + + This is the iterative method. The matrix lines are combined + as to modify the variable values towards the best solution possible. + The method returns when the matrix is in the optimal state. +*/ void QSimplex::solveMaxHelper() { reducedRowEchelon(); @@ -235,23 +333,21 @@ void QSimplex::clearColumns(int first, int last) void QSimplex::dumpMatrix() { - printf("---- Simplex Matrix ----\n"); + qDebug("---- Simplex Matrix ----\n"); - printf(" "); + QString str(QLatin1String(" ")); for (int j = 0; j < columns; ++j) - printf(" <% 2d >", j); - printf("\n"); - + str += QString::fromAscii(" <%1 >").arg(j, 2); + qDebug("%s", qPrintable(str)); for (int i = 0; i < rows; ++i) { - printf("Row %2d:", i); + str = QString::fromAscii("Row %1:").arg(i, 2); qreal *row = matrix + i * columns; - for (int j = 0; j < columns; ++j) { - printf(" % 2.2f", row[j]); - } - printf("\n"); + for (int j = 0; j < columns; ++j) + str += QString::fromAscii("%1").arg(row[j], 7, 'f', 2); + qDebug("%s", qPrintable(str)); } - printf("------------------------\n\n"); + qDebug("------------------------\n"); } void QSimplex::combineRows(int toIndex, int fromIndex, qreal factor) @@ -292,6 +388,23 @@ int QSimplex::findPivotColumn() return minIndex; } +/*! + \internal + + For a given pivot column, find the pivot row. That is, the row with the + minimum associated "quotient" where: + + - quotient is the division of the value in the last column by the value + in the pivot column. + - rows with value less or equal to zero are ignored + - if two rows have the same quotient, lines are chosen based on the + highest variable index (value in the first column) + + The last condition avoids a bug where artificial variables would be + left behind for the second-phase simplex, and with 'good' + constraints would be removed before it, what would lead to incorrect + results. +*/ int QSimplex::pivotRowForColumn(int column) { qreal min = qreal(999999999999.0); // ### @@ -306,6 +419,8 @@ int QSimplex::pivotRowForColumn(int column) if (quotient < min) { min = quotient; minIndex = i; + } else if ((quotient == min) && (valueAt(i, 0) > valueAt(minIndex, 0))) { + minIndex = i; } } @@ -320,6 +435,12 @@ void QSimplex::reducedRowEchelon() } } +/*! + \internal + + Does one iteration towards a better solution for the problem. + See 'solveMaxHelper'. +*/ bool QSimplex::iterate() { // Find Pivot column @@ -351,7 +472,7 @@ bool QSimplex::iterate() setValueAt(pivotRow, 0, pivotColumn); // dumpMatrix(); - // printf("------------ end of iteration --------------\n"); + // qDebug("------------ end of iteration --------------\n"); return true; } @@ -361,7 +482,13 @@ bool QSimplex::iterate() Both solveMin and solveMax are interfaces to this method. The enum solverFactor admits 2 values: Minimum (-1) and Maximum (+1). - */ + + This method sets the original objective and runs the second phase + Simplex to obtain the optimal solution for the problem. As the internal + simplex solver is only able to _maximize_ objectives, we handle the + minimization case by inverting the original objective and then + maximizing it. +*/ qreal QSimplex::solver(solverFactor factor) { // Remove old objective @@ -381,16 +508,28 @@ qreal QSimplex::solver(solverFactor factor) return factor * valueAt(0, columns - 1); } +/*! + Minimize the original objective. +*/ qreal QSimplex::solveMin() { return solver(Minimum); } +/*! + Maximize the original objective. +*/ qreal QSimplex::solveMax() { return solver(Maximum); } +/*! + \internal + + Reads results from the simplified matrix and saves them in the + "result" member of each QSimplexVariable. +*/ void QSimplex::collectResults() { // All variables are zero unless overridden below. diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index aff186b..074f3eb 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -696,14 +696,17 @@ bool QImageReader::autoDetectImageFormat() const /*! - Specifies that the image reader should decide which plugin to use - solely based on the contents in the datastream. + If \a ignored is set to true, then the image reader will ignore + specified formats or file extensions and decide which plugin to + use only based on the contents in the datastream. Setting this flag means that all image plugins gets loaded. Each plugin will read the first bytes in the image data and decide if - the plugin is compatible or not. The flag is set to \a ignored. + the plugin is compatible or not. - This also disables auto detecting image format. + This also disables auto detecting the image format. + + \sa decideFormatFromContent() */ void QImageReader::setDecideFormatFromContent(bool ignored) @@ -713,8 +716,11 @@ void QImageReader::setDecideFormatFromContent(bool ignored) /*! - Returns wether the image reader should decide which plugin to use - sloley based on the contents of the datastream + Returns whether the image reader should decide which plugin to use + only based on the contents of the datastream rather than on the file + extension. + + \sa setDecideFormatFromContent() */ bool QImageReader::decideFormatFromContent() const diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp index 48aee1c..42b8dea 100644 --- a/src/gui/image/qmovie.cpp +++ b/src/gui/image/qmovie.cpp @@ -47,6 +47,10 @@ \ingroup painting + This class is used to show simple animations without sound. If you want + to display video and media content, use the \l{Phonon Module}{Phonon} + multimedia framework instead. + First, create a QMovie object by passing either the name of a file or a pointer to a QIODevice containing an animated image format to QMovie's constructor. You can call isValid() to check if the image data is valid, diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 4f145af..558ae54 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1678,12 +1678,15 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) operation, you can use QBitmap::fromImage() instead. In addition, on Windows, the QPixmap class supports conversion to - and from HBitmap: the toWinHBITMAP() function creates a HBITMAP + and from HBITMAP: the toWinHBITMAP() function creates a HBITMAP equivalent to the QPixmap, based on the given HBitmapFormat, and returns the HBITMAP handle. The fromWinHBITMAP() function returns a QPixmap that is equivalent to the given bitmap which has the - specified format. - + specified format. The QPixmap class also supports conversion to + and from HICON: the toWinHICON() function creates a HICON equivalent + to the QPixmap, and returns the HICON handle. The fromWinHICON() + function returns a QPixmap that is equivalent to the given icon. + In addition, on Symbian, the QPixmap class supports conversion to and from CFbsBitmap: the toSymbianCFbsBitmap() function creates CFbsBitmap equivalent to the QPixmap, based on given mode and returns @@ -2040,7 +2043,7 @@ QPixmapData* QPixmap::pixmapData() const \warning This function is only available on Windows. - \sa fromWinHBITMAP() + \sa fromWinHBITMAP(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} */ /*! \fn QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format) @@ -2054,6 +2057,31 @@ QPixmapData* QPixmap::pixmapData() const */ +/*! \fn HICON QPixmap::toWinHICON() const + \since 4.6 + + \bold{Win32 only:} Creates a \c HICON equivalent to the QPixmap. + Returns the \c HICON handle. + + It is the caller's responsibility to free the \c HICON data after use. + + \warning This function is only available on Windows. + + \sa fromWinHICON(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} +*/ + +/*! \fn QPixmap QPixmap::fromWinHICON(HICON icon) + \since 4.6 + + \bold{Win32 only:} Returns a QPixmap that is equivalent to the given + \a icon. + + \warning This function is only available on Windows. + + \sa toWinHICON(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} + +*/ + /*! \fn const QX11Info &QPixmap::x11Info() const \bold{X11 only:} Returns information about the configuration of the X display used to display the widget. diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 54e89ff..a891637 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -149,7 +149,10 @@ public: }; HBITMAP toWinHBITMAP(HBitmapFormat format = NoAlpha) const; + HICON toWinHICON() const; + static QPixmap fromWinHBITMAP(HBITMAP hbitmap, HBitmapFormat format = NoAlpha); + static QPixmap fromWinHICON(HICON hicon); #endif #if defined(Q_WS_MAC) @@ -158,10 +161,8 @@ public: #endif #if defined(Q_OS_SYMBIAN) - enum ConversionMode { CopyData, DuplicateHandle }; - - CFbsBitmap *toSymbianCFbsBitmap(ConversionMode mode = DuplicateHandle) const; - static QPixmap fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode = DuplicateHandle); + CFbsBitmap *toSymbianCFbsBitmap() const; + static QPixmap fromSymbianCFbsBitmap(CFbsBitmap *bitmap); RSgImage* toSymbianRSgImage() const; static QPixmap fromSymbianRSgImage(RSgImage *sgImage); #endif diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index 303e923..dccc691 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -64,13 +64,14 @@ const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; - /*! + \class QSymbianFbsClient \since 4.6 + \internal - Symbian Font And Bitmap server client that is - used to lock the global bitmap heap. Only used in - S60 v3.1 and S60 v3.2. + Symbian Font And Bitmap server client that is + used to lock the global bitmap heap. Only used in + S60 v3.1 and S60 v3.2. */ class QSymbianFbsClient { @@ -145,7 +146,9 @@ void QSymbianFbsHeapLock::relock() } /*! + \class QSymbianBitmapDataAccess \since 4.6 + \internal Data access class that is used to locks/unlocks pixel data when drawing or modifying CFbsBitmap pixel data. @@ -297,231 +300,55 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h) } /*! - \enum QPixmap::ConversionMode - - \bold{Symbian only:} This enum defines how the conversion between \c - CFbsBitmap and QPixmap is performed. - - \warning This enum is only available on Symbian. - - \value CopyData Copied CFbsBitmap data. - - \value DuplicateHandle Duplicates CFbsBitmap handle. This also means - that pixmap data will be explicitly shared. - - \sa fromSymbianCFbsBitmap(), toSymbianCFbsBitmap() -*/ - - -/*! - \fn CFbsBitmap *QPixmap::toSymbianCFbsBitmap(ConversionMode mode) + \fn CFbsBitmap *QPixmap::toSymbianCFbsBitmap() const \since 4.6 - Creates \c CFbsBitmap that is equivalent to the QPixmap, based on - the given \a mode. If the creation then this function returns 0. + Creates a \c CFbsBitmap that is equivalent to the QPixmap. Internally this + function will try to duplicate the handle instead of copying the data, + however in scenarios where this is not possible the data will be copied. + If the creation fails or the pixmap is null, then this function returns 0. It is the caller's responsibility to release the \c CFbsBitmap data after use either by deleting the bitmap or calling \c Reset(). - \warning On S60 3.1 and S60 3.2 conversion mode will always be CopyData - if QPixmap pixels have alpha values. + \warning On S60 3.1 and S60 3.2, semi-transparent pixmaps are always copied + and not duplicated. \warning This function is only available on Symbian OS. \sa fromSymbianCFbsBitmap() */ -CFbsBitmap *QPixmap::toSymbianCFbsBitmap(ConversionMode mode) const +CFbsBitmap *QPixmap::toSymbianCFbsBitmap() const { - QS60PixmapData *s60data = static_cast<QS60PixmapData *>(data.data()); - - if (isNull() || !s60data->cfbsBitmap) + QPixmapData *data = pixmapData(); + if (data->isNull()) return 0; - bool convertToArgb32 = false; - - QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion(); - if (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3) { - // Convert argb32_premultiplied to argb32 since Symbian 9.2 and Symbian 9.3 do - // not support premultipied format. - - if (s60data->image.format() == QImage::Format_ARGB32_Premultiplied) { - mode = CopyData; - convertToArgb32 = true; - } - } - - CFbsBitmap *bitmap = 0; - - TDisplayMode displayMode = s60data->cfbsBitmap->DisplayMode(); - - if(displayMode == EGray2) { - //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid - //So invert mono bitmaps so that masks work correctly. - s60data->image.invertPixels(); - mode = CopyData; - } - - if (mode == CopyData) { - QImage source; - - if (convertToArgb32) { - source = s60data->image.convertToFormat(QImage::Format_ARGB32); - displayMode = EColor16MA; - } else { - source = s60data->image; - } - - CFbsBitmap *newBitmap = createSymbianCFbsBitmap(TSize(source.width(), source.height()), displayMode); - const uchar *sptr = source.bits(); - s60data->symbianBitmapDataAccess->beginDataAccess(newBitmap); - - uchar *dptr = (uchar*)newBitmap->DataAddress(); - Mem::Copy(dptr, sptr, source.numBytes()); - - s60data->symbianBitmapDataAccess->endDataAccess(newBitmap); - - bitmap = newBitmap; - } else { - - QT_TRAP_THROWING(bitmap = new (ELeave) CFbsBitmap); - - TInt err = bitmap->Duplicate(s60data->cfbsBitmap->Handle()); - if (err != KErrNone) { - qWarning("Could not duplicate CFbsBitmap"); - delete bitmap; - bitmap = 0; - } - } - - if(displayMode == EGray2) { - // restore pixels - s60data->image.invertPixels(); - } - - return bitmap; + return reinterpret_cast<CFbsBitmap*>(data->toNativeType(QPixmapData::FbsBitmap)); } /*! - \fn QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode) + \fn QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap) \since 4.6 - Creates a QPixmap from native \c CFbsBitmap \a bitmap. The conversion - is based on the specified \a mode. Conversion mode is always QPixmap::CopyData - if given \a bitmap does not have display mode of TDisplayMode::EGray2, - \c TDisplayMode::EColor16MU or \c TDisplayMode::EColor16MAP. - + Creates a QPixmap from a \c CFbsBitmap \a bitmap. Internally this function + will try to duplicate the bitmap handle instead of copying the data, however + in scenarios where this is not possible the data will be copied. + To be sure that QPixmap does not modify your original instance, you should + make a copy of your \c CFbsBitmap before calling this function. If the CFbsBitmap is not valid this function will return a null QPixmap. \warning This function is only available on Symbian OS. \sa toSymbianCFbsBitmap(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} */ -QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode) +QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap) { - if (bitmap) { - - bool deleteSourceBitmap = false; - -#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE - - // Rasterize extended bitmaps - - TUid extendedBitmapType = bitmap->ExtendedBitmapType(); - if (extendedBitmapType != KNullUid) { - CFbsBitmap *rasterBitmap = createSymbianCFbsBitmap(bitmap->SizeInPixels(), EColor16MA); - - CFbsBitmapDevice *rasterBitmapDev = 0; - QT_TRAP_THROWING(rasterBitmapDev = CFbsBitmapDevice::NewL(rasterBitmap)); - - CFbsBitGc *rasterBitmapGc = 0; - TInt err = rasterBitmapDev->CreateContext(rasterBitmapGc); - if (err != KErrNone) { - delete rasterBitmap; - delete rasterBitmapDev; - rasterBitmapDev = 0; - return QPixmap(); - } - - rasterBitmapGc->BitBlt(TPoint( 0, 0), bitmap); - - bitmap = rasterBitmap; - - delete rasterBitmapDev; - delete rasterBitmapGc; - - rasterBitmapDev = 0; - rasterBitmapGc = 0; - - deleteSourceBitmap = true; - } -#endif - - - deleteSourceBitmap = bitmap->IsCompressedInRAM(); - CFbsBitmap *sourceBitmap = uncompress(bitmap); - - TDisplayMode displayMode = sourceBitmap->DisplayMode(); - QImage::Format format = qt_TDisplayMode2Format(displayMode); - - QImage::Format opaqueFormat = QNativeImage::systemFormat(); - QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied; - - if (format != opaqueFormat && format != alphaFormat && format != QImage::Format_MonoLSB) - mode = CopyData; - - - QPixmapData::PixelType type = (format!=QImage::Format_MonoLSB) - ? QPixmapData::PixmapType - : QPixmapData::BitmapType; - - QS60PixmapData *pixmapData = 0; - - if (mode == CopyData) { - - TSize size = sourceBitmap->SizeInPixels(); - - QSymbianBitmapDataAccess da; - da.beginDataAccess(sourceBitmap); - uchar *bytes = (uchar*)sourceBitmap->DataAddress(); - QImage img = QImage(bytes, size.iWidth, size.iHeight, format); - da.endDataAccess(sourceBitmap); - - pixmapData = new QS60PixmapData(type); - pixmapData->fromImage(img, Qt::AutoColor); - - if(deleteSourceBitmap) - delete sourceBitmap; - - if(displayMode == EGray2) { - //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid - //So invert mono bitmaps so that masks work correctly. - pixmapData->image.invertPixels(); - } - } else { - CFbsBitmap* duplicate = 0; - QT_TRAP_THROWING(duplicate = new (ELeave) CFbsBitmap); - - TInt err = duplicate->Duplicate(sourceBitmap->Handle()); - if (err != KErrNone) { - qWarning("Could not duplicate CFbsBitmap"); - - if(deleteSourceBitmap) - delete sourceBitmap; - - delete duplicate; - return QPixmap(); - } - - pixmapData = new QS60PixmapData(type); - pixmapData->fromSymbianBitmap(duplicate); - - if(deleteSourceBitmap) - delete sourceBitmap; - } - - return QPixmap(pixmapData); - } + if (!bitmap) + return QPixmap(); - return QPixmap(); + QPixmap pixmap; + pixmap.pixmapData()->fromNativeType(reinterpret_cast<void*>(bitmap), QPixmapData::FbsBitmap); + return pixmap; } QS60PixmapData::QS60PixmapData(PixelType type) : QRasterPixmapData(type), @@ -900,7 +727,7 @@ void QS60PixmapData::endDataAccess(bool readOnly) const /*! \since 4.6 - Returns a QPixmap that wraps given \c RSgImage \a graphics resource. + Returns a QPixmap that wraps given \a sgImage graphics resource. The data should be valid even when original RSgImage handle has been closed. @@ -921,7 +748,7 @@ QPixmap QPixmap::fromSymbianRSgImage(RSgImage *sgImage) return QPixmap(); QPixmap pixmap; - pixmap.pixmapData()->fromRSgImage(sgImage); + pixmap.pixmapData()->fromNativeType(reinterpret_cast<void*>(sgImage), QPixmapData::SgImage); return pixmap; } @@ -949,9 +776,193 @@ RSgImage *QPixmap::toSymbianRSgImage() const if (isNull()) return 0; - RSgImage *sgImage = pixmapData()->toRSgImage(); + RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmapData()->toNativeType(QPixmapData::SgImage)); return sgImage; } +void* QS60PixmapData::toNativeType(NativeType type) +{ + if (type == QPixmapData::SgImage) { + return 0; + } else if (type == QPixmapData::FbsBitmap) { + + if (isNull() || !cfbsBitmap) + return 0; + + bool convertToArgb32 = false; + bool needsCopy = false; + + QSysInfo::SymbianVersion symbianVersion = QSysInfo::symbianVersion(); + if (symbianVersion == QSysInfo::SV_9_2 || symbianVersion == QSysInfo::SV_9_3) { + // Convert argb32_premultiplied to argb32 since Symbian 9.2 and Symbian 9.3 do + // not support premultipied format. + + if (image.format() == QImage::Format_ARGB32_Premultiplied) { + needsCopy = true; + convertToArgb32 = true; + } + } + + CFbsBitmap *bitmap = 0; + + TDisplayMode displayMode = cfbsBitmap->DisplayMode(); + + if(displayMode == EGray2) { + //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid + //So invert mono bitmaps so that masks work correctly. + image.invertPixels(); + needsCopy = true; + } + + if (needsCopy) { + QImage source; + + if (convertToArgb32) { + source = image.convertToFormat(QImage::Format_ARGB32); + displayMode = EColor16MA; + } else { + source = image; + } + + CFbsBitmap *newBitmap = createSymbianCFbsBitmap(TSize(source.width(), source.height()), displayMode); + const uchar *sptr = source.bits(); + symbianBitmapDataAccess->beginDataAccess(newBitmap); + + uchar *dptr = (uchar*)newBitmap->DataAddress(); + Mem::Copy(dptr, sptr, source.numBytes()); + + symbianBitmapDataAccess->endDataAccess(newBitmap); + + bitmap = newBitmap; + } else { + + QT_TRAP_THROWING(bitmap = new (ELeave) CFbsBitmap); + + TInt err = bitmap->Duplicate(cfbsBitmap->Handle()); + if (err != KErrNone) { + qWarning("Could not duplicate CFbsBitmap"); + delete bitmap; + bitmap = 0; + } + } + + if(displayMode == EGray2) { + // restore pixels + image.invertPixels(); + } + + return reinterpret_cast<void*>(bitmap); + + } + + return 0; +} + +void QS60PixmapData::fromNativeType(void* pixmap, NativeType nativeType) +{ + if (nativeType == QPixmapData::SgImage) { + return; + } else if (nativeType == QPixmapData::FbsBitmap && pixmap) { + + CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap); + + bool deleteSourceBitmap = false; + bool needsCopy = false; + +#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE + + // Rasterize extended bitmaps + + TUid extendedBitmapType = bitmap->ExtendedBitmapType(); + if (extendedBitmapType != KNullUid) { + CFbsBitmap *rasterBitmap = createSymbianCFbsBitmap(bitmap->SizeInPixels(), EColor16MA); + + CFbsBitmapDevice *rasterBitmapDev = 0; + QT_TRAP_THROWING(rasterBitmapDev = CFbsBitmapDevice::NewL(rasterBitmap)); + + CFbsBitGc *rasterBitmapGc = 0; + TInt err = rasterBitmapDev->CreateContext(rasterBitmapGc); + if (err != KErrNone) { + delete rasterBitmap; + delete rasterBitmapDev; + rasterBitmapDev = 0; + return; + } + + rasterBitmapGc->BitBlt(TPoint( 0, 0), bitmap); + + bitmap = rasterBitmap; + + delete rasterBitmapDev; + delete rasterBitmapGc; + + rasterBitmapDev = 0; + rasterBitmapGc = 0; + + deleteSourceBitmap = true; + } +#endif + + + deleteSourceBitmap = bitmap->IsCompressedInRAM(); + CFbsBitmap *sourceBitmap = uncompress(bitmap); + + TDisplayMode displayMode = sourceBitmap->DisplayMode(); + QImage::Format format = qt_TDisplayMode2Format(displayMode); + + QImage::Format opaqueFormat = QNativeImage::systemFormat(); + QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied; + + if (format != opaqueFormat && format != alphaFormat && format != QImage::Format_MonoLSB) + needsCopy = true; + + + type = (format != QImage::Format_MonoLSB) + ? QPixmapData::PixmapType + : QPixmapData::BitmapType; + + if (needsCopy) { + + TSize size = sourceBitmap->SizeInPixels(); + + QSymbianBitmapDataAccess da; + da.beginDataAccess(sourceBitmap); + uchar *bytes = (uchar*)sourceBitmap->DataAddress(); + QImage img = QImage(bytes, size.iWidth, size.iHeight, format); + da.endDataAccess(sourceBitmap); + + fromImage(img, Qt::AutoColor); + + if(deleteSourceBitmap) + delete sourceBitmap; + + if(displayMode == EGray2) { + //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid + //So invert mono bitmaps so that masks work correctly. + image.invertPixels(); + } + } else { + CFbsBitmap* duplicate = 0; + QT_TRAP_THROWING(duplicate = new (ELeave) CFbsBitmap); + + TInt err = duplicate->Duplicate(sourceBitmap->Handle()); + if (err != KErrNone) { + qWarning("Could not duplicate CFbsBitmap"); + + if(deleteSourceBitmap) + delete sourceBitmap; + + delete duplicate; + return; + } + + fromSymbianBitmap(duplicate); + + if(deleteSourceBitmap) + delete sourceBitmap; + } + } +} + QT_END_NAMESPACE diff --git a/src/gui/image/qpixmap_s60_p.h b/src/gui/image/qpixmap_s60_p.h index b56b270..4498c05 100644 --- a/src/gui/image/qpixmap_s60_p.h +++ b/src/gui/image/qpixmap_s60_p.h @@ -1,11 +1,41 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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 qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -36,17 +66,17 @@ class QSymbianBitmapDataAccess; class QSymbianFbsHeapLock { public: - + enum LockAction { Unlock }; - + explicit QSymbianFbsHeapLock(LockAction a); ~QSymbianFbsHeapLock(); - void relock(); - + void relock(); + private: - + LockAction action; bool wasLocked; }; @@ -72,13 +102,16 @@ public: void beginDataAccess(); void endDataAccess(bool readOnly=false) const; + void* toNativeType(NativeType type); + void fromNativeType(void* pixmap, NativeType type); + private: - void release(); - void fromSymbianBitmap(CFbsBitmap* bitmap); - bool initSymbianBitmapContext(); + void release(); + void fromSymbianBitmap(CFbsBitmap* bitmap); + bool initSymbianBitmapContext(); QSymbianBitmapDataAccess *symbianBitmapDataAccess; - + CFbsBitmap *cfbsBitmap; CFbsBitmapDevice *bitmapDevice; CBitmapContext *bitmapContext; diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index 9042840..1b61484 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -236,6 +236,44 @@ QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format) return fromImage(result); } +HBITMAP qt_createIconMask(const QBitmap &bitmap) +{ + QImage bm = bitmap.toImage().convertToFormat(QImage::Format_Mono); + int w = bm.width(); + int h = bm.height(); + int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment + uchar *bits = new uchar[bpl*h]; + bm.invertPixels(); + for (int y=0; y<h; y++) + memcpy(bits+y*bpl, bm.scanLine(y), bpl); + HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits); + delete [] bits; + return hbm; +} + +HICON QPixmap::toWinHICON() const +{ + QBitmap maskBitmap = mask(); + if (maskBitmap.isNull()) { + maskBitmap= QBitmap(size()); + maskBitmap.fill(Qt::color1); + } + + ICONINFO ii; + ii.fIcon = true; + ii.hbmMask = qt_createIconMask(maskBitmap); + ii.hbmColor = toWinHBITMAP(QPixmap::Alpha); + ii.xHotspot = 0; + ii.yHotspot = 0; + + HICON hIcon = CreateIconIndirect(&ii); + + DeleteObject(ii.hbmColor); + DeleteObject(ii.hbmMask); + + return hIcon; +} + #ifdef Q_WS_WIN #ifndef Q_WS_WINCE @@ -273,7 +311,7 @@ static QImage qt_fromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h) return image; } -QPixmap convertHIconToPixmap( const HICON icon) +QPixmap QPixmap::fromWinHICON(HICON icon) { bool foundAlpha = false; HDC screenDevice = GetDC(0); @@ -283,7 +321,7 @@ QPixmap convertHIconToPixmap( const HICON icon) ICONINFO iconinfo; bool result = GetIconInfo(icon, &iconinfo); //x and y Hotspot describes the icon center if (!result) - qWarning("convertHIconToPixmap(), failed to GetIconInfo()"); + qWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()"); int w = iconinfo.xHotspot * 2; int h = iconinfo.yHotspot * 2; @@ -342,60 +380,84 @@ QPixmap convertHIconToPixmap( const HICON icon) return QPixmap::fromImage(image); } #else //ifndef Q_WS_WINCE -QPixmap convertHIconToPixmap( const HICON icon, bool large) +QPixmap QPixmap::fromWinHICON(HICON icon) { HDC screenDevice = GetDC(0); HDC hdc = CreateCompatibleDC(screenDevice); ReleaseDC(0, screenDevice); - int size = large ? 64 : 32; + ICONINFO iconinfo; + bool result = GetIconInfo(icon, &iconinfo); + if (!result) + qWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()"); + + int w = 0; + int h = 0; + if (!iconinfo.xHotspot || !iconinfo.yHotspot) { + // We could not retrieve the icon size via GetIconInfo, + // so we try again using the icon bitmap. + BITMAP bm; + int result = GetObject(iconinfo.hbmColor, sizeof(BITMAP), &bm); + if (!result) result = GetObject(iconinfo.hbmMask, sizeof(BITMAP), &bm); + if (!result) { + qWarning("QPixmap::fromWinHICON(), failed to retrieve icon size"); + return QPixmap(); + } + w = bm.bmWidth; + h = bm.bmHeight; + } else { + // x and y Hotspot describes the icon center + w = iconinfo.xHotspot * 2; + h = iconinfo.yHotspot * 2; + } + const DWORD dwImageSize = w * h * 4; BITMAPINFO bmi; memset(&bmi, 0, sizeof(bmi)); bmi.bmiHeader.biSize = sizeof(BITMAPINFO); - bmi.bmiHeader.biWidth = size; - bmi.bmiHeader.biHeight = -size; + bmi.bmiHeader.biWidth = w; + bmi.bmiHeader.biHeight = -h; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = size*size*4; + bmi.bmiHeader.biSizeImage = dwImageSize; uchar* bits; HBITMAP winBitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**) &bits, 0, 0); if (winBitmap ) - memset(bits, 0xff, size*size*4); + memset(bits, 0xff, dwImageSize); if (!winBitmap) { - qWarning("convertHIconToPixmap(), failed to CreateDIBSection()"); + qWarning("QPixmap::fromWinHICON(), failed to CreateDIBSection()"); return QPixmap(); } HGDIOBJ oldhdc = (HBITMAP)SelectObject(hdc, winBitmap); - if (!DrawIconEx( hdc, 0, 0, icon, size, size, 0, 0, DI_NORMAL)) - qWarning("convertHIconToPixmap(), failed to DrawIcon()"); + if (!DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_NORMAL)) + qWarning("QPixmap::fromWinHICON(), failed to DrawIcon()"); uint mask = 0xff000000; // Create image and copy data into image. - QImage image(size, size, QImage::Format_ARGB32); + QImage image(w, h, QImage::Format_ARGB32); if (!image.isNull()) { // failed to alloc? - int bytes_per_line = size * sizeof(QRgb); - for (int y=0; y<size; ++y) { + int bytes_per_line = w * sizeof(QRgb); + for (int y=0; y < h; ++y) { QRgb *dest = (QRgb *) image.scanLine(y); const QRgb *src = (const QRgb *) (bits + y * bytes_per_line); - for (int x=0; x<size; ++x) { + for (int x=0; x < w; ++x) { dest[x] = src[x]; } } } - if (!DrawIconEx( hdc, 0, 0, icon, size, size, 0, 0, DI_MASK)) - qWarning("convertHIconToPixmap(), failed to DrawIcon()"); + if (!DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_MASK)) + qWarning("QPixmap::fromWinHICON(), failed to DrawIcon()"); if (!image.isNull()) { // failed to alloc? - int bytes_per_line = size * sizeof(QRgb); - for (int y=0; y<size; ++y) { + int bytes_per_line = w * sizeof(QRgb); + for (int y=0; y < h; ++y) { QRgb *dest = (QRgb *) image.scanLine(y); const QRgb *src = (const QRgb *) (bits + y * bytes_per_line); - for (int x=0; x<size; ++x) { + for (int x=0; x < w; ++x) { if (!src[x]) dest[x] = dest[x] | mask; } @@ -407,25 +469,6 @@ QPixmap convertHIconToPixmap( const HICON icon, bool large) return QPixmap::fromImage(image); } #endif //ifndef Q_WS_WINCE - -QPixmap loadIconFromShell32( int resourceId, int size ) -{ -#ifdef Q_OS_WINCE - HMODULE hmod = LoadLibrary(L"ceshell.dll"); -#else - HMODULE hmod = LoadLibrary(L"shell32.dll"); -#endif - if( hmod ) { - HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size, size, 0); - if( iconHandle ) { - QPixmap iconpixmap = convertHIconToPixmap( iconHandle ); - DestroyIcon(iconHandle); - return iconpixmap; - } - } - return QPixmap(); -} - -#endif +#endif //ifdef Q_WS_WIN QT_END_NAMESPACE diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp index 65899a4..93fc2eb 100644 --- a/src/gui/image/qpixmapdata.cpp +++ b/src/gui/image/qpixmapdata.cpp @@ -224,14 +224,15 @@ QImage* QPixmapData::buffer() } #if defined(Q_OS_SYMBIAN) -RSgImage* QPixmapData::toRSgImage() +void* QPixmapData::toNativeType(NativeType /* type */) { return 0; } -void QPixmapData::fromRSgImage(RSgImage* rsgImage) +void QPixmapData::fromNativeType(void* /* pixmap */, NativeType /* typre */) { return; } #endif + QT_END_NAMESPACE diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index bac5065..3e85236 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -56,10 +56,6 @@ #include <QtGui/qpixmap.h> #include <QtCore/qatomic.h> -#if defined(Q_OS_SYMBIAN) -class RSgImage; -#endif - QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QPixmapData @@ -70,6 +66,12 @@ public: // Must match QPixmap::Type PixmapType, BitmapType }; +#if defined(Q_OS_SYMBIAN) + enum NativeType { + FbsBitmap, + SgImage + }; +#endif enum ClassId { RasterClass, X11Class, MacClass, DirectFBClass, OpenGLClass, OpenVGClass, CustomClass = 1024 }; @@ -114,8 +116,8 @@ public: inline bool isNull() const { return is_null; } #if defined(Q_OS_SYMBIAN) - virtual RSgImage* toRSgImage(); - virtual void fromRSgImage(RSgImage* rsgImage); + virtual void* toNativeType(NativeType type); + virtual void fromNativeType(void* pixmap, NativeType type); #endif protected: @@ -129,6 +131,7 @@ private: friend class QPixmap; friend class QGLContextPrivate; friend class QX11PixmapData; + friend class QS60PixmapData; friend class QGLTextureCache; //Needs to check the reference count friend class QExplicitlySharedDataPointer<QPixmapData>; @@ -141,15 +144,6 @@ private: uint is_cached; }; -#ifdef Q_WS_WIN -#ifndef Q_WS_WINCE -QPixmap convertHIconToPixmap( const HICON icon); -#else -QPixmap convertHIconToPixmap( const HICON icon, bool large = false); -#endif -QPixmap loadIconFromShell32( int resourceId, int size ); -#endif - # define QT_XFORM_TYPE_MSBFIRST 0 # define QT_XFORM_TYPE_LSBFIRST 1 # if defined(Q_WS_WIN) diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 4fb650f..ba9a1e2 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -489,7 +489,7 @@ void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const Q which is applied when \l{QPixmapFilter::}{draw()} is called. The filter lets you specialize the radius of the blur as well - as the quality. + as hint as to whether to prefer performance or quality. By default, the blur effect is produced by applying an exponential filter generated from the specified blurRadius(). Paint engines @@ -504,10 +504,10 @@ void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const Q class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate { public: - QPixmapBlurFilterPrivate() : radius(5), quality(Qt::FastTransformation) {} + QPixmapBlurFilterPrivate() : radius(5), hint(QPixmapBlurFilter::PerformanceHint) {} int radius; - Qt::TransformationMode quality; + QPixmapBlurFilter::BlurHint hint; }; @@ -553,29 +553,29 @@ int QPixmapBlurFilter::radius() const } /*! - Setting the quality to FastTransformation causes the implementation + Setting the blur hint to PerformanceHint causes the implementation to trade off visual quality to blur the image faster. Setting the - quality to SmoothTransformation causes the implementation to improve + blur hint to QualityHint causes the implementation to improve visual quality at the expense of speed. The implementation is free to ignore this value if it only has a single blur algorithm. \internal */ -void QPixmapBlurFilter::setQuality(Qt::TransformationMode quality) +void QPixmapBlurFilter::setBlurHint(QPixmapBlurFilter::BlurHint hint) { Q_D(QPixmapBlurFilter); - d->quality = quality; + d->hint = hint; } /*! - Gets the quality of the blur filter. + Gets the blur hint of the blur filter. \internal */ -Qt::TransformationMode QPixmapBlurFilter::quality() const +QPixmapBlurFilter::BlurHint QPixmapBlurFilter::blurHint() const { Q_D(const QPixmapBlurFilter); - return d->quality; + return d->hint; } /*! @@ -672,7 +672,7 @@ void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap QPixmapBlurFilter *blurFilter = static_cast<QPixmapBlurFilter*>(filter); if (blurFilter) { blurFilter->setRadius(d->radius); - blurFilter->setQuality(d->quality); + blurFilter->setBlurHint(d->hint); blurFilter->draw(painter, p, src, srcRect); return; } diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index 2565110..92c8e56 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -126,14 +126,19 @@ class Q_GUI_EXPORT QPixmapBlurFilter : public QPixmapFilter Q_DECLARE_PRIVATE(QPixmapBlurFilter) public: + enum BlurHint { + PerformanceHint, + QualityHint + }; + QPixmapBlurFilter(QObject *parent = 0); ~QPixmapBlurFilter(); void setRadius(int radius); - void setQuality(Qt::TransformationMode mode); + void setBlurHint(BlurHint hint); int radius() const; - Qt::TransformationMode quality() const; + BlurHint blurHint() const; QRectF boundingRectFor(const QRectF &rect) const; void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index b198ae1..fc55a0f 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -98,7 +98,9 @@ QCoeFepInputContext::~QCoeFepInputContext() void QCoeFepInputContext::reset() { - CCoeEnv::Static()->Fep()->CancelTransaction(); + CCoeFep* fep = CCoeEnv::Static()->Fep(); + if (fep) + fep->CancelTransaction(); } void QCoeFepInputContext::ReportAknEdStateEvent(MAknEdStateObserver::EAknEdwinStateEvent aEventType) @@ -626,7 +628,9 @@ void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian) m_isEditing = false; if (!triggeredBySymbian) { - CCoeEnv::Static()->Fep()->CancelTransaction(); + CCoeFep* fep = CCoeEnv::Static()->Fep(); + if (fep) + fep->CancelTransaction(); } } diff --git a/src/gui/inputmethod/qinputcontext.cpp b/src/gui/inputmethod/qinputcontext.cpp index 620880a..8ee417f 100644 --- a/src/gui/inputmethod/qinputcontext.cpp +++ b/src/gui/inputmethod/qinputcontext.cpp @@ -295,7 +295,7 @@ void QInputContext::sendEvent(const QInputMethodEvent &event) The \a event parameter is the event that was sent to the editor widget. The event type is QEvent::MouseButtonPress, QEvent::MouseButtonRelease, QEvent::MouseButtonDblClick or - QEvent::MouseButtonMove. The event's button and state indicate + QEvent::MouseMove. The event's button and state indicate the kind of operation that was performed. */ void QInputContext::mouseHandler(int /*x*/, QMouseEvent *event) @@ -469,6 +469,8 @@ bool QInputContext::x11FilterEvent(QWidget * /*keywidget*/, XEvent * /*event*/) #ifdef Q_WS_S60 /*! + \since 4.6 + This function may be overridden only if input method is depending on Symbian and you need raw TWsEvent. Otherwise, this function must not. diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 757ded9..303f45b 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -61,7 +61,7 @@ #ifndef QT_NO_ACCESSIBILITY #include <qaccessible.h> #endif -#include <private/qactiontokeyeventmapper_p.h> +#include <private/qsoftkeymanager_p.h> QT_BEGIN_NAMESPACE @@ -88,6 +88,9 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate() overwrite(false), dropIndicatorPosition(QAbstractItemView::OnItem), #endif +#ifdef QT_SOFTKEYS_ENABLED + doneSoftKey(0), +#endif autoScroll(true), autoScrollMargin(16), autoScrollCount(0), @@ -128,6 +131,10 @@ void QAbstractItemViewPrivate::init() doDelayedItemsLayout(); q->setAttribute(Qt::WA_InputMethodEnabled); + +#ifdef QT_SOFTKEYS_ENABLED + doneSoftKey = QSoftKeyManager::createKeyedAction(QSoftKeyManager::DoneSoftKey, Qt::Key_Back, q); +#endif } void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index) @@ -2064,14 +2071,18 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) if (QApplication::keypadNavigationEnabled()) { if (!hasEditFocus()) { setEditFocus(true); - QActionToKeyEventMapper::addSoftKey(QAction::BackSoftKey, Qt::Key_Back, this); +#ifdef QT_SOFTKEYS_ENABLED + addAction(d->doneSoftKey); +#endif return; } } break; case Qt::Key_Back: if (QApplication::keypadNavigationEnabled() && hasEditFocus()) { - QActionToKeyEventMapper::removeSoftkey(this); +#ifdef QT_SOFTKEYS_ENABLED + removeAction(d->doneSoftKey); +#endif setEditFocus(false); } else { event->ignore(); @@ -2166,6 +2177,12 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) #endif case Qt::Key_Left: case Qt::Key_Right: +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { + event->accept(); // don't change horizontal focus in directional mode + break; + } +#endif // QT_KEYPAD_NAVIGATION case Qt::Key_Home: case Qt::Key_End: case Qt::Key_PageUp: diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 6b1ec8e..84c0892 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -379,6 +379,10 @@ public: QAbstractItemView::DropIndicatorPosition dropIndicatorPosition; #endif +#ifdef QT_SOFTKEYS_ENABLED + QAction *doneSoftKey; +#endif + QString keyboardInput; QTime keyboardInputTime; diff --git a/src/gui/itemviews/qdirmodel.cpp b/src/gui/itemviews/qdirmodel.cpp index 26e1557..2973741 100644 --- a/src/gui/itemviews/qdirmodel.cpp +++ b/src/gui/itemviews/qdirmodel.cpp @@ -190,6 +190,9 @@ void QDirModelPrivate::invalidate() \ingroup model-view + \note The usage of QDirModel is not recommended anymore. The + QFileSystemModel class is a more performant alternative. + This class provides access to the local filesystem, providing functions for renaming and removing files and directories, and for creating new directories. In the simplest case, it can be used with a suitable display @@ -228,10 +231,7 @@ void QDirModelPrivate::invalidate() \note QDirModel requires an instance of a GUI application. - \note The usage of QDirModel is not recommended anymore. The - QFileSystemModel class is a more performant alternative. - - \sa nameFilters(), setFilter(), filter(), QListView, QTreeView, QFileSystemModel + \sa nameFilters(), setFilter(), filter(), QListView, QTreeView, QFileSystemModel, {Dir View Example}, {Model Classes} */ diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp index 76e1a7e..4abdef9 100644 --- a/src/gui/itemviews/qfileiconprovider.cpp +++ b/src/gui/itemviews/qfileiconprovider.cpp @@ -51,7 +51,6 @@ #include <qt_windows.h> #include <commctrl.h> #include <objbase.h> -#include <private/qpixmapdata_p.h> #elif defined(Q_WS_MAC) #include <private/qt_cocoa_helpers_mac_p.h> #endif @@ -262,9 +261,9 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const } if (pixmap.isNull()) { #ifndef Q_OS_WINCE - pixmap = convertHIconToPixmap(info.hIcon); + pixmap = QPixmap::fromWinHICON(info.hIcon); #else - pixmap = convertHIconToPixmap(ImageList_GetIcon((HIMAGELIST) val, info.iIcon, ILD_NORMAL)); + pixmap = QPixmap::fromWinHICON(ImageList_GetIcon((HIMAGELIST) val, info.iIcon, ILD_NORMAL)); #endif if (!pixmap.isNull()) { retIcon.addPixmap(pixmap); @@ -292,9 +291,9 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const key = QString::fromLatin1("qt_dir_%1").arg(info.iIcon); } #ifndef Q_OS_WINCE - pixmap = convertHIconToPixmap(info.hIcon); + pixmap = QPixmap::fromWinHICON(info.hIcon); #else - pixmap = convertHIconToPixmap(ImageList_GetIcon((HIMAGELIST) val, info.iIcon, ILD_NORMAL), true); + pixmap = QPixmap::fromWinHICON(ImageList_GetIcon((HIMAGELIST) val, info.iIcon, ILD_NORMAL)); #endif if (!pixmap.isNull()) { retIcon.addPixmap(pixmap); diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index a4cebe3..9b0b00f 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -2429,7 +2429,7 @@ void QIconModeViewBase::appendHiddenRow(int row) void QIconModeViewBase::removeHiddenRow(int row) { - QCommonListViewBase::appendHiddenRow(row); + QCommonListViewBase::removeHiddenRow(row); if (row >= 0 && row < items.count()) //insert item tree.insertLeaf(items.at(row).rect(), row); } diff --git a/src/gui/itemviews/qstandarditemmodel.cpp b/src/gui/itemviews/qstandarditemmodel.cpp index e8b7d08..3924a41 100644 --- a/src/gui/itemviews/qstandarditemmodel.cpp +++ b/src/gui/itemviews/qstandarditemmodel.cpp @@ -2971,7 +2971,7 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const Used by QStandardItemModel::dropMimeData stream out an item and his children */ -static void decodeDataRecursive(QDataStream &stream, QStandardItem *item) +void QStandardItemModelPrivate::decodeDataRecursive(QDataStream &stream, QStandardItem *item) { int colCount, childCount; stream >> *item; @@ -2982,7 +2982,7 @@ static void decodeDataRecursive(QDataStream &stream, QStandardItem *item) while(childPos > 0) { childPos--; - QStandardItem *child = new QStandardItem; + QStandardItem *child = createItem(); decodeDataRecursive(stream, child); item->setChild( childPos / colCount, childPos % colCount, child); } @@ -2995,6 +2995,7 @@ static void decodeDataRecursive(QDataStream &stream, QStandardItem *item) bool QStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { + Q_D(QStandardItemModel); // check if the action is supported if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction)) return false; @@ -3026,9 +3027,9 @@ bool QStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction acti while (!stream.atEnd()) { int r, c; - QStandardItem *item = new QStandardItem; + QStandardItem *item = d->createItem(); stream >> r >> c; - decodeDataRecursive(stream, item); + d->decodeDataRecursive(stream, item); rows.append(r); columns.append(c); diff --git a/src/gui/itemviews/qstandarditemmodel_p.h b/src/gui/itemviews/qstandarditemmodel_p.h index 53ee6e3..3f6e0ca 100644 --- a/src/gui/itemviews/qstandarditemmodel_p.h +++ b/src/gui/itemviews/qstandarditemmodel_p.h @@ -176,6 +176,8 @@ public: void _q_emitItemChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void decodeDataRecursive(QDataStream &stream, QStandardItem *item); + QVector<QStandardItem*> columnHeaderItems; QVector<QStandardItem*> rowHeaderItems; QScopedPointer<QStandardItem> root; diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 8489817..7cde384 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -46,7 +46,8 @@ HEADERS += \ kernel/qgesture.h \ kernel/qgesture_p.h \ kernel/qstandardgestures.h \ - kernel/qstandardgestures_p.h + kernel/qstandardgestures_p.h \ + kernel/qsoftkeymanager_p.h SOURCES += \ kernel/qaction.cpp \ @@ -77,7 +78,8 @@ SOURCES += \ kernel/qwidgetaction.cpp \ kernel/qkeymapper.cpp \ kernel/qgesture.cpp \ - kernel/qstandardgestures.cpp + kernel/qstandardgestures.cpp \ + kernel/qsoftkeymanager.cpp win32 { DEFINES += QT_NO_DIRECTDRAW diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp index c641281..6a6e549 100644 --- a/src/gui/kernel/qaction.cpp +++ b/src/gui/kernel/qaction.cpp @@ -81,7 +81,7 @@ static QString qt_strippedText(QString s) QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0), visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false), - menuRole(QAction::TextHeuristicRole), softKeyRole(QAction::OptionsSoftKey), + menuRole(QAction::TextHeuristicRole), softKeyRole(QAction::NoSoftKey), priority(QAction::NormalPriority), iconVisibleInMenu(-1) { #ifdef QT3_SUPPORT @@ -269,24 +269,24 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map) MenuRole for the actions in that submenu have no effect. They will never be moved. */ -/*! \enum QAction::SoftKeyRole - \value OptionsSoftKey - \value SelectSoftKey - \value BackSoftKey - \value NextSoftKey - \value PreviousSoftKey - \value OkSoftKey - \value CancelSoftKey - \value EditSoftKey - \value ViewSoftKey - \value BackSpaceSoftKey - \value EndEditSoftKey - \value RevertEditSoftKey - \value DeselectSoftKey - \value FinishSoftKey - \value MenuSoftKey - \value ContextMenuSoftKey - \value ExitSoftKey +/*! \since 4.6 + + \enum QAction::SoftKeyRole + + This enum describes how an action should be placed in the softkey bar. Currently this enum only + has an effect on the Symbian platform. + + \value NoSoftKey This action should be used as a softkey + \value PositiveSoftKey This action is used to describe a softkey with a positive or non-destructive + role such as Ok, Select, or Options. + \value NegativeSoftKey This action is used to describe a soft ey with a negative or destructive role + role such as Cancel, Discard, or Close. + \value SelectSoftKey This action is used to describe a role that selects a particular item or widget + in the application. + + Actions with a softkey role defined are only visible in the softkey bar when the widget containing + the action has focus. If no widget currently has focus, the softkey framework will traverse up the + widget parent heirarchy looking for a widget containing softkey actions. */ /*! @@ -1437,8 +1437,9 @@ QAction::MenuRole QAction::menuRole() const \brief the action's softkey role \since 4.6 - This indicates what softkey action this action is. Usually used on mobile - platforms to map QActions to hardware keys. + This indicates what type of role this action describes in the softkey framework + on platforms where such a framework is supported. Currently this is only + supported on the Symbian platform. The softkey role can be changed any time. */ diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h index 59c1765..bfc7491 100644 --- a/src/gui/kernel/qaction.h +++ b/src/gui/kernel/qaction.h @@ -93,10 +93,8 @@ class Q_GUI_EXPORT QAction : public QObject public: enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole, AboutRole, PreferencesRole, QuitRole }; - enum SoftKeyRole { OptionsSoftKey, SelectSoftKey, BackSoftKey, NextSoftKey, PreviousSoftKey, - OkSoftKey, CancelSoftKey, EditSoftKey, ViewSoftKey, BackSpaceSoftKey, - EndEditSoftKey, RevertEditSoftKey, DeselectSoftKey, FinishSoftKey, - MenuSoftKey, ContextMenuSoftKey, ExitSoftKey }; + enum SoftKeyRole { + NoSoftKey, PositiveSoftKey, NegativeSoftKey, SelectSoftKey }; enum Priority { LowPriority = 0, NormalPriority = 128, HighPriority = 256}; diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 0ff7314..2ad89a2 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -68,6 +68,9 @@ #include "private/qstylesheetstyle_p.h" #include "private/qstyle_p.h" #include "qmessagebox.h" +#include "qlineedit.h" +#include "qlistview.h" +#include "qtextedit.h" #include <QtGui/qgraphicsproxywidget.h> #include "qinputcontext.h" @@ -1160,6 +1163,7 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis || event->type() == QEvent::Resize || event->type() == QEvent::Move || event->type() == QEvent::LanguageChange + || event->type() == QEvent::UpdateSoftKeys || event->type() == QEvent::InputMethod)) { for (int i = 0; i < postedEvents->size(); ++i) { const QPostEvent &cur = postedEvents->at(i); @@ -1177,6 +1181,8 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis ((QMoveEvent *)(cur.event))->p = ((QMoveEvent *)event)->p; } else if (cur.event->type() == QEvent::LanguageChange) { ; + } else if (cur.event->type() == QEvent::UpdateSoftKeys) { + ; } else if ( cur.event->type() == QEvent::InputMethod ) { *(QInputMethodEvent *)(cur.event) = *(QInputMethodEvent *)event; } else { @@ -2484,8 +2490,6 @@ void QApplication::setActiveWindow(QWidget* act) */ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool next) { - uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus; - QWidget *f = toplevel->focusWidget(); if (!f) f = toplevel; @@ -2493,11 +2497,22 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool QWidget *w = f; QWidget *test = f->d_func()->focus_next; while (test && test != f) { - if ((test->focusPolicy() & focus_flag) == focus_flag + if ((test->focusPolicy() & Qt::TabFocus) && !(test->d_func()->extra && test->d_func()->extra->focus_proxy) && test->isVisibleTo(toplevel) && test->isEnabled() && !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(test)) - && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test))) { + && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test)) + && (qt_tab_all_widgets +#ifndef QT_NO_LINEEDIT + || qobject_cast<QLineEdit*>(test) +#endif +#ifndef QT_NO_TEXTEDIT + || qobject_cast<QTextEdit*>(test) +#endif +#ifndef QT_NO_ITEMVIEWS + || qobject_cast<QListView*>(test) +#endif + )) { w = test; if (next) break; @@ -4781,13 +4796,13 @@ void QApplicationPrivate::emitLastWindowClosed() \note On Windows CE this feature is disabled by default for touch device mkspecs. To enable keypad navigation, build Qt with QT_KEYPAD_NAVIGATION defined. - + \note On Symbian, setting the mode to Qt::NavigationModeCursorAuto will enable a virtual mouse cursor on non touchscreen devices, which is controlled by the cursor keys if there is no analog pointer device. On other platforms and on touchscreen devices, it has the same meaning as Qt::NavigationModeNone. - + \since 4.6 \sa keypadNavigationEnabled() @@ -4810,10 +4825,10 @@ void QApplication::setNavigationMode(Qt::NavigationMode mode) \note On Windows CE this feature is disabled by default for touch device mkspecs. To enable keypad navigation, build Qt with QT_KEYPAD_NAVIGATION defined. - + \note On Symbian, the default mode is Qt::NavigationModeNone for touch devices, and Qt::NavigationModeKeypadDirectional. - + \since 4.6 \sa keypadNavigationEnabled() @@ -4829,12 +4844,11 @@ Qt::NavigationMode QApplication::navigationMode() This feature is available in Qt for Embedded Linux, Symbian and Windows CE only. - \note On Windows CE this feature is disabled by default for touch device mkspecs. To enable keypad navigation, build Qt with QT_KEYPAD_NAVIGATION defined. - + \deprecated \sa setNavigationMode() @@ -4846,7 +4860,7 @@ void QApplication::setKeypadNavigationEnabled(bool enable) QApplication::setNavigationMode(Qt::NavigationModeKeypadDirectional); #else QApplication::setNavigationMode(Qt::NavigationModeKeypadTabOrder); -#endif +#endif } else { QApplication::setNavigationMode(Qt::NavigationModeNone); @@ -4863,7 +4877,7 @@ void QApplication::setKeypadNavigationEnabled(bool enable) \note On Windows CE this feature is disabled by default for touch device mkspecs. To enable keypad navigation, build Qt with QT_KEYPAD_NAVIGATION defined. - + \deprecated \sa navigationMode() diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 0562251..5f21a56 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -64,6 +64,9 @@ QT_BEGIN_HEADER #if defined(Q_OS_SYMBIAN) class TWsEvent; #endif +#if defined(Q_WS_S60) +class CApaApplication; +#endif QT_BEGIN_NAMESPACE @@ -114,6 +117,11 @@ class Q_GUI_EXPORT QApplication : public QCoreApplication public: enum Type { Tty, GuiClient, GuiServer }; + +#ifdef Q_WS_S60 + typedef CApaApplication * (*QS60MainApplicationFactory)(); +#endif + #ifndef qdoc QApplication(int &argc, char **argv, int = QT_VERSION); QApplication(int &argc, char **argv, bool GUIenabled, int = QT_VERSION); @@ -122,6 +130,9 @@ public: QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0, int = QT_VERSION); QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0, int = QT_VERSION); #endif +#if defined(Q_WS_S60) + QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int = QT_VERSION); +#endif #endif virtual ~QApplication(); @@ -357,6 +368,9 @@ public: QApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0); QApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); #endif +#if defined(Q_WS_S60) || defined(qdoc) + QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv); +#endif #endif private: diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 7e8d96f..a656c7f 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -972,6 +972,7 @@ static EventTypeSpec app_events[] = { { kEventClassWindow, kEventWindowActivated }, { kEventClassWindow, kEventWindowDeactivated }, + { kEventClassMouse, kEventMouseScroll }, { kEventClassMouse, kEventMouseWheelMoved }, { kEventClassMouse, kEventMouseDown }, { kEventClassMouse, kEventMouseUp }, @@ -1639,6 +1640,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event case kEventMouseDown: edesc = "MouseButtonPress"; break; case kEventMouseUp: edesc = "MouseButtonRelease"; break; case kEventMouseDragged: case kEventMouseMoved: edesc = "MouseMove"; break; + case kEventMouseScroll: edesc = "MouseWheelScroll"; break; case kEventMouseWheelMoved: edesc = "MouseWheelMove"; break; } if(ekind == kEventMouseDown || ekind == kEventMouseUp) @@ -1659,12 +1661,43 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event sizeof(mac_buttons), 0, &mac_buttons); buttons = qt_mac_get_buttons(mac_buttons); } - int wheel_delta=0; - if(ekind == kEventMouseWheelMoved) { - int mdelt = 0; - GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0, + + int wheel_deltaX = 0; + int wheel_deltaY = 0; + static EventRef compatibilityEvent = 0; + + if (ekind == kEventMouseScroll) { + // kEventMouseScroll is the new way of dealing with mouse wheel + // events (kEventMouseWheelMoved was the old). kEventMouseScroll results + // in much smoother scrolling when using Mighty Mouse or TrackPad. For + // compatibility with older applications, carbon will also send us + // kEventMouseWheelMoved events if we dont eat this event + // (actually two events; one for horizontal and one for vertical). + // As a results of this, and to make sure we dont't receive duplicate events, + // we try to detect when this happend by checking the 'compatibilityEvent'. + SInt32 mdelt = 0; + GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0, + sizeof(mdelt), 0, &mdelt); + wheel_deltaX = mdelt; + GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0, sizeof(mdelt), 0, &mdelt); - wheel_delta = mdelt * 120; + wheel_deltaY = mdelt; + GetEventParameter(event, kEventParamEventRef, typeEventRef, 0, + sizeof(compatibilityEvent), 0, &compatibilityEvent); + } else if (ekind == kEventMouseWheelMoved) { + if (event != compatibilityEvent) { + compatibilityEvent = 0; + int mdelt = 0; + GetEventParameter(event, kEventParamMouseWheelDelta, typeSInt32, 0, + sizeof(mdelt), 0, &mdelt); + EventMouseWheelAxis axis; + GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0, + sizeof(axis), 0, &axis); + if (axis == kEventMouseWheelAxisX) + wheel_deltaX = mdelt * 120; + else + wheel_deltaY = mdelt * 120; + } } Qt::MouseButton button = Qt::NoButton; @@ -2054,20 +2087,29 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event qt_mac_dblclick.last_button = button; qt_mac_dblclick.last_time = GetEventTime(event); } - if(wheel_delta) { - EventMouseWheelAxis axis; - GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, 0, - sizeof(axis), 0, &axis); - QWheelEvent qwe(plocal, p, wheel_delta, buttons, modifiers, - axis == kEventMouseWheelAxisX ? Qt::Horizontal : Qt::Vertical); - QApplication::sendSpontaneousEvent(widget, &qwe); - if(!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) { - QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p, - wheel_delta, buttons, modifiers, - axis == kEventMouseWheelAxisX ? Qt::Horizontal : Qt::Vertical); - QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2); - if(!qwe2.isAccepted()) - handled_event = false; + + if (wheel_deltaX || wheel_deltaY) { + if (wheel_deltaX) { + QWheelEvent qwe(plocal, p, wheel_deltaX, buttons, modifiers, Qt::Horizontal); + QApplication::sendSpontaneousEvent(widget, &qwe); + if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) { + QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p, + wheel_deltaX, buttons, modifiers, Qt::Horizontal); + QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2); + if (!qwe2.isAccepted()) + handled_event = false; + } + } + if (wheel_deltaY) { + QWheelEvent qwe(plocal, p, wheel_deltaY, buttons, modifiers, Qt::Vertical); + QApplication::sendSpontaneousEvent(widget, &qwe); + if (!qwe.isAccepted() && QApplicationPrivate::focus_widget && QApplicationPrivate::focus_widget != widget) { + QWheelEvent qwe2(QApplicationPrivate::focus_widget->mapFromGlobal(p), p, + wheel_deltaY, buttons, modifiers, Qt::Vertical); + QApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, &qwe2); + if (!qwe2.isAccepted()) + handled_event = false; + } } } else { #ifdef QMAC_SPEAK_TO_ME @@ -2130,7 +2172,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event plocal.x(), plocal.y(), event_desc, (QWidget*)widget, widget ? widget->objectName().toLocal8Bit().constData() : "*Unknown*", widget ? widget->metaObject()->className() : "*Unknown*", - button, (int)buttons, (int)modifiers, wheel_delta); + button, (int)buttons, (int)modifiers, wheel_deltaX); #endif } else { handled_event = false; diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 707caaa..aec21fd 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -576,6 +576,11 @@ public: void _q_readRX71MultiTouchEvents(); #endif +#if defined(Q_WS_S60) + int maxTouchPressure; + QList<QTouchEvent::TouchPoint> appAllTouchPoints; +#endif + private: #ifdef Q_WS_QWS QMap<const QScreen*, QRect> maxWindowRects; diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 6a381f5..0637652 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -59,6 +59,7 @@ #include "private/qwindowsurface_s60_p.h" #include "qpaintengine.h" #include "private/qmenubar_p.h" +#include "private/qsoftkeymanager_p.h" #include "apgwgnam.h" // For CApaWindowGroupName #include <MdaAudioTonePlayer.h> // For CMdaAudioToneUtility @@ -367,8 +368,81 @@ void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, cons m_previousEventLongTap = true; } +#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER +void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event) +{ + QApplicationPrivate *d = QApplicationPrivate::instance(); + + QRect screenGeometry = qApp->desktop()->screenGeometry(qwidget); + + while (d->appAllTouchPoints.count() <= event->PointerNumber()) + d->appAllTouchPoints.append(QTouchEvent::TouchPoint(d->appAllTouchPoints.count())); + + Qt::TouchPointStates allStates = 0; + for (int i = 0; i < d->appAllTouchPoints.count(); ++i) { + QTouchEvent::TouchPoint &touchPoint = d->appAllTouchPoints[i]; + + if (touchPoint.id() == event->PointerNumber()) { + Qt::TouchPointStates state; + switch (event->iType) { + case TPointerEvent::EButton1Down: + case TPointerEvent::EEnterHighPressure: + state = Qt::TouchPointPressed; + break; + case TPointerEvent::EButton1Up: + case TPointerEvent::EExitCloseProximity: + state = Qt::TouchPointReleased; + break; + case TPointerEvent::EDrag: + state = Qt::TouchPointMoved; + break; + default: + // how likely is this to happen? + state = Qt::TouchPointStationary; + break; + } + if (event->PointerNumber() == 0) + state |= Qt::TouchPointPrimary; + touchPoint.setState(state); + + QPointF screenPos = QPointF(event->iPosition.iX, event->iPosition.iY); + touchPoint.setScreenPos(screenPos); + touchPoint.setNormalizedPos(QPointF(screenPos.x() / screenGeometry.width(), + screenPos.y() / screenGeometry.height())); + + touchPoint.setPressure(event->Pressure() / qreal(d->maxTouchPressure)); + } else if (touchPoint.state() != Qt::TouchPointReleased) { + // all other active touch points should be marked as stationary + touchPoint.setState(Qt::TouchPointStationary); + } + + allStates |= touchPoint.state(); + } + + if ((allStates & Qt::TouchPointStateMask) == Qt::TouchPointReleased) { + // all touch points released + d->appAllTouchPoints.clear(); + } + + QApplicationPrivate::translateRawTouchEvent(qwidget, + QTouchEvent::TouchScreen, + d->appAllTouchPoints); +} +#endif + void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent) { +#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER + if (pEvent.IsAdvancedPointerEvent()) { + const TAdvancedPointerEvent *advancedPointerEvent = pEvent.AdvancedPointerEvent(); + translateAdvancedPointerEvent(advancedPointerEvent); + if (advancedPointerEvent->PointerNumber() != 0) { + // only send mouse events for the first touch point + return; + } + } +#endif + m_longTapDetector->PointerEventL(pEvent); QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent)); } @@ -406,7 +480,7 @@ void QSymbianControl::HandlePointerEvent(const TPointerEvent& pEvent) alienWidget = qwidget; S60->mousePressTarget = alienWidget; } - + alienWidget = S60->mousePressTarget; if (alienWidget != S60->lastPointerEventTarget) @@ -526,7 +600,7 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod if (keyCode >= Qt::Key_Left && keyCode <= Qt::Key_Down || keyCode == Qt::Key_Select) { /*Explanation about virtualMouseAccel: Tapping an arrow key allows precise pixel positioning - Holding an arrow key down, acceleration is applied to allow cursor + Holding an arrow key down, acceleration is applied to allow cursor to be quickly moved to another part of the screen by key repeats. */ if (S60->virtualMouseLastKey == keyCode) { @@ -594,7 +668,7 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod } } #endif - + Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers); QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode, mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods), @@ -816,11 +890,50 @@ TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id) return CCoeControl::MopSupplyObject(id); } +/*! + \typedef QApplication::QS60MainApplicationFactory + + This is a typedef for a pointer to a function with the following + signature: + + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 47 + + \sa QApplication::QApplication(QApplication::QS60MainApplicationFactory, int &, char **) +*/ + +/*! + \since 4.6 + + Creates an application using the application factory given in + \a factory, and using \a argc command line arguments in \a argv. + \a factory can be leaving, but the error will be converted to a + standard exception. + + This function is only available on S60. +*/ +QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) +{ + Q_D(QApplication); + S60->s60ApplicationFactory = factory; + d->construct(); +} + +QApplication::QApplication(QApplication::QS60MainApplicationFactory factory, int &argc, char **argv, int _internal) + : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient)) +{ + Q_D(QApplication); + S60->s60ApplicationFactory = factory; + d->construct(); + QApplicationPrivate::app_compile_version = _internal; +} + void qt_init(QApplicationPrivate * /* priv */, int) { if (!CCoeEnv::Static()) { // The S60 framework has not been initalized. We need to do it. - TApaApplicationFactory factory(NewApplication); + TApaApplicationFactory factory(S60->s60ApplicationFactory ? + S60->s60ApplicationFactory : newS60Application); CApaCommandLine* commandLine = 0; TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(commandLine); // After this construction, CEikonEnv will be available from CEikonEnv::Static(). @@ -880,13 +993,13 @@ void qt_init(QApplicationPrivate * /* priv */, int) S60->hasTouchscreen = true; S60->virtualMouseRequired = false; } - + if (touch) { QApplicationPrivate::navigationMode = Qt::NavigationModeNone; } else { QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional; } - + #ifndef QT_NO_CURSOR //Check if window server pointer cursors are supported or not #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS @@ -950,7 +1063,7 @@ void qt_cleanup() // it dies. delete QApplicationPrivate::inputContext; QApplicationPrivate::inputContext = 0; - + //Change mouse pointer back S60->wsSession().SetPointerCursorMode(EPointerCursorNone); @@ -1192,6 +1305,7 @@ void QApplication::beep() /*! \warning This function is only available on Symbian. + \since 4.6 This function processes an individual Symbian window server \a event. It returns 1 if the event was handled, 0 if @@ -1270,7 +1384,8 @@ int QApplication::s60ProcessEvent(TWsEvent *event) } else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) && !w->d_func()->maybeBackingStore()) { w->d_func()->topData()->backingStore = new QWidgetBackingStore(w); - w->update(); + w->d_func()->invalidateBuffer(w->rect()); + w->repaint(); } return 1; } @@ -1313,6 +1428,7 @@ int QApplication::s60ProcessEvent(TWsEvent *event) /*! \warning This virtual function is only available on Symbian. + \since 4.6 If you create an application that inherits QApplication and reimplement this function, you get direct access to events that the are received @@ -1330,6 +1446,7 @@ bool QApplication::s60EventFilter(TWsEvent * /* aEvent */) /*! \warning This function is only available on Symbian. + \since 4.6 Handles \a{command}s which are typically handled by CAknAppUi::HandleCommandL(). Qts Ui integration into Symbian is @@ -1348,17 +1465,12 @@ void QApplication::symbianHandleCommand(int command) exit(); break; default: - if (command >= SOFTKEYSTART && command <= SOFTKEYEND) { - int index= command-SOFTKEYSTART; - QWidget *focused = QApplication::focusWidget(); - QWidget *softKeySource = focused ? focused : QApplication::activeWindow(); - const QList<QAction*>& softKeys = softKeySource->softKeys(); - Q_ASSERT(index < softKeys.count()); - softKeys.at(index)->activate(QAction::Trigger); - } + bool handled = QSoftKeyManager::handleCommand(command); #ifdef Q_WS_S60 - else + if (!handled) QMenuBarPrivate::symbianCommands(command); +#else + Q_UNUSED(handled); #endif break; } @@ -1366,6 +1478,7 @@ void QApplication::symbianHandleCommand(int command) /*! \warning This function is only available on Symbian. + \since 4.6 Handles the resource change specified by \a type. @@ -1445,9 +1558,14 @@ TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym) } } - void QApplicationPrivate::initializeMultitouch_sys() -{ } +{ +#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER + if (HAL::Get(HALData::EPointer3DMaxPressure, maxTouchPressure) != KErrNone) + maxTouchPressure = KMaxTInt; +#endif +} + void QApplicationPrivate::cleanupMultitouch_sys() { } @@ -1486,7 +1604,7 @@ void QApplicationPrivate::setNavigationMode(Qt::NavigationMode mode) const bool isCursorOn = (mode == Qt::NavigationModeCursorAuto && !S60->hasTouchscreen) || mode == Qt::NavigationModeCursorForceVisible; - + if (!wasCursorOn && isCursorOn) { //Show the cursor, when changing from another mode to cursor mode qt_symbian_set_cursor_visible(true); @@ -1516,7 +1634,7 @@ void QApplication::restoreOverrideCursor() if (qApp->d_func()->cursor_list.isEmpty()) return; qApp->d_func()->cursor_list.removeFirst(); - + if (!qApp->d_func()->cursor_list.isEmpty()) { qt_symbian_setGlobalCursor(qApp->d_func()->cursor_list.first()); } diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 2b1aaf5..6ecd535 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -220,7 +220,7 @@ static void resolveAygLibs() # define FE_FONTSMOOTHINGCLEARTYPE 0x0002 #endif -bool qt_cleartype_enabled; +Q_GUI_EXPORT bool qt_cleartype_enabled; Q_GUI_EXPORT bool qt_win_owndc_required; // CS_OWNDC is required if we use the GL graphicssystem as default typedef HCTX (API *PtrWTOpen)(HWND, LPLOGCONTEXT, BOOL); diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 7693ca7..f482d1c 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -63,6 +63,11 @@ #include <qdebug.h> +@interface NSEvent (DeviceDelta) + - (CGFloat)deviceDeltaX; + - (CGFloat)deviceDeltaY; + - (CGFloat)deviceDeltaZ; +@end QT_BEGIN_NAMESPACE @@ -776,17 +781,27 @@ extern "C" { Qt::MouseButton buttons = cocoaButton2QtButton([theEvent buttonNumber]); bool wheelOK = false; Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]); - QWidget *widgetToGetMouse = qwidget; - - // Mouse wheel deltas seem to tick in at increments of 0.1. Qt widgets - // expect the delta to be a multiple of 120. - const int ScrollFactor = 10 * 120; - // The qMax(...) factor reduces the - // acceleration for large wheel deltas. - int deltaX = [theEvent deltaX] * ScrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaX])); - int deltaY = [theEvent deltaY] * ScrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaY])); - int deltaZ = [theEvent deltaZ] * ScrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaZ])); + int deltaX = 0; + int deltaY = 0; + int deltaZ = 0; + + const EventRef carbonEvent = (EventRef)[theEvent eventRef]; + const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0; + if (carbonEventKind == kEventMouseScroll) { + // The mouse device containts pixel scroll + // wheel support (Mighty Mouse, Trackpad) + deltaX = (int)[theEvent deviceDeltaX] * 120; + deltaY = (int)[theEvent deviceDeltaY] * 120; + deltaZ = (int)[theEvent deviceDeltaZ] * 120; + } else { // carbonEventKind == kEventMouseWheelMoved + // Mouse wheel deltas seem to tick in at increments of 0.1. + // Qt widgets expect the delta to be a multiple of 120. + const int scrollFactor = 10 * 120; + deltaX = [theEvent deltaX] * scrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaX])); + deltaY = [theEvent deltaY] * scrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaY])); + deltaZ = [theEvent deltaZ] * scrollFactor * qMax(0.6, 1.1 - qAbs([theEvent deltaZ])); + } if (deltaX != 0) { QWheelEvent qwe(qlocal, qglobal, deltaX, buttons, keyMods, Qt::Horizontal); diff --git a/src/gui/kernel/qdesktopwidget.qdoc b/src/gui/kernel/qdesktopwidget.qdoc index 7d3ecf8..bc7f5ae 100644 --- a/src/gui/kernel/qdesktopwidget.qdoc +++ b/src/gui/kernel/qdesktopwidget.qdoc @@ -46,46 +46,65 @@ \ingroup advanced \ingroup desktop - QApplication::desktop() function should be used to get an instance - of the QDesktopWidget. - Systems with more than one graphics card and monitor can manage the physical screen space available either as multiple desktops, or as a - large virtual desktop, which usually has the size of the bounding - rectangle of all the screens (see virtualDesktop). For an - application, one of the available screens is the primary screen, i.e. - the screen where the main widget resides (see primaryScreen). All - windows opened in the context of the application should be - constrained to the boundaries of the primary screen; for example, - it would be inconvenient if a dialog box popped up on a different - screen, or split over two screens. + large virtual desktop. + + This class provides information about the user's desktop, such as its + total size, number of screens, the geometry of each screen, and whether + they are configured as separate desktops or a single virtual desktop. + + Widgets provided by Qt use this class to place tooltips, menus and + dialog boxes on the correct screen for their parent or application + widgets. Applications can use this class to obtain information that + can be used to save window positions, or to place child widgets and + dialogs on one particular screen. - The QDesktopWidget provides information about the geometry of the - available screens with screenGeometry(). The number of screens - available is returned by screenCount, and the screenCountChanged - signal is emitted when screens are added or removed during runtime. + \section1 Obtaining a Desktop Widget + + The QApplication::desktop() function is used to get an instance of + QDesktopWidget. + + The widget's screenGeometry() function provides information about the + geometry of the available screens with. The number of screens + available is returned by screenCount, and the screenCountChanged() + signal is emitted when screens are added or removed. The screen number that a particular point or widget is located in is returned by screenNumber(). - Widgets provided by Qt use this class, for example, to place - tooltips, menus and dialog boxes according to the parent or - application widget. Applications can use this class to save window - positions, or to place child widgets and dialogs on one particular - screen. - - \img qdesktopwidget.png Managing Multiple Screens + \section1 Screen Geometry - In the illustration above, Application One's primary screen is - screen 0, and App Two's primary screen is screen 1. + To obtain the dimensions of a particular screen, call the screenGeometry() + function. On some desktop environments, not all of the screen is + available for applications to use; for example, an application dock or + menu bar may take up some space. Use the availableGeometry() function + to obtain the available area for applications. - \target multiple screens note - \note QDesktopWidget inherits the QWidget properties, width() and + QDesktopWidget also inherits the QWidget properties, width() and height(), which specify the size of the desktop. However, for desktops with multiple screens, the size of the desktop is the union of all the screen sizes, so width() and height() should \e not be used for computing the size of a widget to be placed on one of the - screens. The correct width and height values are obtained using - availableGeometry() or screenGeometry() for a particular screen. + screens. + + On systems that are configured to use the available screens as a + single, large virtual desktop, the virtualDesktop property will be + set to true. In this case, the widget's size is usually the size of + the bounding rectangle of all the screens. + + \section1 Use of the Primary Screen + + For an application, the screen where the main widget resides is the + primary screen. This is stored in the primaryScreen property. + All windows opened in the context of the application should be + constrained to the boundaries of the primary screen; for example, + it would be inconvenient if a dialog box popped up on a different + screen, or split over two screens. + + \image qdesktopwidget.png Managing Multiple Screens + + In the illustration above, Application One's primary screen is + screen 0, and App Two's primary screen is screen 1. \sa QApplication, QApplication::desktop(), QX11Info::appRootWindow() */ diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 9cb2090..ce64c68 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3776,7 +3776,7 @@ QTouchEvent::~QTouchEvent() */ /*! \class QTouchEvent::TouchPoint - \brief The QTouchEvent::TouchPoint class provides information about a touch point in a QTouchEvent. + \brief The TouchPoint class provides information about a touch point in a QTouchEvent. \since 4.6 */ diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 697b93a..fa2b22f 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -70,7 +70,7 @@ public: QInputEvent(Type type, Qt::KeyboardModifiers modifiers = Qt::NoModifier); ~QInputEvent(); inline Qt::KeyboardModifiers modifiers() const { return modState; } - inline void setModifiers(Qt::KeyboardModifiers modifiers) { modState = modifiers; } + inline void setModifiers(Qt::KeyboardModifiers amodifiers) { modState = amodifiers; } protected: Qt::KeyboardModifiers modState; }; @@ -805,10 +805,10 @@ public: inline const QList<QTouchEvent::TouchPoint> &touchPoints() const { return _touchPoints; } // internal - inline void setWidget(QWidget *widget) { _widget = widget; } - inline void setDeviceType(DeviceType deviceType) { _deviceType = deviceType; } + inline void setWidget(QWidget *awidget) { _widget = awidget; } + inline void setDeviceType(DeviceType adeviceType) { _deviceType = adeviceType; } inline void setTouchPointStates(Qt::TouchPointStates touchPointStates) { _touchPointStates = touchPointStates; } - inline void setTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints) { _touchPoints = touchPoints; } + inline void setTouchPoints(const QList<QTouchEvent::TouchPoint> &atouchPoints) { _touchPoints = atouchPoints; } protected: QWidget *_widget; diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index f05d56f..7152705 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -909,6 +909,21 @@ QEventDispatcherMac::QEventDispatcherMac(QObject *parent) QEventDispatcherMacPrivate::waitingObserverCallback, &observerContext); CFRunLoopAddObserver(mainRunLoop(), d->waitingObserver, kCFRunLoopCommonModes); + + /* The first cycle in the loop adds the source and the events of the source + are not processed. + We use an observer to process the posted events for the first + execution of the loop. */ + CFRunLoopObserverContext firstTimeObserverContext; + bzero(&firstTimeObserverContext, sizeof(CFRunLoopObserverContext)); + firstTimeObserverContext.info = d; + d->firstTimeObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, + kCFRunLoopEntry, + /* repeats = */ false, + 0, + QEventDispatcherMacPrivate::firstLoopEntry, + &firstTimeObserverContext); + CFRunLoopAddObserver(mainRunLoop(), d->firstTimeObserver, kCFRunLoopCommonModes); } void QEventDispatcherMacPrivate::waitingObserverCallback(CFRunLoopObserverRef, @@ -925,9 +940,8 @@ Boolean QEventDispatcherMacPrivate::postedEventSourceEqualCallback(const void *i return info1 == info2; } -void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info) +inline static void processPostedEvents(QEventDispatcherMacPrivate *const d, const bool blockSendPostedEvents) { - QEventDispatcherMacPrivate *d = static_cast<QEventDispatcherMacPrivate *>(info); if (blockSendPostedEvents) { CFRunLoopSourceSignal(d->postedEventsSource); } else { @@ -938,6 +952,20 @@ void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info) } } +void QEventDispatcherMacPrivate::firstLoopEntry(CFRunLoopObserverRef ref, + CFRunLoopActivity activity, + void *info) +{ + Q_UNUSED(ref); + Q_UNUSED(activity); + processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents); +} + +void QEventDispatcherMacPrivate::postedEventsSourcePerformCallback(void *info) +{ + processPostedEvents(static_cast<QEventDispatcherMacPrivate *>(info), blockSendPostedEvents); +} + void QEventDispatcherMac::interrupt() { Q_D(QEventDispatcherMac); @@ -996,6 +1024,9 @@ QEventDispatcherMac::~QEventDispatcherMac() CFRunLoopObserverInvalidate(d->waitingObserver); CFRelease(d->waitingObserver); + + CFRunLoopObserverInvalidate(d->firstTimeObserver); + CFRelease(d->firstTimeObserver); } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/gui/kernel/qeventdispatcher_mac_p.h b/src/gui/kernel/qeventdispatcher_mac_p.h index e94d98a..dfcb91f 100644 --- a/src/gui/kernel/qeventdispatcher_mac_p.h +++ b/src/gui/kernel/qeventdispatcher_mac_p.h @@ -187,6 +187,7 @@ public: QList<void *> queuedUserInputEvents; // List of EventRef in Carbon, and NSEvent * in Cocoa CFRunLoopSourceRef postedEventsSource; CFRunLoopObserverRef waitingObserver; + CFRunLoopObserverRef firstTimeObserver; QAtomicInt serialNumber; int lastSerial; bool interrupt; @@ -196,6 +197,7 @@ private: static void activateTimer(CFRunLoopTimerRef, void *info); static void waitingObserverCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info); + static void firstLoopEntry(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info); }; #ifdef QT_MAC_USE_COCOA diff --git a/src/gui/kernel/qeventdispatcher_x11.cpp b/src/gui/kernel/qeventdispatcher_x11.cpp index ce1a11f..59977ec 100644 --- a/src/gui/kernel/qeventdispatcher_x11.cpp +++ b/src/gui/kernel/qeventdispatcher_x11.cpp @@ -105,7 +105,7 @@ bool QEventDispatcherX11::processEvents(QEventLoop::ProcessEventsFlags flags) // _qt_scrolldone protocols, queue all other // client messages if (event.xclient.format == 32) { - if (event.xclient.message_type == ATOM(WM_PROTOCOLS) || + if (event.xclient.message_type == ATOM(WM_PROTOCOLS) && (Atom) event.xclient.data.l[0] == ATOM(WM_TAKE_FOCUS)) { break; } else if (event.xclient.message_type == ATOM(_QT_SCROLL_DONE)) { diff --git a/src/gui/kernel/qguieventdispatcher_glib.cpp b/src/gui/kernel/qguieventdispatcher_glib.cpp index 6e98428..f8a638c 100644 --- a/src/gui/kernel/qguieventdispatcher_glib.cpp +++ b/src/gui/kernel/qguieventdispatcher_glib.cpp @@ -120,7 +120,7 @@ static gboolean x11EventSourceDispatch(GSource *s, GSourceFunc callback, gpointe // _qt_scrolldone protocols, queue all other // client messages if (event.xclient.format == 32) { - if (event.xclient.message_type == ATOM(WM_PROTOCOLS) || + if (event.xclient.message_type == ATOM(WM_PROTOCOLS) && (Atom) event.xclient.data.l[0] == ATOM(WM_TAKE_FOCUS)) { break; } else if (event.xclient.message_type == ATOM(_QT_SCROLL_DONE)) { diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp new file mode 100644 index 0000000..91f4163 --- /dev/null +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -0,0 +1,277 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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 qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qapplication.h" +#include "qevent.h" +#ifdef Q_WS_S60 +#include "qstyle.h" +#include "private/qt_s60_p.h" +#endif +#include "private/qsoftkeymanager_p.h" +#include "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +#ifdef Q_WS_S60 +static const int s60CommandStart = 6000; +#endif + +class QSoftKeyManagerPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QSoftKeyManager) + +public: + static void updateSoftKeys_sys(const QList<QAction*> &softKeys); + +private: + QHash<QAction*, Qt::Key> keyedActions; + static QSoftKeyManager *self; + static QWidget *softKeySource; +}; + +QWidget *QSoftKeyManagerPrivate::softKeySource = 0; +QSoftKeyManager *QSoftKeyManagerPrivate::self = 0; + +const char *QSoftKeyManager::standardSoftKeyText(StandardSoftKey standardKey) +{ + const char *softKeyText = 0; + switch (standardKey) { + case OkSoftKey: + softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Ok"); + break; + case SelectSoftKey: + softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Select"); + break; + case DoneSoftKey: + softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Done"); + break; + case MenuSoftKey: + softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Options"); + break; + case CancelSoftKey: + softKeyText = QT_TRANSLATE_NOOP("QSoftKeyManager", "Cancel"); + break; + default: + break; + }; + + return softKeyText; +} + +QSoftKeyManager *QSoftKeyManager::instance() +{ + if (!QSoftKeyManagerPrivate::self) + QSoftKeyManagerPrivate::self = new QSoftKeyManager; + + return QSoftKeyManagerPrivate::self; +} + +QSoftKeyManager::QSoftKeyManager() : QObject(*(new QSoftKeyManagerPrivate), 0) +{ +} + +QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *actionWidget) +{ + const char* text = standardSoftKeyText(standardKey); + QAction *action = new QAction(QSoftKeyManager::tr(text), actionWidget); + QAction::SoftKeyRole softKeyRole; + switch (standardKey) { + case OkSoftKey: + case SelectSoftKey: + case DoneSoftKey: + case MenuSoftKey: + softKeyRole = QAction::PositiveSoftKey; + break; + case CancelSoftKey: + softKeyRole = QAction::NegativeSoftKey; + break; + } + action->setSoftKeyRole(softKeyRole); + action->setEnabled(actionWidget->isEnabled()); + return action; +} + +/*! \internal + + Creates a QAction and registers the 'triggered' signal to send the given key event to + \a actionWidget as a convenience. + +*/ +QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget) +{ + QScopedPointer<QAction> action(createAction(standardKey, actionWidget)); + + connect(action.data(), SIGNAL(triggered()), QSoftKeyManager::instance(), SLOT(sendKeyEvent())); + + QSoftKeyManager::instance()->d_func()->keyedActions.insert(action.data(), key); + return action.take(); +} + +void QSoftKeyManager::sendKeyEvent() +{ + Q_D(QSoftKeyManager); + QAction *action = qobject_cast<QAction*>(sender()); + + if (!action) + return; + + Qt::Key keyToSend = d->keyedActions.value(action, Qt::Key_unknown); + + if (keyToSend != Qt::Key_unknown) + QApplication::postEvent(action->parentWidget(), + new QKeyEvent(QEvent::KeyPress, keyToSend, Qt::NoModifier)); +} + +void QSoftKeyManager::updateSoftKeys() +{ + QEvent *event = new QEvent(QEvent::UpdateSoftKeys); + QApplication::postEvent(QSoftKeyManager::instance(), event); +} + +bool QSoftKeyManager::event(QEvent *e) +{ + if (e->type() == QEvent::UpdateSoftKeys) { + QList<QAction*> softKeys; + QWidget *source = QApplication::focusWidget(); + do { + if (source) { + QList<QAction*> actions = source->actions(); + for (int i = 0; i < actions.count(); ++i) { + if (actions.at(i)->softKeyRole() != QAction::NoSoftKey) + softKeys.append(actions.at(i)); + } + + QWidget *parent = source->parentWidget(); + if (parent && softKeys.isEmpty()) + source = parent; + else + break; + } else { + source = QApplication::activeWindow(); + } + } while (source); + + QSoftKeyManagerPrivate::softKeySource = source; + QSoftKeyManagerPrivate::updateSoftKeys_sys(softKeys); + return true; + } + return false; +} + +#ifdef Q_WS_S60 +void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) +{ + CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer(); + QT_TRAP_THROWING(nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS)); + + int position = -1; + int command; + bool needsExitButton = true; + + for (int index = 0; index < softkeys.count(); index++) { + const QAction* softKeyAction = softkeys.at(index); + switch (softKeyAction->softKeyRole()) { + // Positive Actions go on LSK + case QAction::PositiveSoftKey: + position = 0; + break; + case QAction::SelectSoftKey: + position = 0; + break; + // Negative Actions on the RSK + case QAction::NegativeSoftKey: + needsExitButton = false; + position = 2; + break; + default: + break; + } + + command = (softKeyAction->objectName().contains("_q_menuSoftKeyAction")) + ? EAknSoftkeyOptions + : s60CommandStart + index; + + if (position != -1) { + const int underlineShortCut = QApplication::style()->styleHint(QStyle::SH_UnderlineShortcut); + QString iconText = softKeyAction->iconText(); + TPtrC text = qt_QString2TPtrC( underlineShortCut ? softKeyAction->text() : iconText); + QT_TRAP_THROWING(nativeContainer->SetCommandL(position, command, text)); + } + } + + if (needsExitButton) + QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QObject::tr("Exit")))); + + nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation +} + +bool QSoftKeyManager::handleCommand(int command) +{ + if (command >= s60CommandStart && QSoftKeyManagerPrivate::softKeySource) { + int index = command - s60CommandStart; + const QList<QAction*>& softKeys = QSoftKeyManagerPrivate::softKeySource->actions(); + for (int i = 0, j = 0; i < softKeys.count(); ++i) { + QAction *action = softKeys.at(i); + if (action->softKeyRole() != QAction::NoSoftKey) { + if (j == index) { + if (action->isEnabled()) { + action->activate(QAction::Trigger); + return true; + } + } + j++; + } + } + } + + return false; +} + +#else + +void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &) +{ +} + +#endif + +QT_END_NAMESPACE + diff --git a/src/gui/widgets/qactiontokeyeventmapper_p.h b/src/gui/kernel/qsoftkeymanager_p.h index 984eed9..c4bb84d 100644 --- a/src/gui/widgets/qactiontokeyeventmapper_p.h +++ b/src/gui/kernel/qsoftkeymanager_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QACTIONTOKEYEVENTMAPPER_P_H -#define QACTIONTOKEYEVENTMAPPER_P_H +#ifndef QSOFTKEYMANAGER_P_H +#define QSOFTKEYMANAGER_P_H // // W A R N I N G @@ -55,21 +55,46 @@ #include <QtCore/qobject.h> #include "QtGui/qaction.h" + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QActionToKeyEventMapper : public QObject +class QSoftKeyManagerPrivate; + +class Q_AUTOTEST_EXPORT QSoftKeyManager : public QObject { Q_OBJECT + Q_DECLARE_PRIVATE(QSoftKeyManager) + public: - QActionToKeyEventMapper(QAction *softKeyAction, Qt::Key key, QObject *parent); - static QString roleText(QAction::SoftKeyRole role); - static void addSoftKey(QAction::SoftKeyRole standardRole, Qt::Key key, QWidget *actionWidget); - static void removeSoftkey(QWidget *focussedWidget); + + enum StandardSoftKey { + OkSoftKey, + SelectSoftKey, + DoneSoftKey, + MenuSoftKey, + CancelSoftKey, + }; + + static void updateSoftKeys(); + static QAction *createAction(StandardSoftKey standardKey, QWidget *actionWidget); + static QAction *createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget); + +#ifdef Q_WS_S60 + static bool handleCommand(int); +#endif + private: - QAction *m_softKeyAction; - Qt::Key m_key; + QSoftKeyManager(); + static QSoftKeyManager *instance(); + static const char *standardSoftKeyText(StandardSoftKey standardKey); + +protected: + bool event(QEvent *e); + + Q_DISABLE_COPY(QSoftKeyManager) + private Q_SLOTS: void sendKeyEvent(); }; @@ -78,4 +103,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif //QACTIONTOKEYEVENTMAPPER_P_H +#endif //QSOFTKEYMANAGER_P_H diff --git a/src/gui/kernel/qsound_qws.cpp b/src/gui/kernel/qsound_qws.cpp index 33a0922..8595faa 100644 --- a/src/gui/kernel/qsound_qws.cpp +++ b/src/gui/kernel/qsound_qws.cpp @@ -279,7 +279,7 @@ QAuBucketQWS::QAuBucketQWS( QAuServerQWS *server, QSound *sound, QObject* parent sound->setObjectName( m_id.toString() ); - m_channel = new QCopChannel(QLatin1String("QPE/QSound/") + m_id ), this ); + m_channel = new QCopChannel(QLatin1String("QPE/QSound/") + m_id, this ); connect( m_channel, SIGNAL(received(QString,QByteArray)), this, SLOT(processMessage(QString,QByteArray)) ); diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index b43c950..0d48634 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -61,6 +61,7 @@ #include "QtGui/qimage.h" #include "QtGui/qevent.h" #include "qpointer.h" +#include "qapplication.h" #include <w32std.h> #include <coecntrl.h> #include <eikenv.h> @@ -77,7 +78,7 @@ QT_BEGIN_NAMESPACE // Application internal HandleResourceChangeL events, -// system evens seems to start with 0x10 +// system events seems to start with 0x10 const TInt KInternalStatusPaneChange = 0x50000000; class QS60Data @@ -101,12 +102,13 @@ public: int virtualMouseAccel; int virtualMouseMaxAccel; #ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS - bool brokenPointerCursors; + int brokenPointerCursors : 1; #endif - bool hasTouchscreen; - bool mouseInteractionEnabled; - bool virtualMouseRequired; + int hasTouchscreen : 1; + int mouseInteractionEnabled : 1; + int virtualMouseRequired : 1; int qtOwnsS60Environment : 1; + QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type static inline void updateScreenSize(); static inline RWsSession& wsSession(); static inline RWindowGroup& windowGroup(); @@ -167,6 +169,9 @@ private: TKeyResponse sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent); bool sendMouseEvent(QWidget *widget, QMouseEvent *mEvent); void HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation ); +#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER + void translateAdvancedPointerEvent(const TAdvancedPointerEvent *event); +#endif private: QWidget *qwidget; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index c86012d..2397793 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -82,6 +82,7 @@ #include "private/qstyle_p.h" #include "private/qinputcontext_p.h" #include "qfileinfo.h" +#include "private/qsoftkeymanager_p.h" #if defined (Q_WS_WIN) # include <private/qwininputcontext_p.h> @@ -410,7 +411,6 @@ void QWidget::setEditFocus(bool on) QApplication::sendEvent(f, &event); QApplication::sendEvent(f->style(), &event); } - f->repaint(); // Widget might want to repaint a focus indicator } #endif @@ -2106,6 +2106,13 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrus painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); } #endif // Q_WS_MAC + + } else if (brush.gradient() + && brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode) { + painter->save(); + painter->setClipRegion(rgn); + painter->fillRect(0, 0, painter->device()->width(), painter->device()->height(), brush); + painter->restore(); } else { const QVector<QRect> &rects = rgn.rects(); for (int i = 0; i < rects.size(); ++i) @@ -2146,7 +2153,6 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int if (q->autoFillBackground()) fillRegion(painter, rgn, autoFillBrush); - if (q->testAttribute(Qt::WA_StyledBackground)) { painter->setClipRegion(rgn); QStyleOption opt; @@ -3323,7 +3329,7 @@ QPoint QWidget::pos() const \note Do not use this function to find the width of a screen on a \l{QDesktopWidget}{multiple screen desktop}. Read - \l{multiple screens note}{this note} for details. + \l{QDesktopWidget#Screen Geometry}{this note} for details. By default, this property contains a value that depends on the user's platform and screen geometry. @@ -3339,8 +3345,8 @@ QPoint QWidget::pos() const issues with windows. \note Do not use this function to find the height of a screen - on a \l {QDesktopWidget} {multiple screen desktop}. Read - \l {multiple screens note} {this note} for details. + on a \l{QDesktopWidget}{multiple screen desktop}. Read + \l{QDesktopWidget#Screen Geometry}{this note} for details. By default, this property contains a value that depends on the user's platform and screen geometry. @@ -4972,15 +4978,11 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, d->extra->inRenderWithPainter = false; } -#if !defined(Q_OS_SYMBIAN) -void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys) -{ - Q_UNUSED(softkeys) -} -#endif // !defined(Q_OS_SYMBIAN) - /*! - Returns a pointer to this widget's effect if it has one; otherwise 0. + \brief The graphicsEffect function returns a pointer to the + widget's graphics effect. + + If the widget has no graphics effect, 0 is returned. \since 4.6 @@ -4993,6 +4995,9 @@ QGraphicsEffect *QWidget::graphicsEffect() const } /*! + + \brief The setGraphicsEffect function is for setting the widget's graphics effect. + Sets \a effect as the widget's effect. If there already is an effect installed on this widget, QWidget will delete the existing effect before installing the new \a effect. @@ -5688,7 +5693,7 @@ void QWidget::setWindowIconText(const QString &iconText) void QWidget::setWindowTitle(const QString &title) { - if (QWidget::windowTitle() == title) + if (QWidget::windowTitle() == title && !title.isEmpty() && !title.isNull()) return; Q_D(QWidget); @@ -6212,7 +6217,8 @@ QWidget *QWidget::nextInFocusChain() const } /*! - Returns the previous widget in this widget's focus chain. + \brief The previousInFocusChain function returns the previous + widget in this widget's focus chain. \sa nextInFocusChain() @@ -6449,6 +6455,8 @@ void QWidgetPrivate::reparentFocusWidgets(QWidget * oldtlw) This function is called from QDesktopwidget::screen(QPoint) to find the closest screen for a point. + In directional KeypadNavigation, it is called to find the closest + widget to the current focus widget center. */ int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r) { @@ -6713,14 +6721,14 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) */ /*! - Sets the margins around the contents of the widget to have the - sizes \a left, \a top, \a right, and \a bottom. The margins are - used by the layout system, and may be used by subclasses to - specify the area to draw in (e.g. excluding the frame). + Sets the margins around the contents of the widget to have the sizes + \a left, \a top, \a right, and \a bottom. The margins are used by + the layout system, and may be used by subclasses to specify the area + to draw in (e.g. excluding the frame). - Changing the margins will trigger a resizeEvent(). + Changing the margins will trigger a resizeEvent(). - \sa contentsRect(), getContentsMargins() + \sa contentsRect(), getContentsMargins() */ void QWidget::setContentsMargins(int left, int top, int right, int bottom) { @@ -6755,6 +6763,9 @@ void QWidget::setContentsMargins(int left, int top, int right, int bottom) \overload \since 4.6 + \brief The setContentsMargins function sets the margins around the + widget's contents. + Sets the margins around the contents of the widget to have the sizes determined by \a margins. The margins are used by the layout system, and may be used by subclasses to @@ -6792,7 +6803,7 @@ void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) c /*! \since 4.6 - Returns the widget's contents margins. + \brief The contentsMargins function returns the widget's contents margins. \sa getContentsMargins(), setContentsMargins(), contentsRect() */ @@ -7929,10 +7940,21 @@ bool QWidget::event(QEvent *event) #ifdef QT_KEYPAD_NAVIGATION if (!k->isAccepted() && QApplication::keypadNavigationEnabled() && !(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::ShiftModifier))) { - if (k->key() == Qt::Key_Up) - res = focusNextPrevChild(false); - else if (k->key() == Qt::Key_Down) - res = focusNextPrevChild(true); + if (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder) { + if (k->key() == Qt::Key_Up) + res = focusNextPrevChild(false); + else if (k->key() == Qt::Key_Down) + res = focusNextPrevChild(true); + } else if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { + if (k->key() == Qt::Key_Up) + res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionNorth); + else if (k->key() == Qt::Key_Right) + res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionEast); + else if (k->key() == Qt::Key_Down) + res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionSouth); + else if (k->key() == Qt::Key_Left) + res = QWidgetPrivate::navigateToDirection(QWidgetPrivate::DirectionWest); + } if (res) { k->accept(); break; @@ -7985,7 +8007,9 @@ bool QWidget::event(QEvent *event) } break; case QEvent::FocusIn: - d->setSoftKeys_sys(softKeys()); +#ifdef QT_SOFTKEYS_ENABLED + QSoftKeyManager::updateSoftKeys(); +#endif focusInEvent((QFocusEvent*)event); break; @@ -8136,8 +8160,10 @@ bool QWidget::event(QEvent *event) QApplication::sendEvent(w, event); } +#ifdef QT_SOFTKEYS_ENABLED if (isWindow() && isActiveWindow()) - d->setSoftKeys_sys(softKeys()); + QSoftKeyManager::updateSoftKeys(); +#endif break; } @@ -8246,6 +8272,9 @@ bool QWidget::event(QEvent *event) case QEvent::ActionAdded: case QEvent::ActionRemoved: case QEvent::ActionChanged: +#ifdef QT_SOFTKEYS_ENABLED + QSoftKeyManager::updateSoftKeys(); +#endif actionEvent((QActionEvent*)event); break; #endif @@ -8477,8 +8506,10 @@ void QWidget::mouseReleaseEvent(QMouseEvent *event) The default implementation generates a normal mouse press event. - Note that the widgets gets a mousePressEvent() and a - mouseReleaseEvent() before the mouseDoubleClickEvent(). + \note The widget will also receive mouse press and mouse release + events in addition to the double click event. It is up to the + developer to ensure that the application interprets these events + correctly. \sa mousePressEvent(), mouseReleaseEvent() mouseMoveEvent(), event(), QMouseEvent @@ -10114,7 +10145,8 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute"); #ifdef Q_WS_WIN - if (attribute == Qt::WA_PaintOnScreen && on) { + // ### Don't use PaintOnScreen+paintEngine() to do native painting in 5.0 + if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) { // see qwidget_win.cpp, ::paintEngine for details paintEngine(); if (d->noPaintOnScreen) @@ -10366,7 +10398,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; case Qt::WA_AcceptTouchEvents: -#if defined(Q_WS_WIN) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_WS_S60) if (on) d->registerTouchWindow(); #endif @@ -11373,6 +11405,74 @@ QRect QWidgetPrivate::frameStrut() const return maybeTopData() ? maybeTopData()->frameStrut : QRect(); } +#ifdef QT_KEYPAD_NAVIGATION +/*! + \internal + + Changes the focus from the current focusWidget to a widget in + the \a direction. + + Returns true, if there was a widget in that direction +*/ +bool QWidgetPrivate::navigateToDirection(Direction direction) +{ + QWidget *targetWidget = widgetInNavigationDirection(direction); + if (targetWidget) + targetWidget->setFocus(); + return (targetWidget != 0); +} + +/*! + \internal + + Searches for a widget that is positioned in the \a direction, starting + from the current focusWidget. + + Returns the pointer to a found widget or 0, if there was no widget in + that direction. +*/ +QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction) +{ + const QWidget *sourceWidget = QApplication::focusWidget(); + if (!sourceWidget) + return 0; + const QRect sourceRect = sourceWidget->rect().translated(sourceWidget->mapToGlobal(QPoint())); + const int sourceX = + (direction == DirectionNorth || direction == DirectionSouth) ? + (sourceRect.left() + (sourceRect.right() - sourceRect.left()) / 2) + :(direction == DirectionEast ? sourceRect.right() : sourceRect.left()); + const int sourceY = + (direction == DirectionEast || direction == DirectionWest) ? + (sourceRect.top() + (sourceRect.bottom() - sourceRect.top()) / 2) + :(direction == DirectionSouth ? sourceRect.bottom() : sourceRect.top()); + const QPoint sourcePoint(sourceX, sourceY); + const QPoint sourceCenter = sourceRect.center(); + const QWidget *sourceWindow = sourceWidget->window(); + + QWidget *targetWidget = 0; + int shortestDistance = INT_MAX; + foreach(QWidget *targetCandidate, QApplication::allWidgets()) { + const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint())); + if ( targetCandidate != sourceWidget + && targetCandidate->focusPolicy() & Qt::TabFocus + && !(direction == DirectionNorth && targetCandidateRect.bottom() > sourceRect.top()) + && !(direction == DirectionEast && targetCandidateRect.left() < sourceRect.right()) + && !(direction == DirectionSouth && targetCandidateRect.top() < sourceRect.bottom()) + && !(direction == DirectionWest && targetCandidateRect.right() > sourceRect.left()) + && targetCandidate->isEnabled() + && targetCandidate->isVisible() + && targetCandidate->window() == sourceWindow) { + const int targetCandidateDistance = pointToRect(sourcePoint, targetCandidateRect); + if (targetCandidateDistance < shortestDistance) { + shortestDistance = targetCandidateDistance; + targetWidget = targetCandidate; + } + } + } + return targetWidget; +} +#endif + /*! \preliminary \since 4.2 @@ -11858,67 +11958,6 @@ void QWidget::clearMask() setMask(QRegion()); } -/*! - \preliminary - \since 4.6 - - Returns the (possibly empty) list of this widget's softkeys. - Returned list cannot be changed. Softkeys should be added - and removed via method called setSoftKeys - - \sa setSoftKey(), setSoftKeys() -*/ -const QList<QAction*>& QWidget::softKeys() const -{ - Q_D(const QWidget); - if( d->softKeys.count() > 0) - return d->softKeys; - if (isWindow() || !parentWidget()) - return d->softKeys; - - return parentWidget()->softKeys(); -} - -/*! - \preliminary - \since 4.6 - - Sets the softkey \a softKey to this widget's list of softkeys. - Setting 0 as softkey will clear all the existing softkeys set - to the widget. A QWidget can have 0 or more softkeys. - - \sa softKeys(), setSoftKeys() -*/ -void QWidget::setSoftKey(QAction *softKey) -{ - Q_D(QWidget); - qDeleteAll(d->softKeys); - d->softKeys.clear(); - if (softKey) - d->softKeys.append(softKey); - if ((!QApplication::focusWidget() && this == QApplication::activeWindow()) - || QApplication::focusWidget() == this) - d->setSoftKeys_sys(this->softKeys()); -} - -/*! - Sets the list of softkeys \a softKeys to this widget's list of softkeys. - A QWidget can have 0 or more softkeys. - - \sa softKeys(), setSoftKey() -*/ -void QWidget::setSoftKeys(const QList<QAction*> &softKeys) -{ - Q_D(QWidget); - qDeleteAll(d->softKeys); - d->softKeys.clear(); - d->softKeys = softKeys; - - if ((!QApplication::focusWidget() && this == QApplication::activeWindow()) - || QApplication::focusWidget() == this) - d->setSoftKeys_sys(this->softKeys()); -} - /*! \fn const QX11Info &QWidget::x11Info() const Returns information about the configuration of the X display used to display the widget. diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 8410775..7e250e2 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -564,9 +564,6 @@ public: void removeAction(QAction *action); QList<QAction*> actions() const; #endif - const QList<QAction*>& softKeys() const; - void setSoftKey(QAction *softKey); - void setSoftKeys(const QList<QAction*> &softKeys); QWidget *parentWidget() const; diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 6b040bc..c966aa3 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -3617,7 +3617,7 @@ void QWidgetPrivate::raise_sys() QMacCocoaAutoReleasePool pool; if (isRealWindow()) { // Calling orderFront shows the window on Cocoa too. - if (!q->testAttribute(Qt::WA_DontShowOnScreen)) { + if (!q->testAttribute(Qt::WA_DontShowOnScreen) && q->isVisible()) { [qt_mac_window_for(q) orderFront:qt_mac_window_for(q)]; } if (qt_mac_raise_process) { //we get to be the active process now diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 7eb8f04..296c5b1 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -85,9 +85,6 @@ #if defined(Q_OS_SYMBIAN) class RDrawableWindow; class CCoeControl; -// The following 2 defines may only be needed for s60. To be seen. -const int SOFTKEYSTART=5000; -const int SOFTKEYEND=5004; #endif QT_BEGIN_NAMESPACE @@ -252,11 +249,17 @@ public: CloseWithSpontaneousEvent }; + enum Direction { + DirectionNorth = 0x01, + DirectionEast = 0x10, + DirectionSouth = 0x02, + DirectionWest = 0x20 + }; + // Functions. explicit QWidgetPrivate(int version = QObjectPrivateVersion); ~QWidgetPrivate(); - void setSoftKeys_sys(const QList<QAction*> &softkeys); QWExtra *extraData() const; QTLWExtra *topData() const; QTLWExtra *maybeTopData() const; @@ -398,6 +401,11 @@ public: void updateFrameStrut(); QRect frameStrut() const; +#ifdef QT_KEYPAD_NAVIGATION + static bool navigateToDirection(Direction direction); + static QWidget *widgetInNavigationDirection(Direction direction); +#endif + void setWindowIconText_sys(const QString &cap); void setWindowIconText_helper(const QString &cap); void setWindowTitle_sys(const QString &cap); @@ -505,7 +513,6 @@ public: QWidget *focus_next; QWidget *focus_prev; QWidget *focus_child; - QList<QAction*> softKeys; QLayout *layout; QRegion *needsFlush; QPaintDevice *redirectDev; @@ -686,6 +693,7 @@ public: static QWidget *keyboardGrabber; void s60UpdateIsOpaque(); void reparentChildren(); + void registerTouchWindow(); #endif }; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 3744377..6b5e9b7 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -78,78 +78,6 @@ static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b) return true; } - -void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys) -{ -#ifdef Q_WS_S60 - Q_Q(QWidget); - if (QApplication::focusWidget() && q!=QApplication::focusWidget()) { - QList<QAction *> old = QApplication::focusWidget()->softKeys(); - if (isEqual(old, softkeys )) - return; - } - CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer(); - QT_TRAP_THROWING(nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS)); - - int position = -1; - int command; - bool needsExitButton = true; - - for (int index = 0; index < softkeys.count(); index++) { - const QAction* softKeyAction = softkeys.at(index); - switch (softKeyAction->softKeyRole()) { - // Positive Actions go on LSK - case QAction::OptionsSoftKey: - case QAction::MenuSoftKey: - case QAction::ContextMenuSoftKey: - command = EAknSoftkeyOptions; //Calls DynInitMenuPane in AppUI - position = 0; - break; - case QAction::SelectSoftKey: - case QAction::PreviousSoftKey: - case QAction::OkSoftKey: - case QAction::EditSoftKey: - case QAction::ViewSoftKey: - case QAction::EndEditSoftKey: - case QAction::FinishSoftKey: - command = SOFTKEYSTART + index; - position = 0; - break; - // Negative Actions on the RSK - case QAction::BackSoftKey: - case QAction::NextSoftKey: - case QAction::CancelSoftKey: - case QAction::BackSpaceSoftKey: - case QAction::RevertEditSoftKey: - case QAction::DeselectSoftKey: - needsExitButton = false; - command = SOFTKEYSTART + index; - position = 2; - break; - case QAction::ExitSoftKey: - needsExitButton = false; - command = EAknSoftkeyExit; //Calls HandleCommand in AppUI - position = 2; - break; - default: - break; - } - - if (position != -1) { - TPtrC text = qt_QString2TPtrC(softKeyAction->text()); - QT_TRAP_THROWING(nativeContainer->SetCommandL(position, command, text)); - } - } - - if (needsExitButton) - QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QObject::tr("Exit")))); - - nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation -#else - Q_UNUSED(softkeys) -#endif -} - void QWidgetPrivate::setWSGeometry(bool /* dontShow */, const QRect & /* rect */) { @@ -371,6 +299,9 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw); CBase::Delete(destroyw); } + + if (q->testAttribute(Qt::WA_AcceptTouchEvents)) + registerTouchWindow(); } @@ -872,6 +803,17 @@ void QWidgetPrivate::setMask_sys(const QRegion& /* region */) } +void QWidgetPrivate::registerTouchWindow() +{ +#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER + Q_Q(QWidget); + if (q->testAttribute(Qt::WA_WState_Created) && q->windowType() != Qt::Desktop) { + RWindow *rwindow = static_cast<RWindow *>(q->effectiveWinId()->DrawableWindow()); + rwindow->EnableAdvancedPointers(); + } +#endif +} + int QWidget::metric(PaintDeviceMetric m) const { Q_D(const QWidget); diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 211e9d4..c705e2a 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -747,25 +747,6 @@ void QWidgetPrivate::setWindowTitle_sys(const QString &caption) SetWindowText(q->internalWinId(), (wchar_t*)caption.utf16()); } -/* - Create an icon mask the way Windows wants it using CreateBitmap. -*/ - -HBITMAP qt_createIconMask(const QBitmap &bitmap) -{ - QImage bm = bitmap.toImage().convertToFormat(QImage::Format_Mono); - int w = bm.width(); - int h = bm.height(); - int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment - uchar *bits = new uchar[bpl*h]; - bm.invertPixels(); - for (int y=0; y<h; y++) - memcpy(bits+y*bpl, bm.scanLine(y), bpl); - HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits); - delete [] bits; - return hbm; -} - HICON qt_createIcon(QIcon icon, int xSize, int ySize, QPixmap **cache) { HICON result = 0; @@ -775,27 +756,12 @@ HICON qt_createIcon(QIcon icon, int xSize, int ySize, QPixmap **cache) if (pm.isNull()) return 0; - QBitmap mask = pm.mask(); - if (mask.isNull()) { - mask = QBitmap(pm.size()); - mask.fill(Qt::color1); - } - - HBITMAP im = qt_createIconMask(mask); - ICONINFO ii; - ii.fIcon = true; - ii.hbmMask = im; - ii.hbmColor = pm.toWinHBITMAP(QPixmap::Alpha); - ii.xHotspot = 0; - ii.yHotspot = 0; - result = CreateIconIndirect(&ii); + result = pm.toWinHICON(); if (cache) { delete *cache; *cache = new QPixmap(pm);; } - DeleteObject(ii.hbmColor); - DeleteObject(im); } return result; } diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 43a6bad..283dfb2 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -346,6 +346,10 @@ Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w) qt_x11_enforce_cursor(w, false); } +static Bool checkForConfigureAndExpose(Display *, XEvent *e, XPointer) +{ + return e->type == ConfigureNotify || e->type == Expose; +} Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w) { @@ -355,18 +359,42 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w) XEvent ev; QTime t; t.start(); + static const int maximumWaitTime = 2000; if (!w->testAttribute(Qt::WA_WState_Created)) return; - while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), ReparentNotify, &ev)) { - if (XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), MapNotify, &ev)) - break; - if (t.elapsed() > 500) - return; // give up, no event available + + if (!(w->windowFlags() & Qt::X11BypassWindowManagerHint)) { + // if the window is not override-redirect, then the window manager + // will reparent us to the frame decoration window. + while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), ReparentNotify, &ev)) { + if (t.elapsed() > maximumWaitTime) + return; + qApp->syncX(); // non-busy wait + } + } + + while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), MapNotify, &ev)) { + if (t.elapsed() > maximumWaitTime) + return; qApp->syncX(); // non-busy wait } + qApp->x11ProcessEvent(&ev); - if (XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), ConfigureNotify, &ev)) - qApp->x11ProcessEvent(&ev); + + // ok, seems like the window manager successfully reparented us, we'll wait + // for the first paint event to arrive, while handling ConfigureNotify in + // the arrival order + while(1) + { + if (XCheckIfEvent(X11->display, &ev, checkForConfigureAndExpose, 0)) { + qApp->x11ProcessEvent(&ev); + if (ev.type == Expose) + return; + } + if (t.elapsed() > maximumWaitTime) + return; + qApp->syncX(); // non-busy wait + } } void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0) diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 123c0f0..ed1b13d 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -1502,7 +1502,17 @@ QTransform QMatrix4x4::toTransform(qreal distanceToPlane) const Maps \a point by multiplying this matrix by \a point. - \sa mapRect() + \sa mapRect(), mapVector() +*/ + +/*! + \fn QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const + + Maps \a vector by multiplying the top 3x3 portion of this matrix + by \a vector. The translation and projection components of + this matrix are ignored. + + \sa map() */ #endif diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index 7631ae7..cfa3f2a 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -165,6 +165,7 @@ public: QPointF map(const QPointF& point) const; #ifndef QT_NO_VECTOR3D QVector3D map(const QVector3D& point) const; + QVector3D mapVector(const QVector3D& vector) const; #endif #ifndef QT_NO_VECTOR4D QVector4D map(const QVector4D& point) const; @@ -940,6 +941,27 @@ inline QVector3D QMatrix4x4::map(const QVector3D& point) const return *this * point; } +inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const +{ + if (flagBits == Identity || flagBits == Translation) { + return vector; + } else if (flagBits == Scale || flagBits == (Translation | Scale)) { + return QVector3D(vector.x() * m[0][0], + vector.y() * m[1][1], + vector.z() * m[2][2]); + } else { + return QVector3D(vector.x() * m[0][0] + + vector.y() * m[1][0] + + vector.z() * m[2][0], + vector.x() * m[0][1] + + vector.y() * m[1][1] + + vector.z() * m[2][1], + vector.x() * m[0][2] + + vector.y() * m[1][2] + + vector.z() * m[2][2]); + } +} + #endif #ifndef QT_NO_VECTOR4D diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index e48bced..d5ec054 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -239,7 +239,11 @@ qreal QQuaternion::lengthSquared() const */ QQuaternion QQuaternion::normalized() const { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp) + + double(wp) * double(wp); if (qFuzzyIsNull(len - 1.0f)) return *this; else if (!qFuzzyIsNull(len)) @@ -256,7 +260,11 @@ QQuaternion QQuaternion::normalized() const */ void QQuaternion::normalize() { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp) + + double(wp) * double(wp); if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len)) return; diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp index f12bec0..2555a6f 100644 --- a/src/gui/math3d/qvector2d.cpp +++ b/src/gui/math3d/qvector2d.cpp @@ -190,7 +190,9 @@ qreal QVector2D::lengthSquared() const */ QVector2D QVector2D::normalized() const { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp); if (qFuzzyIsNull(len - 1.0f)) return *this; else if (!qFuzzyIsNull(len)) @@ -207,7 +209,9 @@ QVector2D QVector2D::normalized() const */ void QVector2D::normalize() { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp); if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len)) return; diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp index 2893f5f..e17cbdf 100644 --- a/src/gui/math3d/qvector3d.cpp +++ b/src/gui/math3d/qvector3d.cpp @@ -206,7 +206,10 @@ QVector3D::QVector3D(const QVector4D& vector) */ QVector3D QVector3D::normalized() const { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp); if (qFuzzyIsNull(len - 1.0f)) return *this; else if (!qFuzzyIsNull(len)) @@ -223,7 +226,10 @@ QVector3D QVector3D::normalized() const */ void QVector3D::normalize() { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp); if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len)) return; diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp index 17acfff..1691a6d 100644 --- a/src/gui/math3d/qvector4d.cpp +++ b/src/gui/math3d/qvector4d.cpp @@ -255,7 +255,11 @@ qreal QVector4D::lengthSquared() const */ QVector4D QVector4D::normalized() const { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp) + + double(wp) * double(wp); if (qFuzzyIsNull(len - 1.0f)) return *this; else if (!qFuzzyIsNull(len)) @@ -272,7 +276,11 @@ QVector4D QVector4D::normalized() const */ void QVector4D::normalize() { - qreal len = lengthSquared(); + // Need some extra precision if the length is very small. + double len = double(xp) * double(xp) + + double(yp) * double(yp) + + double(zp) * double(zp) + + double(wp) * double(wp); if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len)) return; diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 5659aef..62e08f3 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -691,6 +691,8 @@ void QColor::setHsv(int h, int s, int v, int a) } /*! + \since 4.6 + Sets the contents pointed to by \a h, \a s, \a l, and \a a, to the hue, saturation, lightness, and alpha-channel (transparency) components of the color's HSL value. @@ -719,6 +721,8 @@ void QColor::getHslF(qreal *h, qreal *s, qreal *l, qreal *a) const } /*! + \since 4.6 + Sets the contents pointed to by \a h, \a s, \a l, and \a a, to the hue, saturation, lightness, and alpha-channel (transparency) components of the color's HSL value. @@ -747,6 +751,8 @@ void QColor::getHsl(int *h, int *s, int *l, int *a) const } /*! + \since 4.6 + Sets a HSL color lightness; \a h is the hue, \a s is the saturation, \a l is the lightness and \a a is the alpha component of the HSL color. @@ -773,6 +779,8 @@ void QColor::setHslF(qreal h, qreal s, qreal l, qreal a) } /*! + \since 4.6 + Sets a HSL color value; \a h is the hue, \a s is the saturation, \a l is the lightness and \a a is the alpha component of the HSL color. @@ -1332,6 +1340,8 @@ qreal QColor::valueF() const } /*! + \since 4.6 + Returns the hue color component of this color. \sa getHslF(), getHsl() @@ -1344,6 +1354,8 @@ int QColor::hslHue() const } /*! + \since 4.6 + Returns the saturation color component of this color. \sa saturationF(), getHsv(), {QColor#The HSV Color Model}{The HSV Color @@ -1357,6 +1369,8 @@ int QColor::hslSaturation() const } /*! + \since 4.6 + Returns the lightness color component of this color. \sa lightnessF(), getHsl() @@ -1369,6 +1383,8 @@ int QColor::lightness() const } /*! + \since 4.6 + Returns the hue color component of this color. \sa hue(), getHslF() @@ -1381,6 +1397,8 @@ qreal QColor::hslHueF() const } /*! + \since 4.6 + Returns the saturation color component of this color. \sa saturationF() getHslF() @@ -1393,6 +1411,8 @@ qreal QColor::hslSaturationF() const } /*! + \since 4.6 + Returns the lightness color component of this color. \sa value() getHslF() @@ -1979,6 +1999,8 @@ QColor QColor::fromHsvF(qreal h, qreal s, qreal v, qreal a) } /*! + \since 4.6 + Static convenience function that returns a QColor constructed from the HSV color values, \a h (hue), \a s (saturation), \a l (lightness), and \a a (alpha-channel, i.e. transparency). @@ -2010,6 +2032,7 @@ QColor QColor::fromHsl(int h, int s, int l, int a) /*! \overload + \since 4.6 Static convenience function that returns a QColor constructed from the HSV color values, \a h (hue), \a s (saturation), \a l (lightness), and \a a diff --git a/src/gui/painting/qdrawhelper_mmx.cpp b/src/gui/painting/qdrawhelper_mmx.cpp index 0dcc3dd..d81e2a9 100644 --- a/src/gui/painting/qdrawhelper_mmx.cpp +++ b/src/gui/painting/qdrawhelper_mmx.cpp @@ -128,7 +128,7 @@ void qt_blend_rgb32_on_rgb32_mmx(uchar *destPixels, int dbpl, } } +QT_END_NAMESPACE #endif // QT_HAVE_MMX -QT_END_NAMESPACE diff --git a/src/gui/painting/qdrawhelper_mmx3dnow.cpp b/src/gui/painting/qdrawhelper_mmx3dnow.cpp index 0db89f0..2d40ae3 100644 --- a/src/gui/painting/qdrawhelper_mmx3dnow.cpp +++ b/src/gui/painting/qdrawhelper_mmx3dnow.cpp @@ -101,6 +101,7 @@ void qt_blend_color_argb_mmx3dnow(int count, const QSpan *spans, void *userData) (CompositionFunctionSolid*)qt_functionForModeSolid_MMX3DNOW); } +QT_END_NAMESPACE + #endif // QT_HAVE_3DNOW -QT_END_NAMESPACE diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp index 0a82a9f..716300e 100644 --- a/src/gui/painting/qdrawutil.cpp +++ b/src/gui/painting/qdrawutil.cpp @@ -1070,6 +1070,9 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs, \since 4.6 \overload + \brief The qDrawBorderPixmap function is for drawing a pixmap into + the margins of a rectangle. + Draws the given \a pixmap into the given \a target rectangle, using the given \a painter. The pixmap will be split into nine segments and drawn according to the \a margins structure. diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp index 0f0d405..88b2b7a 100644 --- a/src/gui/painting/qmatrix.cpp +++ b/src/gui/painting/qmatrix.cpp @@ -1209,6 +1209,9 @@ QDebug operator<<(QDebug dbg, const QMatrix &m) \relates QMatrix \since 4.6 + \brief The qFuzzyCompare function is for comparing two matrices + using a fuzziness factor. + Returns true if \a m1 and \a m2 are equal, allowing for a small fuzziness factor for floating-point comparisons; false otherwise. */ diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h index 983ebd5..8887f0e 100644 --- a/src/gui/painting/qmatrix.h +++ b/src/gui/painting/qmatrix.h @@ -129,13 +129,13 @@ private: , _m22(1.) , _dx(0.) , _dy(0.) {} - inline QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy, bool) - : _m11(m11) - , _m12(m12) - , _m21(m21) - , _m22(m22) - , _dx(dx) - , _dy(dy) {} + inline QMatrix(qreal am11, qreal am12, qreal am21, qreal am22, qreal adx, qreal ady, bool) + : _m11(am11) + , _m12(am12) + , _m21(am21) + , _m22(am22) + , _dx(adx) + , _dy(ady) {} friend class QTransform; qreal _m11, _m12; qreal _m21, _m22; diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp index 1038f74..6b9d77c 100644 --- a/src/gui/painting/qpaintbuffer.cpp +++ b/src/gui/painting/qpaintbuffer.cpp @@ -44,11 +44,14 @@ //#include <private/qtextengine_p.h> #include <private/qfontengine_p.h> #include <private/qemulationpaintengine_p.h> +#include <private/qimage_p.h> #include <QDebug> //#define QPAINTBUFFER_DEBUG_DRAW +QT_BEGIN_NAMESPACE + extern int qt_defaultDpiX(); extern int qt_defaultDpiY(); extern void qt_format_text(const QFont &font, @@ -890,6 +893,12 @@ void QPaintBufferEngine::drawPixmap(const QPointF &pos, const QPixmap &pm) buffer->updateBoundingRect(QRectF(pos, pm.size())); } +static inline QImage qpaintbuffer_storable_image(const QImage &src) +{ + QImageData *d = const_cast<QImage &>(src).data_ptr(); + return d->own_data ? src : src.copy(); +} + void QPaintBufferEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags /*flags */) { @@ -897,7 +906,8 @@ void QPaintBufferEngine::drawImage(const QRectF &r, const QImage &image, const Q qDebug() << "QPaintBufferEngine: drawImage: src/dest rects " << r << sr; #endif QPaintBufferCommand *cmd = - buffer->addCommand(QPaintBufferPrivate::Cmd_DrawPixmapRect, QVariant(image)); + buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImageRect, + QVariant(qpaintbuffer_storable_image(image))); cmd->extra = buffer->addData((qreal *) &r, 4); buffer->addData((qreal *) &sr, 4); // ### flags... @@ -911,7 +921,8 @@ void QPaintBufferEngine::drawImage(const QPointF &pos, const QImage &image) qDebug() << "QPaintBufferEngine: drawImage: pos:" << pos; #endif QPaintBufferCommand *cmd = - buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImagePos, QVariant(image)); + buffer->addCommand(QPaintBufferPrivate::Cmd_DrawImagePos, + QVariant(qpaintbuffer_storable_image(image))); cmd->extra = buffer->addData((qreal *) &pos, 2); if (buffer->calculateBoundingRect) buffer->updateBoundingRect(QRectF(pos, image.size())); @@ -1740,7 +1751,9 @@ struct QPaintBufferCacheEntry QVariant::Type type; quint64 cacheKey; }; +QT_END_NAMESPACE Q_DECLARE_METATYPE(QPaintBufferCacheEntry) +QT_BEGIN_NAMESPACE QDataStream &operator<<(QDataStream &stream, const QPaintBufferCacheEntry &entry) { @@ -1832,3 +1845,4 @@ QDataStream &operator>>(QDataStream &stream, QPaintBuffer &buffer) return stream; } +QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintbuffer_p.h b/src/gui/painting/qpaintbuffer_p.h index a80fa8d..6a7ac73 100644 --- a/src/gui/painting/qpaintbuffer_p.h +++ b/src/gui/painting/qpaintbuffer_p.h @@ -59,6 +59,8 @@ #include <private/qtextengine_p.h> #include <QDebug> +QT_BEGIN_NAMESPACE + class QPaintBufferPrivate; class QPaintBufferPlayback; @@ -440,4 +442,6 @@ private: FreeFunc free; }; +QT_END_NAMESPACE + #endif // QPAINTBUFFER_P_H diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index f41d7b4..6037bd5 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3056,7 +3056,43 @@ void QRasterPaintEngine::drawCachedGlyphs(const QPointF &p, const QTextItemInt & return; } +#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) +void QRasterPaintEngine::drawGlyphsS60(const QPointF &p, const QTextItemInt &ti) +{ + Q_D(QRasterPaintEngine); + QRasterPaintEngineState *s = state(); + + QFontEngine *fontEngine = ti.fontEngine; + if (fontEngine->type() != QFontEngine::S60FontEngine) { + QPaintEngineEx::drawTextItem(p, ti); + return; + } + + QFontEngineS60 *fe = static_cast<QFontEngineS60 *>(fontEngine); + + QVarLengthArray<QFixedPoint> positions; + QVarLengthArray<glyph_t> glyphs; + QTransform matrix = s->matrix; + matrix.translate(p.x(), p.y()); + ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); + + const QFixed aliasDelta = QFixed::fromReal(aliasedCoordinateDelta); + + for (int i=0; i<glyphs.size(); ++i) { + TOpenFontCharMetrics tmetrics; + const TUint8 *glyphBitmapBytes; + TSize glyphBitmapSize; + fe->getCharacterData(glyphs[i], tmetrics, glyphBitmapBytes, glyphBitmapSize); + const glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]); + const int x = qFloor(positions[i].x + metrics.x + aliasDelta); + const int y = qFloor(positions[i].y + metrics.y + aliasDelta); + alphaPenBlt(glyphBitmapBytes, glyphBitmapSize.iWidth, 8, x, y, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight); + } + + return; +} +#endif // Q_OS_SYMBIAN && QT_NO_FREETYPE /*! * Returns true if the rectangle is completly within the current clip @@ -3191,7 +3227,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte ensurePen(); ensureState(); -#if defined (Q_WS_WIN) || defined(Q_WS_MAC) || (defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)) +#if defined (Q_WS_WIN) || defined(Q_WS_MAC) bool drawCached = true; @@ -3224,7 +3260,12 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte return; } -#else // Q_WS_WIN || Q_WS_MAC || Q_OS_SYMBIAN && QT_NO_FREETYPE +#elif defined (Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) // Q_WS_WIN || Q_WS_MAC + if (s->matrix.type() <= QTransform::TxTranslate) { + drawGlyphsS60(p, ti); + return; + } +#else // Q_WS_WIN || Q_WS_MAC QFontEngine *fontEngine = ti.fontEngine; @@ -3622,6 +3663,7 @@ void QRasterPaintEngine::drawEllipse(const QRectF &rect) ensurePen(); if (((qpen_style(s->lastPen) == Qt::SolidLine && s->flags.fast_pen) || (qpen_style(s->lastPen) == Qt::NoPen && !s->flags.antialiased)) + && qMax(rect.width(), rect.height()) < QT_RASTER_COORD_LIMIT #ifdef FLOATING_POINT_BUGGY_OR_NO_FPU && qMax(rect.width(), rect.height()) < 128 // integer math breakdown #endif diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index fcf92cd..1787d16 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -259,6 +259,10 @@ private: void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti); +#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) + void drawGlyphsS60(const QPointF &p, const QTextItemInt &ti); +#endif // Q_OS_SYMBIAN && QT_NO_FREETYPE + inline void ensureBrush(const QBrush &brush) { if (!qbrush_fast_equals(state()->lastBrush, brush) || state()->fillFlags) updateBrush(brush); diff --git a/src/gui/painting/qpaintengine_s60.cpp b/src/gui/painting/qpaintengine_s60.cpp index 2aa179a..e17dba1 100644 --- a/src/gui/painting/qpaintengine_s60.cpp +++ b/src/gui/painting/qpaintengine_s60.cpp @@ -1,14 +1,43 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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 qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ ** ****************************************************************************/ - #include <private/qpaintengine_s60_p.h> #include <private/qpixmap_s60_p.h> #include <private/qt_s60_p.h> diff --git a/src/gui/painting/qpaintengine_s60_p.h b/src/gui/painting/qpaintengine_s60_p.h index b38ef93..33067b5 100644 --- a/src/gui/painting/qpaintengine_s60_p.h +++ b/src/gui/painting/qpaintengine_s60_p.h @@ -1,11 +1,41 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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 qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index e5da392..60e4df6 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -416,8 +416,8 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin) flags |= QVectorPath::CurvedShapeHint; - qreal txscale = 1; - if (!(pen.isCosmetic() || (qt_scaleForTransform(state()->matrix, &txscale) && txscale != 1))) { + // ### Perspective Xforms are currently not supported... + if (!pen.isCosmetic()) { // We include cosmetic pens in this case to avoid having to // change the current transform. Normal transformed, // non-cosmetic pens will be transformed as part of fill @@ -474,8 +474,6 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) flags); fill(strokePath, pen.brush()); } else { - const qreal strokeWidth = d->stroker.strokeWidth(); - d->stroker.setStrokeWidth(strokeWidth * txscale); // For cosmetic pens we need a bit of trickery... We to process xform the input points if (state()->matrix.type() >= QTransform::TxProject) { QPainterPath painterPath = state()->matrix.map(path.convertToPainterPath()); @@ -535,7 +533,6 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) d->activeStroker->end(); } - d->stroker.setStrokeWidth(strokeWidth); QVectorPath strokePath(d->strokeHandler->pts.data(), d->strokeHandler->types.size(), d->strokeHandler->types.data(), diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index ed1b5d1..f271af9 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1895,6 +1895,8 @@ QPaintEngine *QPainter::paintEngine() const } /*! + \since 4.6 + Flushes the painting pipeline and prepares for the user issuing commands directly to the underlying graphics context. Must be followed by a call to endNativePainting(). @@ -1919,6 +1921,8 @@ void QPainter::beginNativePainting() } /*! + \since 4.6 + Restores the painter after manually issuing native painting commands. Lets the painter restore any native state that it relies on before calling any other painter commands. diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp index 1471fe3..e73282f 100644 --- a/src/gui/painting/qprintengine_pdf.cpp +++ b/src/gui/painting/qprintengine_pdf.cpp @@ -935,7 +935,7 @@ void QPdfEnginePrivate::writeInfo() "/Title (%s)\n" // "/Author (%s)\n" "/Creator (%s)\n" - "/Producer (Qt " QT_VERSION_STR " (C) 1992-$THISYEAR$ Nokia Corporation and/or its subsidiary(-ies))\n", + "/Producer (Qt " QT_VERSION_STR " (C) 2009 Nokia Corporation and/or its subsidiary(-ies))\n", title.toUtf8().constData(), // author.toUtf8().constData(), creator.toUtf8().constData()); diff --git a/src/gui/painting/qprintengine_win.cpp b/src/gui/painting/qprintengine_win.cpp index e59155c..a3f94d9 100644 --- a/src/gui/painting/qprintengine_win.cpp +++ b/src/gui/painting/qprintengine_win.cpp @@ -374,6 +374,11 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem convertToText = false; break; } + + if (ti.logClusters[i] != i) { + convertToText = false; + break; + } } COLORREF cf = RGB(qRed(brushColor), qGreen(brushColor), qBlue(brushColor)); diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp index eb9b11b..5ff0b96 100644 --- a/src/gui/painting/qprinter.cpp +++ b/src/gui/painting/qprinter.cpp @@ -1275,7 +1275,7 @@ QPrinter::ColorMode QPrinter::colorMode() const buffering up the copies and in those cases the application must make an explicit call to the print code for each copy. - \sa setNumCopies() + \sa setNumCopies(), actualNumCopies() */ int QPrinter::numCopies() const @@ -1286,13 +1286,15 @@ int QPrinter::numCopies() const /*! + \since 4.6 + Returns the number of copies that will be printed. The default value is 1. This function always returns the actual value specified in the print dialog or using setNumCopies(). - \sa setNumCopies(), numCopies(); + \sa setNumCopies(), numCopies() */ int QPrinter::actualNumCopies() const { diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp index ffd6f17..5e4433c 100644 --- a/src/gui/painting/qwindowsurface_x11.cpp +++ b/src/gui/painting/qwindowsurface_x11.cpp @@ -139,7 +139,8 @@ void QX11WindowSurface::setGeometry(const QRect &rect) QWindowSurface::setGeometry(rect); const QSize size = rect.size(); - if (d_ptr->device.size() == size) + + if (d_ptr->device.size() == size || size.width() <= 0 || size.height() <= 0) return; #ifndef QT_NO_XRENDER if (d_ptr->translucentBackground) { @@ -183,10 +184,14 @@ void QX11WindowSurface::setGeometry(const QRect &rect) } } - if (gc) + if (gc) { XFreeGC(X11->display, gc); - gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0); - XSetGraphicsExposures(X11->display, gc, False); + gc = 0; + } + if (!d_ptr->device.isNull()) { + gc = XCreateGC(X11->display, d_ptr->device.handle(), 0, 0); + XSetGraphicsExposures(X11->display, gc, False); + } } bool QX11WindowSurface::scroll(const QRegion &area, int dx, int dy) diff --git a/src/gui/s60framework/qs60mainapplication.cpp b/src/gui/s60framework/qs60mainapplication.cpp index f12ed1f..54fb3b1 100644 --- a/src/gui/s60framework/qs60mainapplication.cpp +++ b/src/gui/s60framework/qs60mainapplication.cpp @@ -41,53 +41,86 @@ // INCLUDE FILES #include <exception> -#include "qs60maindocument_p.h" +#include "qs60maindocument.h" #include "qs60mainapplication_p.h" +#include "qs60mainapplication.h" #include <bautils.h> #include <coemain.h> QT_BEGIN_NAMESPACE /** - * factory function to create the QtS60Main application class + * factory function to create the QS60Main application class */ -CApaApplication* NewApplication() +CApaApplication *newS60Application() { return new QS60MainApplication; } -// ============================ MEMBER FUNCTIONS =============================== +_LIT(KQtWrapperResourceFile, "\\resource\\apps\\s60main.rsc"); +/*! + * \class QS60MainApplication + * \obsolete + * \since 4.6 + * \brief Helper class for S60 migration + * + * The QS60MainApplication provides a helper class for use in migrating from existing S60 based + * applications to Qt based applications. It is used in the exact same way as the + * \c CAknApplication class from Symbian, but internally provides extensions used by Qt. + * + * When modifying old S60 applications that rely on implementing functions in \c CAknApplication, + * the class should be modified to inherit from this class instead of \c CAknApplication. Then the + * application can choose to override only certain functions. To make Qt use the custom application + * objects, pass a factory function to + * QApplication::QApplication(QApplication::QS60MainApplicationFactory, int &, char **). + * + * For more information on \c CAknApplication, please see the S60 documentation. + * + * Unlike other Qt classes, QS60MainApplication behaves like an S60 class, and can throw Symbian + * leaves. + * + * \sa QS60MainDocument, QS60MainAppUi, QApplication::QApplication(QApplication::QS60MainApplicationFactory, int &, char **) + */ -_LIT(KQtWrapperResourceFile, "\\resource\\apps\\s60main.rsc"); +/*! + * \brief Contructs an instance of QS60MainApplication. + */ +QS60MainApplication::QS60MainApplication() +{ +} -// ----------------------------------------------------------------------------- -// QS60MainApplication::CreateDocumentL() -// Creates CApaDocument object -// ----------------------------------------------------------------------------- -// -CApaDocument* QS60MainApplication::CreateDocumentL() +/*! + * \brief Destroys the QS60MainApplication. + */ +QS60MainApplication::~QS60MainApplication() +{ +} + +/*! + * \brief Creates an instance of QS60MainDocument. + * + * \sa QS60MainDocument + */ +CApaDocument *QS60MainApplication::CreateDocumentL() { // Create an QtS60Main document, and return a pointer to it - return (static_cast<CApaDocument*>(QS60MainDocument::NewL(*this))); + return new (ELeave) QS60MainDocument(*this); } -// ----------------------------------------------------------------------------- -// QS60MainApplication::AppDllUid() -// Returns application UID -// ----------------------------------------------------------------------------- -// + +/*! + * \brief Returns the UID of the application. + */ TUid QS60MainApplication::AppDllUid() const { // Return the UID for the QtS60Main application - return ProcessUid(); + return RProcess().SecureId().operator TUid(); } -// ----------------------------------------------------------------------------- -// QS60MainApplication::ResourceFileName() -// Returns application resource filename -// ----------------------------------------------------------------------------- -// +/*! + * \brief Returns the resource file name. + */ TFileName QS60MainApplication::ResourceFileName() const { TFindFile finder(iCoeEnv->FsSession()); @@ -98,5 +131,3 @@ TFileName QS60MainApplication::ResourceFileName() const } QT_END_NAMESPACE - -// End of File diff --git a/src/gui/s60framework/qs60mainapplication.h b/src/gui/s60framework/qs60mainapplication.h new file mode 100644 index 0000000..457764c --- /dev/null +++ b/src/gui/s60framework/qs60mainapplication.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Symbian application wrapper of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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 qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QS60MAINAPPLICATION_H +#define QS60MAINAPPLICATION_H + +#include <qglobal.h> + +#ifdef Q_WS_S60 + +#include <aknapp.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QS60MainApplication : public CAknApplication +{ +public: + QS60MainApplication(); + // The virtuals are for qdoc. + virtual ~QS60MainApplication(); + + virtual TUid AppDllUid() const; + + virtual TFileName ResourceFileName() const; + +protected: + + virtual CApaDocument *CreateDocumentL(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // Q_WS_S60 + +#endif // QS60MAINAPPLICATION_H diff --git a/src/gui/s60framework/qs60mainapplication_p.h b/src/gui/s60framework/qs60mainapplication_p.h index 40562da..863d872 100644 --- a/src/gui/s60framework/qs60mainapplication_p.h +++ b/src/gui/s60framework/qs60mainapplication_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the Symbian application wrapper of the Qt Toolkit. +** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -46,67 +46,21 @@ // W A R N I N G // ------------- // -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. // // We mean it. // -// INCLUDES -#include <aknapp.h> - #include <qglobal.h> -// CLASS DECLARATION +#include <apparc.h> QT_BEGIN_NAMESPACE -CApaApplication* NewApplication(); - -static TUid ProcessUid() -{ - RProcess me; - TSecureId securId = me.SecureId(); - me.Close(); - return securId.operator TUid(); -} - -/** -* QS60MainApplication application class. -* Provides factory to create concrete document object. -* An instance of QS60MainApplication is the application part of the -* AVKON application framework for the QtS60Main example application. -*/ -class QS60MainApplication : public CAknApplication -{ -public: // Functions from base classes - - /** - * From CApaApplication, AppDllUid. - * @return Application's UID (KUidQtS60MainApp). - */ - TUid AppDllUid() const; - - /** - * From CApaApplication, ResourceFileName - * @return Application's resource filename (KUidQtS60MainApp). - */ - TFileName ResourceFileName() const; - -protected: // Functions from base classes - - /** - * From CApaApplication, CreateDocumentL. - * Creates QS60MainDocument document object. The returned - * pointer in not owned by the QS60MainApplication object. - * @return A pointer to the created document object. - */ - CApaDocument* CreateDocumentL(); -}; +CApaApplication *newS60Application(); QT_END_NAMESPACE #endif // QS60MAINAPPLICATION_P_H - -// End of File diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index 4f5227c..9e2333b 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -48,21 +48,42 @@ #include <s60main.rsg> #include <avkon.rsg> -#include "qs60mainappui_p.h" +#include "qs60mainappui.h" #include <QtGui/qapplication.h> #include <QtGui/qmenu.h> #include <QtGui/private/qt_s60_p.h> QT_BEGIN_NAMESPACE -// ============================ MEMBER FUNCTIONS =============================== - - -// ----------------------------------------------------------------------------- -// QS60MainAppUi::ConstructL() -// Symbian 2nd phase constructor can leave. -// ----------------------------------------------------------------------------- -// +/*! + * \class QS60MainAppUi + * \obsolete + * \since 4.6 + * \brief Helper class for S60 migration + * + * The QS60MainAppUi provides a helper class for use in migrating from existing S60 based + * applications to Qt based applications. It is used in the exact same way as the + * \c CAknAppUi class from Symbian, but internally provides extensions used by Qt. + * + * When modifying old S60 applications that rely on implementing functions in \c CAknAppUi, + * the class should be modified to inherit from this class instead of \c CAknAppUi. Then the + * application can choose to override only certain functions. + * + * For more information on \c CAknAppUi, please see the S60 documentation. + * + * Unlike other Qt classes, QS60MainAppUi behaves like an S60 class, and can throw Symbian + * leaves. + * + * \sa QS60MainDocument, QS60MainApplication + */ + +/*! + * \brief Second phase Symbian constructor. + * + * Constructs all the elements of the class that can cause a leave to happen. + * + * If you override this function, you should call the base class implementation as well. + */ void QS60MainAppUi::ConstructL() { // Cone's heap and handle checks on app destruction are not suitable for Qt apps, as many @@ -80,104 +101,142 @@ void QS60MainAppUi::ConstructL() nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); } -// ----------------------------------------------------------------------------- -// QS60MainAppUi::QS60MainAppUi() -// C++ default constructor can NOT contain any code, that might leave. -// ----------------------------------------------------------------------------- -// +/*! + * \brief Contructs an instance of QS60MainAppUi. + */ QS60MainAppUi::QS60MainAppUi() { // No implementation required } -// ----------------------------------------------------------------------------- -// QS60MainAppUi::~QS60MainAppUi() -// Destructor. -// ----------------------------------------------------------------------------- -// +/*! + * \brief Destroys the QS60MainAppUi. + */ QS60MainAppUi::~QS60MainAppUi() { } -// ----------------------------------------------------------------------------- -// QS60MainAppUi::HandleCommandL() -// Takes care of command handling. -// ----------------------------------------------------------------------------- -// -void QS60MainAppUi::HandleCommandL(TInt aCommand) +/*! + * \brief Handles commands produced by the S60 framework. + * + * \a command holds the ID of the command to handle, and is S60 specific. + * + * If you override this function, you should call the base class implementation if you do not + * handle the command. + */ +void QS60MainAppUi::HandleCommandL(TInt command) { if (qApp) - qApp->symbianHandleCommand(aCommand); + QT_TRYCATCH_LEAVING(qApp->symbianHandleCommand(command)); } -// ----------------------------------------------------------------------------- -// QS60MainAppUi::HandleResourceChangeL() -// Takes care of event handling. -// ----------------------------------------------------------------------------- -// -void QS60MainAppUi::HandleResourceChangeL(TInt aType) +/*! + * \brief Handles a resource change in the S60 framework. + * + * Resource changes include layout switches. \a type holds the type of resource change that + * occurred. + * + * If you override this function, you should call the base class implementation if you do not + * handle the resource change. + */ +void QS60MainAppUi::HandleResourceChangeL(TInt type) { - CAknAppUi::HandleResourceChangeL(aType); + CAknAppUi::HandleResourceChangeL(type); if (qApp) - qApp->symbianResourceChange(aType); + QT_TRYCATCH_LEAVING(qApp->symbianResourceChange(type)); } -void QS60MainAppUi::HandleWsEventL(const TWsEvent& aEvent, CCoeControl *control) +/*! + * \brief Handles raw window server events. + * + * The event type and information is passed in \a event, while the receiving control is passed in + * \a destination. + * + * If you override this function, you should call the base class implementation if you do not + * handle the event. + */ +void QS60MainAppUi::HandleWsEventL(const TWsEvent& event, CCoeControl *destination) { int result = 0; if (qApp) QT_TRYCATCH_LEAVING( - result = qApp->s60ProcessEvent(const_cast<TWsEvent*>(&aEvent)) + result = qApp->s60ProcessEvent(const_cast<TWsEvent*>(&event)) ); if (result <= 0) - CAknAppUi::HandleWsEventL(aEvent, control); + CAknAppUi::HandleWsEventL(event, destination); } -// ----------------------------------------------------------------------------- -// Called by the framework when the application status pane -// size is changed. Passes the new client rectangle to the -// AppView -// ----------------------------------------------------------------------------- -// +/*! + * \brief Handles changes to the status pane size. + * + * Called by the framework when the application status pane size is changed. + * + * If you override this function, you should call the base class implementation if you do not + * handle the size change. + */ void QS60MainAppUi::HandleStatusPaneSizeChange() { - HandleResourceChangeL(KInternalStatusPaneChange); + TRAP_IGNORE(HandleResourceChangeL(KInternalStatusPaneChange)); HandleStackedControlsResourceChange(KInternalStatusPaneChange); } -void QS60MainAppUi::DynInitMenuBarL(TInt, CEikMenuBar *) +/*! + * \brief Dynamically initializes a menu bar. + * + * The resource associated with the menu is given in \a resourceId, and the actual menu bar is + * passed in \a menuBar. + * + * If you override this function, you should call the base class implementation as well. + */ +void QS60MainAppUi::DynInitMenuBarL(TInt /* resourceId */, CEikMenuBar * /* menuBar */) { } -void QS60MainAppUi::DynInitMenuPaneL(TInt aResourceId, CEikMenuPane *aMenuPane) +/*! + * \brief Dynamically initializes a menu pane. + * + * The resource associated with the menu is given in \a resourceId, and the actual menu pane is + * passed in \a menuPane. + * + * If you override this function, you should call the base class implementation as well. + */ +void QS60MainAppUi::DynInitMenuPaneL(TInt resourceId, CEikMenuPane *menuPane) { - if (aResourceId == R_QT_WRAPPERAPP_MENU) { - if (aMenuPane->NumberOfItemsInPane() <= 1) - qt_symbian_show_toplevel(aMenuPane); - - } else if (aResourceId != R_AVKON_MENUPANE_FEP_DEFAULT && aResourceId != R_AVKON_MENUPANE_EDITTEXT_DEFAULT && aResourceId != R_AVKON_MENUPANE_LANGUAGE_DEFAULT) { - qt_symbian_show_submenu(aMenuPane, aResourceId); + if (resourceId == R_QT_WRAPPERAPP_MENU) { + if (menuPane->NumberOfItemsInPane() <= 1) + QT_TRYCATCH_LEAVING(qt_symbian_show_toplevel(menuPane)); + + } else if (resourceId != R_AVKON_MENUPANE_FEP_DEFAULT + && resourceId != R_AVKON_MENUPANE_EDITTEXT_DEFAULT + && resourceId != R_AVKON_MENUPANE_LANGUAGE_DEFAULT) { + QT_TRYCATCH_LEAVING(qt_symbian_show_submenu(menuPane, resourceId)); } } -void QS60MainAppUi::RestoreMenuL(CCoeControl* aMenuWindow, TInt aMenuId, TMenuType aMenuType) +/*! + * \brief Restores a menu window. + * + * The menu window to restore is given in \a menuWindow. The resource ID and type of menu is given + * in \a resourceId and \a menuType, respectively. + * + * If you override this function, you should call the base class implementation as well. + */ +void QS60MainAppUi::RestoreMenuL(CCoeControl* menuWindow, TInt resourceId, TMenuType menuType) { - if ((aMenuId == R_QT_WRAPPERAPP_MENUBAR) || (aMenuId == R_AVKON_MENUPANE_FEP_DEFAULT)) { + if ((resourceId == R_QT_WRAPPERAPP_MENUBAR) || (resourceId == R_AVKON_MENUPANE_FEP_DEFAULT)) { TResourceReader reader; - iCoeEnv->CreateResourceReaderLC(reader, aMenuId); - aMenuWindow->ConstructFromResourceL(reader); + iCoeEnv->CreateResourceReaderLC(reader, resourceId); + menuWindow->ConstructFromResourceL(reader); CleanupStack::PopAndDestroy(); } - if (aMenuType == EMenuPane) - DynInitMenuPaneL(aMenuId, (CEikMenuPane*)aMenuWindow); + if (menuType == EMenuPane) + DynInitMenuPaneL(resourceId, (CEikMenuPane*)menuWindow); else - DynInitMenuBarL(aMenuId, (CEikMenuBar*)aMenuWindow); + DynInitMenuBarL(resourceId, (CEikMenuBar*)menuWindow); } QT_END_NAMESPACE - -// End of File diff --git a/src/gui/s60framework/qs60mainappui.h b/src/gui/s60framework/qs60mainappui.h new file mode 100644 index 0000000..c2c6ef2 --- /dev/null +++ b/src/gui/s60framework/qs60mainappui.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Symbian application wrapper of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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 qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QS60MAINAPPUI_H +#define QS60MAINAPPUI_H + +#include <qglobal.h> + +#ifdef Q_WS_S60 + +#include <aknappui.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QS60MainAppUi : public CAknAppUi +{ +public: + QS60MainAppUi(); + // The virtuals are for qdoc. + virtual ~QS60MainAppUi(); + + virtual void ConstructL(); + + virtual void RestoreMenuL(CCoeControl* menuWindow,TInt resourceId,TMenuType menuType); + virtual void DynInitMenuBarL(TInt resourceId, CEikMenuBar *menuBar); + virtual void DynInitMenuPaneL(TInt resourceId, CEikMenuPane *menuPane); + + virtual void HandleCommandL( TInt command ); + + virtual void HandleResourceChangeL(TInt type); + + virtual void HandleStatusPaneSizeChange(); + +protected: + virtual void HandleWsEventL(const TWsEvent& event, CCoeControl* destination); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // Q_WS_S60 + +#endif // QS60MAINAPPUI_H diff --git a/src/gui/s60framework/qs60mainappui_p.h b/src/gui/s60framework/qs60mainappui_p.h deleted file mode 100644 index 4b10833..0000000 --- a/src/gui/s60framework/qs60mainappui_p.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the Symbian application wrapper of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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 qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QS60MAINAPPUI_P_H -#define QS60MAINAPPUI_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -// INCLUDES -#include <aknappui.h> - -#include <qglobal.h> - -QT_BEGIN_NAMESPACE - -// FORWARD DECLARATIONS - -// CLASS DECLARATION -/** -* QS60MainAppUi application UI class. -* Interacts with the user through the UI and request message processing -* from the handler class -*/ -class QS60MainAppUi : public CAknAppUi -{ -public: // Constructors and destructor - - /** - * ConstructL. - * 2nd phase constructor. - */ - void ConstructL(); - - /** - * QS60MainAppUi. - * C++ default constructor. This needs to be public due to - * the way the framework constructs the AppUi - */ - QS60MainAppUi(); - - /** - * ~QS60MainAppUi. - * Virtual Destructor. - */ - virtual ~QS60MainAppUi(); - -protected: - void RestoreMenuL(CCoeControl* aMenuWindow,TInt aMenuId,TMenuType aMenuType); - void DynInitMenuBarL(TInt aResourceId, CEikMenuBar *aMenuBar); - void DynInitMenuPaneL(TInt aResourceId, CEikMenuPane *aMenuPane); - -private: // Functions from base classes - - /** - * From CEikAppUi, HandleCommandL. - * Takes care of command handling. - * @param aCommand Command to be handled. - */ - void HandleCommandL( TInt aCommand ); - - /** - * From CAknAppUi, HandleResourceChangeL - * Handles resource change events such as layout switches in global level. - * @param aType event type. - */ - void HandleResourceChangeL(TInt aType); - - /** - * HandleStatusPaneSizeChange. - * Called by the framework when the application status pane - * size is changed. - */ - void HandleStatusPaneSizeChange(); - -protected: - void HandleWsEventL(const TWsEvent& aEvent, CCoeControl* aDestination); -}; - -QT_END_NAMESPACE - -#endif // QS60MAINAPPUI_P_H - -// End of File diff --git a/src/gui/s60framework/qs60maindocument.cpp b/src/gui/s60framework/qs60maindocument.cpp index ba66e98..52595db 100644 --- a/src/gui/s60framework/qs60maindocument.cpp +++ b/src/gui/s60framework/qs60maindocument.cpp @@ -39,77 +39,60 @@ ** ****************************************************************************/ -// INCLUDE FILES +#include "qs60mainappui.h" +#include "qs60maindocument.h" + #include <exception> -#include "qs60mainappui_p.h" -#include "qs60maindocument_p.h" QT_BEGIN_NAMESPACE -// ============================ MEMBER FUNCTIONS =============================== - -// ----------------------------------------------------------------------------- -// QS60MainDocument::NewL() -// Two-phased constructor. -// ----------------------------------------------------------------------------- -// -QS60MainDocument* QS60MainDocument::NewL(CEikApplication& aApp) -{ - QS60MainDocument* self = NewLC(aApp); - CleanupStack::Pop(self); - return self; -} - -// ----------------------------------------------------------------------------- -// QS60MainDocument::NewLC() -// Two-phased constructor. -// ----------------------------------------------------------------------------- -// -QS60MainDocument* QS60MainDocument::NewLC(CEikApplication& aApp) -{ - QS60MainDocument* self = new(ELeave) QS60MainDocument(aApp); - CleanupStack::PushL(self); - self->ConstructL(); - return self; -} - -// ----------------------------------------------------------------------------- -// QS60MainDocument::ConstructL() -// Symbian 2nd phase constructor can leave. -// ----------------------------------------------------------------------------- -// -void QS60MainDocument::ConstructL() -{ - // No implementation required -} +/*! + * \class QS60MainDocument + * \obsolete + * \since 4.6 + * \brief Helper class for S60 migration + * + * The QS60MainDocument provides a helper class for use in migrating from existing S60 based + * applications to Qt based applications. It is used in the exact same way as the + * \c CAknDocument class from Symbian, but internally provides extensions used by Qt. + * + * When modifying old S60 applications that rely on implementing functions in \c CAknDocument, + * the class should be modified to inherit from this class instead of \c CAknDocument. Then the + * application can choose to override only certain functions. + * + * For more information on \c CAknDocument, please see the S60 documentation. + * + * Unlike other Qt classes, QS60MainDocument behaves like an S60 class, and can throw Symbian + * leaves. + * + * \sa QS60MainApplication, QS60MainAppUi + */ -// ----------------------------------------------------------------------------- -// QS60MainDocument::QS60MainDocument() -// C++ default constructor can NOT contain any code, that might leave. -// ----------------------------------------------------------------------------- -// -QS60MainDocument::QS60MainDocument(CEikApplication& aApp) - : CAknDocument(aApp) +/*! + * \brief Constructs an instance of QS60MainDocument. + * + * \a mainApplication should contain a pointer to a QS60MainApplication instance. + */ +QS60MainDocument::QS60MainDocument(CEikApplication& mainApplication) + : CAknDocument(mainApplication) { // No implementation required } -// --------------------------------------------------------------------------- -// QS60MainDocument::~QS60MainDocument() -// Destructor. -// --------------------------------------------------------------------------- -// +/*! + * \brief Destroys the QS60MainDocument. + */ QS60MainDocument::~QS60MainDocument() { // No implementation required } -// --------------------------------------------------------------------------- -// QS60MainDocument::CreateAppUiL() -// Constructs CreateAppUi. -// --------------------------------------------------------------------------- -// -CEikAppUi* QS60MainDocument::CreateAppUiL() +/*! + * \brief Creates an instance of QS60MainAppUi. + * + * \sa QS60MainAppUi + */ +CEikAppUi *QS60MainDocument::CreateAppUiL() { // Create the application user interface, and return a pointer to it; // the framework takes ownership of this object @@ -117,5 +100,3 @@ CEikAppUi* QS60MainDocument::CreateAppUiL() } QT_END_NAMESPACE - -// End of File diff --git a/src/gui/s60framework/qs60maindocument.h b/src/gui/s60framework/qs60maindocument.h new file mode 100644 index 0000000..366d311 --- /dev/null +++ b/src/gui/s60framework/qs60maindocument.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Symbian application wrapper of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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 qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QS60MAINDOCUMENT_H +#define QS60MAINDOCUMENT_H + +#include <qglobal.h> + +#ifdef Q_WS_S60 + +#include <akndoc.h> + +class CEikApplication; + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QS60MainAppUi; + +class Q_GUI_EXPORT QS60MainDocument : public CAknDocument +{ +public: + + QS60MainDocument(CEikApplication &mainApplication); + // The virtuals are for qdoc. + virtual ~QS60MainDocument(); + +public: + + virtual CEikAppUi *CreateAppUiL(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // Q_WS_S60 + +#endif // QS60MAINDOCUMENT_H diff --git a/src/gui/s60framework/qs60maindocument_p.h b/src/gui/s60framework/qs60maindocument_p.h deleted file mode 100644 index d7cee13..0000000 --- a/src/gui/s60framework/qs60maindocument_p.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the Symbian application wrapper of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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 qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QS60MAINDOCUMENT_P_H -#define QS60MAINDOCUMENT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -// INCLUDES -#include <akndoc.h> - -#include <qglobal.h> - -class CEikApplication; - -QT_BEGIN_NAMESPACE - -// FORWARD DECLARATIONS -class QS60MainAppUi; - -// CLASS DECLARATION - -/** -* QS60MainDocument application class. -* An instance of class QS60MainDocument is the Document part of the -* AVKON application framework for the QtS60Main application. -*/ -class QS60MainDocument : public CAknDocument -{ -public: // Constructors and destructor - - /** - * NewL. - * Two-phased constructor. - * Construct a QS60MainDocument for the AVKON application aApp - * using two phase construction, and return a pointer - * to the created object. - * @param aApp Application creating this document. - * @return A pointer to the created instance of QS60MainDocument. - */ - static QS60MainDocument* NewL( CEikApplication& aApp ); - - /** - * NewLC. - * Two-phased constructor. - * Construct a QS60MainDocument for the AVKON application aApp - * using two phase construction, and return a pointer - * to the created object. - * @param aApp Application creating this document. - * @return A pointer to the created instance of QS60MainDocument. - */ - static QS60MainDocument* NewLC( CEikApplication& aApp ); - - /** - * ~QS60MainDocument - * Virtual Destructor. - */ - virtual ~QS60MainDocument(); - -public: // Functions from base classes - - /** - * CreateAppUiL - * From CEikDocument, CreateAppUiL. - * Create a QS60MainAppUi object and return a pointer to it. - * The object returned is owned by the Uikon framework. - * @return Pointer to created instance of AppUi. - */ - CEikAppUi* CreateAppUiL(); - -private: // Constructors - - /** - * ConstructL - * 2nd phase constructor. - */ - void ConstructL(); - - /** - * QS60MainDocument. - * C++ default constructor. - * @param aApp Application creating this document. - */ - QS60MainDocument( CEikApplication& aApp ); - -}; - -QT_END_NAMESPACE - -#endif // QS60MAINDOCUMENT_P_H - -// End of File diff --git a/src/gui/s60framework/s60framework.pri b/src/gui/s60framework/s60framework.pri index f9a6d95..fea74fe 100644 --- a/src/gui/s60framework/s60framework.pri +++ b/src/gui/s60framework/s60framework.pri @@ -3,5 +3,6 @@ SOURCES += s60framework/qs60mainapplication.cpp \ s60framework/qs60maindocument.cpp HEADERS += s60framework/qs60mainapplication_p.h \ - s60framework/qs60mainappui_p.h \ - s60framework/qs60maindocument_p.h + s60framework/qs60mainapplication.h \ + s60framework/qs60mainappui.h \ + s60framework/qs60maindocument.h diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp index 825b2ec..dee3168 100644 --- a/src/gui/statemachine/qkeyeventtransition.cpp +++ b/src/gui/statemachine/qkeyeventtransition.cpp @@ -44,7 +44,7 @@ #ifndef QT_NO_STATEMACHINE #include "qbasickeyeventtransition_p.h" -#include <QtCore/qwrappedevent.h> +#include <QtCore/qstatemachine.h> #include <private/qeventtransition_p.h> QT_BEGIN_NAMESPACE @@ -160,7 +160,7 @@ bool QKeyEventTransition::eventTest(QEvent *event) Q_D(const QKeyEventTransition); if (!QEventTransition::eventTest(event)) return false; - QWrappedEvent *we = static_cast<QWrappedEvent*>(event); + QStateMachine::WrappedEvent *we = static_cast<QStateMachine::WrappedEvent*>(event); d->transition->setEventType(we->event()->type()); return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event()); } diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp index 564c8d2..86cacf7 100644 --- a/src/gui/statemachine/qmouseeventtransition.cpp +++ b/src/gui/statemachine/qmouseeventtransition.cpp @@ -44,7 +44,7 @@ #ifndef QT_NO_STATEMACHINE #include "qbasicmouseeventtransition_p.h" -#include <QtCore/qwrappedevent.h> +#include <QtCore/qstatemachine.h> #include <QtGui/qpainterpath.h> #include <private/qeventtransition_p.h> @@ -188,7 +188,7 @@ bool QMouseEventTransition::eventTest(QEvent *event) Q_D(const QMouseEventTransition); if (!QEventTransition::eventTest(event)) return false; - QWrappedEvent *we = static_cast<QWrappedEvent*>(event); + QStateMachine::WrappedEvent *we = static_cast<QStateMachine::WrappedEvent*>(event); d->transition->setEventType(we->event()->type()); return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event()); } diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp index d53a280..1cb0ca4 100644 --- a/src/gui/styles/gtksymbols.cpp +++ b/src/gui/styles/gtksymbols.cpp @@ -211,7 +211,8 @@ static QString classPath(GtkWidget *widget) static void resolveGtk() { - QLibrary libgtk(QLS("gtk-x11-2.0")); + // enforce the "0" suffix, so we'll open libgtk-x11-2.0.so.0 + QLibrary libgtk(QLS("gtk-x11-2.0"), 0, 0); QGtk::gtk_init = (Ptr_gtk_init)libgtk.resolve("gtk_init"); QGtk::gtk_window_new = (Ptr_gtk_window_new)libgtk.resolve("gtk_window_new"); QGtk::gtk_style_attach = (Ptr_gtk_style_attach)libgtk.resolve("gtk_style_attach"); @@ -423,27 +424,32 @@ static void init_gtk_window() static QString themeName; if (!gtkWidgetMap()->contains(QLS("GtkWindow")) && themeName.isEmpty()) { themeName = getThemeName(); - // Due to namespace conflicts with Qt3 and obvious recursion with Qt4, - // we cannot support the GTK_Qt Gtk engine - if (!(themeName.isEmpty() || themeName == QLS("Qt") || themeName == QLS("Qt4"))) { - resolveGtk(); - if (QGtk::gtk_init) { - // Gtk will set the Qt error handler so we have to reset it afterwards - x11ErrorHandler qt_x_errhandler = XSetErrorHandler(0); - QGtk::gtk_init (NULL, NULL); - XSetErrorHandler(qt_x_errhandler); - - GtkWidget* gtkWindow = QGtk::gtk_window_new(GTK_WINDOW_POPUP); - QGtk::gtk_widget_realize(gtkWindow); - if (displayDepth == -1) - displayDepth = QGtk::gdk_drawable_get_depth(gtkWindow->window); - gtkWidgetMap()->insert(QLS("GtkWindow"), gtkWindow); - } - else { - qWarning("QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries."); - } - } else { + + if (themeName.isEmpty()) { + qWarning("QGtkStyle was unable to detect the current GTK+ theme."); + return; + } else if (themeName == QLS("Qt") || themeName == QLS("Qt4")) { + // Due to namespace conflicts with Qt3 and obvious recursion with Qt4, + // we cannot support the GTK_Qt Gtk engine qWarning("QGtkStyle cannot be used together with the GTK_Qt engine."); + return; + } + + resolveGtk(); + + if (QGtk::gtk_init) { + // Gtk will set the Qt error handler so we have to reset it afterwards + x11ErrorHandler qt_x_errhandler = XSetErrorHandler(0); + QGtk::gtk_init (NULL, NULL); + XSetErrorHandler(qt_x_errhandler); + + GtkWidget* gtkWindow = QGtk::gtk_window_new(GTK_WINDOW_POPUP); + QGtk::gtk_widget_realize(gtkWindow); + if (displayDepth == -1) + displayDepth = QGtk::gdk_drawable_get_depth(gtkWindow->window); + gtkWidgetMap()->insert(QLS("GtkWindow"), gtkWindow); + } else { + qWarning("QGtkStyle could not resolve GTK. Make sure you have installed the proper libraries."); } } } diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index 8647c90..fabd7ca 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -517,13 +517,13 @@ static void qt_cleanlooks_draw_buttongradient(QPainter *painter, const QRect &re gradient->setStops(bgBrush.gradient()->stops()); else { int size = horizontal ? rect.width() : rect.height() ; - if (size < 1) - size = 1; - float edge = 4.0/(float)size; - gradient->setColorAt(0, gradientStart); - gradient->setColorAt(edge, gradientMid.lighter(104)); - gradient->setColorAt(1.0 - edge, gradientMid.darker(100)); - gradient->setColorAt(1.0, gradientStop); + if (size > 4) { + float edge = 4.0/(float)size; + gradient->setColorAt(0, gradientStart); + gradient->setColorAt(edge, gradientMid.lighter(104)); + gradient->setColorAt(1.0 - edge, gradientMid.darker(100)); + gradient->setColorAt(1.0, gradientStop); + } } painter->fillRect(rect, *gradient); delete gradient; diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index f3dc4ac..414580e 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -3063,14 +3063,14 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple if (!arrowWidget) return QCleanlooksStyle::subControlRect(control, option, subControl, widget); - QRect buttonRect(arrowWidget->allocation.x, arrowWidget->allocation.y, + QRect buttonRect(option->rect.left() + arrowWidget->allocation.x, + option->rect.top() + arrowWidget->allocation.y, arrowWidget->allocation.width, arrowWidget->allocation.height); switch (subControl) { case SC_ComboBoxArrow: // Note: this indicates the arrowbutton for editable combos rect = buttonRect; - break; case SC_ComboBoxEditField: { diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp index 0b2d6a7..5052755 100644 --- a/src/gui/styles/qplastiquestyle.cpp +++ b/src/gui/styles/qplastiquestyle.cpp @@ -1056,7 +1056,8 @@ void QPlastiqueStylePrivate::drawPartialFrame(QPainter *painter, const QStyleOpt frameOpt.rect.adjust(reverse ? -2 : 0, 0, reverse ? 0 : 2, 0); frameOpt.lineWidth = q->pixelMetric(QStyle::PM_DefaultFrameWidth); frameOpt.midLineWidth = 0; - frameOpt.state |= QStyle::State_Sunken; + frameOpt.state = option->state | QStyle::State_Sunken; + frameOpt.palette = option->palette; q->drawPrimitive(QStyle::PE_PanelLineEdit, &frameOpt, painter, widget); painter->restore(); diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index 664ee41..1e57167 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -706,10 +706,11 @@ void QS60StylePrivate::setThemePalette(QPalette *palette) const palette->setColor(QPalette::AlternateBase, Qt::transparent); palette->setBrush(QPalette::Base, Qt::transparent); // set button and tooltipbase based on pixel colors - const QColor buttonColor = this->colorFromFrameGraphics(SF_ButtonNormal); - palette->setColor(QPalette::Button, buttonColor ); - const QColor toolTipColor = this->colorFromFrameGraphics(SF_ToolTip); - palette->setColor(QPalette::ToolTipBase, toolTipColor ); +// After natitive pixmap support, colorFromFrameGraphics caused reproducable crashes on some setups. +// const QColor buttonColor = colorFromFrameGraphics(SF_ButtonNormal); +// palette->setColor(QPalette::Button, buttonColor); +// const QColor toolTipColor = colorFromFrameGraphics(SF_ToolTip); +// palette->setColor(QPalette::ToolTipBase, toolTipColor); palette->setColor(QPalette::Light, palette->color(QPalette::Button).lighter()); palette->setColor(QPalette::Dark, palette->color(QPalette::Button).darker()); palette->setColor(QPalette::Midlight, palette->color(QPalette::Button).lighter(125)); diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 9f2d245..0f3a88b 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -1759,7 +1759,7 @@ QRenderRule QStyleSheetStyle::renderRule(const QWidget *w, const QStyleOption *o QStyle::SubControl subControl = knownPseudoElements[pseudoElement].subControl; if (!(complex->activeSubControls & subControl)) - state = QStyle::State(state & (QStyle::State_Enabled | QStyle::State_Horizontal)); + state &= (QStyle::State_Enabled | QStyle::State_Horizontal | QStyle::State_HasFocus); } switch (pseudoElement) { @@ -2903,6 +2903,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC if (const QStyleOptionSpinBox *spin = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { QStyleOptionSpinBox spinOpt(*spin); rule.configurePalette(&spinOpt.palette, QPalette::ButtonText, QPalette::Button); + rule.configurePalette(&spinOpt.palette, QPalette::Text, QPalette::Base); spinOpt.rect = rule.borderRect(opt->rect); bool customUp = true, customDown = true; QRenderRule upRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton); @@ -3135,19 +3136,25 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { rule.drawRule(p, opt->rect); - QRenderRule subRule = renderRule(w, opt, PseudoElement_SliderGroove); - if (!subRule.hasDrawable()) { - baseStyle()->drawComplexControl(cc, slider, p, w); - return; + QRenderRule grooveSubRule = renderRule(w, opt, PseudoElement_SliderGroove); + QRenderRule handleSubRule = renderRule(w, opt, PseudoElement_SliderHandle); + if (!grooveSubRule.hasDrawable()) { + QStyleOptionSlider slOpt(*slider); + bool handleHasRule = handleSubRule.hasDrawable(); + // If the style specifies a different handler rule, draw the groove without the handler. + if (handleHasRule) + slOpt.subControls &= ~SC_SliderHandle; + baseStyle()->drawComplexControl(cc, &slOpt, p, w); + if (!handleHasRule) + return; } QRect gr = subControlRect(cc, opt, SC_SliderGroove, w); if (slider->subControls & SC_SliderGroove) { - subRule.drawRule(p, gr); + grooveSubRule.drawRule(p, gr); } if (slider->subControls & SC_SliderHandle) { - QRenderRule subRule = renderRule(w, opt, PseudoElement_SliderHandle); QRect hr = subControlRect(cc, opt, SC_SliderHandle, w); QRenderRule subRule1 = renderRule(w, opt, PseudoElement_SliderSubPage); @@ -3168,7 +3175,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC subRule2.drawRule(p, r); } - subRule.drawRule(p, subRule.boxRect(hr, Margin)); + handleSubRule.drawRule(p, grooveSubRule.boxRect(hr, Margin)); } if (slider->subControls & SC_SliderTickmarks) { @@ -4169,6 +4176,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op QRenderRule spinboxRule = renderRule(w->parentWidget(), opt); if (!spinboxRule.hasNativeBorder() || !spinboxRule.baseStyleCanDraw()) return; + rule = spinboxRule; } #endif if (rule.hasNativeBorder()) { diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 742b5b0..0f72440 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -41,7 +41,6 @@ #include "qwindowsstyle.h" #include "qwindowsstyle_p.h" -#include <private/qpixmapdata_p.h> #include <private/qstylehelper_p.h> #if !defined(QT_NO_STYLE_WINDOWS) || defined(QT_PLUGIN) @@ -927,6 +926,26 @@ static const char *const question_xpm[] = { #endif //QT_NO_IMAGEFORMAT_XPM +#ifdef Q_OS_WIN +static QPixmap loadIconFromShell32( int resourceId, int size ) +{ +#ifdef Q_OS_WINCE + HMODULE hmod = LoadLibrary(L"ceshell.dll"); +#else + HMODULE hmod = LoadLibrary(L"shell32.dll"); +#endif + if( hmod ) { + HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size, size, 0); + if( iconHandle ) { + QPixmap iconpixmap = QPixmap::fromWinHICON( iconHandle ); + DestroyIcon(iconHandle); + return iconpixmap; + } + } + return QPixmap(); +} +#endif + /*! \reimp */ @@ -1016,28 +1035,28 @@ QPixmap QWindowsStyle::standardPixmap(StandardPixmap standardPixmap, const QStyl case SP_MessageBoxInformation: { HICON iconHandle = LoadIcon(NULL, IDI_INFORMATION); - desktopIcon = convertHIconToPixmap( iconHandle ); + desktopIcon = QPixmap::fromWinHICON( iconHandle ); DestroyIcon(iconHandle); break; } case SP_MessageBoxWarning: { HICON iconHandle = LoadIcon(NULL, IDI_WARNING); - desktopIcon = convertHIconToPixmap( iconHandle ); + desktopIcon = QPixmap::fromWinHICON( iconHandle ); DestroyIcon(iconHandle); break; } case SP_MessageBoxCritical: { HICON iconHandle = LoadIcon(NULL, IDI_ERROR); - desktopIcon = convertHIconToPixmap( iconHandle ); + desktopIcon = QPixmap::fromWinHICON( iconHandle ); DestroyIcon(iconHandle); break; } case SP_MessageBoxQuestion: { HICON iconHandle = LoadIcon(NULL, IDI_QUESTION); - desktopIcon = convertHIconToPixmap( iconHandle ); + desktopIcon = QPixmap::fromWinHICON( iconHandle ); DestroyIcon(iconHandle); break; } @@ -1052,7 +1071,7 @@ QPixmap QWindowsStyle::standardPixmap(StandardPixmap standardPixmap, const QStyl memset(&iconInfo, 0, sizeof(iconInfo)); iconInfo.cbSize = sizeof(iconInfo); if (pSHGetStockIconInfo(_SIID_SHIELD, _SHGFI_ICON | _SHGFI_SMALLICON, &iconInfo) == S_OK) { - pixmap = convertHIconToPixmap(iconInfo.hIcon); + pixmap = QPixmap::fromWinHICON(iconInfo.hIcon); DestroyIcon(iconInfo.hIcon); return pixmap; } @@ -3011,6 +3030,8 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp ar.adjust(2, 2, -2, -2); if (opt->state & State_Enabled) flags |= State_Enabled; + if (opt->state & State_HasFocus) + flags |= State_HasFocus; if (sunkenArrow) flags |= State_Sunken; @@ -3346,7 +3367,7 @@ QIcon QWindowsStyle::standardIconImplementation(StandardPixmap standardIcon, con memset(&iconInfo, 0, sizeof(iconInfo)); iconInfo.cbSize = sizeof(iconInfo); if (pSHGetStockIconInfo(_SIID_SHIELD, _SHGFI_ICON | _SHGFI_LARGEICON, &iconInfo) == S_OK) { - icon.addPixmap(convertHIconToPixmap(iconInfo.hIcon)); + icon.addPixmap(QPixmap::fromWinHICON(iconInfo.hIcon)); DestroyIcon(iconInfo.hIcon); } } diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index 7803e92..b062a3f 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -1214,7 +1214,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption alignment |= Qt::TextHideMnemonic; //The rect adjustment is a workaround for the menu not really filling its background. - XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_BARBACKGROUND, 0, option->rect.adjusted(-1, 1 , 2, 1)); + XPThemeData theme(widget, painter, QLatin1String("MENU"), MENU_BARBACKGROUND, 0, option->rect.adjusted(-1, 0, 2, 1)); d->drawBackground(theme); int stateId = MBI_NORMAL; diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 0dc1832..9ef30e5 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -621,12 +621,21 @@ void QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) QMatrix m = painter->matrix(); bool complexXForm = m.m11() != 1.0 || m.m22() != 1.0 || m.m12() != 0.0 || m.m21() != 0.0; + bool translucentToplevel = false; + QPaintDevice *pdev = painter->device(); + if (pdev->devType() == QInternal::Widget) { + QWidget *win = ((QWidget *) pdev)->window(); + translucentToplevel = win->testAttribute(Qt::WA_TranslucentBackground); + } + bool useFallback = painter->paintEngine()->getDC() == 0 || painter->opacity() != 1.0 || themeData.rotate || complexXForm || themeData.mirrorVertically - || (themeData.mirrorHorizontally && pDrawThemeBackgroundEx == 0); + || (themeData.mirrorHorizontally && pDrawThemeBackgroundEx == 0) + || translucentToplevel; + if (!useFallback) drawBackgroundDirectly(themeData); else @@ -3290,17 +3299,6 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con } break; - case PM_MenuButtonIndicator: - { - XPThemeData theme(widget, 0, QLatin1String("TOOLBAR"), TP_SPLITBUTTONDROPDOWN); - if (theme.isValid()) { - SIZE size; - pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = size.cx; - } - } - break; - case PM_TitleBarHeight: { #ifdef QT3_SUPPORT diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 49149c5..3da1593 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -647,8 +647,14 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) { defaultFormat = format; this->antialias = antialias; + if (!antialias) glyphFormat = QFontEngineGlyphCache::Raster_Mono; + else if (format == Format_A8) + glyphFormat = QFontEngineGlyphCache::Raster_A8; + else if (format == Format_A32) + glyphFormat = QFontEngineGlyphCache::Raster_RGBMask; + face_id = faceId; freetype = QFreetypeFace::getFace(face_id); if (!freetype) { @@ -1848,6 +1854,28 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g) return img; } +QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, int margin, const QTransform &t) +{ + if (t.type() > QTransform::TxTranslate) + return QFontEngine::alphaRGBMapForGlyph(g, margin, t); + + lockFace(); + + GlyphFormat glyph_format = Format_A32; + + Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format); + if (!glyph) { + unlockFace(); + return QFontEngine::alphaRGBMapForGlyph(g, margin, t); + } + + QImage img(glyph->width, glyph->height, QImage::Format_RGB32); + memcpy(img.bits(), glyph->data, 4 * glyph->width * glyph->height); + unlockFace(); + + return img; +} + void QFontEngineFT::removeGlyphFromCache(glyph_t glyph) { delete defaultGlyphSet.glyph_data.take(glyph); diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 6704c8f..99b40f8 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -227,6 +227,7 @@ public: virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; virtual QImage alphaMapForGlyph(glyph_t); + virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t); virtual void removeGlyphFromCache(glyph_t glyph); virtual int glyphCount() const; diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 1703ac8..40db7b4 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -1014,6 +1014,8 @@ bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyph | kATSLineDisableAllJustification ; + layopts |= kATSLineUseDeviceMetrics; + if (fontDef.styleStrategy & QFont::NoAntialias) layopts |= kATSLineNoAntiAliasing; diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h index dc4ff2f..44f8122 100644 --- a/src/gui/text/qfontengine_s60_p.h +++ b/src/gui/text/qfontengine_s60_p.h @@ -119,11 +119,12 @@ public: Type type() const; + void getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const; + private: friend class QFontPrivate; QFixed glyphAdvance(HB_Glyph glyph) const; - void getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const; CFbsBitmap *m_textRenderBitmap; CFbsBitmapDevice *m_textRenderBitmapDevice; diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 25006b1..6def06e 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -271,7 +271,9 @@ bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) } #ifdef QT_KEYPAD_NAVIGATION else if (QApplication::keypadNavigationEnabled() - && (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down)) { + && ((e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) + || QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional + && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right))) { return false; } #endif diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index 8b85d2d..ce62834 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -92,8 +92,12 @@ QTextCursorPrivate::AdjustResult QTextCursorPrivate::adjustPosition(int position { QTextCursorPrivate::AdjustResult result = QTextCursorPrivate::CursorMoved; // not(!) <= , so that inserting text adjusts the cursor correctly - if (position < positionOfChange || - (position == positionOfChange && op == QTextUndoCommand::KeepCursor)) { + if (position < positionOfChange + || (position == positionOfChange + && (op == QTextUndoCommand::KeepCursor + || anchor < position) + ) + ) { result = CursorUnchanged; } else { if (charsAddedOrRemoved < 0 && position < positionOfChange - charsAddedOrRemoved) diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 57d4b7a..a8956b8 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -985,7 +985,7 @@ bool QTextDocument::isRedoAvailable() const int QTextDocument::revision() const { Q_D(const QTextDocument); - return d->undoState; + return d->revision; } @@ -1096,8 +1096,10 @@ void QTextDocument::setPlainText(const QString &text) Q_D(QTextDocument); bool previousState = d->isUndoRedoEnabled(); d->enableUndoRedo(false); + d->beginEditBlock(); d->clear(); QTextCursor(this).insertText(text); + d->endEditBlock(); d->enableUndoRedo(previousState); } @@ -1123,8 +1125,10 @@ void QTextDocument::setHtml(const QString &html) Q_D(QTextDocument); bool previousState = d->isUndoRedoEnabled(); d->enableUndoRedo(false); + d->beginEditBlock(); d->clear(); QTextHtmlImporter(this, html, QTextHtmlImporter::ImportToDocument).import(); + d->endEditBlock(); d->enableUndoRedo(previousState); } diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 7bfdf6c..2ad6512 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -195,6 +195,7 @@ QTextDocumentPrivate::QTextDocumentPrivate() docChangeFrom = -1; undoState = 0; + revision = -1; // init() inserts a block, bringing it to 0 lout = 0; @@ -203,7 +204,6 @@ QTextDocumentPrivate::QTextDocumentPrivate() undoEnabled = true; inContentsChange = false; - inEdit = false; defaultTextOption.setTabStop(80); // same as in qtextengine.cpp defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); @@ -429,11 +429,11 @@ int QTextDocumentPrivate::insertBlock(const QChar &blockSeparator, Q_ASSERT(undoState == undoStack.size()); // update revision numbers of the modified blocks. - B->revision = (atBlockEnd && !atBlockStart)? oldRevision : undoState; + B->revision = (atBlockEnd && !atBlockStart)? oldRevision : revision; b = blocks.next(b); if (b) { B = blocks.fragment(b); - B->revision = atBlockStart ? oldRevision : undoState; + B->revision = atBlockStart ? oldRevision : revision; } if (formats.charFormat(charFormat).objectIndex() == -1) @@ -456,7 +456,6 @@ void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format Q_ASSERT(pos >= 0 && pos < fragments.length()); Q_ASSERT(formats.format(format).isCharFormat()); - beginEdit(); insert_string(pos, strPos, strLength, format, QTextUndoCommand::MoveCursor); if (undoEnabled) { int b = blocks.findNode(pos); @@ -466,7 +465,7 @@ void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format QTextUndoCommand::MoveCursor, format, strPos, pos, strLength, B->revision); appendUndoItem(c); - B->revision = undoState; + B->revision = revision; Q_ASSERT(undoState == undoStack.size()); } finishEdit(); @@ -582,7 +581,6 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O if (pos == to) return; - beginEdit(); const bool needsInsert = to != -1; #if !defined(QT_NO_DEBUG) @@ -653,7 +651,7 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O } appendUndoItem(c); if (B) - B->revision = undoState; + B->revision = revision; x = n; if (needsInsert) @@ -1111,6 +1109,7 @@ void QTextDocumentPrivate::joinPreviousEditBlock() void QTextDocumentPrivate::endEditBlock() { + Q_ASSERT(editBlock > 0); if (--editBlock) return; @@ -1131,8 +1130,6 @@ void QTextDocumentPrivate::finishEdit() if (editBlock) return; - inEdit = false; - if (framesDirty) scan_frames(docChangeFrom, docChangeOldLength, docChangeLength); @@ -1195,19 +1192,19 @@ void QTextDocumentPrivate::documentChange(int from, int length) adjustDocumentChangesAndCursors is called whenever there is an insert or remove of characters. param from is the cursor position in the document param addedOrRemoved is the amount of characters added or removed. A negative number means characters are removed. + + The function stores information to be emitted when finishEdit() is called. */ void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOrRemoved, QTextUndoCommand::Operation op) { - Q_Q(QTextDocument); + if (!editBlock) + ++revision; + for (int i = 0; i < cursors.size(); ++i) { QTextCursorPrivate *curs = cursors.at(i); if (curs->adjustPosition(from, addedOrRemoved, op) == QTextCursorPrivate::CursorMoved) { - if (editBlock || inEdit) { - if (!changedCursors.contains(curs)) - changedCursors.append(curs); - } else { - emit q->cursorPositionChanged(QTextCursor(curs)); - } + if (!changedCursors.contains(curs)) + changedCursors.append(curs); } } @@ -1223,7 +1220,6 @@ void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOr } // qDebug("adjustDocumentChanges:"); // qDebug(" -> %d %d %d", docChangeFrom, docChangeOldLength, docChangeLength); - contentsChanged(); return; } @@ -1248,7 +1244,6 @@ void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOr docChangeLength += added - removedInside + diff; // qDebug(" -> %d %d %d", docChangeFrom, docChangeOldLength, docChangeLength); - contentsChanged(); } @@ -1541,7 +1536,7 @@ void QTextDocumentPrivate::deleteObject(QTextObject *object) void QTextDocumentPrivate::contentsChanged() { Q_Q(QTextDocument); - if (editBlock || inEdit) + if (editBlock) return; bool m = undoEnabled ? (modifiedState != undoState) : true; diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h index 36f3241..ce25c57 100644 --- a/src/gui/text/qtextdocument_p.h +++ b/src/gui/text/qtextdocument_p.h @@ -201,10 +201,9 @@ public: inline void undo() { undoRedo(true); } inline void redo() { undoRedo(false); } void appendUndoItem(QAbstractUndoItem *); - inline void beginEditBlock() { editBlock++; } + inline void beginEditBlock() { if (0 == editBlock++) ++revision; } void joinPreviousEditBlock(); void endEditBlock(); - inline void beginEdit() { inEdit = true; } void finishEdit(); inline bool isInEditBlock() const { return editBlock; } void enableUndoRedo(bool enable); @@ -306,6 +305,7 @@ private: QVector<QTextUndoCommand> undoStack; bool undoEnabled; int undoState; + int revision; // position in undo stack of the last setModified(false) call int modifiedState; bool modified; @@ -340,7 +340,6 @@ public: int maximumBlockCount; uint needsEnsureMaximumBlockCount : 1; uint inContentsChange : 1; - uint inEdit : 1; // between beginEdit() and finishEdit() QSizeF pageSize; QString title; QString url; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index f8b0cbc..c5f0e35 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1720,10 +1720,15 @@ void QTextLine::layout_helper(int maxGlyphs) goto found; QFixed x = line.x + line.textWidth + lbh.tmpData.textWidth + lbh.spaceData.textWidth; - lbh.spaceData.textWidth += eng->calculateTabWidth(item, x); + QFixed tabWidth = eng->calculateTabWidth(item, x); + + lbh.spaceData.textWidth += tabWidth; lbh.spaceData.length++; newItem = item + 1; - ++lbh.glyphCount; + + QFixed averageCharWidth = eng->fontEngine(current)->averageCharWidth(); + lbh.glyphCount += qRound(tabWidth / averageCharWidth); + if (lbh.checkFullOtherwiseExtend(line)) goto found; } else if (current.analysis.flags == QScriptAnalysis::LineOrParagraphSeparator) { @@ -1808,7 +1813,7 @@ void QTextLine::layout_helper(int maxGlyphs) glyph_t glyph = glyphs.glyphs[logClusters[pos - 1]]; glyph_metrics_t gi = fontEngine->boundingBox(glyph); if (gi.isValid()) - lbh.rightBearing = -qRound(gi.xoff - gi.x - gi.width); + lbh.rightBearing = qMax(QFixed(), -(gi.xoff - gi.x - gi.width)); } if ((sb_or_ws|breakany) && lbh.checkFullOtherwiseExtend(line)) { diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index b6ff39f..d9438fd 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -1370,7 +1370,7 @@ int QTextBlock::firstLineNumber() const Sets the line count to \a count. -/sa lineCount() +\sa lineCount() */ void QTextBlock::setLineCount(int count) { diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp index b78e51b..fd06cf3 100644 --- a/src/gui/util/qdesktopservices_s60.cpp +++ b/src/gui/util/qdesktopservices_s60.cpp @@ -70,7 +70,6 @@ QT_BEGIN_NAMESPACE _LIT(KCacheSubDir, "Cache\\"); _LIT(KSysBin, "\\Sys\\Bin\\"); -_LIT(KTempDir, "\\System\\Temp\\"); _LIT(KBrowserPrefix, "4 " ); _LIT(KFontsDir, "z:\\resource\\Fonts\\"); const TUid KUidBrowser = { 0x10008D39 }; @@ -381,9 +380,7 @@ QString QDesktopServices::storageLocation(StandardLocation type) #endif break; case TempLocation: - path.Append(writableExeDrive().Name()); - path.Append(KTempDir); - //return QDir::tempPath(); break; + return QDir::tempPath(); break; case HomeLocation: path.Append(writableDataRoot()); diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp index fc3d527..362be5b 100644 --- a/src/gui/util/qsystemtrayicon_win.cpp +++ b/src/gui/util/qsystemtrayicon_win.cpp @@ -98,7 +98,6 @@ public: bool allowsMessages(); bool supportsMessages(); QRect findIconGeometry(const int a_iButtonID); - HBITMAP createIconMask(const QBitmap &bitmap); void createIcon(); HICON hIcon; QPoint globalPos; @@ -241,21 +240,6 @@ bool QSystemTrayIconSys::iconDrawItem(LPDRAWITEMSTRUCT lpdi) return true; } -HBITMAP QSystemTrayIconSys::createIconMask(const QBitmap &bitmap) -{ - QImage bm = bitmap.toImage().convertToFormat(QImage::Format_Mono); - int w = bm.width(); - int h = bm.height(); - int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment - uchar *bits = new uchar[bpl*h]; - bm.invertPixels(); - for (int y=0; y<h; y++) - memcpy(bits+y*bpl, bm.scanLine(y), bpl); - HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits); - delete [] bits; - return hbm; -} - void QSystemTrayIconSys::createIcon() { hIcon = 0; @@ -270,23 +254,7 @@ void QSystemTrayIconSys::createIcon() if (pm.isNull()) return; - QBitmap mask = pm.mask(); - if (mask.isNull()) { - mask = QBitmap(pm.size()); - mask.fill(Qt::color1); - } - - HBITMAP im = createIconMask(mask); - ICONINFO ii; - ii.fIcon = true; - ii.hbmMask = im; - ii.hbmColor = pm.toWinHBITMAP(QPixmap::Alpha); - ii.xHotspot = 0; - ii.yHotspot = 0; - hIcon = CreateIconIndirect(&ii); - - DeleteObject(ii.hbmColor); - DeleteObject(im); + hIcon = pm.toWinHICON(); } bool QSystemTrayIconSys::winEvent( MSG *m, long *result ) diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp index d2f4baf..cb46791 100644 --- a/src/gui/widgets/qabstractbutton.cpp +++ b/src/gui/widgets/qabstractbutton.cpp @@ -1172,7 +1172,10 @@ void QAbstractButton::keyPressEvent(QKeyEvent *e) case Qt::Key_Right: case Qt::Key_Down: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)) { + if ((QApplication::keypadNavigationEnabled() + && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)) + || (!QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional + || (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down))) { e->ignore(); return; } diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp index 34fe340..a50c105 100644 --- a/src/gui/widgets/qabstractslider.cpp +++ b/src/gui/widgets/qabstractslider.cpp @@ -47,6 +47,9 @@ #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" #endif +#ifdef QT_KEYPAD_NAVIGATION +#include "qtabwidget.h" // Needed in inTabWidget() +#endif // QT_KEYPAD_NAVIGATION #include <limits.h> QT_BEGIN_NAMESPACE @@ -724,6 +727,45 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e) } } #endif +#ifdef QT_KEYPAD_NAVIGATION +/*! + \internal + + Tells us if it there is currently a reachable widget by keypad navigation in + a certain \a orientation. + If no navigation is possible, occuring key events in that \a orientation may + be used to interact with the value in the focussed widget, even though it + currently has not the editFocus. + + \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus() +*/ +inline static bool canKeypadNavigate(Qt::Orientation orientation) +{ + return orientation == Qt::Horizontal? + (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast) + || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest)) + :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth) + || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth)); +} +/*! + \internal + + Checks, if the \a widget is inside a QTabWidget. If is is inside + one, left/right key events will be used to switch between tabs in keypad + navigation. If there is no QTabWidget, the horizontal key events can be used to + interact with the value in the focussed widget, even though it currently has + not the editFocus. + + \sa QWidget::hasEditFocus() +*/ +inline static bool inTabWidget(QWidget *widget) +{ + for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget()) + if (qobject_cast<const QTabWidget*>(tabWidget)) + return true; + return false; +} +#endif // QT_KEYPAD_NAVIGATION /*! \reimp */ @@ -751,7 +793,13 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) // It seems we need to use invertedAppearance for Left and right, otherwise, things look weird. case Qt::Key_Left: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + // In QApplication::KeypadNavigationDirectional, we want to change the slider + // value if there is no left/right navigation possible and if this slider is not + // inside a tab widget. + if (QApplication::keypadNavigationEnabled() + && (!hasEditFocus() && QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder + || d->orientation == Qt::Vertical + || !hasEditFocus() && (canKeypadNavigate(Qt::Horizontal) || inTabWidget(this)))) { ev->ignore(); return; } @@ -766,7 +814,11 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) break; case Qt::Key_Right: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { + // Same logic as in Qt::Key_Left + if (QApplication::keypadNavigationEnabled() + && (!hasEditFocus() && QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder + || d->orientation == Qt::Vertical + || !hasEditFocus() && (canKeypadNavigate(Qt::Horizontal) || inTabWidget(this)))) { ev->ignore(); return; } @@ -781,7 +833,12 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) break; case Qt::Key_Up: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + // In QApplication::KeypadNavigationDirectional, we want to change the slider + // value if there is no up/down navigation possible. + if (QApplication::keypadNavigationEnabled() + && (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder + || d->orientation == Qt::Horizontal + || !hasEditFocus() && canKeypadNavigate(Qt::Vertical))) { ev->ignore(); break; } @@ -790,7 +847,11 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) break; case Qt::Key_Down: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + // Same logic as in Qt::Key_Up + if (QApplication::keypadNavigationEnabled() + && (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder + || d->orientation == Qt::Horizontal + || !hasEditFocus() && canKeypadNavigate(Qt::Vertical))) { ev->ignore(); break; } diff --git a/src/gui/widgets/qactiontokeyeventmapper.cpp b/src/gui/widgets/qactiontokeyeventmapper.cpp deleted file mode 100644 index 171b82d..0000000 --- a/src/gui/widgets/qactiontokeyeventmapper.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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 qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qapplication.h" -#include "qevent.h" -#include "qactiontokeyeventmapper_p.h" - -QT_BEGIN_NAMESPACE - -QActionToKeyEventMapper::QActionToKeyEventMapper(QAction *softKeyAction, Qt::Key key, QObject *parent) - : QObject(parent) - , m_softKeyAction(softKeyAction) - , m_key(key) -{ - -} - -QString QActionToKeyEventMapper::roleText(QAction::SoftKeyRole role) -{ - switch (role) { - case QAction::OptionsSoftKey: - return QAction::tr("Options"); - case QAction::SelectSoftKey: - return QAction::tr("Select"); - case QAction::BackSoftKey: - return QAction::tr("Back"); - case QAction::NextSoftKey: - return QAction::tr("Next"); - case QAction::PreviousSoftKey: - return QAction::tr("Previous"); - case QAction::OkSoftKey: - return QAction::tr("Ok"); - case QAction::CancelSoftKey: - return QAction::tr("Cancel"); - case QAction::EditSoftKey: - return QAction::tr("Edit"); - case QAction::ViewSoftKey: - return QAction::tr("View"); - default: - return QString(); - }; -} -void QActionToKeyEventMapper::addSoftKey(QAction::SoftKeyRole standardRole, Qt::Key key, QWidget *actionWidget) -{ - QAction *action = new QAction(actionWidget); - action->setSoftKeyRole(standardRole); - action->setText(roleText(standardRole)); - QActionToKeyEventMapper *softKey = new QActionToKeyEventMapper(action, key, actionWidget); - connect(action, SIGNAL(triggered()), softKey, SLOT(sendKeyEvent())); - connect(action, SIGNAL(destroyed()), softKey, SLOT(deleteLater())); - actionWidget->setSoftKey(action); -} - -void QActionToKeyEventMapper::removeSoftkey(QWidget *focussedWidget) -{ - focussedWidget->setSoftKey(0); -} - -void QActionToKeyEventMapper::sendKeyEvent() -{ - QApplication::postEvent(parent(), new QKeyEvent(QEvent::KeyPress, m_key, Qt::NoModifier)); -} - -QT_END_NAMESPACE - diff --git a/src/gui/widgets/qcalendarwidget.cpp b/src/gui/widgets/qcalendarwidget.cpp index 71588c4..08ed7f6 100644 --- a/src/gui/widgets/qcalendarwidget.cpp +++ b/src/gui/widgets/qcalendarwidget.cpp @@ -3022,11 +3022,21 @@ bool QCalendarWidget::event(QEvent *event) bool QCalendarWidget::eventFilter(QObject *watched, QEvent *event) { Q_D(QCalendarWidget); - if (event->type() == QEvent::MouseButtonPress && d->yearEdit->hasFocus() && !QRect(d->yearEdit->mapToGlobal(QPoint(0, 0)), d->yearEdit->size()).contains(static_cast<QMouseEvent *>(event)->globalPos())) { - event->accept(); - d->_q_yearEditingFinished(); - setFocus(); - return true; + if (event->type() == QEvent::MouseButtonPress && d->yearEdit->hasFocus()) { + QWidget *tlw = window(); + QWidget *widget = static_cast<QWidget*>(watched); + //as we have a event filter on the whole application we first make sure that the top level widget + //of both this and the watched widget are the same to decide if we should finish the year edition. + if (widget->window() == tlw) { + QPoint mousePos = widget->mapTo(tlw, static_cast<QMouseEvent *>(event)->pos()); + QRect geom = QRect(d->yearEdit->mapTo(tlw, QPoint(0, 0)), d->yearEdit->size()); + if (!geom.contains(mousePos)) { + event->accept(); + d->_q_yearEditingFinished(); + setFocus(); + return true; + } + } } return QWidget::eventFilter(watched, event); } diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 220f04e..61532b9 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -63,8 +63,8 @@ #include <private/qcombobox_p.h> #include <private/qabstractitemmodel_p.h> #include <private/qabstractscrollarea_p.h> +#include <private/qsoftkeymanager_p.h> #include <qdebug.h> -#include <private/qactiontokeyeventmapper_p.h> #ifdef Q_WS_X11 #include <private/qt_x11_p.h> #endif @@ -402,6 +402,13 @@ QComboBoxPrivateContainer::QComboBoxPrivateContainer(QAbstractItemView *itemView layout->setSpacing(0); layout->setMargin(0); +#ifdef QT_SOFTKEYS_ENABLED + selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, itemView); + cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Escape, itemView); + addAction(selectAction); + addAction(cancelAction); +#endif + // set item view setItemView(itemView); @@ -564,6 +571,11 @@ void QComboBoxPrivateContainer::setItemView(QAbstractItemView *itemView) this, SLOT(setCurrentIndex(QModelIndex))); connect(view, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); + +#ifdef QT_SOFTKEYS_ENABLED + selectAction->setParent(itemView); + cancelAction->setParent(itemView); +#endif } /*! @@ -629,9 +641,6 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) case Qt::Key_Select: #endif if (view->currentIndex().isValid() && (view->currentIndex().flags() & Qt::ItemIsEnabled) ) { -#ifdef QT_KEYPAD_NAVIGATION - QActionToKeyEventMapper::removeSoftkey(this); -#endif combo->hidePopup(); emit itemSelected(view->currentIndex()); } @@ -642,10 +651,6 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e) // fall through case Qt::Key_F4: case Qt::Key_Escape: -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Back: - QActionToKeyEventMapper::removeSoftkey(this); -#endif combo->hidePopup(); return true; default: @@ -2477,7 +2482,6 @@ void QComboBox::showPopup() #ifdef QT_KEYPAD_NAVIGATION if (QApplication::keypadNavigationEnabled()) view()->setEditFocus(true); - QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, view()); #endif } diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h index 507820c..f7458c4 100644 --- a/src/gui/widgets/qcombobox_p.h +++ b/src/gui/widgets/qcombobox_p.h @@ -78,6 +78,8 @@ QT_BEGIN_NAMESPACE +class QAction; + class QComboBoxListView : public QListView { Q_OBJECT @@ -253,6 +255,10 @@ private: QAbstractItemView *view; QComboBoxPrivateScroller *top; QComboBoxPrivateScroller *bottom; +#ifdef QT_SOFTKEYS_ENABLED + QAction *selectAction; + QAction *cancelAction; +#endif }; class QComboMenuDelegate : public QAbstractItemDelegate diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp index ef0b7b2..6cc720d 100644 --- a/src/gui/widgets/qdialogbuttonbox.cpp +++ b/src/gui/widgets/qdialogbuttonbox.cpp @@ -49,6 +49,11 @@ #include "qdialogbuttonbox.h" +#ifdef QT_SOFTKEYS_ENABLED +#include <QtGui/qaction.h> +#endif + + QT_BEGIN_NAMESPACE /*! @@ -263,6 +268,9 @@ public: QList<QAbstractButton *> buttonLists[QDialogButtonBox::NRoles]; QHash<QPushButton *, QDialogButtonBox::StandardButton> standardButtonHash; +#ifdef QT_SOFTKEYS_ENABLED + QHash<QAbstractButton *, QAction *> softKeyActions; +#endif Qt::Orientation orientation; QDialogButtonBox::ButtonLayout layoutPolicy; @@ -282,6 +290,9 @@ public: void addButtonsToLayout(const QList<QAbstractButton *> &buttonList, bool reverse); void retranslateStrings(); const char *standardButtonText(QDialogButtonBox::StandardButton sbutton) const; +#ifdef QT_SOFTKEYS_ENABLED + QAction *createSoftKey(QAbstractButton *button, QDialogButtonBox::ButtonRole role); +#endif }; QDialogButtonBoxPrivate::QDialogButtonBoxPrivate(Qt::Orientation orient) @@ -457,6 +468,18 @@ void QDialogButtonBoxPrivate::layoutButtons() if (center) buttonLayout->addStretch(); + +#ifdef QT_SOFTKEYS_ENABLED + QWidget *dialog = 0; + QWidget *p = q; + while (p && !p->isWindow()) { + p = p->parentWidget(); + if (dialog = qobject_cast<QDialog *>(p)) + break; + } + if (dialog) + q->setFixedSize(0, 0); +#endif } QPushButton *QDialogButtonBoxPrivate::createButton(QDialogButtonBox::StandardButton sbutton, @@ -536,10 +559,45 @@ void QDialogButtonBoxPrivate::addButton(QAbstractButton *button, QDialogButtonBo QObject::connect(button, SIGNAL(clicked()), q, SLOT(_q_handleButtonClicked())); QObject::connect(button, SIGNAL(destroyed()), q, SLOT(_q_handleButtonDestroyed())); buttonLists[role].append(button); +#ifdef QT_SOFTKEYS_ENABLED + softKeyActions.insert(button, createSoftKey(button, role)); +#endif if (doLayout) layoutButtons(); } +#ifdef QT_SOFTKEYS_ENABLED +QAction* QDialogButtonBoxPrivate::createSoftKey(QAbstractButton *button, QDialogButtonBox::ButtonRole role) +{ + Q_Q(QDialogButtonBox); + QAction::SoftKeyRole softkeyRole; + + QAction *action = new QAction(button->text(), q); + + switch (role) { + case ApplyRole: + case AcceptRole: + case YesRole: + case ActionRole: + case HelpRole: + softkeyRole = QAction::PositiveSoftKey; + break; + case RejectRole: + case DestructiveRole: + case NoRole: + case ResetRole: + softkeyRole = QAction::NegativeSoftKey; + break; + default: + break; + } + QObject::connect(action, SIGNAL(triggered()), button, SIGNAL(clicked())); + action->setSoftKeyRole(softkeyRole); + action->setEnabled(button->isEnabled()); + return action; +} +#endif + void QDialogButtonBoxPrivate::createStandardButtons(QDialogButtonBox::StandardButtons buttons) { uint i = QDialogButtonBox::FirstButton; @@ -631,6 +689,11 @@ void QDialogButtonBoxPrivate::retranslateStrings() if (buttonText) { QPushButton *button = it.key(); button->setText(QDialogButtonBox::tr(buttonText)); +#ifdef QT_SOFTKEYS_ENABLED + QAction *action = softKeyActions.value(button, 0); + if (action) + action->setText(button->text()); +#endif } ++it; } @@ -900,6 +963,13 @@ void QDialogButtonBox::removeButton(QAbstractButton *button) } } } +#ifdef QT_SOFTKEYS_ENABLED + QAction *action = d->softKeyActions.value(button, 0); + if (action) { + d->softKeyActions.remove(button); + delete action; + } +#endif if (!d->internalRemove) button->setParent(0); } @@ -1125,6 +1195,12 @@ bool QDialogButtonBox::event(QEvent *event) } if (!hasDefault && firstAcceptButton) firstAcceptButton->setDefault(true); +#ifdef QT_SOFTKEYS_ENABLED + if (dialog) + dialog->addActions(d->softKeyActions.values()); + else + addActions(d->softKeyActions.values()); +#endif }else if (event->type() == QEvent::LanguageChange) { d->retranslateStrings(); } diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 990d821..0947e1b 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -65,6 +65,9 @@ QT_BEGIN_NAMESPACE extern OSWindowRef qt_mac_window_for(const QWidget *); // qwidget_mac.cpp QT_END_NAMESPACE #endif +#ifdef QT_SOFTKEYS_ENABLED +#include <private/qsoftkeymanager_p.h> +#endif QT_BEGIN_NAMESPACE @@ -77,6 +80,9 @@ public: #ifdef Q_WS_MAC , useHIToolBar(false) #endif +#ifdef QT_SOFTKEYS_ENABLED + , menuBarAction(0) +#endif #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR) , hasOldCursor(false) , cursorAdjusted(false) #endif @@ -88,6 +94,9 @@ public: #ifdef Q_WS_MAC bool useHIToolBar; #endif +#ifdef QT_SOFTKEYS_ENABLED + QAction *menuBarAction; +#endif void init(); QList<int> hoverSeparator; QPoint hoverPos; @@ -108,6 +117,10 @@ void QMainWindowPrivate::init() const int metric = q->style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q); iconSize = QSize(metric, metric); q->setAttribute(Qt::WA_Hover); +#ifdef QT_SOFTKEYS_ENABLED + menuBarAction = QSoftKeyManager::createAction(QSoftKeyManager::MenuSoftKey, q); + menuBarAction->setObjectName("_q_menuSoftKeyAction"); +#endif } /* @@ -479,11 +492,13 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar) oldMenuBar->deleteLater(); } d->layout->setMenuBar(menuBar); - if (menuBar) { - QAction* menu = new QAction(QString::fromLatin1("Options"), this); - menu->setSoftKeyRole(QAction::MenuSoftKey); - setSoftKey(menu); - } + +#ifdef QT_SOFTKEYS_ENABLED + if (menuBar) + addAction(d->menuBarAction); + else + removeAction(d->menuBarAction); +#endif } /*! @@ -1412,16 +1427,6 @@ bool QMainWindow::event(QEvent *event) } break; #endif -#ifndef QT_NO_MENUBAR - case QEvent::WindowActivate: - if (d->layout->menuBar()) { - // ### TODO: This is evil, there is no need to create a new action every time - QAction* menu = new QAction(QString::fromLatin1("Options"), this); - menu->setSoftKeyRole(QAction::MenuSoftKey); - setSoftKey(menu); - } - break; -#endif default: break; } diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 94df85c..687e1bc 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -60,13 +60,13 @@ #ifndef QT_NO_WHATSTHIS # include <qwhatsthis.h> #endif -#include <private/qactiontokeyeventmapper_p.h> #include "qmenu_p.h" #include "qmenubar_p.h" #include "qwidgetaction.h" #include "qtoolbutton.h" #include <private/qaction_p.h> +#include <private/qsoftkeymanager_p.h> #ifdef QT3_SUPPORT #include <qmenudata.h> #endif // QT3_SUPPORT @@ -162,6 +162,15 @@ void QMenuPrivate::init() scroll = new QMenuPrivate::QMenuScroller; scroll->scrollFlags = QMenuPrivate::QMenuScroller::ScrollNone; } + +#ifdef QT_SOFTKEYS_ENABLED + selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, q); + cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Back, q); + selectAction->setVisible(false); // Don't show these in the menu + cancelAction->setVisible(false); + q->addAction(selectAction); + q->addAction(cancelAction); +#endif } int QMenuPrivate::scrollerHeight() const @@ -570,11 +579,6 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason // Since the menu is a pop-up, it uses the popup reason. if (!q->hasFocus()) { q->setFocus(Qt::PopupFocusReason); -#ifdef QT_KEYPAD_NAVIGATION - // TODO: aportale, remove KEYPAD_NAVIGATION_HACK when softkey stack - // handles focus related and user related actions separately... - QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, q); -#endif } } } @@ -1303,6 +1307,11 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action) do not support the signals: aboutToHide (), aboutToShow () and hovered (). It is not possible to display an icon in a native menu on Windows Mobile. + \section1 QMenu on Mac OS X with Qt build against Cocoa + + QMenu can be inserted only once in a menu/menubar. Subsequent insertions will + have no effect or will result in a disabled menu item. + See the \l{mainwindows/menus}{Menus} example for an example of how to use QMenuBar and QMenu in your application. @@ -1926,9 +1935,6 @@ void QMenu::popup(const QPoint &p, QAction *atAction) #ifndef QT_NO_ACCESSIBILITY QAccessible::updateAccessibility(this, 0, QAccessible::PopupMenuStart); #endif -#ifdef QT_KEYPAD_NAVIGATION - QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, this); -#endif } /*! @@ -2587,7 +2593,6 @@ void QMenu::keyPressEvent(QKeyEvent *e) case Qt::Key_Escape: #ifdef QT_KEYPAD_NAVIGATION case Qt::Key_Back: - QActionToKeyEventMapper::removeSoftkey(this); #endif key_consumed = true; if (d->tornoff) { diff --git a/src/gui/widgets/qmenu.h b/src/gui/widgets/qmenu.h index 1f77442..3d41727 100644 --- a/src/gui/widgets/qmenu.h +++ b/src/gui/widgets/qmenu.h @@ -61,8 +61,8 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) #ifdef Q_WS_S60 - IMPORT_C void qt_symbian_show_toplevel(CEikMenuPane* menuPane); - IMPORT_C void qt_symbian_show_submenu(CEikMenuPane* menuPane, int id); +void qt_symbian_show_toplevel(CEikMenuPane* menuPane); +void qt_symbian_show_submenu(CEikMenuPane* menuPane, int id); #endif // Q_WS_S60 #ifndef QT_NO_MENU diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index 3f4cd43..4fc3d3d 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -1424,7 +1424,15 @@ QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action) GetMenuItemProperty(action->menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(caused), 0, &caused); SetMenuItemProperty(data.submenuHandle, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, sizeof(caused), &caused); #else - [item setSubmenu:static_cast<NSMenu *>(action->action->menu()->macMenu())]; + NSMenu *subMenu = static_cast<NSMenu *>(action->action->menu()->macMenu()); + if ([subMenu supermenu] != nil) { + // The menu is already a sub-menu of another one. Cocoa will throw an exception, + // in such cases. For the time being, a new QMenu with same set of actions is the + // only workaround. + action->action->setEnabled(false); + } else { + [item setSubmenu:subMenu]; + } #endif } else { //respect some other items #ifndef QT_MAC_USE_COCOA @@ -1710,7 +1718,10 @@ QMenuBarPrivate::QMacMenuBarPrivate::syncAction(QMacMenuAction *action) GetMenuItemProperty(action->menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(caused), 0, &caused); SetMenuItemProperty(submenu, 0, kMenuCreatorQt, kMenuPropertyCausedQWidget, sizeof(caused), &caused); #else - [item setSubmenu:submenu]; + if ([submenu supermenu] != nil) + return; + else + [item setSubmenu:submenu]; #endif } #ifndef QT_MAC_USE_COCOA diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h index 33b892a..2d5632e 100644 --- a/src/gui/widgets/qmenu_p.h +++ b/src/gui/widgets/qmenu_p.h @@ -139,7 +139,12 @@ class QMenuPrivate : public QWidgetPrivate public: QMenuPrivate() : itemsDirty(0), maxIconWidth(0), tabWidth(0), ncols(0), collapsibleSeparators(true), activationRecursionGuard(false), hasHadMouse(0), aboutToHide(0), motions(0), - currentAction(0), scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0), + currentAction(0), +#ifdef QT_KEYPAD_NAVIGATION + selectAction(0), + cancelAction(0), +#endif + scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0), hasCheckableItems(0), sloppyAction(0), doChildEffects(false) #ifdef Q_WS_MAC ,mac_menu(0) @@ -193,6 +198,10 @@ public: uint aboutToHide : 1; int motions; QAction *currentAction; +#ifdef QT_KEYPAD_NAVIGATION + QAction *selectAction; + QAction *cancelAction; +#endif static QBasicTimer menuDelayTimer; enum SelectionReason { SelectedFromKeyboard, diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp index 00ceb98..6fc4371 100644 --- a/src/gui/widgets/qmenu_symbian.cpp +++ b/src/gui/widgets/qmenu_symbian.cpp @@ -103,22 +103,6 @@ static bool hasContextMenu(QWidget* widget) } return false; } -// ### FIX THIS, copy/paste of original (faulty) stripped text implementation. -// Implementation should be removed from QAction implementation to some generic place -static QString qt_strippedText_copy_from_qaction(QString s) -{ - s.remove(QString::fromLatin1("...")); - int i = 0; - while (i < s.size()) { - ++i; - if (s.at(i-1) != QLatin1Char('&')) - continue; - if (i < s.size() && s.at(i) == QLatin1Char('&')) - ++i; - s.remove(i-1,1); - } - return s.trimmed(); -}; static SymbianMenuItem* qt_symbian_find_menu(int id, const QList<SymbianMenuItem*> &parent) { @@ -161,11 +145,9 @@ static void qt_symbian_insert_action(QSymbianMenuAction* action, QList<SymbianMe if (action->action->isSeparator()) return; -// ### FIX THIS, the qt_strippedText2 doesn't work perfectly for stripping & marks. Same bug is in QAction -// New really working method is needed in a place where the implementation isn't copy/pasted - QString text = qt_strippedText_copy_from_qaction(action->action->text()); - TPtrC menuItemText(qt_QString2TPtrC(text)); - + const int underlineShortCut = QApplication::style()->styleHint(QStyle::SH_UnderlineShortcut); + QString iconText = action->action->iconText(); + TPtrC menuItemText = qt_QString2TPtrC( underlineShortCut ? action->action->text() : iconText); if (action->action->menu()) { SymbianMenuItem* menuItem = new SymbianMenuItem(); menuItem->menuItemData.iCascadeId = action->command; @@ -240,7 +222,7 @@ static void rebuildMenu() } #ifdef Q_WS_S60 -Q_GUI_EXPORT void qt_symbian_show_toplevel( CEikMenuPane* menuPane) +void qt_symbian_show_toplevel( CEikMenuPane* menuPane) { if (!menuExists()) return; @@ -249,7 +231,7 @@ Q_GUI_EXPORT void qt_symbian_show_toplevel( CEikMenuPane* menuPane) QT_TRAP_THROWING(menuPane->AddMenuItemL(symbianMenus.at(i)->menuItemData)); } -Q_GUI_EXPORT void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id) +void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id) { SymbianMenuItem* menu = qt_symbian_find_menu(id, symbianMenus); if (menu) { diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index 7b0f37e..13e7de4 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -1072,16 +1072,10 @@ void QMenuBar::paintEvent(QPaintEvent *e) */ void QMenuBar::setVisible(bool visible) { -#if defined(Q_WS_MAC) || defined(Q_OS_WINCE) +#if defined(Q_WS_MAC) || defined(Q_OS_WINCE) || defined(Q_WS_S60) if (isNativeMenuBar()) return; #endif -#ifdef Q_WS_S60 - Q_D(QMenuBar); - if(d->symbian_menubar) - return; -#endif - QWidget::setVisible(visible); } @@ -1278,10 +1272,12 @@ void QMenuBar::actionEvent(QActionEvent *e) { Q_D(QMenuBar); d->itemsDirty = true; -#if defined (Q_WS_MAC) || defined(Q_OS_WINCE) +#if defined (Q_WS_MAC) || defined(Q_OS_WINCE) || defined(Q_WS_S60) if (isNativeMenuBar()) { #ifdef Q_WS_MAC QMenuBarPrivate::QMacMenuBarPrivate *nativeMenuBar = d->mac_menubar; +#elif defined(Q_WS_S60) + QMenuBarPrivate::QSymbianMenuBarPrivate *nativeMenuBar = d->symbian_menubar; #else QMenuBarPrivate::QWceMenuBarPrivate *nativeMenuBar = d->wce_menubar; #endif @@ -1295,16 +1291,6 @@ void QMenuBar::actionEvent(QActionEvent *e) nativeMenuBar->syncAction(e->action()); } #endif -#ifdef Q_WS_S60 - if(d->symbian_menubar) { - if(e->type() == QEvent::ActionAdded) - d->symbian_menubar->addAction(e->action(), d->symbian_menubar->findAction(e->before())); - else if(e->type() == QEvent::ActionRemoved) - d->symbian_menubar->removeAction(e->action()); - else if(e->type() == QEvent::ActionChanged) - d->symbian_menubar->syncAction(e->action()); - } -#endif if(e->type() == QEvent::ActionAdded) { connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered())); diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp index fda063a..d519bfe 100644 --- a/src/gui/widgets/qplaintextedit.cpp +++ b/src/gui/widgets/qplaintextedit.cpp @@ -1639,6 +1639,15 @@ void QPlainTextEdit::keyPressEvent(QKeyEvent *e) return; } break; + case Qt::Key_Left: + case Qt::Key_Right: + if (QApplication::keypadNavigationEnabled() + && QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { + // Same as for Key_Up and Key_Down. + e->ignore(); + return; + } + break; case Qt::Key_Back: if (!e->isAutoRepeat()) { if (QApplication::keypadNavigationEnabled()) { diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp index e682364..9eb07ac 100644 --- a/src/gui/widgets/qspinbox.cpp +++ b/src/gui/widgets/qspinbox.cpp @@ -61,8 +61,6 @@ QT_BEGIN_NAMESPACE # define QSBDEBUG if (false) qDebug #endif -static bool isIntermediateValueHelper(qint64 num, qint64 minimum, qint64 maximum, qint64 *match = 0); - class QSpinBoxPrivate : public QAbstractSpinBoxPrivate { Q_DECLARE_PUBLIC(QSpinBox) @@ -74,7 +72,6 @@ public: virtual QString textFromValue(const QVariant &n) const; QVariant validateAndInterpret(QString &input, int &pos, QValidator::State &state) const; - bool isIntermediateValue(const QString &str) const; QChar thousand; inline void init() { @@ -90,7 +87,6 @@ class QDoubleSpinBoxPrivate : public QAbstractSpinBoxPrivate public: QDoubleSpinBoxPrivate(QWidget *parent = 0); void emitSignals(EmitPolicy ep, const QVariant &); - bool isIntermediateValue(const QString &str) const; virtual QVariant valueFromText(const QString &n) const; virtual QString textFromValue(const QVariant &n) const; @@ -991,51 +987,6 @@ QVariant QSpinBoxPrivate::valueFromText(const QString &text) const /*! - \internal - - Return true if str can become a number which is between minimum and - maximum or false if this is not possible. -*/ - -bool QSpinBoxPrivate::isIntermediateValue(const QString &str) const -{ - const int num = locale.toInt(str, 0, 10); - const int min = minimum.toInt(); - const int max = maximum.toInt(); - - int numDigits = 0; - int digits[10]; - int tmp = num; - if (tmp == 0) { - numDigits = 1; - digits[0] = 0; - } else { - tmp = num; - for (int i=0; tmp != 0; ++i) { - digits[numDigits++] = qAbs(tmp % 10); - tmp /= 10; - } - } - - int failures = 0; - for (int number=min; /*number<=max*/; ++number) { - tmp = number; - for (int i=0; tmp != 0;) { - if (digits[i] == qAbs(tmp % 10)) { - if (++i == numDigits) - return true; - } - tmp /= 10; - } - if (failures++ == 500000) //upper bound - return true; - if (number == max) // needed for INT_MAX - break; - } - return false; -} - -/*! \internal Multi purpose function that parses input, sets state to the appropriate state and returns the value it will be interpreted as. @@ -1089,9 +1040,8 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, state = QValidator::Invalid; QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; } else { - state = isIntermediateValue(copy) ? QValidator::Intermediate : QValidator::Invalid; - QSBDEBUG() << __FILE__ << __LINE__<< "state is set to " - << (state == QValidator::Intermediate ? "Intermediate" : "Acceptable"); + state = QValidator::Intermediate; + QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Intermediate"; } } } @@ -1151,105 +1101,6 @@ void QDoubleSpinBoxPrivate::emitSignals(EmitPolicy ep, const QVariant &old) } -bool QDoubleSpinBoxPrivate::isIntermediateValue(const QString &str) const -{ - QSBDEBUG() << "input is" << str << minimum << maximum; - qint64 dec = 1; - for (int i=0; i<decimals; ++i) - dec *= 10; - - const QLatin1Char dot('.'); - - // I know QString::number() uses CLocale so I use dot - const QString minstr = QString::number(minimum.toDouble(), 'f', decimals); - bool ok; - qint64 min_left = minstr.left(minstr.indexOf(dot)).toLongLong(&ok); - if (!ok) - return false; - qint64 min_right = minstr.mid(minstr.indexOf(dot) + 1).toLongLong(); - - const QString maxstr = QString::number(maximum.toDouble(), 'f', decimals); - qint64 max_left = maxstr.left(maxstr.indexOf(dot)).toLongLong(&ok); - if (!ok) - return true; - qint64 max_right = maxstr.mid(maxstr.indexOf(dot) + 1).toLongLong(); - - const int dotindex = str.indexOf(delimiter); - const bool negative = maximum.toDouble() < 0; - qint64 left = 0, right = 0; - bool doleft = true; - bool doright = true; - if (dotindex == -1) { - left = str.toLongLong(); - doright = false; - } else if (dotindex == 0 || (dotindex == 1 && str.at(0) == QLatin1Char('+'))) { - if (negative) { - QSBDEBUG() << __FILE__ << __LINE__ << "returns false"; - return false; - } - doleft = false; - right = str.mid(dotindex + 1).toLongLong(); - } else if (dotindex == 1 && str.at(0) == QLatin1Char('-')) { - if (!negative) { - QSBDEBUG() << __FILE__ << __LINE__ << "returns false"; - return false; - } - doleft = false; - right = str.mid(dotindex + 1).toLongLong(); - } else { - left = str.left(dotindex).toLongLong(); - if (dotindex == str.size() - 1) { - doright = false; - } else { - right = str.mid(dotindex + 1).toLongLong(); - } - } - if ((left >= 0 && max_left < 0 && !str.startsWith(QLatin1Char('-'))) || (left < 0 && min_left >= 0)) { - QSBDEBUG("returns false 0"); - return false; - } - - qint64 match = min_left; - if (doleft && !isIntermediateValueHelper(left, min_left, max_left, &match)) { - QSBDEBUG() << __FILE__ << __LINE__ << "returns false"; - return false; - } - if (doright) { - QSBDEBUG() << "match" << match << "min_left" << min_left << "max_left" << max_left; - if (!doleft) { - if (min_left == max_left) { - const bool ret = isIntermediateValueHelper(qAbs(left), - negative ? max_right : min_right, - negative ? min_right : max_right); - QSBDEBUG() << __FILE__ << __LINE__ << "returns" << ret; - return ret; - } else if (qAbs(max_left - min_left) == 1) { - const bool ret = isIntermediateValueHelper(qAbs(left), min_right, negative ? 0 : dec) - || isIntermediateValueHelper(qAbs(left), negative ? dec : 0, max_right); - QSBDEBUG() << __FILE__ << __LINE__ << "returns" << ret; - return ret; - } else { - const bool ret = isIntermediateValueHelper(qAbs(left), 0, dec); - QSBDEBUG() << __FILE__ << __LINE__ << "returns" << ret; - return ret; - } - } - if (match != min_left) { - min_right = negative ? dec : 0; - } - if (match != max_left) { - max_right = negative ? 0 : dec; - } - qint64 tmpl = negative ? max_right : min_right; - qint64 tmpr = negative ? min_right : max_right; - const bool ret = isIntermediateValueHelper(right, tmpl, tmpr); - QSBDEBUG() << __FILE__ << __LINE__ << "returns" << ret; - return ret; - } - QSBDEBUG() << __FILE__ << __LINE__ << "returns true"; - return true; -} - /*! \internal \reimp @@ -1415,9 +1266,8 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, state = QValidator::Invalid; QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; } else { - state = isIntermediateValue(copy) ? QValidator::Intermediate : QValidator::Invalid; - QSBDEBUG() << __FILE__ << __LINE__<< "state is set to " - << (state == QValidator::Intermediate ? "Intermediate" : "Acceptable"); + state = QValidator::Intermediate; + QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Intermediate"; } } } @@ -1475,62 +1325,6 @@ QString QDoubleSpinBoxPrivate::textFromValue(const QVariant &f) const Use minimum() instead. */ -/*! - \internal Returns whether \a str is a string which value cannot be - parsed but still might turn into something valid. -*/ - -static bool isIntermediateValueHelper(qint64 num, qint64 min, qint64 max, qint64 *match) -{ - QSBDEBUG() << num << min << max; - - if (num >= min && num <= max) { - if (match) - *match = num; - QSBDEBUG("returns true 0"); - return true; - } - qint64 tmp = num; - - int numDigits = 0; - int digits[10]; - if (tmp == 0) { - numDigits = 1; - digits[0] = 0; - } else { - tmp = qAbs(num); - for (int i=0; tmp > 0; ++i) { - digits[numDigits++] = tmp % 10; - tmp /= 10; - } - } - - int failures = 0; - qint64 number; - for (number=max; number>=min; --number) { - tmp = qAbs(number); - for (int i=0; tmp > 0;) { - if (digits[i] == (tmp % 10)) { - if (++i == numDigits) { - if (match) - *match = number; - QSBDEBUG("returns true 1"); - return true; - } - } - tmp /= 10; - } - if (failures++ == 500000) { //upper bound - if (match) - *match = num; - QSBDEBUG("returns true 2"); - return true; - } - } - QSBDEBUG("returns false"); - return false; -} - /*! \reimp */ bool QSpinBox::event(QEvent *event) { diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index 92e4eb4..6c9761c 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -1100,7 +1100,7 @@ QVariant QTabBar::tabData(int index) const } /*! - Returns the visual rectangle of the of the tab at position \a + Returns the visual rectangle of the tab at position \a index, or a null rectangle if \a index is out of range. */ QRect QTabBar::tabRect(int index) const diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp index a727b2b..40c0b02 100644 --- a/src/gui/widgets/qtoolbar.cpp +++ b/src/gui/widgets/qtoolbar.cpp @@ -307,6 +307,8 @@ bool QToolBarPrivate::mouseReleaseEvent(QMouseEvent*) return true; } else { #ifdef Q_WS_MAC + if (!macWindowDragging) + return false; macWindowDragging = false; macWindowDragPressPosition = QPoint(); return true; diff --git a/src/gui/widgets/qtoolbutton.cpp b/src/gui/widgets/qtoolbutton.cpp index 828cd77..91f366f 100644 --- a/src/gui/widgets/qtoolbutton.cpp +++ b/src/gui/widgets/qtoolbutton.cpp @@ -871,7 +871,9 @@ void QToolButtonPrivate::_q_buttonPressed() Q_Q(QToolButton); if (!hasMenu()) return; // no menu to show - if (delay > 0 && !popupTimer.isActive() && popupMode == QToolButton::DelayedPopup) + if (popupMode == QToolButton::MenuButtonPopup) + return; + else if (delay > 0 && !popupTimer.isActive() && popupMode == QToolButton::DelayedPopup) popupTimer.start(delay, q); else if (delay == 0 || popupMode == QToolButton::InstantPopup) q->showMenu(); diff --git a/src/gui/widgets/qwidgetanimator.cpp b/src/gui/widgets/qwidgetanimator.cpp index d4a61e3..f440961 100644 --- a/src/gui/widgets/qwidgetanimator.cpp +++ b/src/gui/widgets/qwidgetanimator.cpp @@ -60,7 +60,9 @@ void QWidgetAnimator::abort(QWidget *w) QPropertyAnimation *anim = *it; m_animation_map.erase(it); anim->stop(); +#ifndef QT_NO_MAINWINDOW m_mainWindowLayout->animationFinished(w); +#endif #else Q_UNUSED(w); //there is no animation to abort #endif //QT_NO_ANIMATION diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri index 4567902..6883dd8 100644 --- a/src/gui/widgets/widgets.pri +++ b/src/gui/widgets/widgets.pri @@ -81,8 +81,7 @@ HEADERS += \ widgets/qtoolbararealayout_p.h \ widgets/qplaintextedit.h \ widgets/qplaintextedit_p.h \ - widgets/qprintpreviewwidget.h \ - widgets/qactiontokeyeventmapper_p.h + widgets/qprintpreviewwidget.h SOURCES += \ widgets/qabstractbutton.cpp \ widgets/qabstractslider.cpp \ @@ -143,8 +142,7 @@ SOURCES += \ widgets/qwidgetanimator.cpp \ widgets/qtoolbararealayout.cpp \ widgets/qplaintextedit.cpp \ - widgets/qprintpreviewwidget.cpp \ - widgets/qactiontokeyeventmapper.cpp + widgets/qprintpreviewwidget.cpp !embedded:mac { HEADERS += widgets/qmacnativewidget_mac.h \ |