diff options
Diffstat (limited to 'src')
69 files changed, 1282 insertions, 722 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index fb7fa0c..a519f4a 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -280,9 +280,7 @@ public: WindowStaysOnTopHint = 0x00040000, // reserved for Qt3Support: // WMouseNoMask = 0x00080000, - WindowOkButtonHint = 0x00080000, // WDestructiveClose = 0x00100000, - WindowCancelButtonHint = 0x00100000, // WStaticContents = 0x00200000, // WGroupLeader = 0x00400000, // WShowModal = 0x00800000, @@ -291,7 +289,9 @@ public: WindowStaysOnBottomHint = 0x04000000, WindowCloseButtonHint = 0x08000000, MacWindowToolBarButtonHint = 0x10000000, - BypassGraphicsProxyWidget = 0x20000000 + BypassGraphicsProxyWidget = 0x20000000, + WindowOkButtonHint = 0x00080000, + WindowCancelButtonHint = 0x00100000 #ifdef QT3_SUPPORT , diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 880e95c..c4061f4 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -1059,11 +1059,20 @@ bool QEventDispatcherWin32::event(QEvent *e) QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e); WinTimerInfo *t = d->timerDict.value(zte->timerId()); if (t) { + t->inTimerEvent = true; + QTimerEvent te(zte->timerId()); QCoreApplication::sendEvent(t->obj, &te); - WinTimerInfo *tn = d->timerDict.value(zte->timerId()); - if (tn && t == tn) - QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId())); + + t = d->timerDict.value(zte->timerId()); + if (t) { + if (t->interval == 0 && t->inTimerEvent) { + // post the next zero timer event as long as the timer was not restarted + QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId())); + } + + t->inTimerEvent = false; + } } return true; } else if (e->type() == QEvent::Timer) { diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 9c637ac..375d672 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -579,7 +579,7 @@ const QString::Null QString::null = { }; '\\0' character for a null string (\e not a null pointer), and QString() compares equal to QString(""). We recommend that you always use the isEmpty() function and avoid isNull(). - + \section1 Argument Formats In member functions where an argument \e format can be specified @@ -1433,7 +1433,7 @@ QString &QString::append(QChar ch) truncated at the specified \a position. \snippet doc/src/snippets/qstring/main.cpp 37 - + \sa insert(), replace() */ QString &QString::remove(int pos, int len) @@ -1552,7 +1552,7 @@ QString &QString::replace(int pos, int len, const QChar *unicode, int size) return *this; if (pos + len > d->size) len = d->size - pos; - + uint index = pos; replace_helper(&index, 1, len, unicode, size); return *this; @@ -1561,15 +1561,13 @@ QString &QString::replace(int pos, int len, const QChar *unicode, int size) /*! \fn QString &QString::replace(int position, int n, QChar after) \overload replace() - + Replaces \a n characters beginning at index \a position with the character \a after and returns a reference to this string. */ QString &QString::replace(int pos, int len, QChar after) { - uint index = pos; - replace_helper(&index, 1, len, &after, 1); - return *this; + return replace(pos, len, &after, 1); } /*! @@ -1602,7 +1600,7 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar { if (blen == alen) { detach(); - for (int i = 0; i < nIndices; ++i) + for (int i = 0; i < nIndices; ++i) memcpy(d->data + indices[i], after, alen * sizeof(QChar)); } else if (alen < blen) { detach(); @@ -1633,7 +1631,7 @@ void QString::replace_helper(uint *indices, int nIndices, int blen, const QChar int newLen = d->size + adjust; int moveend = d->size; resize(newLen); - + while (nIndices) { --nIndices; int movestart = indices[nIndices] + blen; @@ -1685,7 +1683,7 @@ QString &QString::replace(const QChar *before, int blen, memcpy(copy, before, blen*sizeof(QChar)); b = copy; } - + QStringMatcher matcher(b, blen, cs); int index = 0; @@ -1712,7 +1710,7 @@ QString &QString::replace(const QChar *before, int blen, // index has to be adjusted in case we get back into the loop above. index += pos*(alen-blen); } - + if (a != after) ::free((QChar *)a); if (b != before) @@ -2250,7 +2248,7 @@ int QString::indexOf(const QLatin1String &str, int from, Qt::CaseSensitivity cs) QVarLengthArray<ushort> s(len); for (int i = 0; i < len; ++i) s[i] = str.latin1()[i]; - + return qFindString(unicode(), length(), from, (const QChar *)s.data(), len, cs); } @@ -2346,7 +2344,7 @@ static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *nee /* See indexOf() for explanations. */ - + const ushort *end = haystack; haystack += from; const int sl_minus_1 = sl-1; @@ -2408,7 +2406,7 @@ int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) c const int sl = str.d->size; if (sl == 1) return lastIndexOf(QChar(str.d->data[0]), from, cs); - + const int l = d->size; if (from < 0) from += l; @@ -2446,7 +2444,7 @@ int QString::lastIndexOf(const QLatin1String &str, int from, Qt::CaseSensitivity const int sl = qstrlen(str.latin1()); if (sl == 1) return lastIndexOf(QLatin1Char(str.latin1()[0]), from, cs); - + const int l = d->size; if (from < 0) from += l; @@ -5995,7 +5993,7 @@ QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersi } if (simple) return *this; - + QString s = *this; if (version != CURRENT_VERSION) { for (int i = 0; i < NumNormalizationCorrections; ++i) { @@ -6207,7 +6205,7 @@ static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int f /*! Returns a copy of this string with the lowest numbered place marker replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99. - + \a fieldWidth specifies the minimum amount of space that argument \a a shall occupy. If \a a requires less space than \a fieldWidth, it is padded to \a fieldWidth with character \a fillChar. A positive @@ -6819,7 +6817,7 @@ void QString::updateProperties() const Appends the given \a ch character onto the end of this string. */ -/*! +/*! \fn std::string QString::toStdString() const Returns a std::string object with the data contained in this diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 6bea03b..3fd52ee 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -98,6 +98,8 @@ struct QVectorTypedData T array[1]; }; +class QRegion; + template <typename T> class QVector { diff --git a/src/gui/accessible/qaccessible_mac.mm b/src/gui/accessible/qaccessible_mac.mm index b6412c2..68efb8f 100644 --- a/src/gui/accessible/qaccessible_mac.mm +++ b/src/gui/accessible/qaccessible_mac.mm @@ -72,55 +72,36 @@ typedef NSString * const QAXRoleType; #define QAXApplicationRole NSAccessibilityApplicationRole #define QAXButtonRole NSAccessibilityButtonRole #define QAXCancelAction NSAccessibilityCancelAction -#define QAXCancelAction NSAccessibilityCancelAction #define QAXCheckBoxRole NSAccessibilityCheckBoxRole #define QAXChildrenAttribute NSAccessibilityChildrenAttribute -#define QAXChildrenAttribute NSAccessibilityChildrenAttribute -#define QAXChildrenAttribute NSAccessibilityChildrenAttribute #define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute #define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute #define QAXColumnRole NSAccessibilityColumnRole #define QAXConfirmAction NSAccessibilityConfirmAction -#define QAXConfirmAction NSAccessibilityConfirmAction #define QAXContentsAttribute NSAccessibilityContentsAttribute -#define QAXContentsAttribute NSAccessibilityContentsAttribute -#define QAXDecrementAction NSAccessibilityDecrementAction #define QAXDecrementAction NSAccessibilityDecrementAction #define QAXDecrementArrowSubrole NSAccessibilityDecrementArrowSubrole #define QAXDecrementPageSubrole NSAccessibilityDecrementPageSubrole #define QAXDescriptionAttribute NSAccessibilityDescriptionAttribute -#define QAXDescriptionAttribute NSAccessibilityDescriptionAttribute -#define QAXDescriptionAttribute NSAccessibilityDescriptionAttribute -#define QAXDescriptionAttribute NSAccessibilityDescriptionAttribute -#define QAXEnabledAttribute NSAccessibilityEnabledAttribute #define QAXEnabledAttribute NSAccessibilityEnabledAttribute #define QAXExpandedAttribute NSAccessibilityExpandedAttribute #define QAXFocusedAttribute NSAccessibilityFocusedAttribute -#define QAXFocusedAttribute NSAccessibilityFocusedAttribute -#define QAXFocusedAttribute NSAccessibilityFocusedAttribute #define QAXFocusedUIElementChangedNotification NSAccessibilityFocusedUIElementChangedNotification #define QAXFocusedWindowChangedNotification NSAccessibilityFocusedWindowChangedNotification #define QAXGroupRole NSAccessibilityGroupRole #define QAXGrowAreaAttribute NSAccessibilityGrowAreaAttribute -#define QAXGrowAreaAttribute NSAccessibilityGrowAreaAttribute #define QAXGrowAreaRole NSAccessibilityGrowAreaRole #define QAXHelpAttribute NSAccessibilityHelpAttribute -#define QAXHelpAttribute NSAccessibilityHelpAttribute -#define QAXHelpAttribute NSAccessibilityHelpAttribute #define QAXHorizontalOrientationValue NSAccessibilityHorizontalOrientationValue #define QAXHorizontalScrollBarAttribute NSAccessibilityHorizontalScrollBarAttribute -#define QAXHorizontalScrollBarAttribute NSAccessibilityHorizontalScrollBarAttribute -#define QAXIncrementAction NSAccessibilityIncrementAction #define QAXIncrementAction NSAccessibilityIncrementAction #define QAXIncrementArrowSubrole NSAccessibilityIncrementArrowSubrole #define QAXIncrementPageSubrole NSAccessibilityIncrementPageSubrole #define QAXIncrementorRole NSAccessibilityIncrementorRole #define QAXLinkedUIElementsAttribute NSAccessibilityLinkedUIElementsAttribute -#define QAXLinkedUIElementsAttribute NSAccessibilityLinkedUIElementsAttribute #define QAXListRole NSAccessibilityListRole #define QAXMainAttribute NSAccessibilityMainAttribute #define QAXMaxValueAttribute NSAccessibilityMaxValueAttribute -#define QAXMaxValueAttribute NSAccessibilityMaxValueAttribute #define QAXMenuBarRole NSAccessibilityMenuBarRole #define QAXMenuButtonRole NSAccessibilityMenuButtonRole #define QAXMenuClosedNotification NSAccessibilityMenuClosedNotification @@ -128,151 +109,90 @@ typedef NSString * const QAXRoleType; #define QAXMenuOpenedNotification NSAccessibilityMenuOpenedNotification #define QAXMenuRole NSAccessibilityMenuRole #define QAXMinValueAttribute NSAccessibilityMinValueAttribute -#define QAXMinValueAttribute NSAccessibilityMinValueAttribute #define QAXMinimizeButtonAttribute NSAccessibilityMinimizeButtonAttribute -#define QAXMinimizeButtonAttribute NSAccessibilityMinimizeButtonAttribute -#define QAXMinimizedAttribute NSAccessibilityMinimizedAttribute #define QAXMinimizedAttribute NSAccessibilityMinimizedAttribute #define QAXNextContentsAttribute NSAccessibilityNextContentsAttribute -#define QAXNextContentsAttribute NSAccessibilityNextContentsAttribute -#define QAXOrientationAttribute NSAccessibilityOrientationAttribute -#define QAXOrientationAttribute NSAccessibilityOrientationAttribute #define QAXOrientationAttribute NSAccessibilityOrientationAttribute #define QAXParentAttribute NSAccessibilityParentAttribute #define QAXPickAction NSAccessibilityPickAction -#define QAXPickAction NSAccessibilityPickAction #define QAXPopUpButtonRole NSAccessibilityPopUpButtonRole #define QAXPositionAttribute NSAccessibilityPositionAttribute -#define QAXPositionAttribute NSAccessibilityPositionAttribute -#define QAXPressAction NSAccessibilityPressAction #define QAXPressAction NSAccessibilityPressAction #define QAXPreviousContentsAttribute NSAccessibilityPreviousContentsAttribute -#define QAXPreviousContentsAttribute NSAccessibilityPreviousContentsAttribute -#define QAXPreviousContentsAttribute NSAccessibilityPreviousContentsAttribute #define QAXProgressIndicatorRole NSAccessibilityProgressIndicatorRole #define QAXRadioButtonRole NSAccessibilityRadioButtonRole #define QAXRoleAttribute NSAccessibilityRoleAttribute -#define QAXRoleAttribute NSAccessibilityRoleAttribute #define QAXRoleDescriptionAttribute NSAccessibilityRoleDescriptionAttribute #define QAXRowRole NSAccessibilityRowRole #define QAXRowsAttribute NSAccessibilityRowsAttribute -#define QAXRowsAttribute NSAccessibilityRowsAttribute -#define QAXScrollAreaRole NSAccessibilityScrollAreaRole -#define QAXScrollAreaRole NSAccessibilityScrollAreaRole #define QAXScrollAreaRole NSAccessibilityScrollAreaRole #define QAXScrollBarRole NSAccessibilityScrollBarRole #define QAXSelectedAttribute NSAccessibilitySelectedAttribute #define QAXSelectedChildrenAttribute NSAccessibilitySelectedChildrenAttribute #define QAXSelectedRowsAttribute NSAccessibilitySelectedRowsAttribute -#define QAXSelectedRowsAttribute NSAccessibilitySelectedRowsAttribute -#define QAXSizeAttribute NSAccessibilitySizeAttribute #define QAXSizeAttribute NSAccessibilitySizeAttribute #define QAXSliderRole NSAccessibilitySliderRole #define QAXSplitGroupRole NSAccessibilitySplitGroupRole #define QAXSplitterRole NSAccessibilitySplitterRole -#define QAXSplitterRole NSAccessibilitySplitterRole -#define QAXSplitterRole NSAccessibilitySplitterRole -#define QAXSplittersAttribute NSAccessibilitySplittersAttribute #define QAXSplittersAttribute NSAccessibilitySplittersAttribute #define QAXStaticTextRole NSAccessibilityStaticTextRole -#define QAXStaticTextRole NSAccessibilityStaticTextRole -#define QAXSubroleAttribute NSAccessibilitySubroleAttribute #define QAXSubroleAttribute NSAccessibilitySubroleAttribute #define QAXSubroleAttribute NSAccessibilitySubroleAttribute #define QAXTabGroupRole NSAccessibilityTabGroupRole -#define QAXTabGroupRole NSAccessibilityTabGroupRole #define QAXTableRole NSAccessibilityTableRole #define QAXTabsAttribute NSAccessibilityTabsAttribute -#define QAXTabsAttribute NSAccessibilityTabsAttribute #define QAXTextFieldRole NSAccessibilityTextFieldRole -#define QAXTextFieldRole NSAccessibilityTextFieldRole -#define QAXTitleAttribute NSAccessibilityTitleAttribute -#define QAXTitleAttribute NSAccessibilityTitleAttribute #define QAXTitleAttribute NSAccessibilityTitleAttribute -#define QAXTitleAttribute NSAccessibilityTitleAttribute -#define QAXTitleUIElementAttribute NSAccessibilityTitleUIElementAttribute #define QAXTitleUIElementAttribute NSAccessibilityTitleUIElementAttribute #define QAXToolbarButtonAttribute NSAccessibilityToolbarButtonAttribute -#define QAXToolbarButtonAttribute NSAccessibilityToolbarButtonAttribute #define QAXToolbarRole NSAccessibilityToolbarRole #define QAXTopLevelUIElementAttribute NSAccessibilityTopLevelUIElementAttribute -#define QAXTopLevelUIElementAttribute NSAccessibilityTopLevelUIElementAttribute -#define QAXTopLevelUIElementAttribute NSAccessibilityTopLevelUIElementAttribute -#define QAXUnknownRole NSAccessibilityUnknownRole #define QAXUnknownRole NSAccessibilityUnknownRole #define QAXValueAttribute NSAccessibilityValueAttribute -#define QAXValueAttribute NSAccessibilityValueAttribute -#define QAXValueAttribute NSAccessibilityValueAttribute -#define QAXValueAttribute NSAccessibilityValueAttribute #define QAXValueChangedNotification NSAccessibilityValueChangedNotification #define QAXValueIndicatorRole NSAccessibilityValueIndicatorRole #define QAXVerticalOrientationValue NSAccessibilityVerticalOrientationValue #define QAXVerticalScrollBarAttribute NSAccessibilityVerticalScrollBarAttribute -#define QAXVerticalScrollBarAttribute NSAccessibilityVerticalScrollBarAttribute #define QAXVisibleRowsAttribute NSAccessibilityVisibleRowsAttribute -#define QAXVisibleRowsAttribute NSAccessibilityVisibleRowsAttribute -#define QAXWindowAttribute NSAccessibilityWindowAttribute -#define QAXWindowAttribute NSAccessibilityWindowAttribute #define QAXWindowAttribute NSAccessibilityWindowAttribute #define QAXWindowCreatedNotification NSAccessibilityWindowCreatedNotification #define QAXWindowMovedNotification NSAccessibilityWindowMovedNotification #define QAXWindowRole NSAccessibilityWindowRole #define QAXZoomButtonAttribute NSAccessibilityZoomButtonAttribute -#define QAXZoomButtonAttribute NSAccessibilityZoomButtonAttribute #else typedef CFStringRef const QAXRoleType; #define QAXApplicationRole kAXApplicationRole #define QAXButtonRole kAXButtonRole #define QAXCancelAction kAXCancelAction -#define QAXCancelAction kAXCancelAction #define QAXCheckBoxRole kAXCheckBoxRole #define QAXChildrenAttribute kAXChildrenAttribute -#define QAXChildrenAttribute kAXChildrenAttribute -#define QAXChildrenAttribute kAXChildrenAttribute -#define QAXCloseButtonAttribute kAXCloseButtonAttribute #define QAXCloseButtonAttribute kAXCloseButtonAttribute #define QAXColumnRole kAXColumnRole #define QAXConfirmAction kAXConfirmAction -#define QAXConfirmAction kAXConfirmAction #define QAXContentsAttribute kAXContentsAttribute -#define QAXContentsAttribute kAXContentsAttribute -#define QAXDecrementAction kAXDecrementAction #define QAXDecrementAction kAXDecrementAction #define QAXDecrementArrowSubrole kAXDecrementArrowSubrole #define QAXDecrementPageSubrole kAXDecrementPageSubrole #define QAXDescriptionAttribute kAXDescriptionAttribute -#define QAXDescriptionAttribute kAXDescriptionAttribute -#define QAXDescriptionAttribute kAXDescriptionAttribute -#define QAXDescriptionAttribute kAXDescriptionAttribute -#define QAXEnabledAttribute kAXEnabledAttribute #define QAXEnabledAttribute kAXEnabledAttribute #define QAXExpandedAttribute kAXExpandedAttribute #define QAXFocusedAttribute kAXFocusedAttribute -#define QAXFocusedAttribute kAXFocusedAttribute -#define QAXFocusedAttribute kAXFocusedAttribute #define QAXFocusedUIElementChangedNotification kAXFocusedUIElementChangedNotification #define QAXFocusedWindowChangedNotification kAXFocusedWindowChangedNotification #define QAXGroupRole kAXGroupRole #define QAXGrowAreaAttribute kAXGrowAreaAttribute -#define QAXGrowAreaAttribute kAXGrowAreaAttribute #define QAXGrowAreaRole kAXGrowAreaRole #define QAXHelpAttribute kAXHelpAttribute -#define QAXHelpAttribute kAXHelpAttribute -#define QAXHelpAttribute kAXHelpAttribute #define QAXHorizontalOrientationValue kAXHorizontalOrientationValue #define QAXHorizontalScrollBarAttribute kAXHorizontalScrollBarAttribute -#define QAXHorizontalScrollBarAttribute kAXHorizontalScrollBarAttribute -#define QAXIncrementAction kAXIncrementAction #define QAXIncrementAction kAXIncrementAction #define QAXIncrementArrowSubrole kAXIncrementArrowSubrole #define QAXIncrementPageSubrole kAXIncrementPageSubrole #define QAXIncrementorRole kAXIncrementorRole #define QAXLinkedUIElementsAttribute kAXLinkedUIElementsAttribute -#define QAXLinkedUIElementsAttribute kAXLinkedUIElementsAttribute #define QAXListRole kAXListRole #define QAXMainAttribute kAXMainAttribute #define QAXMaxValueAttribute kAXMaxValueAttribute -#define QAXMaxValueAttribute kAXMaxValueAttribute #define QAXMenuBarRole kAXMenuBarRole #define QAXMenuButtonRole kAXMenuButtonRole #define QAXMenuClosedNotification kAXMenuClosedNotification @@ -280,97 +200,55 @@ typedef CFStringRef const QAXRoleType; #define QAXMenuOpenedNotification kAXMenuOpenedNotification #define QAXMenuRole kAXMenuRole #define QAXMinValueAttribute kAXMinValueAttribute -#define QAXMinValueAttribute kAXMinValueAttribute #define QAXMinimizeButtonAttribute kAXMinimizeButtonAttribute -#define QAXMinimizeButtonAttribute kAXMinimizeButtonAttribute -#define QAXMinimizedAttribute kAXMinimizedAttribute #define QAXMinimizedAttribute kAXMinimizedAttribute #define QAXNextContentsAttribute kAXNextContentsAttribute -#define QAXNextContentsAttribute kAXNextContentsAttribute -#define QAXOrientationAttribute kAXOrientationAttribute -#define QAXOrientationAttribute kAXOrientationAttribute #define QAXOrientationAttribute kAXOrientationAttribute #define QAXParentAttribute kAXParentAttribute #define QAXPickAction kAXPickAction -#define QAXPickAction kAXPickAction #define QAXPopUpButtonRole kAXPopUpButtonRole #define QAXPositionAttribute kAXPositionAttribute -#define QAXPositionAttribute kAXPositionAttribute -#define QAXPressAction kAXPressAction #define QAXPressAction kAXPressAction #define QAXPreviousContentsAttribute kAXPreviousContentsAttribute -#define QAXPreviousContentsAttribute kAXPreviousContentsAttribute -#define QAXPreviousContentsAttribute kAXPreviousContentsAttribute #define QAXProgressIndicatorRole kAXProgressIndicatorRole #define QAXRadioButtonRole kAXRadioButtonRole #define QAXRoleAttribute kAXRoleAttribute -#define QAXRoleAttribute kAXRoleAttribute #define QAXRoleDescriptionAttribute kAXRoleDescriptionAttribute #define QAXRowRole kAXRowRole #define QAXRowsAttribute kAXRowsAttribute -#define QAXRowsAttribute kAXRowsAttribute -#define QAXScrollAreaRole kAXScrollAreaRole -#define QAXScrollAreaRole kAXScrollAreaRole #define QAXScrollAreaRole kAXScrollAreaRole #define QAXScrollBarRole kAXScrollBarRole #define QAXSelectedAttribute kAXSelectedAttribute #define QAXSelectedChildrenAttribute kAXSelectedChildrenAttribute #define QAXSelectedRowsAttribute kAXSelectedRowsAttribute -#define QAXSelectedRowsAttribute kAXSelectedRowsAttribute -#define QAXSizeAttribute kAXSizeAttribute #define QAXSizeAttribute kAXSizeAttribute #define QAXSliderRole kAXSliderRole #define QAXSplitGroupRole kAXSplitGroupRole #define QAXSplitterRole kAXSplitterRole -#define QAXSplitterRole kAXSplitterRole -#define QAXSplitterRole kAXSplitterRole -#define QAXSplittersAttribute kAXSplittersAttribute #define QAXSplittersAttribute kAXSplittersAttribute #define QAXStaticTextRole kAXStaticTextRole -#define QAXStaticTextRole kAXStaticTextRole -#define QAXSubroleAttribute kAXSubroleAttribute #define QAXSubroleAttribute kAXSubroleAttribute -#define QAXSubroleAttribute kAXSubroleAttribute -#define QAXTabGroupRole kAXTabGroupRole #define QAXTabGroupRole kAXTabGroupRole #define QAXTableRole kAXTableRole #define QAXTabsAttribute kAXTabsAttribute -#define QAXTabsAttribute kAXTabsAttribute -#define QAXTextFieldRole kAXTextFieldRole #define QAXTextFieldRole kAXTextFieldRole #define QAXTitleAttribute kAXTitleAttribute -#define QAXTitleAttribute kAXTitleAttribute -#define QAXTitleAttribute kAXTitleAttribute -#define QAXTitleAttribute kAXTitleAttribute #define QAXTitleUIElementAttribute kAXTitleUIElementAttribute -#define QAXTitleUIElementAttribute kAXTitleUIElementAttribute -#define QAXToolbarButtonAttribute kAXToolbarButtonAttribute #define QAXToolbarButtonAttribute kAXToolbarButtonAttribute #define QAXToolbarRole kAXToolbarRole #define QAXTopLevelUIElementAttribute kAXTopLevelUIElementAttribute -#define QAXTopLevelUIElementAttribute kAXTopLevelUIElementAttribute -#define QAXTopLevelUIElementAttribute kAXTopLevelUIElementAttribute #define QAXUnknownRole kAXUnknownRole -#define QAXUnknownRole kAXUnknownRole -#define QAXValueAttribute kAXValueAttribute -#define QAXValueAttribute kAXValueAttribute -#define QAXValueAttribute kAXValueAttribute #define QAXValueAttribute kAXValueAttribute #define QAXValueChangedNotification kAXValueChangedNotification #define QAXValueIndicatorRole kAXValueIndicatorRole #define QAXVerticalOrientationValue kAXVerticalOrientationValue #define QAXVerticalScrollBarAttribute kAXVerticalScrollBarAttribute -#define QAXVerticalScrollBarAttribute kAXVerticalScrollBarAttribute -#define QAXVisibleRowsAttribute kAXVisibleRowsAttribute #define QAXVisibleRowsAttribute kAXVisibleRowsAttribute #define QAXWindowAttribute kAXWindowAttribute -#define QAXWindowAttribute kAXWindowAttribute -#define QAXWindowAttribute kAXWindowAttribute #define QAXWindowCreatedNotification kAXWindowCreatedNotification #define QAXWindowMovedNotification kAXWindowMovedNotification #define QAXWindowRole kAXWindowRole #define QAXZoomButtonAttribute kAXZoomButtonAttribute -#define QAXZoomButtonAttribute kAXZoomButtonAttribute #endif diff --git a/src/gui/accessible/qaccessiblewidget.cpp b/src/gui/accessible/qaccessiblewidget.cpp index 4b2b2ab..753ac57 100644 --- a/src/gui/accessible/qaccessiblewidget.cpp +++ b/src/gui/accessible/qaccessiblewidget.cpp @@ -131,9 +131,16 @@ QString Q_GUI_EXPORT qt_accHotKey(const QString &text) int fa = 0; QChar ac; while ((fa = text.indexOf(QLatin1Char('&'), fa)) != -1) { - if (fa == text.length() - 1 || text.at(fa+1) != QLatin1Char('&')) { - ac = text.at(fa+1); - break; + ++fa; + if (fa < text.length()) { + // ignore "&&" + if (text.at(fa) == QLatin1Char('&')) { + ++fa; + continue; + } else { + ac = text.at(fa); + break; + } } } if (ac.isNull()) diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm index 4c13d01..90af9fc 100644 --- a/src/gui/dialogs/qfiledialog_mac.mm +++ b/src/gui/dialogs/qfiledialog_mac.mm @@ -278,7 +278,7 @@ QT_USE_NAMESPACE { Q_UNUSED(sender); QString qtFileName = QT_PREPEND_NAMESPACE(qt_mac_NSStringToQString)(filename); - QFileInfo info(qtFileName); + QFileInfo info(qtFileName.normalized(QT_PREPEND_NAMESPACE(QString::NormalizationForm_C))); QString path = info.absolutePath(); if (path != *mLastFilterCheckPath){ *mLastFilterCheckPath = path; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index e7f9bd3..70f5537 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -4350,9 +4350,9 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect */ QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const { - if (!d_ptr->hasTransform) - return QPolygonF(rect.translated(d_ptr->pos)); - return transform().map(rect.translated(d_ptr->pos)); + QPolygonF p = !d_ptr->hasTransform ? rect : transform().map(rect); + p.translate(d_ptr->pos); + return p; } /*! @@ -4419,8 +4419,8 @@ QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, const QRectF &rec */ QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const { - QRectF r = rect.translated(d_ptr->pos.x(), d_ptr->pos.y()); - return !d_ptr->hasTransform ? r : transform().mapRect(r); + QRectF r = !d_ptr->hasTransform ? rect : transform().mapRect(rect); + return r.translated(d_ptr->pos); } /*! @@ -4551,9 +4551,9 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &p */ QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const { - QPolygonF p = polygon; + QPolygonF p = !d_ptr->hasTransform ? polygon : transform().map(polygon); p.translate(d_ptr->pos); - return d_ptr->hasTransform ? transform().map(p) : p; + return p; } /*! @@ -5826,12 +5826,11 @@ void QGraphicsItem::removeFromIndex() */ void QGraphicsItem::prepareGeometryChange() { - if (!d_ptr->scene) - return; - - d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); - QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); - scenePrivate->removeFromIndex(this); + if (d_ptr->scene) { + d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); + QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); + scenePrivate->removeFromIndex(this); + } if (d_ptr->inSetPosHelper) return; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index bd66c3d..c616e91 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -766,6 +766,15 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) unpolishedItems.removeAll(item); dirtyItems.removeAll(item); + //We remove all references of item from the sceneEventFilter arrays + QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin(); + while (iterator != sceneEventFilters.end()) { + if (iterator.value() == item || iterator.key() == item) + iterator = sceneEventFilters.erase(iterator); + else + ++iterator; + } + // Remove from scene transform cache int transformIndex = item->d_func()->sceneTransformIndex; if (transformIndex != -1) { @@ -3332,6 +3341,16 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) d->unpolishedItems.removeAll(item); d->dirtyItems.removeAll(item); + //We remove all references of item from the sceneEventFilter arrays + QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = d->sceneEventFilters.begin(); + while (iterator != d->sceneEventFilters.end()) { + if (iterator.value() == item || iterator.key() == item) + iterator = d->sceneEventFilters.erase(iterator); + else + ++iterator; + } + + //Ensure dirty flag have the correct default value so the next time it will be added it will receive updates item->d_func()->dirty = 0; item->d_func()->dirtyChildren = 0; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 797c895..bffbf4d 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3647,30 +3647,30 @@ void QGraphicsView::scrollContentsBy(int dx, int dy) if (isRightToLeft()) dx = -dx; - if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate - && d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) { - for (int i = 0; i < d->dirtyRects.size(); ++i) - d->dirtyRects[i].translate(dx, dy); - for (int i = 0; i < d->dirtyRegions.size(); ++i) - d->dirtyRegions[i].translate(dx, dy); - } - + if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) { + if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) { + for (int i = 0; i < d->dirtyRects.size(); ++i) + d->dirtyRects[i].translate(dx, dy); + for (int i = 0; i < d->dirtyRegions.size(); ++i) + d->dirtyRegions[i].translate(dx, dy); + if (d->accelerateScrolling) { #ifndef QT_NO_RUBBERBAND - // Update old rubberband - if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate && !d->rubberBandRect.isEmpty()) { - if (d->viewportUpdateMode != FullViewportUpdate) - viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect)); - else - viewport()->update(); - } + // Update new and old rubberband regions + if (!d->rubberBandRect.isEmpty()) { + QRegion rubberBandRegion(d->rubberBandRegion(viewport(), d->rubberBandRect)); + rubberBandRegion += rubberBandRegion.translated(-dx, -dy); + viewport()->update(rubberBandRegion); + } #endif - - if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate){ - if (d->accelerateScrolling && d->viewportUpdateMode != FullViewportUpdate) - viewport()->scroll(dx, dy); - else + viewport()->scroll(dx, dy); + } else { + viewport()->update(); + } + } else { viewport()->update(); + } } + d->updateLastCenterPoint(); if ((d->cacheMode & CacheBackground) diff --git a/src/gui/inputmethod/qwininputcontext_win.cpp b/src/gui/inputmethod/qwininputcontext_win.cpp index 663184f..0ba4cd4 100644 --- a/src/gui/inputmethod/qwininputcontext_win.cpp +++ b/src/gui/inputmethod/qwininputcontext_win.cpp @@ -57,15 +57,17 @@ #ifdef Q_IME_DEBUG #include "qdebug.h" -#endif - -QT_BEGIN_NAMESPACE +#endif -extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); #if defined(Q_OS_WINCE) extern void qt_wince_show_SIP(bool show); // defined in qguifunctions_wince.cpp #endif +QT_BEGIN_NAMESPACE + +extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); + + DEFINE_GUID(IID_IActiveIMMApp, 0x08c0e040, 0x62d1, 0x11d1, 0x93, 0x26, 0x0, 0x60, 0xb0, 0x67, 0xb8, 0x6e); diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 09ea444..b1aac37 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -1400,6 +1400,9 @@ bool QAbstractItemView::event(QEvent *event) case QEvent::FocusOut: d->checkPersistentEditorFocus(); break; + case QEvent::FontChange: + d->doDelayedItemsLayout(); // the size of the items will change + break; default: break; } diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index 10bcb9a..b0137d2 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -274,6 +274,9 @@ IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping( Mapping *m = new Mapping; + if (model->canFetchMore(source_parent)) + model->fetchMore(source_parent); + int source_rows = model->rowCount(source_parent); for (int i = 0; i < source_rows; ++i) { if (q->filterAcceptsRow(i, source_parent)) diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 6dddfab..61f1b5b 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -2019,6 +2019,7 @@ int QTreeView::verticalOffset() const // If we are scrolling per item and have non-uniform row heights, // finding the vertical offset in pixels is going to be relatively slow. // ### find a faster way to do this + d->executePostedLayout(); int offset = 0; for (int i = 0; i < d->viewItems.count(); ++i) { if (i == verticalScrollBar()->value()) diff --git a/src/gui/kernel/qcocoaapplication_mac.mm b/src/gui/kernel/qcocoaapplication_mac.mm index f95f004f..a3cc2c1 100644 --- a/src/gui/kernel/qcocoaapplication_mac.mm +++ b/src/gui/kernel/qcocoaapplication_mac.mm @@ -1,11 +1,11 @@ /**************************************************************************** - ** - ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) - ** - ** This file is part of the QtGui module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ +** +** 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 @@ -36,11 +36,11 @@ ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ - ** - ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - ** - ****************************************************************************/ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ /**************************************************************************** ** diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm index e6bd511..6571068 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm @@ -1,11 +1,11 @@ /**************************************************************************** - ** - ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) - ** - ** This file is part of the QtGui module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ +** +** 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 @@ -36,11 +36,11 @@ ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ - ** - ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - ** - ****************************************************************************/ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ /**************************************************************************** ** diff --git a/src/gui/kernel/qcocoamenuloader_mac.mm b/src/gui/kernel/qcocoamenuloader_mac.mm index 7ecb765..e836286 100644 --- a/src/gui/kernel/qcocoamenuloader_mac.mm +++ b/src/gui/kernel/qcocoamenuloader_mac.mm @@ -1,11 +1,11 @@ /**************************************************************************** - ** - ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) - ** - ** This file is part of the QtGui module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ +** +** 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 @@ -36,11 +36,11 @@ ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ - ** - ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - ** - ****************************************************************************/ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ #include "qmacdefines_mac.h" #ifdef QT_MAC_USE_COCOA diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm index c17b30c..95e20af 100644 --- a/src/gui/kernel/qcocoapanel_mac.mm +++ b/src/gui/kernel/qcocoapanel_mac.mm @@ -157,10 +157,11 @@ QT_USE_NAMESPACE [self release]; } - - (BOOL)makeFirstResponder:(NSResponder *)responder { - if (responder == nil) + // For some reason Cocoa wants to flip the first responder + // when Qt doesn't want to, sorry, but "No" :-) + if (responder == nil && qApp->focusWidget()) return NO; return [super makeFirstResponder:responder]; } diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 2d6f5ad..118d54c 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -181,6 +181,7 @@ QT_FORWARD_DECLARE_CLASS(QAbstractScrollAreaPrivate) QT_FORWARD_DECLARE_CLASS(QPaintEvent) QT_FORWARD_DECLARE_CLASS(QPainter) QT_FORWARD_DECLARE_CLASS(QHoverEvent) +QT_FORWARD_DECLARE_CLASS(QCursor) QT_USE_NAMESPACE extern "C" { extern NSString *NSTextInputReplacementRangeAttributeName; @@ -237,6 +238,34 @@ extern "C" { } } +- (void)resetCursorRects +{ + QWidget *cursorWidget = qwidget; + + if (cursorWidget->testAttribute(Qt::WA_TransparentForMouseEvents)) + cursorWidget = QApplication::widgetAt(qwidget->mapToGlobal(qwidget->rect().center())); + + if (cursorWidget == 0) + return; + + if (!cursorWidget->testAttribute(Qt::WA_SetCursor)) { + [super resetCursorRects]; + return; + } + + QRegion mask = qt_widget_private(cursorWidget)->extra->mask; + NSCursor *nscursor = static_cast<NSCursor *>(nsCursorForQCursor(cursorWidget->cursor())); + if (mask.isEmpty()) { + [self addCursorRect:[qt_mac_nativeview_for(cursorWidget) visibleRect] cursor:nscursor]; + } else { + const QVector<QRect> &rects = mask.rects(); + for (int i = 0; i < rects.size(); ++i) { + const QRect &rect = rects.at(i); + [self addCursorRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()) cursor:nscursor]; + } + } +} + - (void)removeDropData { if (dropData) { @@ -301,11 +330,13 @@ extern "C" { NSPoint windowPoint = [sender draggingLocation]; NSPoint globalPoint = [[sender draggingDestinationWindow] convertBaseToScreen:windowPoint]; NSPoint localPoint = [self convertPoint:windowPoint fromView:nil]; + NSDragOperation nsActions = [sender draggingSourceOperationMask]; QPoint posDrag(localPoint.x, localPoint.y); - if (qt_mac_mouse_inside_answer_rect(posDrag)) + if (qt_mac_mouse_inside_answer_rect(posDrag) + && QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) == nsActions) return QT_PREPEND_NAMESPACE(qt_mac_mapDropActions)(QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastAction)); // send drag move event to the widget - NSDragOperation nsActions = [sender draggingSourceOperationMask]; + QT_PREPEND_NAMESPACE(qt_mac_dnd_answer_rec.lastOperation) = nsActions; Qt::DropActions qtAllowed = QT_PREPEND_NAMESPACE(qt_mac_mapNSDragOperations)(nsActions); QMimeData *mimeData = dropData; if (QDragManager::self()->source()) diff --git a/src/gui/kernel/qcocoawindow_mac.mm b/src/gui/kernel/qcocoawindow_mac.mm index ba121cd..972e477 100644 --- a/src/gui/kernel/qcocoawindow_mac.mm +++ b/src/gui/kernel/qcocoawindow_mac.mm @@ -1,11 +1,11 @@ /**************************************************************************** - ** - ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) - ** - ** This file is part of the QtGui module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ +** +** 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 @@ -36,11 +36,11 @@ ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ - ** - ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - ** - ****************************************************************************/ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ #include "qmacdefines_mac.h" #ifdef QT_MAC_USE_COCOA @@ -182,7 +182,9 @@ extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview. - (BOOL)makeFirstResponder:(NSResponder *)responder { - if (responder == nil) + // For some reason Cocoa wants to flip the first responder + // when Qt doesn't want to, sorry, but "No" :-) + if (responder == nil && qApp->focusWidget()) return NO; return [super makeFirstResponder:responder]; } diff --git a/src/gui/kernel/qcocoawindowdelegate_mac.mm b/src/gui/kernel/qcocoawindowdelegate_mac.mm index 8480179..03b2fce 100644 --- a/src/gui/kernel/qcocoawindowdelegate_mac.mm +++ b/src/gui/kernel/qcocoawindowdelegate_mac.mm @@ -1,11 +1,11 @@ /**************************************************************************** - ** - ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) - ** - ** This file is part of the QtGui module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ +** +** 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 @@ -36,11 +36,11 @@ ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ - ** - ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - ** - ****************************************************************************/ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ #import "private/qcocoawindowdelegate_mac_p.h" #ifdef QT_MAC_USE_COCOA diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h index 15b4597..ad1860d 100644 --- a/src/gui/kernel/qcursor.h +++ b/src/gui/kernel/qcursor.h @@ -77,6 +77,7 @@ class QBitmap; class QPixmap; #if defined(Q_WS_MAC) +void *nsCursorForQCursor(const QCursor &c); void qt_mac_set_cursor(const QCursor *c, const QPoint &p); #endif @@ -128,6 +129,7 @@ public: private: QCursorData *d; #if defined(Q_WS_MAC) + friend void *nsCursorForQCursor(const QCursor &c); friend void qt_mac_set_cursor(const QCursor *c, const QPoint &p); #endif }; diff --git a/src/gui/kernel/qcursor_mac.mm b/src/gui/kernel/qcursor_mac.mm index d632eb79..ae98f2e 100644 --- a/src/gui/kernel/qcursor_mac.mm +++ b/src/gui/kernel/qcursor_mac.mm @@ -95,9 +95,19 @@ protected: } }; +void *nsCursorForQCursor(const QCursor &c) +{ + c.d->update(); + return [[static_cast<NSCursor *>(c.d->curs.cp.nscursor) retain] autorelease]; +} + static QCursorData *currentCursor = 0; //current cursor void qt_mac_set_cursor(const QCursor *c, const QPoint &) { +#ifdef QT_MAC_USE_COCOA + Q_UNUSED(c); + return; +#else if (!c) { currentCursor = 0; return; @@ -128,10 +138,15 @@ void qt_mac_set_cursor(const QCursor *c, const QPoint &) } } currentCursor = c->d; +#endif } void qt_mac_update_cursor_at_global_pos(const QPoint &globalPos) { +#ifdef QT_MAC_USE_COCOA + Q_UNUSED(globalPos); + return; +#else QCursor cursor(Qt::ArrowCursor); if (QApplication::overrideCursor()) { cursor = *QApplication::overrideCursor(); @@ -144,6 +159,7 @@ void qt_mac_update_cursor_at_global_pos(const QPoint &globalPos) } } qt_mac_set_cursor(&cursor, globalPos); +#endif } void qt_mac_update_cursor() diff --git a/src/gui/kernel/qmacdefines_mac.h b/src/gui/kernel/qmacdefines_mac.h index 97ec544..035b8c5 100644 --- a/src/gui/kernel/qmacdefines_mac.h +++ b/src/gui/kernel/qmacdefines_mac.h @@ -105,7 +105,7 @@ Yes, it is an informative comment ;-) # undef qDebug #endif -#if __LP64__ +#ifdef __LP64__ typedef signed int OSStatus; #else typedef signed long OSStatus; diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h index e65492d..ca995dc 100644 --- a/src/gui/kernel/qt_mac_p.h +++ b/src/gui/kernel/qt_mac_p.h @@ -250,11 +250,13 @@ struct QMacDndAnswerRecord { Qt::KeyboardModifiers modifiers; Qt::MouseButtons buttons; Qt::DropAction lastAction; + unsigned int lastOperation; void clear() { rect = QRect(); modifiers = Qt::NoModifier; buttons = Qt::NoButton; lastAction = Qt::IgnoreAction; + lastOperation = 0; } }; extern QMacDndAnswerRecord qt_mac_dnd_answer_rec; diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 9eac321..5d91c74 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -2166,7 +2166,10 @@ void QWidgetPrivate::finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ voidWin if ((popup || type == Qt::Tool || type == Qt::ToolTip) && !q->isModal()) { [windowRef setHidesOnDeactivate:YES]; [windowRef setHasShadow:YES]; + } else { + [windowRef setHidesOnDeactivate:NO]; } + Q_UNUSED(parentWidget); Q_UNUSED(dialog); @@ -2838,12 +2841,26 @@ void QWidgetPrivate::updateSystemBackground() void QWidgetPrivate::setCursor_sys(const QCursor &) { + Q_Q(QWidget); +#ifndef QT_MAC_USE_COCOA qt_mac_update_cursor(); +#else + if (q->testAttribute(Qt::WA_WState_Created)) { + [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)]; + } +#endif } void QWidgetPrivate::unsetCursor_sys() { + Q_Q(QWidget); +#ifndef QT_MAC_USE_COCOA qt_mac_update_cursor(); +#else + if (q->testAttribute(Qt::WA_WState_Created)) { + [qt_mac_window_for(q) invalidateCursorRectsForView:qt_mac_nativeview_for(q)]; + } +#endif } void QWidgetPrivate::setWindowTitle_sys(const QString &caption) diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp index d931f55..39ce59f 100644 --- a/src/gui/painting/qpaintengine_x11.cpp +++ b/src/gui/painting/qpaintengine_x11.cpp @@ -1760,7 +1760,10 @@ void QX11PaintEngine::drawPath(const QPainterPath &path) QRectF deviceRect(0, 0, d->pdev->width(), d->pdev->height()); // necessary to get aliased alphablended primitives to be drawn correctly if (d->cpen.isCosmetic() || d->has_scaling_xform) { - stroker.setWidth(width == 0 ? 1 : width * d->xform_scale); + if (d->cpen.isCosmetic()) + stroker.setWidth(width == 0 ? 1 : width); + else + stroker.setWidth(width * d->xform_scale); stroker.d_ptr->stroker.setClipRect(deviceRect); stroke = stroker.createStroke(path * d->matrix); if (stroke.isEmpty()) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 133520e..82c22c2 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1465,8 +1465,8 @@ bool QPainter::isActive() const /*! Initializes the painters pen, background and font to the same as - the given \a widget. Call this function after begin() while the - painter is active. + the given \a widget. This function is called automatically when the + painter is opened on a QWidget. \sa begin(), {QPainter#Settings}{Settings} */ diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp index 6c309c7..4f3e71c 100644 --- a/src/gui/painting/qprinter.cpp +++ b/src/gui/painting/qprinter.cpp @@ -284,6 +284,10 @@ void QPrinterPrivate::addToManualSetList(QPrintEngine::PrintEnginePropertyKey ke to send PostScript or PDF output to the printer. As an alternative, the printProgram() function can be used to specify the command or utility to use instead of the system default. + + Note that setting parameters like paper size and resolution on an + invalid printer is undefined. You can use QPrinter::isValid() to + verify this before changing any parameters. QPrinter supports a number of parameters, most of which can be changed by the end user through a \l{QPrintDialog}{print dialog}. In diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index dfcca63..d06107f 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1784,13 +1784,12 @@ QRect QTransform::mapRect(const QRect &rect) const return QRect(x, y, w, h); } else if (t < TxProject) { // see mapToPolygon for explanations of the algorithm. - qreal x0 = 0, y0 = 0; - qreal x, y; - MAP(rect.left(), rect.top(), x0, y0); - qreal xmin = x0; - qreal ymin = y0; - qreal xmax = x0; - qreal ymax = y0; + qreal x = 0, y = 0; + MAP(rect.left(), rect.top(), x, y); + qreal xmin = x; + qreal ymin = y; + qreal xmax = x; + qreal ymax = y; MAP(rect.right() + 1, rect.top(), x, y); xmin = qMin(xmin, x); ymin = qMin(ymin, y); @@ -1854,13 +1853,12 @@ QRectF QTransform::mapRect(const QRectF &rect) const } return QRectF(x, y, w, h); } else if (t < TxProject) { - qreal x0 = 0, y0 = 0; - qreal x, y; - MAP(rect.x(), rect.y(), x0, y0); - qreal xmin = x0; - qreal ymin = y0; - qreal xmax = x0; - qreal ymax = y0; + qreal x = 0, y = 0; + MAP(rect.x(), rect.y(), x, y); + qreal xmin = x; + qreal ymin = y; + qreal xmax = x; + qreal ymax = y; MAP(rect.x() + rect.width(), rect.y(), x, y); xmin = qMin(xmin, x); ymin = qMin(ymin, y); diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index b569b5c..519fed7 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -2507,6 +2507,10 @@ void QGtkStyle::drawControl(ControlElement element, if (selected) { QRect rect = option->rect.adjusted(0, 0, -1, -1); +#ifndef QT_NO_COMBOBOX + if (qobject_cast<const QComboBox*>(widget)) + rect = option->rect; +#endif gtkPainter.paintBox( gtkMenuItem, "menuitem", rect, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, style); } diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp index c52c700..1c03b9e 100644 --- a/src/gui/styles/qwindowsmobilestyle.cpp +++ b/src/gui/styles/qwindowsmobilestyle.cpp @@ -3401,6 +3401,9 @@ int QWindowsMobileStyle::styleHint(StyleHint hint, const QStyleOption *opt, cons case SH_ScrollBar_ContextMenu: ret = false; break; + case SH_MenuBar_AltKeyNavigation: + ret = false; + break; default: ret = QWindowsStyle::styleHint(hint, opt, widget, returnData); break; diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index b14b8b3..013ca1e 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -2396,6 +2396,9 @@ void QWindowsVistaStyle::polish(QWidget *widget) else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) { tree->viewport()->setAttribute(Qt::WA_Hover); } + else if (QListView *list = qobject_cast<QListView *> (widget)) { + list->viewport()->setAttribute(Qt::WA_Hover); + } } /*! diff --git a/src/gui/styles/qwindowsvistastyle_p.h b/src/gui/styles/qwindowsvistastyle_p.h index 877bc50..cef2b71 100644 --- a/src/gui/styles/qwindowsvistastyle_p.h +++ b/src/gui/styles/qwindowsvistastyle_p.h @@ -76,6 +76,7 @@ #include <qscrollbar.h> #include <qprogressbar.h> #include <qdockwidget.h> +#include <qlistview.h> #include <qtreeview.h> #include <qtextedit.h> #include <qmessagebox.h> diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 50cd13f..639eff0 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -608,7 +608,7 @@ void QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData) QPainter *painter = themeData.painter; Q_ASSERT_X(painter != 0, "QWindowsXPStylePrivate::drawBackground()", "Trying to draw a theme part without a painter"); - if (!painter) + if (!painter || !painter->isActive()) return; painter->save(); @@ -2835,7 +2835,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo bflags |= State_MouseOver; } } - + QStyleOption tool(0); tool.palette = toolbutton->palette; if (toolbutton->subControls & SC_ToolButton) { diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp index c25253a..f2a9ceb 100644 --- a/src/gui/widgets/qabstractbutton.cpp +++ b/src/gui/widgets/qabstractbutton.cpp @@ -1250,15 +1250,6 @@ void QAbstractButton::timerEvent(QTimerEvent *e) } } -#if defined(Q_OS_WINCE) && !defined(QT_NO_CONTEXTMENU) -/*! \reimp */ -void QAbstractButton::contextMenuEvent(QContextMenuEvent *e) -{ - e->ignore(); - setDown(false); -} -#endif - /*! \reimp */ void QAbstractButton::focusInEvent(QFocusEvent *e) { diff --git a/src/gui/widgets/qabstractbutton.h b/src/gui/widgets/qabstractbutton.h index 6503a56..f0cbb05 100644 --- a/src/gui/widgets/qabstractbutton.h +++ b/src/gui/widgets/qabstractbutton.h @@ -143,9 +143,6 @@ protected: void focusOutEvent(QFocusEvent *e); void changeEvent(QEvent *e); void timerEvent(QTimerEvent *e); -#ifdef Q_OS_WINCE - void contextMenuEvent(QContextMenuEvent *e); -#endif #ifdef QT3_SUPPORT public: diff --git a/src/gui/widgets/qcocoamenu_mac.mm b/src/gui/widgets/qcocoamenu_mac.mm index c92dfc0..c5fee66 100644 --- a/src/gui/widgets/qcocoamenu_mac.mm +++ b/src/gui/widgets/qcocoamenu_mac.mm @@ -1,11 +1,11 @@ /**************************************************************************** - ** - ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) - ** - ** This file is part of the QtGui module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ +** +** 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 @@ -36,11 +36,11 @@ ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ - ** - ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - ** - ****************************************************************************/ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ #include "qmacdefines_mac.h" #include "qapplication.h" @@ -134,8 +134,9 @@ QT_END_NAMESPACE // If it does, then we will first send the key sequence to the QWidget that has focus // since (in Qt's eyes) it needs to a chance at the key event first. If the widget // accepts the key event, we then return YES, but set the target and action to be nil, - // which means that the action should not be triggered. In every other case we return - // NO, which means that Cocoa can do as it pleases (i.e., fire the menu action). + // which means that the action should not be triggered, and instead dispatch the event ourselves. + // In every other case we return NO, which means that Cocoa can do as it pleases + // (i.e., fire the menu action). NSMenuItem *whichItem; if ([self hasShortcut:menu forKey:[event characters] @@ -158,9 +159,11 @@ QT_END_NAMESPACE accel_ev.ignore(); qt_sendSpontaneousEvent(widget, &accel_ev); if (accel_ev.isAccepted()) { - *target = nil; - *action = nil; - return YES; + if (qt_dispatchKeyEvent(event, widget)) { + *target = nil; + *action = nil; + return YES; + } } } } diff --git a/src/gui/widgets/qmaccocoaviewcontainer_mac.mm b/src/gui/widgets/qmaccocoaviewcontainer_mac.mm index 710af6a..380e983 100644 --- a/src/gui/widgets/qmaccocoaviewcontainer_mac.mm +++ b/src/gui/widgets/qmaccocoaviewcontainer_mac.mm @@ -1,11 +1,11 @@ /**************************************************************************** - ** - ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) - ** - ** This file is part of the QtGui module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ +** +** 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 @@ -36,11 +36,11 @@ ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ - ** - ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - ** - ****************************************************************************/ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ #import <Cocoa/Cocoa.h> #include <private/qwidget_p.h> diff --git a/src/gui/widgets/qmacnativewidget_mac.mm b/src/gui/widgets/qmacnativewidget_mac.mm index 1bc0430..0f4edf9 100644 --- a/src/gui/widgets/qmacnativewidget_mac.mm +++ b/src/gui/widgets/qmacnativewidget_mac.mm @@ -1,11 +1,11 @@ /**************************************************************************** - ** - ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) - ** - ** This file is part of the QtGui module of the Qt Toolkit. - ** - ** $QT_BEGIN_LICENSE:LGPL$ +** +** 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 @@ -36,11 +36,11 @@ ** If you are unsure which license is appropriate for your use, please ** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ - ** - ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE - ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - ** - ****************************************************************************/ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ #import <Cocoa/Cocoa.h> #import <private/qcocoaview_mac_p.h> diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 46d6471..2abc9e8 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -481,7 +481,7 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar) oldMenuBar->deleteLater(); } #ifdef Q_OS_WINCE - if (menuBar->size().height() > 0) + if (menuBar && menuBar->size().height() > 0) #endif d->layout->setMenuBar(menuBar); } diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index 950f758..c807afb 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -1,3 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + #include <private/qmainwindowlayout_p.h> #include <qtoolbar.h> #include <private/qtoolbarlayout_p.h> diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp index 85d6ea2..1babb6d 100644 --- a/src/gui/widgets/qtoolbar.cpp +++ b/src/gui/widgets/qtoolbar.cpp @@ -1153,6 +1153,17 @@ bool QToolBar::event(QEvent *event) if (d->mouseMoveEvent(static_cast<QMouseEvent*>(event))) return true; break; +#ifdef Q_OS_WINCE + case QEvent::ContextMenu: + { + QContextMenuEvent* contextMenuEvent = static_cast<QContextMenuEvent*>(event); + QWidget* child = childAt(contextMenuEvent->pos()); + QAbstractButton* button = qobject_cast<QAbstractButton*>(child); + if (button) + button->setDown(false); + } + break; +#endif case QEvent::Leave: if (d->state != 0 && d->state->dragging) { #ifdef Q_OS_WIN diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 21f4116..c17c65c 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -66,12 +66,10 @@ static const unsigned char gz_magic[2] = {0x1f, 0x8b}; // gzip magic header #define CHUNK 16384 #endif -#ifndef QT_NO_OPENSSL -# include <QtNetwork/qsslsocket.h> -# include <QtNetwork/qsslerror.h> -#else -# include <QtNetwork/qtcpsocket.h> -#endif +#include <QtNetwork/qtcpsocket.h> +// it's safe to include these even if SSL support is not enabled +#include <QtNetwork/qsslsocket.h> +#include <QtNetwork/qsslerror.h> #include <QtNetwork/qnetworkrequest.h> #include <QtNetwork/qnetworkreply.h> diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp index e472b9d..14a04f1 100644 --- a/src/network/access/qnetworkdiskcache.cpp +++ b/src/network/access/qnetworkdiskcache.cpp @@ -255,7 +255,8 @@ void QNetworkDiskCachePrivate::storeItem(QCacheItem *cacheItem) // ### use atomic rename rather then remove & rename if (cacheItem->file->rename(fileName)) currentCacheSize += cacheItem->file->size(); - cacheItem->file->setAutoRemove(true); + else + cacheItem->file->setAutoRemove(true); } if (cacheItem->metaData.url() == lastItem.metaData.url()) lastItem.reset(); diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 4c152e2..303b5e2 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2616,6 +2616,10 @@ const QGLContext* QGLContext::currentContext() QGLWidget. This will side-step the issue altogether, and is what we recommend for users that need this kind of functionality. + On Mac OS X, when Qt is built with Cocoa support, a QGLWidget + can't have any sibling widgets placed ontop of itself. This is due + to limitations in the Cocoa API and is not supported by Apple. + \section1 Overlays The QGLWidget creates a GL overlay context in addition to the diff --git a/src/opengl/qglpixelbuffer_mac.mm b/src/opengl/qglpixelbuffer_mac.mm index 14941ab..9a679b1 100644 --- a/src/opengl/qglpixelbuffer_mac.mm +++ b/src/opengl/qglpixelbuffer_mac.mm @@ -308,10 +308,6 @@ GLuint QGLPixelBuffer::generateDynamicTexture() const GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); - [static_cast<NSOpenGLContext *>(d->share_ctx) - setTextureImageToPixelBuffer:static_cast<NSOpenGLPixelBuffer *>(d->pbuf) - colorBuffer:GL_FRONT]; - glBindTexture(GL_TEXTURE_2D, texture); // updates texture target glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -322,8 +318,6 @@ GLuint QGLPixelBuffer::generateDynamicTexture() const GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); - aglTexImagePBuffer(d->share_ctx, d->pbuf, GL_FRONT); - glBindTexture(GL_TEXTURE_2D, texture); // updates texture target glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); return texture; diff --git a/src/plugins/gfxdrivers/directfb/directfb.pro b/src/plugins/gfxdrivers/directfb/directfb.pro index 399044e..89a289c 100644 --- a/src/plugins/gfxdrivers/directfb/directfb.pro +++ b/src/plugins/gfxdrivers/directfb/directfb.pro @@ -13,6 +13,7 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers #DEFINES += QT_NO_DIRECTFB_MOUSE #DEFINES += QT_NO_DIRECTFB_KEYBOARD #DEFINES += QT_DIRECTFB_TIMING +#DEFINES += QT_NO_DIRECTFB_OPAQUE_DETECTION target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers INSTALLS += target diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index a93bbf7..d9346fd 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -196,10 +196,10 @@ public: void setPen(const QPen &pen); void setBrush(const QBrush &brush); void setCompositionMode(QPainter::CompositionMode mode); - void setOpacity(const qreal value); + void setOpacity(quint8 value); void setRenderHints(QPainter::RenderHints hints); - inline void setDFBColor(const QColor &color) const; + inline void setDFBColor(const QColor &color); inline void lock(); inline void unlock(); @@ -222,21 +222,18 @@ public: void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap); void drawImage(const QRectF &dest, const QImage &image, const QRectF &src); - void updateClip(); - void updateFlags(); + inline void updateClip(); inline void setClipDirty(); - void systemStateChanged(); //Needed to be notified when system clip changes + void systemStateChanged(); void begin(QPaintDevice *device); void end(); + void prepareForBlit(bool alpha); SurfaceCache *surfaceCache; QTransform transform; int lastLockedHeight; private: -// QRegion rectsToClippedRegion(const QRect *rects, int n) const; -// QRegion rectsToClippedRegion(const QRectF *rects, int n) const; - IDirectFB *fb; DFBSurfaceDescription fbDescription; int fbWidth; @@ -244,10 +241,9 @@ private: quint8 opacity; - quint32 drawFlags; - quint32 blitFlags; - quint32 duffFlags; - bool dirtyFlags; + quint32 drawFlagsFromCompositionMode, blitFlagsFromCompositionMode; + DFBSurfacePorterDuffRule porterDuffRule; + bool dirtyClip; bool dfbHandledClip; QDirectFBPaintDevice *dfbDevice; @@ -258,8 +254,9 @@ private: QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p) : surface(0), antialiased(false), forceRasterPrimitives(false), simplePen(false), simpleBrush(false), matrixRotShear(false), matrixScale(false), lastLockedHeight(-1), - fbWidth(-1), fbHeight(-1), opacity(255), drawFlags(0), blitFlags(0), duffFlags(0), - dirtyFlags(false), dirtyClip(true), dfbHandledClip(false), dfbDevice(0), q(p) + fbWidth(-1), fbHeight(-1), opacity(255), drawFlagsFromCompositionMode(0), + blitFlagsFromCompositionMode(0), porterDuffRule(DSPD_SRC_OVER), dirtyClip(true), + dfbHandledClip(false), dfbDevice(0), q(p) { fb = QDirectFBScreen::instance()->dfb(); surfaceCache = new SurfaceCache; @@ -295,7 +292,6 @@ void QDirectFBPaintEnginePrivate::setClipDirty() dirtyClip = true; } - void QDirectFBPaintEnginePrivate::lock() { // We will potentially get a new pointer to the buffer after a @@ -345,11 +341,8 @@ void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device) setTransform(QTransform()); antialiased = false; - drawFlags = DSDRAW_BLEND; - blitFlags = DSBLIT_BLEND_ALPHACHANNEL; - duffFlags = DSPD_SRC_OVER; opacity = 255; - dirtyFlags = true; + setCompositionMode(q->state()->compositionMode()); dirtyClip = true; setPen(q->state()->pen); setDFBColor(pen.color()); @@ -382,91 +375,72 @@ void QDirectFBPaintEnginePrivate::setBrush(const QBrush &b) void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode) { - drawFlags &= ~(DSDRAW_XOR); - blitFlags &= ~(DSBLIT_XOR); - - // TODO: check these mappings!!!! - quint32 duff = DSPD_NONE; - quint32 blit = blitFlags; + blitFlagsFromCompositionMode = DSBLIT_NOFX; + drawFlagsFromCompositionMode = DSDRAW_NOFX; + bool blend = true; switch (mode) { case QPainter::CompositionMode_SourceOver: - duff = DSPD_SRC_OVER; - blit |= DSBLIT_BLEND_ALPHACHANNEL; + porterDuffRule = DSPD_SRC_OVER; break; case QPainter::CompositionMode_DestinationOver: - duff = DSPD_DST_OVER; - blit |= DSBLIT_BLEND_ALPHACHANNEL; + porterDuffRule = DSPD_DST_OVER; break; case QPainter::CompositionMode_Clear: - duff = DSPD_CLEAR; - blit &= ~DSBLIT_BLEND_ALPHACHANNEL; + porterDuffRule = DSPD_CLEAR; + blend = false; break; case QPainter::CompositionMode_Source: - duff = DSPD_SRC; - blit &= ~DSBLIT_BLEND_ALPHACHANNEL; + porterDuffRule = DSPD_SRC; + blend = false; break; case QPainter::CompositionMode_Destination: - blit &= ~DSBLIT_BLEND_ALPHACHANNEL; + porterDuffRule = DSPD_NONE; // ### need to double check this + blend = false; return; case QPainter::CompositionMode_SourceIn: - duff = DSPD_SRC_IN; - blit |= DSBLIT_BLEND_ALPHACHANNEL; + porterDuffRule = DSPD_SRC_IN; break; case QPainter::CompositionMode_DestinationIn: - duff = DSPD_DST_IN; - blit |= DSBLIT_BLEND_ALPHACHANNEL; + porterDuffRule = DSPD_DST_IN; break; case QPainter::CompositionMode_SourceOut: - duff = DSPD_SRC_OUT; - blit |= DSBLIT_BLEND_ALPHACHANNEL; + porterDuffRule = DSPD_SRC_OUT; break; case QPainter::CompositionMode_DestinationOut: - duff = DSPD_DST_OUT; - blit |= DSBLIT_BLEND_ALPHACHANNEL; - break; - case QPainter::CompositionMode_SourceAtop: - duff = DSPD_SRC_OVER; - blit |= DSBLIT_BLEND_ALPHACHANNEL; - break; - case QPainter::CompositionMode_DestinationAtop: - duff = DSPD_DST_OVER; + porterDuffRule = DSPD_DST_OUT; break; case QPainter::CompositionMode_Xor: - duff = DSPD_NONE; - blit |= DSBLIT_BLEND_ALPHACHANNEL; - drawFlags |= DSDRAW_XOR; - blit |= DSBLIT_XOR; - dirtyFlags = true; + porterDuffRule = DSPD_XOR; + blitFlagsFromCompositionMode |= DSBLIT_XOR; + drawFlagsFromCompositionMode |= DSDRAW_XOR; break; +// case QPainter::CompositionMode_Plus: // ??? +// porterDuffRule = DSPD_ADD; +// break; default: qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): " "mode %d not implemented", mode); - break; + return; } - - if (duff != duffFlags || blit != blitFlags) { - duffFlags = duff; - blitFlags = blit; - dirtyFlags = true; + // intentially not comparing with current porterDuffRule. surface might have changed. + if (blend) { + blitFlagsFromCompositionMode |= DSBLIT_BLEND_ALPHACHANNEL; + drawFlagsFromCompositionMode |= DSDRAW_BLEND; + } + if (opacity != 255) { + setOpacity(opacity); } } -void QDirectFBPaintEnginePrivate::setOpacity(const qreal value) +void QDirectFBPaintEnginePrivate::setOpacity(quint8 op) { - const bool wasOpaque = (opacity == 255); - opacity = quint8(value * 255); - const bool opaque = (opacity == 255); - - if (opaque == wasOpaque) - return; - - if (opaque) - blitFlags &= ~(DSBLIT_BLEND_COLORALPHA | DSBLIT_SRC_PREMULTCOLOR); - else - blitFlags |= (DSBLIT_BLEND_COLORALPHA | DSBLIT_SRC_PREMULTCOLOR); - - dirtyFlags = true; + opacity = op; + if (opacity == 255) { + blitFlagsFromCompositionMode &= ~DSBLIT_BLEND_COLORALPHA; + } else { + blitFlagsFromCompositionMode |= DSBLIT_BLEND_COLORALPHA; + } } void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) @@ -478,81 +452,53 @@ void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) } } -void QDirectFBPaintEnginePrivate::updateFlags() +void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) { - if (!dirtyFlags) - return; - surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawFlags)); - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags)); - surface->SetPorterDuff(surface, DFBSurfacePorterDuffRule(duffFlags)); - dirtyFlags = false; + quint32 blittingFlags = blitFlagsFromCompositionMode; + if (alpha) { + surface->SetPorterDuff(surface, + (blittingFlags & DSBLIT_BLEND_COLORALPHA) + ? DSPD_NONE + : porterDuffRule); + } else { + blittingFlags &= ~DSBLIT_BLEND_ALPHACHANNEL; + surface->SetPorterDuff(surface, DSPD_NONE); + } + surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); + surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags)); } -void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) const +void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) { + Q_ASSERT(surface); const quint8 alpha = (opacity == 255 ? color.alpha() : ALPHA_MUL(color.alpha(), opacity)); surface->SetColor(surface, color.red(), color.green(), color.blue(), alpha); + quint32 drawingFlags = drawFlagsFromCompositionMode; + if (alpha == 255) { + drawingFlags &= ~DSDRAW_BLEND; + } + surface->SetPorterDuff(surface, DSPD_NONE); + // PorterDuff messes up alpha values for primitives + surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawingFlags)); } void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n) const { - QVarLengthArray<DFBRegion> regions(n); - for (int i = 0; i < n; ++i) { const QLine l = transform.map(lines[i]); - - regions[i].x1 = l.x1(); - regions[i].y1 = l.y1(); - regions[i].x2 = l.x2(); - regions[i].y2 = l.y2(); + surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); } - surface->DrawLines(surface, regions.data(), n); } void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n) const { - QVarLengthArray<DFBRegion> regions(n); - for (int i = 0; i < n; ++i) { const QLine l = transform.map(lines[i]).toLine(); - - regions[i].x1 = l.x1(); - regions[i].y1 = l.y1(); - regions[i].x2 = l.x2(); - regions[i].y2 = l.y2(); - } - surface->DrawLines(surface, regions.data(), n); -} - -/* ### Commented out until it can be implemented properly using raster's QClipData -QRegion QDirectFBPaintEnginePrivate::rectsToClippedRegion(const QRect *rects, - int n) const -{ - QRegion region; - - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]); - region += clip & r; - } - - return region; -} - -QRegion QDirectFBPaintEnginePrivate::rectsToClippedRegion(const QRectF *rects, - int n) const -{ - QRegion region; - - for (int i = 0; i < n; ++i) { - const QRect r = transform.mapRect(rects[i]).toRect(); - region += clip & r; + surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); } - - return region; } -*/ void QDirectFBPaintEnginePrivate::fillRegion(const QRegion ®ion) const { @@ -601,15 +547,7 @@ void QDirectFBPaintEnginePrivate::drawPixmap(const QRectF &dest, const QPixmap &pixmap, const QRectF &src) { - surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); - - const bool changeFlags = !pixmap.hasAlphaChannel() - && (blitFlags & DSBLIT_BLEND_ALPHACHANNEL); - if (changeFlags) { - quint32 flags = blitFlags & ~DSBLIT_BLEND_ALPHACHANNEL; - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(flags)); - } - + prepareForBlit(pixmap.hasAlphaChannel()); QPixmapData *data = pixmap.pixmapData(); Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); @@ -627,22 +565,12 @@ void QDirectFBPaintEnginePrivate::drawPixmap(const QRectF &dest, } if (result != DFB_OK) DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); - if (changeFlags) - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags)); } void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap) { - surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); - - const bool changeFlags = !pixmap.hasAlphaChannel() - && (blitFlags & DSBLIT_BLEND_ALPHACHANNEL); - if (changeFlags) { - quint32 flags = blitFlags & ~DSBLIT_BLEND_ALPHACHANNEL; - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(flags)); - } - + prepareForBlit(pixmap.hasAlphaChannel()); QPixmapData *data = pixmap.pixmapData(); Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); @@ -688,22 +616,13 @@ void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, if (result != DFB_OK) DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result); - - if (changeFlags) - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags)); } void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest, - const QImage &srcImage, + const QImage &image, const QRectF &src) { - QImage image = srcImage; - if (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN) { - image = image.convertToFormat(image.hasAlphaChannel() - ? QDirectFBScreen::instance()->alphaPixmapFormat() - : QDirectFBScreen::instance()->pixelFormat()); - } - + Q_ASSERT(QDirectFBScreen::getSurfacePixelFormat(image.format()) != DSPF_UNKNOWN); CachedImage *img = imageCache[image.cacheKey()]; IDirectFBSurface *imgSurface = 0; bool doRelease = false; @@ -745,14 +664,7 @@ void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest, const QRect dr = transform.mapRect(dest).toRect(); const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; - surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); - - const bool changeFlags = !image.hasAlphaChannel() - && (blitFlags & DSBLIT_BLEND_ALPHACHANNEL); - if (changeFlags) { - quint32 flags = blitFlags & ~DSBLIT_BLEND_ALPHACHANNEL; - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(flags)); - } + prepareForBlit(image.hasAlphaChannel()); if (dr.size() == sr.size()) { surface->Blit(surface, imgSurface, &sRect, dr.x(), dr.y()); } else { @@ -760,8 +672,6 @@ void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest, dr.width(), dr.height() }; surface->StretchBlit(surface, imgSurface, &sRect, &dRect); } - if (changeFlags) - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags)); if (doRelease) { surface->ReleaseSource(surface); imgSurface->Release(imgSurface); @@ -856,8 +766,7 @@ void QDirectFBPaintEngine::brushChanged() void QDirectFBPaintEngine::opacityChanged() { Q_D(QDirectFBPaintEngine); - d->setOpacity(state()->opacity); - + d->setOpacity(quint8(state()->opacity * 255)); QRasterPaintEngine::opacityChanged(); } @@ -865,7 +774,6 @@ void QDirectFBPaintEngine::compositionModeChanged() { Q_D(QDirectFBPaintEngine); d->setCompositionMode(state()->compositionMode()); - QRasterPaintEngine::compositionModeChanged(); } @@ -894,7 +802,7 @@ void QDirectFBPaintEngine::setState(QPainterState *s) d->setClipDirty(); d->setPen(state()->pen); d->setBrush(state()->brush); - d->setOpacity(state()->opacity); + d->setOpacity(quint8(state()->opacity * 255)); d->setCompositionMode(state()->compositionMode()); d->setTransform(state()->transform()); } @@ -936,12 +844,10 @@ void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount) d->unlock(); if (d->brush != Qt::NoBrush) { - d->updateFlags(); d->setDFBColor(d->brush.color()); d->fillRects(rects, rectCount); } if (d->pen != Qt::NoPen) { - d->updateFlags(); d->setDFBColor(d->pen.color()); d->drawRects(rects, rectCount); } @@ -961,12 +867,10 @@ void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount) d->unlock(); if (d->brush != Qt::NoBrush) { - d->updateFlags(); d->setDFBColor(d->brush.color()); d->fillRects(rects, rectCount); } if (d->pen != Qt::NoPen) { - d->updateFlags(); d->setDFBColor(d->pen.color()); d->drawRects(rects, rectCount); } @@ -984,7 +888,6 @@ void QDirectFBPaintEngine::drawLines(const QLine *lines, int lineCount) if (d->pen != Qt::NoPen) { d->unlock(); - d->updateFlags(); d->setDFBColor(d->pen.color()); d->drawLines(lines, lineCount); } @@ -1002,7 +905,6 @@ void QDirectFBPaintEngine::drawLines(const QLineF *lines, int lineCount) if (d->pen != Qt::NoPen) { d->unlock(); - d->updateFlags(); d->setDFBColor(d->pen.color()); d->drawLines(lines, lineCount); } @@ -1017,7 +919,8 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, #ifndef QT_NO_DIRECTFB_PREALLOCATED d->updateClip(); - if (!d->dfbCanHandleClip(r) || d->matrixRotShear) + if (!d->dfbCanHandleClip(r) || d->matrixRotShear + || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN) #endif { d->lock(); @@ -1027,7 +930,6 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, #ifndef QT_NO_DIRECTFB_PREALLOCATED d->unlock(); - d->updateFlags(); d->drawImage(r, image, sr); #endif } @@ -1046,15 +948,12 @@ void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { d->lock(); QRasterPaintEngine::drawPixmap(r, pixmap, sr); - } - else if (!d->dfbCanHandleClip(r) || d->matrixRotShear) { + } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear) { const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(); d->lock(); QRasterPaintEngine::drawImage(r, *img, sr); - } - else { + } else { d->unlock(); - d->updateFlags(); d->drawPixmap(r, pixmap, sr); } } @@ -1073,18 +972,15 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { d->lock(); QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp); - } - else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()) { + } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()) { const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(); d->lock(); QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType); data->fromImage(*img, Qt::AutoColor); const QPixmap pix(data); QRasterPaintEngine::drawTiledPixmap(r, pix, sp); - } - else { + } else { d->unlock(); - d->updateFlags(); d->drawTiledPixmap(r, pixmap); } } @@ -1167,7 +1063,6 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) if (d->forceRasterPrimitives) break; d->unlock(); - d->updateFlags(); d->setDFBColor(brush.color()); const QRect r = d->transform.mapRect(rect).toRect(); d->surface->FillRectangle(d->surface, r.x(), r.y(), @@ -1177,7 +1072,6 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) if (state()->brushOrigin == QPointF() && brush.transform().isIdentity()) { //could handle certain types of brush.transform() E.g. scale d->unlock(); - d->updateFlags(); d->drawTiledPixmap(rect, brush.texture()); return; } @@ -1199,7 +1093,6 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color) QRasterPaintEngine::fillRect(rect, color); } else { d->unlock(); - d->updateFlags(); d->setDFBColor(color); const QRect r = d->transform.mapRect(rect).toRect(); d->surface->FillRectangle(d->surface, r.x(), r.y(), @@ -1229,6 +1122,7 @@ void QDirectFBPaintEngine::drawColorSpans(const QSpan *spans, int count, } else { DFBSpan span = { spans[i].x, spans[i].len }; uint c = BYTE_MUL(color, spans[i].coverage); + // ### how does this play with setDFBColor d->surface->SetColor(d->surface, qRed(c), qGreen(c), qBlue(c), qAlpha(c)); d->surface->FillSpans(d->surface, spans[i].y, &span, 1); @@ -1249,6 +1143,7 @@ void QDirectFBPaintEngine::drawBufferSpan(const uint *buffer, int bufsize, { Q_D(QDirectFBPaintEngine); IDirectFBSurface *src = d->surfaceCache->getSurface(buffer, bufsize); + // ### how does this play with setDFBColor src->SetColor(src, 0, 0, 0, const_alpha); const DFBRectangle rect = { 0, 0, length, 1 }; d->surface->Blit(d->surface, src, &rect, x, y); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 35ab859..0a1696a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -51,7 +51,7 @@ static int global_ser_no = 0; QDirectFBPixmapData::QDirectFBPixmapData(PixelType pixelType) : QPixmapData(pixelType, DirectFBClass), - engine(0) + engine(0), format(QImage::Format_Invalid), alpha(false) { setSerialNumber(0); } @@ -67,16 +67,18 @@ QDirectFBPixmapData::~QDirectFBPixmapData() void QDirectFBPixmapData::resize(int width, int height) { if (width <= 0 || height <= 0) { - setSerialNumber(0); + invalidate(); return; } - dfbSurface = screen->createDFBSurface(QSize(width, height), - screen->pixelFormat(), - QDirectFBScreen::TrackSurface); - forceRaster = (screen->pixelFormat() == QImage::Format_RGB32); + format = screen->pixelFormat(); + dfbSurface = QDirectFBScreen::instance()->createDFBSurface(QSize(width, height), + format, + QDirectFBScreen::TrackSurface); + alpha = false; + forceRaster = (format == QImage::Format_RGB32); if (!dfbSurface) { - setSerialNumber(0); + invalidate(); qWarning("QDirectFBPixmapData::resize(): Unable to allocate surface"); return; } @@ -84,18 +86,98 @@ void QDirectFBPixmapData::resize(int width, int height) setSerialNumber(++global_ser_no); } + +// mostly duplicated from qimage.cpp (QImageData::checkForAlphaPixels) +static bool checkForAlphaPixels(const QImage &img) +{ + const uchar *bits = img.bits(); + const int bytes_per_line = img.bytesPerLine(); + const uchar *end_bits = bits + bytes_per_line; + const int width = img.width(); + const int height = img.height(); + switch (img.format()) { + case QImage::Format_Indexed8: + return img.hasAlphaChannel(); + case QImage::Format_ARGB32: + case QImage::Format_ARGB32_Premultiplied: + for (int y=0; y<height; ++y) { + for (int x=0; x<width; ++x) { + if ((((uint *)bits)[x] & 0xff000000) != 0xff000000) { + return true; + } + } + bits += bytes_per_line; + } + break; + + case QImage::Format_ARGB8555_Premultiplied: + case QImage::Format_ARGB8565_Premultiplied: + for (int y=0; y<height; ++y) { + while (bits < end_bits) { + if (bits[0] != 0) { + return true; + } + bits += 3; + } + bits = end_bits; + end_bits += bytes_per_line; + } + break; + + case QImage::Format_ARGB6666_Premultiplied: + for (int y=0; y<height; ++y) { + while (bits < end_bits) { + if ((bits[0] & 0xfc) != 0) { + return true; + } + bits += 3; + } + bits = end_bits; + end_bits += bytes_per_line; + } + break; + + case QImage::Format_ARGB4444_Premultiplied: + for (int y=0; y<height; ++y) { + while (bits < end_bits) { + if ((bits[0] & 0xf0) != 0) { + return true; + } + bits += 2; + } + bits = end_bits; + end_bits += bytes_per_line; + } + break; + + default: + break; + } + + return false; +} + void QDirectFBPixmapData::fromImage(const QImage &img, - Qt::ImageConversionFlags) + Qt::ImageConversionFlags flags) { - const QImage::Format format = img.hasAlphaChannel() ? - screen->alphaPixmapFormat() - : screen->pixelFormat(); + Q_ASSERT(img.depth() != 1); // these should be handled by QRasterPixmapData + if (img.hasAlphaChannel() +#ifndef QT_NO_DIRECTFB_OPAQUE_DETECTION + && (flags & Qt::NoOpaqueDetection || ::checkForAlphaPixels(img)) +#endif + ) { + alpha = true; + format = screen->alphaPixmapFormat(); + } else { + alpha = false; + format = screen->pixelFormat(); + } dfbSurface = screen->copyToDFBSurface(img, format, QDirectFBScreen::TrackSurface); forceRaster = (format == QImage::Format_RGB32); if (!dfbSurface) { qWarning("QDirectFBPixmapData::fromImage()"); - setSerialNumber(0); + invalidate(); return; } setSerialNumber(++global_ser_no); @@ -110,15 +192,15 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) IDirectFBSurface *src = static_cast<const QDirectFBPixmapData*>(data)->directFBSurface(); const bool hasAlpha = data->hasAlphaChannel(); - const QImage::Format format = (hasAlpha - ? screen->alphaPixmapFormat() - : screen->pixelFormat()); + format = (hasAlpha + ? QDirectFBScreen::instance()->alphaPixmapFormat() + : QDirectFBScreen::instance()->pixelFormat()); dfbSurface = screen->createDFBSurface(rect.size(), format, QDirectFBScreen::TrackSurface); if (!dfbSurface) { qWarning("QDirectFBPixmapData::copy()"); - setSerialNumber(0); + invalidate(); return; } forceRaster = (format == QImage::Format_RGB32); @@ -135,13 +217,28 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) dfbSurface->ReleaseSource(dfbSurface); if (result != DFB_OK) { DirectFBError("QDirectFBPixmapData::copy()", result); - setSerialNumber(0); + invalidate(); return; } setSerialNumber(++global_ser_no); } +static inline bool isOpaqueFormat(QImage::Format format) +{ + switch (format) { + case QImage::Format_RGB32: + case QImage::Format_RGB16: + case QImage::Format_RGB666: + case QImage::Format_RGB555: + case QImage::Format_RGB888: + case QImage::Format_RGB444: + return true; + default: + break; + } + return false; +} void QDirectFBPixmapData::fill(const QColor &color) { @@ -150,17 +247,19 @@ void QDirectFBPixmapData::fill(const QColor &color) Q_ASSERT(dfbSurface); - if (color.alpha() < 255 && !hasAlphaChannel()) { + alpha = (color.alpha() < 255); + if (alpha && ::isOpaqueFormat(format)) { QSize size; dfbSurface->GetSize(dfbSurface, &size.rwidth(), &size.rheight()); screen->releaseDFBSurface(dfbSurface); + format = screen->alphaPixmapFormat(); dfbSurface = screen->createDFBSurface(size, screen->alphaPixmapFormat(), QDirectFBScreen::TrackSurface); forceRaster = false; setSerialNumber(++global_ser_no); if (!dfbSurface) { - qWarning("QDirectFBPixmapData::fill()"); - setSerialNumber(0); + qWarning("QDirecttFBPixmapData::fill()"); + invalidate(); return; } } @@ -184,19 +283,6 @@ void QDirectFBPixmapData::fill(const QColor &color) } } -bool QDirectFBPixmapData::hasAlphaChannel() const -{ - if (!serialNumber()) - return false; - DFBSurfacePixelFormat format; - dfbSurface->GetPixelFormat(dfbSurface, &format); - return QDirectFBScreen::hasAlpha(format); - - // We don't need to ask DFB for this really. Can just keep track - // of what image format this has. It should always have either - // QDirectFBScreen::alphaPixmapFormat() or QScreen::pixelFormat() -} - QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, Qt::TransformationMode mode) const { @@ -221,11 +307,10 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, return QPixmap(); QDirectFBPixmapData *data = new QDirectFBPixmapData(QPixmapData::PixmapType); - QImage::Format format = screen->pixelFormat(); DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; - if (hasAlphaChannel()) { + data->alpha = alpha; + if (alpha) { flags = DSBLIT_BLEND_ALPHACHANNEL; - format = screen->alphaPixmapFormat(); } data->dfbSurface = screen->createDFBSurface(size, format, @@ -250,7 +335,12 @@ QImage QDirectFBPixmapData::toImage() const #ifndef QT_NO_DIRECTFB_PREALLOCATED QImage ret(size(), QDirectFBScreen::getImageFormat(dfbSurface)); if (IDirectFBSurface *imgSurface = screen->createDFBSurface(ret, QDirectFBScreen::DontTrackSurface)) { - imgSurface->SetBlittingFlags(imgSurface, hasAlphaChannel() ? DSBLIT_BLEND_ALPHACHANNEL : DSBLIT_NOFX); + if (hasAlphaChannel()) { + imgSurface->SetBlittingFlags(imgSurface, DSBLIT_BLEND_ALPHACHANNEL); + imgSurface->Clear(imgSurface, 0, 0, 0, 0); + } else { + imgSurface->SetBlittingFlags(imgSurface, DSBLIT_NOFX); + } imgSurface->Blit(imgSurface, dfbSurface, 0, 0, 0); imgSurface->ReleaseSource(imgSurface); imgSurface->Release(imgSurface); @@ -280,3 +370,10 @@ QImage* QDirectFBPixmapData::buffer() lockDirectFB(); return lockedImage; } + +void QDirectFBPixmapData::invalidate() +{ + setSerialNumber(0); + alpha = false; + format = QImage::Format_Invalid; +} diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h index 32676f8..6cfafcd 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h @@ -64,7 +64,7 @@ public: void fromImage(const QImage &image, Qt::ImageConversionFlags flags); void copy(const QPixmapData *data, const QRect &rect); void fill(const QColor &color); - bool hasAlphaChannel() const; + inline bool hasAlphaChannel() const { return alpha; } QPixmap transformed(const QTransform &matrix, Qt::TransformationMode mode) const; QImage toImage() const; @@ -73,9 +73,12 @@ public: // Pure virtual in QPixmapData, so re-implement here and delegate to QDirectFBPaintDevice int metric(QPaintDevice::PaintDeviceMetric m) const {return QDirectFBPaintDevice::metric(m);} - + inline QImage::Format pixelFormat() const { return format; } private: + void invalidate(); QDirectFBPaintEngine *engine; + QImage::Format format; + bool alpha; }; QT_END_HEADER diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 4ae64f7..041d522 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -85,7 +85,7 @@ public: }; QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen* screen) - : QWSGraphicsSystem(screen), dfb(0), dfbSurface(0), flipFlags(DSFLIP_BLIT) + : QWSGraphicsSystem(screen), dfb(0), dfbSurface(0), flipFlags(DSFLIP_NONE) #ifndef QT_NO_DIRECTFB_LAYER , dfbLayer(0) #endif @@ -233,6 +233,18 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription voDesc.caps = DFBSurfaceCapabilities(voDesc.caps | DSCAPS_VIDEOONLY); } result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &voDesc, &newSurface); + if (result != DFB_OK +#ifdef QT_NO_DEBUG + && (desc->flags & DSDESC_CAPS) && (desc->caps & DSCAPS_PRIMARY) +#endif + ) { + qWarning("QDirectFBScreen::createDFBSurface() Failed to create surface in video memory!\n" + " Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s", + desc->flags, desc->caps, desc->width, desc->height, + desc->pixelformat, DFB_PIXELFORMAT_INDEX(desc->pixelformat), + desc->preallocated[0].data, desc->preallocated[0].pitch, + DirectFBErrorString(result)); + } } if (!newSurface) @@ -710,7 +722,7 @@ int QDirectFBScreen::depth(DFBSurfacePixelFormat format) void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args) { - QRegExp flipRegexp(QLatin1String("^flip=([\\w,]+)$")); + QRegExp flipRegexp(QLatin1String("^flip=([\\w,]*)$")); int index = args.indexOf(flipRegexp); if (index >= 0) { const QStringList flips = flipRegexp.cap(1).split(QLatin1Char(','), @@ -729,6 +741,8 @@ void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args) qWarning("QDirectFBScreen: Unknown flip argument: %s", qPrintable(flip)); } + } else { + flipFlags = DFBSurfaceFlipFlags(DSFLIP_BLIT); } } @@ -758,6 +772,18 @@ static void printDirectFBInfo(IDirectFB *fb) dev.blitting_flags, dev.drawing_flags, dev.video_memory); } +static inline bool setIntOption(const QStringList &arguments, const QString &variable, int *value) +{ + Q_ASSERT(value); + QRegExp rx(QString("%1=?(\\d+)").arg(variable)); + rx.setCaseSensitivity(Qt::CaseInsensitive); + if (arguments.indexOf(rx) != -1) { + *value = rx.cap(1).toInt(); + return true; + } + return false; +} + bool QDirectFBScreen::connect(const QString &displaySpec) { DFBResult result = DFB_OK; @@ -803,6 +829,10 @@ bool QDirectFBScreen::connect(const QString &displaySpec) DFBSurfaceDescription description; description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS); + if (::setIntOption(displayArgs, QLatin1String("width"), &description.width)) + description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_WIDTH); + if (::setIntOption(displayArgs, QLatin1String("height"), &description.height)) + description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_HEIGHT); description.caps = DFBSurfaceCapabilities(DSCAPS_PRIMARY | DSCAPS_DOUBLE | DSCAPS_STATIC_ALLOC); @@ -812,13 +842,6 @@ bool QDirectFBScreen::connect(const QString &displaySpec) | DSCAPS_PREMULTIPLIED); } - if (!(d_ptr->flipFlags & DSFLIP_BLIT)) { - description.caps = DFBSurfaceCapabilities(description.caps - | DSCAPS_DOUBLE - | DSCAPS_TRIPLE); - } - - // We don't track the primary surface as it's released in disconnect d_ptr->dfbSurface = createDFBSurface(&description, DontTrackSurface); if (!d_ptr->dfbSurface) { @@ -875,18 +898,8 @@ bool QDirectFBScreen::connect(const QString &displaySpec) setPixelFormat(getImageFormat(d_ptr->dfbSurface)); physWidth = physHeight = -1; - QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)")); - int dimIdxW = displayArgs.indexOf(mmWidthRx); - if (dimIdxW >= 0) { - mmWidthRx.exactMatch(displayArgs.at(dimIdxW)); - physWidth = mmWidthRx.cap(1).toInt(); - } - QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)")); - int dimIdxH = displayArgs.indexOf(mmHeightRx); - if (dimIdxH >= 0) { - mmHeightRx.exactMatch(displayArgs.at(dimIdxH)); - physHeight = mmHeightRx.cap(1).toInt(); - } + ::setIntOption(displayArgs, QLatin1String("mmWidth"), &physWidth); + ::setIntOption(displayArgs, QLatin1String("mmHeight"), &physHeight); const int dpi = 72; if (physWidth < 0) physWidth = qRound(dw * 25.4 / dpi); @@ -994,19 +1007,21 @@ void QDirectFBScreen::blank(bool on) QWSWindowSurface* QDirectFBScreen::createSurface(QWidget *widget) const { #ifdef QT_NO_DIRECTFB_WM - if (QApplication::type() == QApplication::GuiServer) - return new QDirectFBSurface(const_cast<QDirectFBScreen*>(this), widget); - else + if (QApplication::type() == QApplication::GuiServer) { + return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); + } else { return QScreen::createSurface(widget); + } #else - return new QDirectFBSurface(const_cast<QDirectFBScreen*>(this), widget); + return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); #endif } QWSWindowSurface* QDirectFBScreen::createSurface(const QString &key) const { - if (key == QLatin1String("directfb")) - return new QDirectFBSurface(const_cast<QDirectFBScreen*>(this)); + if (key == QLatin1String("directfb")) { + return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this)); + } return QScreen::createSurface(key); } @@ -1178,21 +1193,29 @@ void QDirectFBScreen::solidFill(const QColor &color, const QRegion ®ion) if (region.isEmpty()) return; - const QVector<QRect> rects = region.rects(); - QVarLengthArray<DFBRectangle> dfbRects(rects.size()); - for (int i = 0; i < rects.size(); ++i) { - const QRect r = rects.at(i); - dfbRects[i].x = r.x(); - dfbRects[i].y = r.y(); - dfbRects[i].w = r.width(); - dfbRects[i].h = r.height(); + if (QDirectFBScreen::getImageFormat(d_ptr->dfbSurface) == QImage::Format_RGB32) { + uchar *mem; + int bpl; + d_ptr->dfbSurface->Lock(d_ptr->dfbSurface, DSLF_WRITE, (void**)&mem, &bpl); + QImage img(mem, w, h, bpl, QImage::Format_RGB32); + QPainter p(&img); + p.setBrush(color); + p.setPen(Qt::NoPen); + const QVector<QRect> rects = region.rects(); + p.drawRects(rects.constData(), rects.size()); + p.end(); + d_ptr->dfbSurface->Unlock(d_ptr->dfbSurface); + } else { + d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, + color.red(), color.green(), color.blue(), + color.alpha()); + const QVector<QRect> rects = region.rects(); + for (int i=0; i<rects.size(); ++i) { + const QRect &r = rects.at(i); + d_ptr->dfbSurface->FillRectangle(d_ptr->dfbSurface, + r.x(), r.y(), r.width(), r.height()); + } } - - d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, - color.red(), color.green(), color.blue(), - color.alpha()); - d_ptr->dfbSurface->FillRectangles(d_ptr->dfbSurface, dfbRects.data(), - dfbRects.size()); } QImage::Format QDirectFBScreen::alphaPixmapFormat() const @@ -1200,7 +1223,6 @@ QImage::Format QDirectFBScreen::alphaPixmapFormat() const return d_ptr->alphaPixmapFormat; } - bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description, QImage::Format format) { diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp index 4b8fe0a..8ed308c 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp @@ -50,12 +50,13 @@ //#define QT_DIRECTFB_DEBUG_SURFACES 1 -QDirectFBSurface::QDirectFBSurface(QDirectFBScreen* scr) +QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen* scr) : QDirectFBPaintDevice(scr) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) #endif , engine(0) + , flipFlags(flip) { setSurfaceFlags(Opaque | Buffered); #ifdef QT_DIRECTFB_TIMING @@ -64,12 +65,13 @@ QDirectFBSurface::QDirectFBSurface(QDirectFBScreen* scr) #endif } -QDirectFBSurface::QDirectFBSurface(QDirectFBScreen* scr, QWidget *widget) +QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr, QWidget *widget) : QWSWindowSurface(widget), QDirectFBPaintDevice(scr) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) #endif , engine(0) + , flipFlags(flip) { onscreen = widget->testAttribute(Qt::WA_PaintOnScreen); if (onscreen) @@ -137,28 +139,32 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) dfbWindow = 0; } #endif - if (dfbSurface) { + if (dfbSurface && dfbSurface != screen->dfbSurface()) { dfbSurface->Release(dfbSurface); dfbSurface = 0; } } else if (rect != geometry()) { - const bool isResize = rect.size() != geometry().size(); DFBResult result = DFB_OK; // If we're in a resize, the surface shouldn't be locked - Q_ASSERT( (lockedImage == 0) || (isResize == false)); + Q_ASSERT((lockedImage == 0) || (rect.size() == geometry().size())); if (onscreen) { - if (dfbSurface) - dfbSurface->Release(dfbSurface); - - DFBRectangle r = { rect.x(), rect.y(), - rect.width(), rect.height() }; IDirectFBSurface *primarySurface = screen->dfbSurface(); Q_ASSERT(primarySurface); - result = primarySurface->GetSubSurface(primarySurface, &r, &dfbSurface); + if (dfbSurface && dfbSurface != primarySurface) + dfbSurface->Release(dfbSurface); + + if (rect == screen->region().boundingRect()) { + dfbSurface = primarySurface; + } else { + const DFBRectangle r = { rect.x(), rect.y(), + rect.width(), rect.height() }; + result = primarySurface->GetSubSurface(primarySurface, &r, &dfbSurface); + } forceRaster = (dfbSurface && QDirectFBScreen::getImageFormat(dfbSurface) == QImage::Format_RGB32); } else { + const bool isResize = rect.size() != geometry().size(); #ifdef QT_NO_DIRECTFB_WM if (isResize) { if (dfbSurface) @@ -244,7 +250,7 @@ void QDirectFBSurface::setPermanentState(const QByteArray &state) bool QDirectFBSurface::scroll(const QRegion ®ion, int dx, int dy) { - if (!dfbSurface) + if (!dfbSurface || !(flipFlags & DSFLIP_BLIT)) return false; const QVector<QRect> rects = region.rects(); @@ -360,23 +366,31 @@ void QDirectFBSurface::flush(QWidget *widget, const QRegion ®ion, if (winOpacity != opacity) dfbWindow->SetOpacity(dfbWindow, winOpacity); } -#endif -#ifndef QT_NO_DIRECTFB_WM - if (region.numRects() > 1) { - const QVector<QRect> rects = region.rects(); - for (int i=0; i<rects.size(); ++i) { - const QRect &r = rects.at(i); + if (!(flipFlags & DSFLIP_BLIT)) { + dfbSurface->Flip(dfbSurface, 0, flipFlags); + } else { + if (region.numRects() > 1) { + const QVector<QRect> rects = region.rects(); + DFBSurfaceFlipFlags tmpFlags = flipFlags; + if (flipFlags & DSFLIP_WAIT) + tmpFlags = DFBSurfaceFlipFlags(flipFlags & ~DSFLIP_WAIT); + for (int i=0; i<rects.size(); ++i) { + const QRect &r = rects.at(i); + const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), + r.x() + r.width() + offset.x(), + r.y() + r.height() + offset.y() }; + dfbSurface->Flip(dfbSurface, &dfbReg, + i + 1 < rects.size() + ? tmpFlags + : flipFlags); + } + } else { + const QRect r = region.boundingRect(); const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), r.x() + r.width() + offset.x(), r.y() + r.height() + offset.y() }; - dfbSurface->Flip(dfbSurface, &dfbReg, DSFLIP_ONSYNC); + dfbSurface->Flip(dfbSurface, &dfbReg, flipFlags); } - } else { - const QRect r = region.boundingRect(); - const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), - r.x() + r.width() + offset.x(), - r.y() + r.height() + offset.y() }; - dfbSurface->Flip(dfbSurface, &dfbReg, DSFLIP_ONSYNC); } #endif #ifdef QT_DIRECTFB_TIMING diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h index 9e2791c..ab4145d 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h @@ -61,8 +61,8 @@ QT_MODULE(Gui) class QDirectFBSurface: public QWSWindowSurface, public QDirectFBPaintDevice { public: - QDirectFBSurface(QDirectFBScreen* scr); - QDirectFBSurface(QDirectFBScreen* scr, QWidget *widget); + QDirectFBSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr); + QDirectFBSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr, QWidget *widget); ~QDirectFBSurface(); bool isValid() const; @@ -99,6 +99,7 @@ private: bool onscreen; QList<QImage*> bufferImages; + DFBSurfaceFlipFlags flipFlags; #ifdef QT_DIRECTFB_TIMING int frames; QTime timer; diff --git a/src/sql/drivers/db2/qsql_db2.cpp b/src/sql/drivers/db2/qsql_db2.cpp index 69383f7..11d0041 100644 --- a/src/sql/drivers/db2/qsql_db2.cpp +++ b/src/sql/drivers/db2/qsql_db2.cpp @@ -49,6 +49,7 @@ #include <qstringlist.h> #include <qvarlengtharray.h> #include <qvector.h> +#include <QDebug> #ifndef UNICODE #define UNICODE @@ -87,8 +88,19 @@ public: {} ~QDB2ResultPrivate() { - for (int i = 0; i < valueCache.count(); ++i) + emptyValueCache(); + } + void clearValueCache() + { + for (int i = 0; i < valueCache.count(); ++i) { delete valueCache[i]; + valueCache[i] = NULL; + } + } + void emptyValueCache() + { + clearValueCache(); + valueCache.clear(); } const QDB2DriverPrivate* dp; @@ -544,7 +556,7 @@ bool QDB2Result::reset (const QString& query) SQLRETURN r; d->recInf.clear(); - d->valueCache.clear(); + d->emptyValueCache(); if (!qMakeStatement(d, isForwardOnly())) return false; @@ -568,6 +580,7 @@ bool QDB2Result::reset (const QString& query) setSelect(false); } d->valueCache.resize(count); + d->valueCache.fill(NULL); setActive(true); return true; } @@ -579,7 +592,7 @@ bool QDB2Result::prepare(const QString& query) SQLRETURN r; d->recInf.clear(); - d->valueCache.clear(); + d->emptyValueCache(); if (!qMakeStatement(d, isForwardOnly())) return false; @@ -607,7 +620,7 @@ bool QDB2Result::exec() SQLRETURN r; d->recInf.clear(); - d->valueCache.clear(); + d->emptyValueCache(); if (!qMakeStatement(d, isForwardOnly(), false)) return false; @@ -811,6 +824,7 @@ bool QDB2Result::exec() } setActive(true); d->valueCache.resize(count); + d->valueCache.fill(NULL); //get out parameters if (!hasOutValues()) @@ -858,7 +872,7 @@ bool QDB2Result::fetch(int i) return false; if (i == at()) return true; - d->valueCache.fill(0); + d->clearValueCache(); int actualIdx = i + 1; if (actualIdx <= 0) { setAt(QSql::BeforeFirstRow); @@ -887,7 +901,7 @@ bool QDB2Result::fetch(int i) bool QDB2Result::fetchNext() { SQLRETURN r; - d->valueCache.fill(0); + d->clearValueCache(); r = SQLFetchScroll(d->hStmt, SQL_FETCH_NEXT, 0); @@ -907,7 +921,7 @@ bool QDB2Result::fetchFirst() return false; if (isForwardOnly()) return fetchNext(); - d->valueCache.fill(0); + d->clearValueCache(); SQLRETURN r; r = SQLFetchScroll(d->hStmt, SQL_FETCH_FIRST, @@ -923,7 +937,7 @@ bool QDB2Result::fetchFirst() bool QDB2Result::fetchLast() { - d->valueCache.fill(0); + d->clearValueCache(); int i = at(); if (i == QSql::AfterLastRow) { @@ -1044,7 +1058,7 @@ QVariant QDB2Result::data(int field) case QSql::HighPrecision: default: // length + 1 for the comma - v = new QVariant(qGetStringData(d->hStmt, field, info.length() + 1, isNull)); + v = new QVariant(value); ok = true; break; } @@ -1101,7 +1115,7 @@ bool QDB2Result::nextResult() setActive(false); setAt(QSql::BeforeFirstRow); d->recInf.clear(); - d->valueCache.clear(); + d->emptyValueCache(); setSelect(false); SQLRETURN r = SQLMoreResults(d->hStmt); @@ -1120,6 +1134,7 @@ bool QDB2Result::nextResult() d->recInf.append(qMakeFieldInfo(d, i)); d->valueCache.resize(fieldCount); + d->valueCache.fill(NULL); setActive(true); return true; @@ -1167,7 +1182,7 @@ QDB2Driver::~QDB2Driver() delete d; } -bool QDB2Driver::open(const QString& db, const QString& user, const QString& password, const QString&, int, +bool QDB2Driver::open(const QString& db, const QString& user, const QString& password, const QString& host, int port, const QString& connOpts) { if (isOpen()) @@ -1190,6 +1205,8 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas setOpenError(true); return false; } + + QString protocol; // Set connection attributes const QStringList opts(connOpts.split(QLatin1Char(';'), QString::SkipEmptyParts)); for (int i = 0; i < opts.count(); ++i) { @@ -1220,7 +1237,10 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas } else if (opt == QLatin1String("SQL_ATTR_LOGIN_TIMEOUT")) { v = val.toUInt(); r = SQLSetConnectAttr(d->hDbc, SQL_ATTR_LOGIN_TIMEOUT, (SQLPOINTER) v, 0); - } else { + } else if (opt.compare(QLatin1String("PROTOCOL"), Qt::CaseInsensitive) == 0) { + protocol = tmp; + } + else { qWarning("QDB2Driver::open: Unknown connection attribute '%s'", tmp.toLocal8Bit().constData()); } @@ -1229,9 +1249,18 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas "Unable to set connection attribute '%1'").arg(opt), d); } + if (protocol.isEmpty()) + protocol = QLatin1String("PROTOCOL=TCPIP"); + + if (port < 0 ) + port = 50000; + QString connQStr; - connQStr = QLatin1String("DSN=") + db + QLatin1String(";UID=") + user + QLatin1String(";PWD=") - + password; + connQStr = protocol + QLatin1String(";DATABASE=") + db + QLatin1String(";HOSTNAME=") + host + + QLatin1String(";PORT=") + QString::number(port) + QLatin1String(";UID=") + user + + QLatin1String(";PWD=") + password; + + SQLTCHAR connOut[SQL_MAX_OPTION_STRING_LENGTH]; SQLSMALLINT cb; @@ -1250,7 +1279,7 @@ bool QDB2Driver::open(const QString& db, const QString& user, const QString& pas return false; } - d->user = user.toUpper(); + d->user = user; setOpen(true); setOpenError(false); return true; @@ -1295,10 +1324,25 @@ QSqlRecord QDB2Driver::record(const QString& tableName) const SQLHANDLE hStmt; QString catalog, schema, table; - qSplitTableQualifier(tableName.toUpper(), &catalog, &schema, &table); + qSplitTableQualifier(tableName, &catalog, &schema, &table); if (schema.isEmpty()) schema = d->user; + if (isIdentifierEscaped(catalog, QSqlDriver::TableName)) + catalog = stripDelimiters(catalog, QSqlDriver::TableName); + else + catalog = catalog.toUpper(); + + if (isIdentifierEscaped(schema, QSqlDriver::TableName)) + schema = stripDelimiters(schema, QSqlDriver::TableName); + else + schema = schema.toUpper(); + + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + else + table = table.toUpper(); + SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT, d->hDbc, &hStmt); @@ -1312,6 +1356,9 @@ QSqlRecord QDB2Driver::record(const QString& tableName) const (SQLPOINTER) SQL_CURSOR_FORWARD_ONLY, SQL_IS_UINTEGER); + + //Aside: szSchemaName and szTableName parameters of SQLColumns + //are case sensitive search patterns, so no escaping is used. r = SQLColumns(hStmt, NULL, 0, @@ -1392,7 +1439,13 @@ QStringList QDB2Driver::tables(QSql::TableType type) const bool isNull; QString fieldVal = qGetStringData(hStmt, 2, -1, isNull); QString userVal = qGetStringData(hStmt, 1, -1, isNull); - if (userVal != d->user) + QString user = d->user; + if ( isIdentifierEscaped(user, QSqlDriver::TableName)) + user = stripDelimiters(user, QSqlDriver::TableName); + else + user = user.toUpper(); + + if (userVal != user) fieldVal = userVal + QLatin1Char('.') + fieldVal; tl.append(fieldVal); r = SQLFetchScroll(hStmt, @@ -1423,7 +1476,23 @@ QSqlIndex QDB2Driver::primaryIndex(const QString& tablename) const return index; } QString catalog, schema, table; - qSplitTableQualifier(tablename.toUpper(), &catalog, &schema, &table); + qSplitTableQualifier(tablename, &catalog, &schema, &table); + + if (isIdentifierEscaped(catalog, QSqlDriver::TableName)) + catalog = stripDelimiters(catalog, QSqlDriver::TableName); + else + catalog = catalog.toUpper(); + + if (isIdentifierEscaped(schema, QSqlDriver::TableName)) + schema = stripDelimiters(schema, QSqlDriver::TableName); + else + schema = schema.toUpper(); + + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + else + table = table.toUpper(); + r = SQLSetStmtAttr(hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index 64f13b5..0705722 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -1552,12 +1552,16 @@ QSqlRecord QIBaseDriver::record(const QString& tablename) const QSqlQuery q(createResult()); q.setForwardOnly(true); - + QString table = tablename; + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + else + table = table.toUpper(); q.exec(QLatin1String("SELECT a.RDB$FIELD_NAME, b.RDB$FIELD_TYPE, b.RDB$FIELD_LENGTH, " "b.RDB$FIELD_SCALE, b.RDB$FIELD_PRECISION, a.RDB$NULL_FLAG " "FROM RDB$RELATION_FIELDS a, RDB$FIELDS b " "WHERE b.RDB$FIELD_NAME = a.RDB$FIELD_SOURCE " - "AND a.RDB$RELATION_NAME = '") + tablename.toUpper() + QLatin1String("' " + "AND a.RDB$RELATION_NAME = '") + table + QLatin1String("' " "ORDER BY a.RDB$FIELD_POSITION")); while (q.next()) { @@ -1585,12 +1589,18 @@ QSqlIndex QIBaseDriver::primaryIndex(const QString &table) const if (!isOpen()) return index; + QString tablename = table; + if (isIdentifierEscaped(tablename, QSqlDriver::TableName)) + tablename = stripDelimiters(tablename, QSqlDriver::TableName); + else + tablename = tablename.toUpper(); + QSqlQuery q(createResult()); q.setForwardOnly(true); q.exec(QLatin1String("SELECT a.RDB$INDEX_NAME, b.RDB$FIELD_NAME, d.RDB$FIELD_TYPE, d.RDB$FIELD_SCALE " "FROM RDB$RELATION_CONSTRAINTS a, RDB$INDEX_SEGMENTS b, RDB$RELATION_FIELDS c, RDB$FIELDS d " "WHERE a.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' " - "AND a.RDB$RELATION_NAME = '") + table.toUpper() + + "AND a.RDB$RELATION_NAME = '") + tablename + QLatin1String(" 'AND a.RDB$INDEX_NAME = b.RDB$INDEX_NAME " "AND c.RDB$RELATION_NAME = a.RDB$RELATION_NAME " "AND c.RDB$FIELD_NAME = b.RDB$FIELD_NAME " diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index 9b57f3c..a84e840 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -1314,7 +1314,7 @@ QSqlIndex QMYSQLDriver::primaryIndex(const QString& tablename) const QSqlQuery i(createResult()); QString stmt(QLatin1String("show index from %1;")); QSqlRecord fil = record(tablename); - i.exec(stmt.arg(escapeIdentifier(tablename, QSqlDriver::TableName))); + i.exec(stmt.arg(tablename)); while (i.isActive() && i.next()) { if (i.value(2).toString() == QLatin1String("PRIMARY")) { idx.append(fil.field(i.value(4).toString())); @@ -1329,10 +1329,14 @@ QSqlIndex QMYSQLDriver::primaryIndex(const QString& tablename) const QSqlRecord QMYSQLDriver::record(const QString& tablename) const { + QString table=tablename; + if(isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + QSqlRecord info; if (!isOpen()) return info; - MYSQL_RES* r = mysql_list_fields(d->mysql, tablename.toLocal8Bit().constData(), 0); + MYSQL_RES* r = mysql_list_fields(d->mysql, table.toLocal8Bit().constData(), 0); if (!r) { return info; } @@ -1443,4 +1447,15 @@ QString QMYSQLDriver::escapeIdentifier(const QString &identifier, IdentifierType return res; } +bool QMYSQLDriver::isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const +{ + Q_UNUSED(type); + bool isLeftDelimited = (identifier.left(1) == QString(QLatin1Char('`'))); + bool isRightDelimited = (identifier.right(1) == QString(QLatin1Char('`'))); + if( identifier.size() > 2 && isLeftDelimited && isRightDelimited ) + return true; + else + return false; +} + QT_END_NAMESPACE diff --git a/src/sql/drivers/mysql/qsql_mysql.h b/src/sql/drivers/mysql/qsql_mysql.h index 97aa346..31d9dcf 100644 --- a/src/sql/drivers/mysql/qsql_mysql.h +++ b/src/sql/drivers/mysql/qsql_mysql.h @@ -123,6 +123,9 @@ public: QVariant handle() const; QString escapeIdentifier(const QString &identifier, IdentifierType type) const; +protected Q_SLOTS: + bool isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const; + protected: bool beginTransaction(); bool commitTransaction(); diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp index 7017d6c..fa9b5f0 100644 --- a/src/sql/drivers/oci/qsql_oci.cpp +++ b/src/sql/drivers/oci/qsql_oci.cpp @@ -2098,7 +2098,7 @@ bool QOCIDriver::open(const QString & db, setOpen(true); setOpenError(false); - d->user = user.toUpper(); + d->user = user; return true; } @@ -2200,8 +2200,15 @@ QStringList QOCIDriver::tables(QSql::TableType type) const "and owner != 'WKSYS'" "and owner != 'CTXSYS'" "and owner != 'WMSYS'")); + + QString user = d->user; + if ( isIdentifierEscaped(user, QSqlDriver::TableName)) + user = stripDelimiters(user, QSqlDriver::TableName); + else + user = user.toUpper(); + while (t.next()) { - if (t.value(0).toString() != d->user) + if (t.value(0).toString() != user) tl.append(t.value(0).toString() + QLatin1String(".") + t.value(1).toString()); else tl.append(t.value(1).toString()); @@ -2237,10 +2244,10 @@ void qSplitTableAndOwner(const QString & tname, QString * tbl, { int i = tname.indexOf(QLatin1Char('.')); // prefixed with owner? if (i != -1) { - *tbl = tname.right(tname.length() - i - 1).toUpper(); - *owner = tname.left(i).toUpper(); + *tbl = tname.right(tname.length() - i - 1); + *owner = tname.left(i); } else { - *tbl = tname.toUpper(); + *tbl = tname; } } @@ -2256,7 +2263,7 @@ QSqlRecord QOCIDriver::record(const QString& tablename) const QString stmt(QLatin1String("select column_name, data_type, data_length, " "data_precision, data_scale, nullable, data_default%1" "from all_tab_columns " - "where upper(table_name)=%2")); + "where table_name=%2")); if (d->serverVersion >= 9) stmt = stmt.arg(QLatin1String(", char_length ")); else @@ -2264,11 +2271,23 @@ QSqlRecord QOCIDriver::record(const QString& tablename) const bool buildRecordInfo = false; QString table, owner, tmpStmt; qSplitTableAndOwner(tablename, &table, &owner); + + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + else + table = table.toUpper(); + tmpStmt = stmt.arg(QLatin1Char('\'') + table + QLatin1Char('\'')); if (owner.isEmpty()) { owner = d->user; } - tmpStmt += QLatin1String(" and upper(owner)='") + owner + QLatin1String("'"); + + if (isIdentifierEscaped(owner, QSqlDriver::TableName)) + owner = stripDelimiters(owner, QSqlDriver::TableName); + else + owner = owner.toUpper(); + + tmpStmt += QLatin1String(" and owner='") + owner + QLatin1String("'"); t.setForwardOnly(true); t.exec(tmpStmt); if (!t.next()) { // try and see if the tablename is a synonym @@ -2317,11 +2336,23 @@ QSqlIndex QOCIDriver::primaryIndex(const QString& tablename) const bool buildIndex = false; QString table, owner, tmpStmt; qSplitTableAndOwner(tablename, &table, &owner); - tmpStmt = stmt + QLatin1String(" and upper(a.table_name)='") + table + QLatin1String("'"); + + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + else + table = table.toUpper(); + + tmpStmt = stmt + QLatin1String(" and a.table_name='") + table + QLatin1String("'"); if (owner.isEmpty()) { owner = d->user; } - tmpStmt += QLatin1String(" and upper(a.owner)='") + owner + QLatin1String("'"); + + if (isIdentifierEscaped(owner, QSqlDriver::TableName)) + owner = stripDelimiters(owner, QSqlDriver::TableName); + else + owner = owner.toUpper(); + + tmpStmt += QLatin1String(" and a.owner='") + owner + QLatin1String("'"); t.setForwardOnly(true); t.exec(tmpStmt); @@ -2415,13 +2446,14 @@ QVariant QOCIDriver::handle() const return qVariantFromValue(d->env); } -QString QOCIDriver::escapeIdentifier(const QString &identifier, IdentifierType /* type */) const +QString QOCIDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const { QString res = identifier; - res.replace(QLatin1Char('"'), QLatin1String("\"\"")); - if (identifier.indexOf(QLatin1Char(' ')) != -1) + if(!identifier.isEmpty() && !isIdentifierEscaped(identifier, type)) { + res.replace(QLatin1Char('"'), QLatin1String("\"\"")); res.prepend(QLatin1Char('"')).append(QLatin1Char('"')); -// res.replace(QLatin1Char('.'), QLatin1String("\".\"")); + res.replace(QLatin1Char('.'), QLatin1String("\".\"")); + } return res; } diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index f6710db..d6423ae 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -55,6 +55,7 @@ #include <qvarlengtharray.h> #include <qvector.h> #include <QDebug> +#include <QSqlQuery> QT_BEGIN_NAMESPACE @@ -88,6 +89,7 @@ static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL class QODBCDriverPrivate { public: + enum DefaultCase{Lower, Mixed, Upper, Sensitive}; QODBCDriverPrivate() : hEnv(0), hDbc(0), useSchema(false), disconnectCount(0), isMySqlServer(false), isMSSqlServer(false), hasSQLFetchScroll(true), hasMultiResultSets(false) @@ -119,6 +121,9 @@ public: bool setConnectionOptions(const QString& connOpts); void splitTableQualifier(const QString &qualifier, QString &catalog, QString &schema, QString &table); + DefaultCase defaultCase() const; + QString adjustCase(const QString&) const; + QChar quoteChar() const; }; class QODBCPrivate @@ -555,6 +560,29 @@ static int qGetODBCVersion(const QString &connOpts) return SQL_OV_ODBC2; } +QChar QODBCDriverPrivate::quoteChar() const +{ + static bool isQuoteInitialized = false; + static QChar quote = QChar::fromLatin1('"'); + if (!isQuoteInitialized) { + char driverResponse[4]; + SQLUSMALLINT casing; + SQLSMALLINT length; + int r = SQLGetInfo(hDbc, + SQL_IDENTIFIER_QUOTE_CHAR, + &driverResponse, + sizeof(driverResponse), + &length); + if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) { + quote = QChar::fromLatin1(driverResponse[0]); + } else { + quote = QChar::fromLatin1('"'); + } + isQuoteInitialized = true; + } + return quote; +} + bool QODBCDriverPrivate::setConnectionOptions(const QString& connOpts) { // Set any connection attributes @@ -705,6 +733,65 @@ void QODBCDriverPrivate::splitTableQualifier(const QString & qualifier, QString } } +QODBCDriverPrivate::DefaultCase QODBCDriverPrivate::defaultCase() const +{ + static bool isInitialized = false; + static DefaultCase ret; + + if (!isInitialized) { + SQLUSMALLINT casing; + int r = SQLGetInfo(hDbc, + SQL_IDENTIFIER_CASE, + &casing, + sizeof(casing), + NULL); + if ( r != SQL_SUCCESS) + ret = Lower;//arbitrary case if driver cannot be queried + else { + switch (casing) { + case (SQL_IC_UPPER): + ret = Upper; + break; + case (SQL_IC_LOWER): + ret = Lower; + break; + case (SQL_IC_SENSITIVE): + ret = Sensitive; + break; + case (SQL_IC_MIXED): + ret = Mixed; + break; + default: + ret = Upper; + } + } + isInitialized = true; + } + return ret; +} + +/* + Adjust the casing of an identifier to match what the + database engine would have done to it. +*/ +QString QODBCDriverPrivate::adjustCase(const QString &identifier) const +{ + QString ret = identifier; + switch(defaultCase()) { + case (Lower): + ret = identifier.toLower(); + break; + case (Upper): + ret = identifier.toUpper(); + break; + case(Mixed): + case(Sensitive): + default: + ret = identifier; + } + return ret; +} + //////////////////////////////////////////////////////////////////////////// QODBCResult::QODBCResult(const QODBCDriver * db, QODBCDriverPrivate* p) @@ -1714,6 +1801,10 @@ bool QODBCDriver::open(const QString & db, d->checkHasMultiResults(); setOpen(true); setOpenError(false); + if(d->isMSSqlServer) { + QSqlQuery i(createResult()); + i.exec(QLatin1String("SET QUOTED_IDENTIFIER ON")); + } return true; } @@ -2084,6 +2175,22 @@ QSqlIndex QODBCDriver::primaryIndex(const QString& tablename) const } QString catalog, schema, table; d->splitTableQualifier(tablename, catalog, schema, table); + + if (isIdentifierEscaped(catalog, QSqlDriver::TableName)) + catalog = stripDelimiters(catalog, QSqlDriver::TableName); + else + catalog = d->adjustCase(catalog); + + if (isIdentifierEscaped(schema, QSqlDriver::TableName)) + schema = stripDelimiters(schema, QSqlDriver::TableName); + else + schema = d->adjustCase(schema); + + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + else + table = d->adjustCase(table); + r = SQLSetStmtAttr(hStmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_FORWARD_ONLY, @@ -2186,6 +2293,22 @@ QSqlRecord QODBCDriver::record(const QString& tablename) const SQLHANDLE hStmt; QString catalog, schema, table; d->splitTableQualifier(tablename, catalog, schema, table); + + if (isIdentifierEscaped(catalog, QSqlDriver::TableName)) + catalog = stripDelimiters(catalog, QSqlDriver::TableName); + else + catalog = d->adjustCase(catalog); + + if (isIdentifierEscaped(schema, QSqlDriver::TableName)) + schema = stripDelimiters(schema, QSqlDriver::TableName); + else + schema = d->adjustCase(schema); + + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + else + table = d->adjustCase(table); + SQLRETURN r = SQLAllocHandle(SQL_HANDLE_STMT, d->hDbc, &hStmt); @@ -2309,4 +2432,15 @@ QString QODBCDriver::escapeIdentifier(const QString &identifier, IdentifierType) return res; } +bool QODBCDriver::isIdentifierEscapedImplementation(const QString &identifier, IdentifierType) const +{ + QString quote = d->quoteChar(); + bool isLeftDelimited = identifier.left(1) == quote; + bool isRightDelimited = identifier.right(1) == quote; + if( identifier.size() > 2 && isLeftDelimited && isRightDelimited ) + return true; + else + return false; +} + QT_END_NAMESPACE diff --git a/src/sql/drivers/odbc/qsql_odbc.h b/src/sql/drivers/odbc/qsql_odbc.h index 4148007..51f53ea 100644 --- a/src/sql/drivers/odbc/qsql_odbc.h +++ b/src/sql/drivers/odbc/qsql_odbc.h @@ -145,10 +145,14 @@ public: QString escapeIdentifier(const QString &identifier, IdentifierType type) const; +protected Q_SLOTS: + bool isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const; + protected: bool beginTransaction(); bool commitTransaction(); bool rollbackTransaction(); + private: void init(); bool endTrans(); diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index afe45fc..16d19f1 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -894,6 +894,16 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const QString schema; qSplitTableName(tbl, schema); + if (isIdentifierEscaped(tbl, QSqlDriver::TableName)) + tbl = stripDelimiters(tbl, QSqlDriver::TableName); + else + tbl = tbl.toLower(); + + if (isIdentifierEscaped(schema, QSqlDriver::TableName)) + schema = stripDelimiters(schema, QSqlDriver::TableName); + else + schema = schema.toLower(); + switch(d->pro) { case QPSQLDriver::Version6: stmt = QLatin1String("select pg_att1.attname, int(pg_att1.atttypid), pg_cl.relname " @@ -926,7 +936,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const "FROM pg_attribute, pg_class " "WHERE %1 pg_class.oid IN " "(SELECT indexrelid FROM pg_index WHERE indisprimary = true AND indrelid IN " - " (SELECT oid FROM pg_class WHERE lower(relname) = '%2')) " + " (SELECT oid FROM pg_class WHERE relname = '%2')) " "AND pg_attribute.attrelid = pg_class.oid " "AND pg_attribute.attisdropped = false " "ORDER BY pg_attribute.attnum"); @@ -934,11 +944,11 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid) AND")); else stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from " - "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema.toLower())); + "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema)); break; } - i.exec(stmt.arg(tbl.toLower())); + i.exec(stmt.arg(tbl)); while (i.isActive() && i.next()) { QSqlField f(i.value(0).toString(), qDecodePSQLType(i.value(1).toInt())); idx.append(f); @@ -957,6 +967,16 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const QString schema; qSplitTableName(tbl, schema); + if (isIdentifierEscaped(tbl, QSqlDriver::TableName)) + tbl = stripDelimiters(tbl, QSqlDriver::TableName); + else + tbl = tbl.toLower(); + + if (isIdentifierEscaped(schema, QSqlDriver::TableName)) + schema = stripDelimiters(schema, QSqlDriver::TableName); + else + schema = schema.toLower(); + QString stmt; switch(d->pro) { case QPSQLDriver::Version6: @@ -1001,7 +1021,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const "left join pg_attrdef on (pg_attrdef.adrelid = " "pg_attribute.attrelid and pg_attrdef.adnum = pg_attribute.attnum) " "where %1 " - "and lower(pg_class.relname) = '%2' " + "and pg_class.relname = '%2' " "and pg_attribute.attnum > 0 " "and pg_attribute.attrelid = pg_class.oid " "and pg_attribute.attisdropped = false " @@ -1010,12 +1030,12 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const stmt = stmt.arg(QLatin1String("pg_table_is_visible(pg_class.oid)")); else stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from " - "pg_namespace where pg_namespace.nspname = '%1')").arg(schema.toLower())); + "pg_namespace where pg_namespace.nspname = '%1')").arg(schema)); break; } QSqlQuery query(createResult()); - query.exec(stmt.arg(tbl.toLower())); + query.exec(stmt.arg(tbl)); if (d->pro >= QPSQLDriver::Version71) { while (query.next()) { int len = query.value(3).toInt(); diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp index 605c4e8..f732077 100644 --- a/src/sql/drivers/sqlite/qsql_sqlite.cpp +++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp @@ -661,9 +661,13 @@ QSqlIndex QSQLiteDriver::primaryIndex(const QString &tblname) const if (!isOpen()) return QSqlIndex(); + QString table = tblname; + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + QSqlQuery q(createResult()); q.setForwardOnly(true); - return qGetTableInfo(q, tblname, true); + return qGetTableInfo(q, table, true); } QSqlRecord QSQLiteDriver::record(const QString &tbl) const @@ -671,9 +675,13 @@ QSqlRecord QSQLiteDriver::record(const QString &tbl) const if (!isOpen()) return QSqlRecord(); + QString table = tbl; + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + QSqlQuery q(createResult()); q.setForwardOnly(true); - return qGetTableInfo(q, tbl); + return qGetTableInfo(q, table); } QVariant QSQLiteDriver::handle() const @@ -681,10 +689,10 @@ QVariant QSQLiteDriver::handle() const return qVariantFromValue(d->access); } -QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType /*type*/) const +QString QSQLiteDriver::escapeIdentifier(const QString &identifier, IdentifierType type) const { QString res = identifier; - if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) { + if(!identifier.isEmpty() && !isIdentifierEscaped(identifier, type) ) { res.replace(QLatin1Char('"'), QLatin1String("\"\"")); res.prepend(QLatin1Char('"')).append(QLatin1Char('"')); res.replace(QLatin1Char('.'), QLatin1String("\".\"")); diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp index ff73caa..d0c6e18 100644 --- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp +++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp @@ -167,7 +167,15 @@ void QSQLite2ResultPrivate::init(const char **cnames, int numCols) for (int i = 0; i < numCols; ++i) { const char* lastDot = strrchr(cnames[i], '.'); const char* fieldName = lastDot ? lastDot + 1 : cnames[i]; - rInf.append(QSqlField(QString::fromAscii(fieldName), + + //remove quotations around the field name if any + QString fieldStr = QString::fromAscii(fieldName); + QString quote = QString::fromLatin1("\""); + if ( fieldStr.length() > 2 && fieldStr.left(1) == quote && fieldStr.right(1) == quote) { + fieldStr = fieldStr.mid(1); + fieldStr.chop(1); + } + rInf.append(QSqlField(fieldStr, nameToType(QString::fromAscii(cnames[i+numCols])))); } } @@ -503,8 +511,11 @@ QSqlIndex QSQLite2Driver::primaryIndex(const QString &tblname) const QSqlQuery q(createResult()); q.setForwardOnly(true); + QString table = tblname; + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); // finrst find a UNIQUE INDEX - q.exec(QLatin1String("PRAGMA index_list('") + tblname + QLatin1String("');")); + q.exec(QLatin1String("PRAGMA index_list('") + table + QLatin1String("');")); QString indexname; while(q.next()) { if (q.value(2).toInt()==1) { @@ -517,7 +528,7 @@ QSqlIndex QSQLite2Driver::primaryIndex(const QString &tblname) const q.exec(QLatin1String("PRAGMA index_info('") + indexname + QLatin1String("');")); - QSqlIndex index(tblname, indexname); + QSqlIndex index(table, indexname); while(q.next()) { QString name = q.value(2).toString(); QVariant::Type type = QVariant::Invalid; @@ -532,6 +543,9 @@ QSqlRecord QSQLite2Driver::record(const QString &tbl) const { if (!isOpen()) return QSqlRecord(); + QString table = tbl; + if (isIdentifierEscaped(tbl, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); QSqlQuery q(createResult()); q.setForwardOnly(true); diff --git a/src/sql/drivers/tds/qsql_tds.cpp b/src/sql/drivers/tds/qsql_tds.cpp index 46e4a0b..515f0de 100644 --- a/src/sql/drivers/tds/qsql_tds.cpp +++ b/src/sql/drivers/tds/qsql_tds.cpp @@ -293,6 +293,8 @@ QTDSResult::QTDSResult(const QTDSDriver* db) // insert d in error handler dict errs()->insert(d->dbproc, d); + dbcmd(d->dbproc, "set quoted_identifier on"); + dbsqlexec(d->dbproc); } QTDSResult::~QTDSResult() @@ -367,7 +369,7 @@ bool QTDSResult::gotoNext(QSqlCachedResult::ValueCache &values, int index) if (qIsNull(d->buffer.at(i * 2 + 1))) values[idx] = QVariant(QVariant::String); else - values[idx] = QString::fromLocal8Bit((const char*)d->buffer.at(i * 2)); + values[idx] = QString::fromLocal8Bit((const char*)d->buffer.at(i * 2)).trimmed(); break; case QVariant::ByteArray: { if (qIsNull(d->buffer.at(i * 2 + 1))) @@ -698,9 +700,14 @@ QSqlRecord QTDSDriver::record(const QString& tablename) const return info; QSqlQuery t(createResult()); t.setForwardOnly(true); + + QString table = tablename; + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + QString stmt (QLatin1String("select name, type, length, prec from syscolumns " "where id = (select id from sysobjects where name = '%1')")); - t.exec(stmt.arg(tablename)); + t.exec(stmt.arg(table)); while (t.next()) { QSqlField f(t.value(0).toString().simplified(), qDecodeTDSType(t.value(1).toInt())); f.setLength(t.value(2).toInt()); @@ -770,13 +777,17 @@ QSqlIndex QTDSDriver::primaryIndex(const QString& tablename) const { QSqlRecord rec = record(tablename); - QSqlIndex idx(tablename); - if ((!isOpen()) || (tablename.isEmpty())) + QString table = tablename; + if (isIdentifierEscaped(table, QSqlDriver::TableName)) + table = stripDelimiters(table, QSqlDriver::TableName); + + QSqlIndex idx(table); + if ((!isOpen()) || (table.isEmpty())) return QSqlIndex(); QSqlQuery t(createResult()); t.setForwardOnly(true); - t.exec(QString::fromLatin1("sp_helpindex '%1'").arg(tablename)); + t.exec(QString::fromLatin1("sp_helpindex '%1'").arg(table)); if (t.next()) { QStringList fNames = t.value(2).toString().simplified().split(QLatin1Char(',')); QRegExp regx(QLatin1String("\\s*(\\S+)(?:\\s+(DESC|desc))?\\s*")); diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp index a995005..40bc0df 100644 --- a/src/sql/kernel/qsqldriver.cpp +++ b/src/sql/kernel/qsqldriver.cpp @@ -49,6 +49,17 @@ QT_BEGIN_NAMESPACE +static QString prepareIdentifier(const QString &identifier, + QSqlDriver::IdentifierType type, const QSqlDriver *driver) +{ + Q_ASSERT( driver != NULL ); + QString ret = identifier; + if (!driver->isIdentifierEscaped(identifier, type)) { + ret = driver->escapeIdentifier(identifier, type); + } + return ret; +} + class QSqlDriverPrivate : public QObjectPrivate { public: @@ -372,6 +383,7 @@ QSqlRecord QSqlDriver::record(const QString & /* tableName */) const on \a type. The default implementation does nothing. + \sa isIdentifierEscaped() */ QString QSqlDriver::escapeIdentifier(const QString &identifier, IdentifierType) const { @@ -379,6 +391,55 @@ QString QSqlDriver::escapeIdentifier(const QString &identifier, IdentifierType) } /*! + Returns whether \a identifier is escaped according to the database rules. + \a identifier can either be a table name or field name, dependent + on \a type. + + \warning Because of binary compatability constraints, this function is not virtual. + If you want to provide your own implementation in your QSqlDriver subclass, + reimplement the isIdentifierEscapedImplementation() slot in your subclass instead. + The isIdentifierEscapedFunction() will dynamically detect the slot and call it. + + \sa stripDelimiters(), escapeIdentifier() + */ +bool QSqlDriver::isIdentifierEscaped(const QString &identifier, IdentifierType type) const +{ + bool result; + QMetaObject::invokeMethod(const_cast<QSqlDriver*>(this), + "isIdentifierEscapedImplementation", Qt::DirectConnection, + Q_RETURN_ARG(bool, result), + Q_ARG(QString, identifier), + Q_ARG(IdentifierType, type)); + return result; +} + +/*! + Returns the \a identifier with the leading and trailing delimiters removed, + \a identifier can either be a table name or field name, + dependent on \a type. If \a identifier does not have leading + and trailing delimiter characters, \a identifier is returned without + modification. + + \warning Because of binary compatability constraints, this function is not virtual, + If you want to provide your own implementation in your QSqlDriver subclass, + reimplement the stripDelimitersImplementation() slot in your subclass instead. + The stripDelimiters() function will dynamically detect the slot and call it. + + \since 4.5 + \sa isIdentifierEscaped() + */ +QString QSqlDriver::stripDelimiters(const QString &identifier, IdentifierType type) const +{ + QString result; + QMetaObject::invokeMethod(const_cast<QSqlDriver*>(this), + "stripDelimitersImplementation", Qt::DirectConnection, + Q_RETURN_ARG(QString, result), + Q_ARG(QString, identifier), + Q_ARG(IdentifierType, type)); + return result; +} + +/*! Returns a SQL statement of type \a type for the table \a tableName with the values from \a rec. If \a preparedStatement is true, the string will contain placeholders instead of values. @@ -397,17 +458,17 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, case SelectStatement: for (i = 0; i < rec.count(); ++i) { if (rec.isGenerated(i)) - s.append(escapeIdentifier(rec.fieldName(i), FieldName)).append(QLatin1String(", ")); + s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)).append(QLatin1String(", ")); } if (s.isEmpty()) return s; s.chop(2); - s.prepend(QLatin1String("SELECT ")).append(QLatin1String(" FROM ")).append(escapeIdentifier(tableName, TableName)); + s.prepend(QLatin1String("SELECT ")).append(QLatin1String(" FROM ")).append(tableName); break; case WhereStatement: if (preparedStatement) { for (int i = 0; i < rec.count(); ++i) { - s.append(escapeIdentifier(rec.fieldName(i), FieldName)); + s.append(prepareIdentifier(rec.fieldName(i), FieldName,this)); if (rec.isNull(i)) s.append(QLatin1String(" IS NULL")); else @@ -416,7 +477,7 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, } } else { for (i = 0; i < rec.count(); ++i) { - s.append(escapeIdentifier(rec.fieldName(i), FieldName)); + s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)); QString val = formatValue(rec.field(i)); if (val == QLatin1String("NULL")) s.append(QLatin1String(" IS NULL")); @@ -431,12 +492,12 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, } break; case UpdateStatement: - s.append(QLatin1String("UPDATE ")).append(escapeIdentifier(tableName, TableName)).append( + s.append(QLatin1String("UPDATE ")).append(tableName).append( QLatin1String(" SET ")); for (i = 0; i < rec.count(); ++i) { if (!rec.isGenerated(i) || !rec.value(i).isValid()) continue; - s.append(escapeIdentifier(rec.fieldName(i), FieldName)).append(QLatin1Char('=')); + s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)).append(QLatin1Char('=')); if (preparedStatement) s.append(QLatin1Char('?')); else @@ -449,15 +510,15 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, s.clear(); break; case DeleteStatement: - s.append(QLatin1String("DELETE FROM ")).append(escapeIdentifier(tableName, TableName)); + s.append(QLatin1String("DELETE FROM ")).append(tableName); break; case InsertStatement: { - s.append(QLatin1String("INSERT INTO ")).append(escapeIdentifier(tableName, TableName)).append(QLatin1String(" (")); + s.append(QLatin1String("INSERT INTO ")).append(tableName).append(QLatin1String(" (")); QString vals; for (i = 0; i < rec.count(); ++i) { if (!rec.isGenerated(i) || !rec.value(i).isValid()) continue; - s.append(escapeIdentifier(rec.fieldName(i), FieldName)).append(QLatin1String(", ")); + s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)).append(QLatin1String(", ")); if (preparedStatement) vals.append(QLatin1String("?")); else @@ -805,4 +866,56 @@ QStringList QSqlDriver::subscribedToNotificationsImplementation() const return QStringList(); } +/*! + This slot returns whether \a identifier is escaped according to the database rules. + \a identifier can either be a table name or field name, dependent + on \a type. + + Because of binary compatability constraints, isIdentifierEscaped() function + (introduced in Qt 4.5) is not virtual. Instead, isIdentifierEscaped() will + dynamically detect and call \e this slot. The default implementation + assumes the escape/delimiter character is a double quote. Reimplement this + slot in your own QSqlDriver if your database engine uses a different + delimiter character. + + \since 4.5 + \sa isIdentifierEscaped() + */ +bool QSqlDriver::isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const +{ + Q_UNUSED(type); + bool isLeftDelimited = identifier.left(1) == QString(QLatin1Char('"')); + bool isRightDelimited = identifier.right(1) == QString(QLatin1Char('"')); + if( identifier.size() > 2 && isLeftDelimited && isRightDelimited ) + return true; + else + return false; +} + +/*! + This slot returns \a identifier with the leading and trailing delimiters removed, + \a identifier can either be a tablename or field name, dependent on \a type. + If \a identifier does not have leading and trailing delimiter characters, \a + identifier is returned without modification. + + Because of binary compatability constraints, the stripDelimiters() function + (introduced in Qt 4.5) is not virtual. Instead, stripDelimiters() will + dynamically detect and call \e this slot. It generally unnecessary + to reimplement this slot. + + \since 4.5 + \sa stripDelimiters() + */ +QString QSqlDriver::stripDelimitersImplementation(const QString &identifier, IdentifierType type) const +{ + QString ret; + if (this->isIdentifierEscaped(identifier, type)) { + ret = identifier.mid(1); + ret.chop(1); + } else { + ret = identifier; + } + return ret; +} + QT_END_NAMESPACE diff --git a/src/sql/kernel/qsqldriver.h b/src/sql/kernel/qsqldriver.h index e763719..8ac1471 100644 --- a/src/sql/kernel/qsqldriver.h +++ b/src/sql/kernel/qsqldriver.h @@ -127,6 +127,9 @@ public: bool unsubscribeFromNotification(const QString &name); // ### Qt 5: make virtual QStringList subscribedToNotifications() const; // ### Qt 5: make virtual + bool isIdentifierEscaped(const QString &identifier, IdentifierType type) const; // ### Qt 5: make virtual + QString stripDelimiters(const QString &identifier, IdentifierType type) const; // ### Qt 5: make virtual + Q_SIGNALS: void notification(const QString &name); @@ -140,6 +143,9 @@ protected Q_SLOTS: bool unsubscribeFromNotificationImplementation(const QString &name); // ### Qt 5: eliminate, see unsubscribeFromNotification() QStringList subscribedToNotificationsImplementation() const; // ### Qt 5: eliminate, see subscribedNotifications() + bool isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const; // ### Qt 5: eliminate, see isIdentifierEscaped() + QString stripDelimitersImplementation(const QString &identifier, IdentifierType type) const; // ### Qt 5: eliminate, see stripDelimiters() + private: Q_DISABLE_COPY(QSqlDriver) }; diff --git a/src/sql/models/qsqlrelationaltablemodel.cpp b/src/sql/models/qsqlrelationaltablemodel.cpp index 935466b..12eae84 100644 --- a/src/sql/models/qsqlrelationaltablemodel.cpp +++ b/src/sql/models/qsqlrelationaltablemodel.cpp @@ -182,10 +182,21 @@ void QRelation::populateDictionary() populateModel(); QSqlRecord record; + QString indexColumn; + QString displayColumn; for (int i=0; i < model->rowCount(); ++i) { record = model->record(i); - dictionary[record.field(rel.indexColumn()).value().toString()] = - record.field(rel.displayColumn()).value(); + + indexColumn = rel.indexColumn(); + if (m_parent->database().driver()->isIdentifierEscaped(indexColumn, QSqlDriver::FieldName)) + indexColumn = m_parent->database().driver()->stripDelimiters(indexColumn, QSqlDriver::FieldName); + + displayColumn = rel.displayColumn(); + if (m_parent->database().driver()->isIdentifierEscaped(displayColumn, QSqlDriver::FieldName)) + displayColumn = m_parent->database().driver()->stripDelimiters(displayColumn, QSqlDriver::FieldName); + + dictionary[record.field(indexColumn).value().toString()] = + record.field(displayColumn).value(); } m_dictInitialized = true; } @@ -215,7 +226,7 @@ public: QSqlRelationalTableModelPrivate() : QSqlTableModelPrivate() {} - QString escapedRelationField(const QString &tableName, const QString &fieldName) const; + QString relationField(const QString &tableName, const QString &fieldName) const; int nameToIndex(const QString &name) const; mutable QVector<QRelation> relations; @@ -255,7 +266,10 @@ void QSqlRelationalTableModelPrivate::revertCachedRow(int row) int QSqlRelationalTableModelPrivate::nameToIndex(const QString &name) const { - return baseRec.indexOf(name); + QString fieldname = name; + if (db.driver()->isIdentifierEscaped(fieldname, QSqlDriver::FieldName)) + fieldname = db.driver()->stripDelimiters(fieldname, QSqlDriver::FieldName); + return baseRec.indexOf(fieldname); } void QSqlRelationalTableModelPrivate::clearEditBuffer() @@ -481,14 +495,14 @@ QSqlRelation QSqlRelationalTableModel::relation(int column) const return d->relations.value(column).rel; } -QString QSqlRelationalTableModelPrivate::escapedRelationField(const QString &tableName, +QString QSqlRelationalTableModelPrivate::relationField(const QString &tableName, const QString &fieldName) const { - QString esc; - esc.reserve(tableName.size() + fieldName.size() + 1); - esc.append(tableName).append(QLatin1Char('.')).append(fieldName); + QString ret; + ret.reserve(tableName.size() + fieldName.size() + 1); + ret.append(tableName).append(QLatin1Char('.')).append(fieldName); - return db.driver()->escapeIdentifier(esc, QSqlDriver::FieldName); + return ret; } /*! @@ -514,15 +528,29 @@ QString QSqlRelationalTableModel::selectStatement() const // Count how many times each field name occurs in the record QHash<QString, int> fieldNames; + QStringList fieldList; for (int i = 0; i < rec.count(); ++i) { QSqlRelation relation = d->relations.value(i, nullRelation).rel; QString name; if (relation.isValid()) + { // Count the display column name, not the original foreign key name = relation.displayColumn(); + if (d->db.driver()->isIdentifierEscaped(name, QSqlDriver::FieldName)) + name = d->db.driver()->stripDelimiters(name, QSqlDriver::FieldName); + + QSqlRecord rec = database().record(relation.tableName()); + for (int i = 0; i < rec.count(); ++i) { + if (name.compare(rec.fieldName(i), Qt::CaseInsensitive) == 0) { + name = rec.fieldName(i); + break; + } + } + } else name = rec.fieldName(i); fieldNames.insert(name, fieldNames.value(name, 0) + 1); + fieldList.append(name); } for (int i = 0; i < rec.count(); ++i) { @@ -531,27 +559,30 @@ QString QSqlRelationalTableModel::selectStatement() const QString relTableAlias = QString::fromLatin1("relTblAl_%1").arg(i); if (!fList.isEmpty()) fList.append(QLatin1String(", ")); - fList.append(d->escapedRelationField(relTableAlias, relation.displayColumn())); + fList.append(d->relationField(relTableAlias,relation.displayColumn())); // If there are duplicate field names they must be aliased - if (fieldNames.value(relation.displayColumn()) > 1) { - fList.append(QString::fromLatin1(" AS %1_%2").arg(relation.tableName()).arg(relation.displayColumn())); + if (fieldNames.value(fieldList[i]) > 1) { + QString relTableName = relation.tableName(); + if (d->db.driver()->isIdentifierEscaped(relTableName, QSqlDriver::TableName)) + relTableName = d->db.driver()->stripDelimiters(relTableName, QSqlDriver::TableName); + QString displayColumn = relation.displayColumn(); + if (d->db.driver()->isIdentifierEscaped(displayColumn, QSqlDriver::FieldName)) + displayColumn = d->db.driver()->stripDelimiters(displayColumn, QSqlDriver::FieldName); + fList.append(QString::fromLatin1(" AS %1_%2").arg(relTableName).arg(displayColumn)); } // this needs fixing!! the below if is borken. - if (!tables.contains(relation.tableName())) - tables.append(d->db.driver()->escapeIdentifier(relation.tableName(),QSqlDriver::TableName) - .append(QLatin1String(" ")) - .append(d->db.driver()->escapeIdentifier(relTableAlias, QSqlDriver::TableName))); + tables.append(relation.tableName().append(QLatin1String(" ")).append(relTableAlias)); if(!where.isEmpty()) where.append(QLatin1String(" AND ")); - where.append(d->escapedRelationField(tableName(), rec.fieldName(i))); + where.append(d->relationField(tableName(), d->db.driver()->escapeIdentifier(rec.fieldName(i), QSqlDriver::FieldName))); where.append(QLatin1String(" = ")); - where.append(d->escapedRelationField(relTableAlias, relation.indexColumn())); + where.append(d->relationField(relTableAlias, relation.indexColumn())); } else { if (!fList.isEmpty()) fList.append(QLatin1String(", ")); - fList.append(d->escapedRelationField(tableName(), rec.fieldName(i))); + fList.append(d->relationField(tableName(), d->db.driver()->escapeIdentifier(rec.fieldName(i), QSqlDriver::FieldName))); } } if (!tables.isEmpty()) @@ -560,7 +591,7 @@ QString QSqlRelationalTableModel::selectStatement() const return query; if(!tList.isEmpty()) tList.prepend(QLatin1String(", ")); - tList.prepend(d->db.driver()->escapeIdentifier(tableName(),QSqlDriver::TableName)); + tList.prepend(tableName()); query.append(QLatin1String("SELECT ")); query.append(fList).append(QLatin1String(" FROM ")).append(tList); qAppendWhereClause(query, where, filter()); @@ -690,7 +721,7 @@ QString QSqlRelationalTableModel::orderByClause() const return QSqlTableModel::orderByClause(); QString s = QLatin1String("ORDER BY "); - s.append(d->escapedRelationField(QLatin1String("relTblAl_") + QString::number(d->sortColumn), + s.append(d->relationField(QLatin1String("relTblAl_") + QString::number(d->sortColumn), rel.displayColumn())); s += d->sortOrder == Qt::AscendingOrder ? QLatin1String(" ASC") : QLatin1String(" DESC"); return s; diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 2fb9b0f..c2442c5 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -98,7 +98,10 @@ bool QSqlTableModelPrivate::setRecord(int row, const QSqlRecord &record) int QSqlTableModelPrivate::nameToIndex(const QString &name) const { - return rec.indexOf(name); + QString fieldname = name; + if (db.driver()->isIdentifierEscaped(fieldname, QSqlDriver::FieldName)) + fieldname = db.driver()->stripDelimiters(fieldname, QSqlDriver::FieldName); + return rec.indexOf(fieldname); } void QSqlTableModelPrivate::initRecordAndPrimaryIndex() @@ -367,10 +370,7 @@ void QSqlTableModel::setTable(const QString &tableName) { Q_D(QSqlTableModel); clear(); - if(d->db.tables().contains(tableName.toUpper())) - d->tableName = tableName.toUpper(); - else - d->tableName = tableName; + d->tableName = tableName; d->initRecordAndPrimaryIndex(); d->initColOffsets(d->rec.count()); @@ -976,7 +976,9 @@ QString QSqlTableModel::orderByClause() const if (!f.isValid()) return s; - QString table = d->db.driver()->escapeIdentifier(d->tableName, QSqlDriver::TableName); + QString table = d->tableName; + //we can safely escape the field because it would have been obtained from the database + //and have the correct case QString field = d->db.driver()->escapeIdentifier(f.name(), QSqlDriver::FieldName); s.append(QLatin1String("ORDER BY ")).append(table).append(QLatin1Char('.')).append(field); s += d->sortOrder == Qt::AscendingOrder ? QLatin1String(" ASC") : QLatin1String(" DESC"); @@ -1317,8 +1319,12 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &record) mrow.rec = d->rec; mrow.primaryValues = d->primaryValues(indexInQuery(createIndex(row, 0)).row()); } + QString fieldName; for (int i = 0; i < record.count(); ++i) { - int idx = mrow.rec.indexOf(record.fieldName(i)); + fieldName = record.fieldName(i); + if (d->db.driver()->isIdentifierEscaped(fieldName, QSqlDriver::FieldName)) + fieldName = d->db.driver()->stripDelimiters(fieldName, QSqlDriver::FieldName); + int idx = mrow.rec.indexOf(fieldName); if (idx == -1) isOk = false; else |