diff options
Diffstat (limited to 'src')
50 files changed, 1004 insertions, 627 deletions
diff --git a/src/corelib/concurrent/qfuturewatcher.cpp b/src/corelib/concurrent/qfuturewatcher.cpp index 3065205..3b808b8 100644 --- a/src/corelib/concurrent/qfuturewatcher.cpp +++ b/src/corelib/concurrent/qfuturewatcher.cpp @@ -499,6 +499,13 @@ void QFutureWatcherBasePrivate::sendCallOutEvent(QFutureCallOutEvent *event) /*! \fn void QFutureWatcher::setFuture(const QFuture<T> &future) Starts watching the given \a future. + + One of the signals might be emitted for the current state of the + \a future. For example, if the future is already stopped, the + finished signal will be emitted. + + To avoid a race condition, it is important to call this function + \i after doing the connections. */ /*! \fn QFuture<T> QFutureWatcher::future() const diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 7e7d7d8..4d48b60 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -814,7 +814,7 @@ namespace QT_NAMESPACE {} # define Q_WS_MAC32 # endif # elif defined(Q_OS_SYMBIAN) -# if (defined(__SERIES60_31__) || defined(__S60_32__) || defined(__S60_50__)) && !defined(QT_NO_S60) +# if !defined(QT_NO_S60) # define Q_WS_S60 # endif # elif !defined(Q_WS_QWS) @@ -2414,10 +2414,11 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); #if defined(Q_OS_SYMBIAN) -#ifdef SYMBIAN_GRAPHICS_USE_GCE +#ifdef SYMBIAN_BUILD_GCE //RWsPointerCursor is fixed, so don't use low performance sprites #define Q_SYMBIAN_FIXED_POINTER_CURSORS #define Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE +#define Q_SYMBIAN_WINDOW_SIZE_CACHE //enabling new graphics resources #define QT_SYMBIAN_SUPPORTS_SGIMAGE #define QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index fc35bfa..2731ae1 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -159,10 +159,9 @@ QT_BEGIN_NAMESPACE \section1 Reading and writing Qt collection classes - The Qt collection classes can also be serialized to a QDataStream. + The Qt container classes can also be serialized to a QDataStream. These include QList, QLinkedList, QVector, QSet, QHash, and QMap. - These classes have have stream operators declared as non-member of - the class. + The stream operators are declared as non-members of the classes. \target Serializing Qt Classes \section1 Reading and writing other Qt classes. diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 7cfdddf..505889e 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -960,13 +960,14 @@ void QDir::setNameFilters(const QStringList &nameFilters) /*! \obsolete + + Use QDir::addSearchPath() with a prefix instead. + Adds \a path to the search paths searched in to find resources that are not specified with an absolute path. The default search path is to search only in the root (\c{:/}). - Use QDir::addSearchPath() with a prefix instead. - - \sa {The Qt Resource System}, QResource::addSearchPath() + \sa {The Qt Resource System} */ void QDir::addResourceSearchPath(const QString &path) { diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 9179485..d2fa744 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -1270,7 +1270,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla int pageSize = getpagesize(); int extra = offset % pageSize; - if (size + extra > (size_t)-1) { + if (quint64(size + extra) > quint64((size_t)-1)) { q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL))); return 0; } diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 4e14ba8..662100a 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1003,8 +1003,8 @@ QByteArray QIODevice::readAll() to a maximum of \a maxSize - 1 bytes, stores the characters in \a data, and returns the number of bytes read. If a line could not be read but no error ocurred, this function returns 0. If an error - occurs, this function returns what it could the length of what - could be read, or -1 if nothing was read. + occurs, this function returns the length of what could be read, or + -1 if nothing was read. A terminating '\0' byte is always appended to \a data, so \a maxSize must be larger than 1. diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index adfbb15..6d33c8b 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -555,16 +555,15 @@ QStringList QResource::children() const /*! \obsolete + Use QDir::addSearchPath() with a prefix instead. + Adds \a path to the search paths searched in to find resources that are not specified with an absolute path. The \a path must be an absolute path (start with \c{/}). The default search path is to search only in the root (\c{:/}). The last path added will be consulted first upon next QResource creation. - - Use QDir::addSearchPath() with a prefix instead. */ - void QResource::addSearchPath(const QString &path) { @@ -578,6 +577,10 @@ QResource::addSearchPath(const QString &path) } /*! + \obsolete + + Use QDir::searchPaths() instead. + Returns the current search path list. This list is consulted when creating a relative resource. diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 0290fb8..acb73fd 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -437,17 +437,19 @@ static bool QT_FASTCALL _unreserved(const char **ptr) } // scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) -static void QT_FASTCALL _scheme(const char **ptr, QUrlParseData *parseData) +static bool QT_FASTCALL _scheme(const char **ptr, QUrlParseData *parseData) { bool first = true; + bool isSchemeValid = true; parseData->scheme = *ptr; for (;;) { char ch = **ptr; if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { ; - } else if (!first && ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.')) { - ; + } else if ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.') { + if (first) + isSchemeValid = false; } else { break; } @@ -457,11 +459,14 @@ static void QT_FASTCALL _scheme(const char **ptr, QUrlParseData *parseData) } if (**ptr != ':') { + isSchemeValid = true; *ptr = parseData->scheme; } else { parseData->schemeLength = *ptr - parseData->scheme; ++(*ptr); // skip ':' } + + return isSchemeValid; } // IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) @@ -3743,7 +3748,19 @@ void QUrlPrivate::parse(ParseOptions parseOptions) const #endif // optional scheme - _scheme(ptr, &parseData); + bool isSchemeValid = _scheme(ptr, &parseData); + + if (isSchemeValid == false) { + that->isValid = false; + char ch = *((*ptr)++); + that->errorInfo.setParams(*ptr, QT_TRANSLATE_NOOP(QUrl, "unexpected URL scheme"), + 0, ch); + QURL_SETFLAG(that->stateFlags, Validated | Parsed); +#if defined (QURL_DEBUG) + qDebug("QUrlPrivate::parse(), unrecognized: %c%s", ch, *ptr); +#endif + return; + } // hierpart _hierPart(ptr, &parseData); diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp index 12badf0..e7dd769 100644 --- a/src/corelib/tools/qscopedpointer.cpp +++ b/src/corelib/tools/qscopedpointer.cpp @@ -225,4 +225,59 @@ QT_BEGIN_NAMESPACE Swap this pointer with \a other. */ +/*! + \class QScopedArrayPointer + + \brief The QScopedArrayPointer class stores a pointer to a + dynamically allocated array of objects, and deletes it upon + destruction. + + \since 4.6 + \reentrant + \ingroup misc + + A QScopedArrayPointer is a QScopedPointer that defaults to + deleting the object it is pointing to with the delete[] operator. It + also features operator[] for convenience, so we can write: + + \code + void foo() + { + QScopedArrayPointer<int> i(new int[10]); + i[2] = 42; + ... + return; // our integer array is now deleted using delete[] + } + \endcode +*/ + +/*! + \fn QScopedArrayPointer::QScopedArrayPointer(T *p = 0) + + Constructs this QScopedArrayPointer instance and sets its pointer + to \a p. +*/ + +/*! + \fn T *QScopedArrayPointer::operator[](int i) + + Provides access to entry \a i of the scoped pointer's array of + objects. + + If the contained pointer is \c null, behavior is undefined. + + \sa isNull() +*/ + +/*! + \fn T *QScopedArrayPointer::operator[](int i) const + + Provides access to entry \a i of the scoped pointer's array of + objects. + + If the contained pointer is \c null, behavior is undefined. + + \sa isNull() +*/ + QT_END_NAMESPACE diff --git a/src/gui/dialogs/qcolordialog_mac.mm b/src/gui/dialogs/qcolordialog_mac.mm index bdcb872..8af0d2b 100644 --- a/src/gui/dialogs/qcolordialog_mac.mm +++ b/src/gui/dialogs/qcolordialog_mac.mm @@ -96,6 +96,7 @@ QT_USE_NAMESPACE - (void)finishOffWithCode:(NSInteger)result; - (void)showColorPanel; - (void)exec; +- (void)setResultSet:(BOOL)result; @end @implementation QCocoaColorPanelDelegate @@ -158,6 +159,11 @@ QT_USE_NAMESPACE [super dealloc]; } +- (void)setResultSet:(BOOL)result +{ + mResultSet = result; +} + - (BOOL)windowShouldClose:(id)window { Q_UNUSED(window); @@ -320,7 +326,7 @@ QT_USE_NAMESPACE } else { mPriv->colorDialog()->accept(); } - } + } } } @@ -433,7 +439,7 @@ void QColorDialogPrivate::openCocoaColorPanel(const QColor &initial, priv:this]; [colorPanel setDelegate:static_cast<QCocoaColorPanelDelegate *>(delegate)]; } - + [delegate setResultSet:false]; setCocoaPanelColor(initial); [static_cast<QCocoaColorPanelDelegate *>(delegate) showColorPanel]; } diff --git a/src/gui/dialogs/qfontdialog.cpp b/src/gui/dialogs/qfontdialog.cpp index 56580a9..a4bf15d 100644 --- a/src/gui/dialogs/qfontdialog.cpp +++ b/src/gui/dialogs/qfontdialog.cpp @@ -989,34 +989,24 @@ void QFontDialog::open(QObject *receiver, const char *member) void QFontDialog::setVisible(bool visible) { Q_D(QFontDialog); - if (visible) - d->selectedFont = QFont(); - -#if defined(Q_WS_MAC) - bool isCurrentlyVisible = (isVisible() || d->delegate); - - if (!visible == !isCurrentlyVisible) - return; - if (visible) { - if (!(d->opts & DontUseNativeDialog) && QFontDialogPrivate::sharedFontPanelAvailable) { - d->delegate = QFontDialogPrivate::openCocoaFontPanel( - currentFont(), parentWidget(), windowTitle(), options(), d); - QFontDialogPrivate::sharedFontPanelAvailable = false; - return; - } - - setWindowFlags(windowModality() == Qt::WindowModal ? Qt::Sheet : DefaultWindowFlags); - } else { - if (d->delegate) { - QFontDialogPrivate::closeCocoaFontPanel(d->delegate); - d->delegate = 0; - QFontDialogPrivate::sharedFontPanelAvailable = true; + if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) return; + } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden)) + return; +#ifdef Q_WS_MAC + if (d->canBeNativeDialog()){ + if (d->setVisible_sys(visible)){ + d->nativeDialogInUse = true; + // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below + // updates the state correctly, but skips showing the non-native version: + setAttribute(Qt::WA_DontShowOnScreen, true); + } else { + d->nativeDialogInUse = false; + setAttribute(Qt::WA_DontShowOnScreen, false); } } -#endif - +#endif // Q_WS_MAC QDialog::setVisible(visible); } @@ -1032,11 +1022,14 @@ void QFontDialog::done(int result) Q_D(QFontDialog); QDialog::done(result); if (result == Accepted) { - d->selectedFont = currentFont(); + // We check if this is the same font we had before, if so we emit currentFontChanged + QFont selectedFont = currentFont(); + if(selectedFont != d->selectedFont) + emit(currentFontChanged(selectedFont)); + d->selectedFont = selectedFont; emit fontSelected(d->selectedFont); - } else { + } else d->selectedFont = QFont(); - } if (d->receiverToDisconnectOnClose) { disconnect(this, SIGNAL(fontSelected(QFont)), d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose); @@ -1045,6 +1038,23 @@ void QFontDialog::done(int result) d->memberToDisconnectOnClose.clear(); } +#ifdef Q_WS_MAC +bool QFontDialogPrivate::canBeNativeDialog() +{ + Q_Q(QFontDialog); + if (nativeDialogInUse) + return true; + if (q->testAttribute(Qt::WA_DontShowOnScreen)) + return false; + if (opts & QFontDialog::DontUseNativeDialog) + return false; + + QLatin1String staticName(QFontDialog::staticMetaObject.className()); + QLatin1String dynamicName(q->metaObject()->className()); + return (staticName == dynamicName); +} +#endif // Q_WS_MAC + /*! \fn QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget* parent, const char* name) \since 4.5 diff --git a/src/gui/dialogs/qfontdialog.h b/src/gui/dialogs/qfontdialog.h index e6f209e..6035a3a 100644 --- a/src/gui/dialogs/qfontdialog.h +++ b/src/gui/dialogs/qfontdialog.h @@ -131,6 +131,9 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_styleHighlighted(int)) Q_PRIVATE_SLOT(d_func(), void _q_sizeHighlighted(int)) Q_PRIVATE_SLOT(d_func(), void _q_updateSample()) +#if defined(Q_WS_MAC) + Q_PRIVATE_SLOT(d_func(), void _q_macRunNativeAppModalPanel()) +#endif }; Q_DECLARE_OPERATORS_FOR_FLAGS(QFontDialog::FontDialogOptions) diff --git a/src/gui/dialogs/qfontdialog_mac.mm b/src/gui/dialogs/qfontdialog_mac.mm index 68f5f00..67d32b8 100644 --- a/src/gui/dialogs/qfontdialog_mac.mm +++ b/src/gui/dialogs/qfontdialog_mac.mm @@ -49,6 +49,7 @@ #include <private/qfontengine_p.h> #include <private/qt_cocoa_helpers_mac_p.h> #include <private/qt_mac_p.h> +#include <qabstracteventdispatcher.h> #include <qdebug.h> #import <AppKit/AppKit.h> #import <Foundation/Foundation.h> @@ -372,7 +373,12 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) [NSApp endModalSession:mModalSession]; mModalSession = 0; } - + // Hack alert! + // Since this code path was never intended to be followed when starting from exec + // we need to force the dialog to communicate the new font, otherwise the signal + // won't get emitted. + if(code == NSOKButton) + mPriv->sampleEdit->setFont([self qtFont]); mPriv->done((code == NSOKButton) ? QDialog::Accepted : QDialog::Rejected); } else { [NSApp stopModalWithCode:code]; @@ -567,7 +573,6 @@ void *QFontDialogPrivate::openCocoaFontPanel(const QFont &initial, [ourPanel makeKeyAndOrderFront:ourPanel]; } } - return delegate; } @@ -640,6 +645,145 @@ void QFontDialogPrivate::setFont(void *delegate, const QFont &font) [static_cast<QCocoaFontPanelDelegate *>(delegate) setQtFont:font]; } +void *QFontDialogPrivate::_q_constructNativePanel() +{ + QMacCocoaAutoReleasePool pool; + + bool sharedFontPanelExisted = [NSFontPanel sharedFontPanelExists]; + NSFontPanel *sharedFontPanel = [NSFontPanel sharedFontPanel]; + [sharedFontPanel setHidesOnDeactivate:false]; + + // hack to ensure that QCocoaApplication's validModesForFontPanel: + // implementation is honored + if (!sharedFontPanelExisted) { + [sharedFontPanel makeKeyAndOrderFront:sharedFontPanel]; + [sharedFontPanel close]; + } + + NSPanel *ourPanel = 0; + NSView *stolenContentView = 0; + NSButton *okButton = 0; + NSButton *cancelButton = 0; + + CGFloat dialogExtraWidth = 0.0; + CGFloat dialogExtraHeight = 0.0; + + // compute dialogExtra{Width,Height} + dialogExtraWidth = 2.0 * DialogSideMargin; + dialogExtraHeight = DialogTopMargin + ButtonTopMargin + ButtonMinHeight + + ButtonBottomMargin; + + // compute initial contents rectangle + NSRect contentRect = [sharedFontPanel contentRectForFrameRect:[sharedFontPanel frame]]; + contentRect.size.width += dialogExtraWidth; + contentRect.size.height += dialogExtraHeight; + + // create the new panel + ourPanel = [[NSPanel alloc] initWithContentRect:contentRect + styleMask:StyleMask + backing:NSBackingStoreBuffered + defer:YES]; + [ourPanel setReleasedWhenClosed:YES]; + + stolenContentView = [sharedFontPanel contentView]; + + // steal the font panel's contents view + [stolenContentView retain]; + [sharedFontPanel setContentView:0]; + + { + // create a new content view and add the stolen one as a subview + NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } }; + NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect]; + [ourContentView addSubview:stolenContentView]; + + // create OK and Cancel buttons and add these as subviews + okButton = macCreateButton("&OK", ourContentView); + cancelButton = macCreateButton("Cancel", ourContentView); + + [ourPanel setContentView:ourContentView]; + [ourPanel setDefaultButtonCell:[okButton cell]]; + } + // create a delegate and set it + QCocoaFontPanelDelegate *delegate = + [[QCocoaFontPanelDelegate alloc] initWithFontPanel:sharedFontPanel + stolenContentView:stolenContentView + okButton:okButton + cancelButton:cancelButton + priv:this + extraWidth:dialogExtraWidth + extraHeight:dialogExtraHeight]; + [ourPanel setDelegate:delegate]; + [[NSFontManager sharedFontManager] setDelegate:delegate]; +#ifdef QT_MAC_USE_COCOA + [[NSFontManager sharedFontManager] setTarget:delegate]; +#endif + setFont(delegate, QApplication::font()); + + { + // hack to get correct initial layout + NSRect frameRect = [ourPanel frame]; + frameRect.size.width += 1.0; + [ourPanel setFrame:frameRect display:NO]; + frameRect.size.width -= 1.0; + frameRect.size = [delegate windowWillResize:ourPanel toSize:frameRect.size]; + [ourPanel setFrame:frameRect display:NO]; + [ourPanel center]; + } + NSString *title = @"Select font"; + [ourPanel setTitle:title]; + + [delegate setModalSession:[NSApp beginModalSessionForWindow:ourPanel]]; + return delegate; +} + +void QFontDialogPrivate::mac_nativeDialogModalHelp() +{ + // Copied from QFileDialogPrivate + // Do a queued meta-call to open the native modal dialog so it opens after the new + // event loop has started to execute (in QDialog::exec). Using a timer rather than + // a queued meta call is intentional to ensure that the call is only delivered when + // [NSApp run] runs (timers are handeled special in cocoa). If NSApp is not + // running (which is the case if e.g a top-most QEventLoop has been + // interrupted, and the second-most event loop has not yet been reactivated (regardless + // if [NSApp run] is still on the stack)), showing a native modal dialog will fail. + if (nativeDialogInUse) { + Q_Q(QFontDialog); + QTimer::singleShot(1, q, SLOT(_q_macRunNativeAppModalPanel())); + } +} + +// The problem with the native font dialog is that OS X does not +// offer a proper dialog, but a panel (i.e. without Ok and Cancel buttons). +// This means we need to "construct" a native dialog by taking the panel +// and "adding" the buttons. +void QFontDialogPrivate::_q_macRunNativeAppModalPanel() +{ + QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active); + Q_Q(QFontDialog); + QCocoaFontPanelDelegate *delegate = (QCocoaFontPanelDelegate *)_q_constructNativePanel(); + NSWindow *ourPanel = [delegate actualPanel]; + [ourPanel retain]; + int rval = [NSApp runModalForWindow:ourPanel]; + QAbstractEventDispatcher::instance()->interrupt(); + [ourPanel release]; + [delegate cleanUpAfterMyself]; + [delegate release]; + bool isOk = (rval == NSOKButton); + if(isOk) + rescode = QDialog::Accepted; + else + rescode = QDialog::Rejected; +} + +bool QFontDialogPrivate::setVisible_sys(bool visible) +{ + Q_Q(QFontDialog); + if (!visible == q->isHidden()) + return false; + return visible; +} + QT_END_NAMESPACE #endif diff --git a/src/gui/dialogs/qfontdialog_p.h b/src/gui/dialogs/qfontdialog_p.h index ca2b10b..7654a80 100644 --- a/src/gui/dialogs/qfontdialog_p.h +++ b/src/gui/dialogs/qfontdialog_p.h @@ -152,6 +152,12 @@ public: inline QFontDialog *fontDialog() { return q_func(); } void *delegate; + bool nativeDialogInUse; + bool canBeNativeDialog(); + bool setVisible_sys(bool visible); + void *_q_constructNativePanel(); + void _q_macRunNativeAppModalPanel(); + void mac_nativeDialogModalHelp(); static bool sharedFontPanelAvailable; #endif diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index ca20101..5735cd6 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -414,12 +414,6 @@ /*! \enum QGraphicsItem::GraphicsItemChange - ItemVisibleHasChanged, - ItemEnabledHasChanged, - ItemSelectedHasChanged, - ItemParentHasChanged, - ItemSceneHasChanged - This enum describes the state changes that are notified by QGraphicsItem::itemChange(). The notifications are sent as the state changes, and in some cases, adjustments can be made (see the documentation @@ -647,9 +641,16 @@ are children of a modal panel are not blocked. The values are: - \value NonModal The panel is not modal and does not block input to other panels. - \value PanelModal The panel is modal to a single item hierarchy and blocks input to its parent pane, all grandparent panels, and all siblings of its parent and grandparent panels. - \value SceneModal The window is modal to the entire scene and blocks input to all panels. + + \value NonModal The panel is not modal and does not block input to + other panels. This is the default value for panels. + + \value PanelModal The panel is modal to a single item hierarchy + and blocks input to its parent pane, all grandparent panels, and + all siblings of its parent and grandparent panels. + + \value SceneModal The window is modal to the entire scene and + blocks input to all panels. \sa QGraphicsItem::setPanelModality(), QGraphicsItem::panelModality(), QGraphicsItem::ItemIsPanel */ diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 40e1d2c..365afdd 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -813,7 +813,8 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, // do it ourselves. if (item) { for (int i = 0; i < views.size(); ++i) - views.at(i)->inputContext()->reset(); + if (views.at(i)->inputContext()) + views.at(i)->inputContext()->reset(); } } #endif //QT_NO_IM @@ -4692,7 +4693,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (widget) item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); viewBoundingRect.adjust(-1, -1, 1, 1); - drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty(); + drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) + : !viewBoundingRect.normalized().isEmpty(); if (!drawItem) { if (!itemHasChildren) return; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 06b7438..1ced3d7 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3400,6 +3400,13 @@ void QGraphicsView::paintEvent(QPaintEvent *event) if (!d->scene->d_func()->painterStateProtection) painter.setWorldTransform(viewTransform); } else { + // Make sure we don't have unpolished items before we draw + if (!d->scene->d_func()->unpolishedItems.isEmpty()) + d->scene->d_func()->_q_polishItems(); + // We reset updateAll here (after we've issued polish events) + // so that we can discard update requests coming from polishEvent(). + d->scene->d_func()->updateAll = false; + // Find all exposed items bool allItems = false; QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform); @@ -3408,9 +3415,25 @@ void QGraphicsView::paintEvent(QPaintEvent *event) const int numItems = itemList.size(); QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid. QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems); + QTransform transform(Qt::Uninitialized); for (int i = 0; i < numItems; ++i) { - itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, - d->exposedRegion, allItems); + QGraphicsItem *item = itemArray[i]; + QGraphicsItemPrivate *itemd = item->d_ptr.data(); + itemd->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems); + // Cache the item's area in view coordinates. + // Note that we have to do this here in case the base class implementation + // (QGraphicsScene::drawItems) is not called. If it is, we'll do this + // operation twice, but that's the price one has to pay for using indirect + // painting :-/. + const QRectF brect = adjustedItemEffectiveBoundingRect(item); + if (!itemd->itemIsUntransformable()) { + transform = item->sceneTransform(); + if (viewTransformed) + transform *= viewTransform; + } else { + transform = item->deviceTransform(viewTransform); + } + itemd->paintedViewBoundingRects.insert(d->viewport, transform.mapRect(brect).toRect()); } // Draw the items. drawItems(&painter, numItems, itemArray, styleOptionArray); diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp index 2226901..8446387 100644 --- a/src/gui/image/qnativeimage.cpp +++ b/src/gui/image/qnativeimage.cpp @@ -182,7 +182,7 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format,bool /* qWarning() << "Error while marking the shared memory segment to be destroyed"; ok = (xshminfo.shmaddr != (char*)-1); if (ok) - image = QImage((uchar *)xshmimg->data, width, height, systemFormat()); + image = QImage((uchar *)xshmimg->data, width, height, format); } xshminfo.readOnly = false; if (ok) diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index adf3ce3..bc6db90 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -2119,6 +2119,11 @@ void QAbstractItemView::focusOutEvent(QFocusEvent *event) Q_D(QAbstractItemView); QAbstractScrollArea::focusOutEvent(event); d->viewport->update(); + +#ifdef QT_SOFTKEYS_ENABLED + if(!hasEditFocus()) + removeAction(d->doneSoftKey); +#endif } /*! @@ -2144,7 +2149,12 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) if (!hasEditFocus()) { setEditFocus(true); #ifdef QT_SOFTKEYS_ENABLED - addAction(d->doneSoftKey); + // If we can't keypad navigate to any direction, there is no sense to add + // "Done" softkey, since it basically does nothing when there is + // only one widget in screen + if(QWidgetPrivate::canKeypadNavigate(Qt::Horizontal) + || QWidgetPrivate::canKeypadNavigate(Qt::Vertical)) + addAction(d->doneSoftKey); #endif return; } @@ -2160,6 +2170,26 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) event->ignore(); } return; + case Qt::Key_Down: + case Qt::Key_Up: + // Let's ignore vertical navigation events, only if there is no other widget + // what can take the focus in vertical direction. This means widget can handle navigation events + // even the widget don't have edit focus, and there is no other widget in requested direction. + if(QApplication::keypadNavigationEnabled() && !hasEditFocus() + && QWidgetPrivate::canKeypadNavigate(Qt::Vertical)) { + event->ignore(); + return; + } + break; + case Qt::Key_Left: + case Qt::Key_Right: + // Similar logic as in up and down events + if(QApplication::keypadNavigationEnabled() && !hasEditFocus() + && (QWidgetPrivate::canKeypadNavigate(Qt::Horizontal) || QWidgetPrivate::inTabWidget(this))) { + event->ignore(); + return; + } + break; default: if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) { event->ignore(); @@ -2245,7 +2275,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) case Qt::Key_Down: case Qt::Key_Up: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::keypadNavigationEnabled()) { + if (QApplication::keypadNavigationEnabled() && QWidgetPrivate::canKeypadNavigate(Qt::Vertical)) { event->accept(); // don't change focus break; } @@ -2253,8 +2283,10 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) case Qt::Key_Left: case Qt::Key_Right: #ifdef QT_KEYPAD_NAVIGATION - if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { - event->accept(); // don't change horizontal focus in directional mode + if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional + && (QWidgetPrivate::canKeypadNavigate(Qt::Horizontal) + || (QWidgetPrivate::inTabWidget(this) && d->model->columnCount(d->root) > 1))) { + event->accept(); // don't change focus break; } #endif // QT_KEYPAD_NAVIGATION diff --git a/src/gui/itemviews/qabstractproxymodel.cpp b/src/gui/itemviews/qabstractproxymodel.cpp index 40345a7..43a1327 100644 --- a/src/gui/itemviews/qabstractproxymodel.cpp +++ b/src/gui/itemviews/qabstractproxymodel.cpp @@ -127,6 +127,7 @@ void QAbstractProxyModel::setSourceModel(QAbstractItemModel *sourceModel) } else { d->model = QAbstractItemModelPrivate::staticEmptyModel(); } + d->roleNames = d->model->roleNames(); } /*! diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 3e2e6f6..baefdfd 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -597,7 +597,9 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode, keyEvent.iCode); int keyCode; - if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { + if (s60Keysym == EKeyNull){ //some key events have 0 in iCode, for them iScanCode should be used + keyCode = qt_keymapper_private()->mapS60ScanCodesToQt(keyEvent.iScanCode); + } else if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) { // Normal characters keys. keyCode = s60Keysym; } else { @@ -1146,6 +1148,10 @@ void qt_init(QApplicationPrivate * /* priv */, int) #endif S60->wsSession().SetAutoFlush(ETrue); +#ifdef Q_SYMBIAN_WINDOW_SIZE_CACHE + TRAP_IGNORE(S60->wsSession().EnableWindowSizeCacheL()); +#endif + S60->updateScreenSize(); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 31d245f..131b9bb 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -1905,8 +1905,13 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam break; if (!msg.wParam) { +#ifdef Q_WS_WINCE + // On Windows CE, lParam parameter is a constant, not a char pointer. + if (msg.lParam == INI_INTL) { +#else QString area = QString::fromWCharArray((wchar_t*)msg.lParam); if (area == QLatin1String("intl")) { +#endif QLocalePrivate::updateSystemPrivate(); if (!widget->testAttribute(Qt::WA_SetLocale)) widget->dptr()->setLocale_helper(QLocale(), true); diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h index 09c36c88..3e42d6e 100644 --- a/src/gui/kernel/qkeymapper_p.h +++ b/src/gui/kernel/qkeymapper_p.h @@ -207,12 +207,12 @@ public: KeyboardLayoutItem *keyLayout[256]; #elif defined(Q_WS_QWS) #elif defined(Q_OS_SYMBIAN) -private: - QHash<TUint, int> s60ToQtKeyMap; - void fillKeyMap(); public: QString translateKeyEvent(int keySym, Qt::KeyboardModifiers modifiers); int mapS60KeyToQt(TUint s60key); + int mapS60ScanCodesToQt(TUint s60key); + int mapQtToS60Key(int qtKey); + int mapQtToS60ScanCodes(int qtKey); #endif }; diff --git a/src/gui/kernel/qkeymapper_s60.cpp b/src/gui/kernel/qkeymapper_s60.cpp index 6e21420..fd263ef 100644 --- a/src/gui/kernel/qkeymapper_s60.cpp +++ b/src/gui/kernel/qkeymapper_s60.cpp @@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE QKeyMapperPrivate::QKeyMapperPrivate() { - fillKeyMap(); } QKeyMapperPrivate::~QKeyMapperPrivate() @@ -74,174 +73,145 @@ QString QKeyMapperPrivate::translateKeyEvent(int keySym, Qt::KeyboardModifiers / return QString(QChar(keySym)); } -void QKeyMapperPrivate::fillKeyMap() +#include <e32keys.h> +struct KeyMapping{ + TKeyCode s60KeyCode; + TStdScanCode s60ScanCode; + Qt::Key qtKey; +}; + +using namespace Qt; + +static const KeyMapping keyMapping[] = { + {EKeyBackspace, EStdKeyBackspace, Key_Backspace}, + {EKeyTab, EStdKeyTab, Key_Tab}, + {EKeyEnter, EStdKeyEnter, Key_Enter}, + {EKeyEscape, EStdKeyEscape, Key_Escape}, + {EKeySpace, EStdKeySpace, Key_Space}, + {EKeyDelete, EStdKeyDelete, Key_Delete}, + {EKeyPrintScreen, EStdKeyPrintScreen, Key_SysReq}, + {EKeyPause, EStdKeyPause, Key_Pause}, + {EKeyHome, EStdKeyHome, Key_Home}, + {EKeyEnd, EStdKeyEnd, Key_End}, + {EKeyPageUp, EStdKeyPageUp, Key_PageUp}, + {EKeyPageDown, EStdKeyPageDown, Key_PageDown}, + {EKeyInsert, EStdKeyInsert, Key_Insert}, + {EKeyLeftArrow, EStdKeyLeftArrow, Key_Left}, + {EKeyRightArrow, EStdKeyRightArrow, Key_Right}, + {EKeyUpArrow, EStdKeyUpArrow, Key_Up}, + {EKeyDownArrow, EStdKeyDownArrow, Key_Down}, + {EKeyLeftShift, EStdKeyLeftShift, Key_Shift}, + {EKeyRightShift, EStdKeyRightShift, Key_Shift}, + {EKeyLeftAlt, EStdKeyLeftAlt, Key_Alt}, + {EKeyRightAlt, EStdKeyRightAlt, Key_AltGr}, + {EKeyLeftCtrl, EStdKeyLeftCtrl, Key_Control}, + {EKeyRightCtrl, EStdKeyRightCtrl, Key_Control}, + {EKeyLeftFunc, EStdKeyLeftFunc, Key_Super_L}, + {EKeyRightFunc, EStdKeyRightFunc, Key_Super_R}, + {EKeyCapsLock, EStdKeyCapsLock, Key_CapsLock}, + {EKeyNumLock, EStdKeyNumLock, Key_NumLock}, + {EKeyScrollLock, EStdKeyScrollLock, Key_ScrollLock}, + {EKeyF1, EStdKeyF1, Key_F1}, + {EKeyF2, EStdKeyF2, Key_F2}, + {EKeyF3, EStdKeyF3, Key_F3}, + {EKeyF4, EStdKeyF4, Key_F4}, + {EKeyF5, EStdKeyF5, Key_F5}, + {EKeyF6, EStdKeyF6, Key_F6}, + {EKeyF7, EStdKeyF7, Key_F7}, + {EKeyF8, EStdKeyF8, Key_F8}, + {EKeyF9, EStdKeyF9, Key_F9}, + {EKeyF10, EStdKeyF10, Key_F10}, + {EKeyF11, EStdKeyF11, Key_F11}, + {EKeyF12, EStdKeyF12, Key_F12}, + {EKeyF13, EStdKeyF13, Key_F13}, + {EKeyF14, EStdKeyF14, Key_F14}, + {EKeyF15, EStdKeyF15, Key_F15}, + {EKeyF16, EStdKeyF16, Key_F16}, + {EKeyF17, EStdKeyF17, Key_F17}, + {EKeyF18, EStdKeyF18, Key_F18}, + {EKeyF19, EStdKeyF19, Key_F19}, + {EKeyF20, EStdKeyF20, Key_F20}, + {EKeyF21, EStdKeyF21, Key_F21}, + {EKeyF22, EStdKeyF22, Key_F22}, + {EKeyF23, EStdKeyF23, Key_F23}, + {EKeyF24, EStdKeyF24, Key_F24}, + {EKeyOff, EStdKeyOff, Key_PowerOff}, +// {EKeyMenu, EStdKeyMenu, Key_Menu}, // Menu is EKeyApplication0 + {EKeyHelp, EStdKeyHelp, Key_Help}, + {EKeyDial, EStdKeyDial, Key_Call}, + {EKeyIncVolume, EStdKeyIncVolume, Key_VolumeUp}, + {EKeyDecVolume, EStdKeyDecVolume, Key_VolumeDown}, + {EKeyDevice0, EStdKeyDevice0, Key_Context1}, // Found by manual testing. + {EKeyDevice1, EStdKeyDevice1, Key_Context2}, // Found by manual testing. + {EKeyDevice3, EStdKeyDevice3, Key_Select}, +// {EKeyDevice7, EStdKeyDevice7, Key_Camera}, //not supported by qt yet + {EKeyApplication0, EStdKeyApplication0, Key_Menu}, // Found by manual testing. + {EKeyApplication1, EStdKeyApplication1, Key_Launch1}, // Found by manual testing. + {EKeyApplication2, EStdKeyApplication2, Key_MediaPlay}, // Found by manual testing. + {EKeyApplication3, EStdKeyApplication3, Key_MediaStop}, // Found by manual testing. + {EKeyApplication4, EStdKeyApplication4, Key_MediaNext}, // Found by manual testing. + {EKeyApplication5, EStdKeyApplication5, Key_MediaPrevious}, // Found by manual testing. + {EKeyApplication6, EStdKeyApplication6, Key_Launch6}, + {EKeyApplication7, EStdKeyApplication7, Key_Launch7}, + {EKeyApplication8, EStdKeyApplication8, Key_Launch8}, + {EKeyApplication9, EStdKeyApplication9, Key_Launch9}, + {EKeyApplicationA, EStdKeyApplicationA, Key_LaunchA}, + {EKeyApplicationB, EStdKeyApplicationB, Key_LaunchB}, + {EKeyApplicationC, EStdKeyApplicationC, Key_LaunchC}, + {EKeyApplicationD, EStdKeyApplicationD, Key_LaunchD}, + {EKeyApplicationE, EStdKeyApplicationE, Key_LaunchE}, + {EKeyApplicationF, EStdKeyApplicationF, Key_LaunchF}, +// {EKeyApplication19, EStdKeyApplication19, Key_CameraFocus}, //not supported by qt yet + {EKeyYes, EStdKeyYes, Key_Yes}, + {EKeyNo, EStdKeyNo, Key_No}, + {TKeyCode(0), TStdScanCode(0), Qt::Key(0)} +}; + +int QKeyMapperPrivate::mapS60KeyToQt(TUint s60key) { - using namespace Qt; - static const struct { - TUint s60Key; - int qtKey; - } map[] = { - {EKeyBell, Key_unknown}, - {EKeyBackspace, Key_Backspace}, - {EKeyTab, Key_Tab}, - {EKeyLineFeed, Key_unknown}, - {EKeyVerticalTab, Key_unknown}, - {EKeyFormFeed, Key_unknown}, - {EKeyEnter, Key_Enter}, - {EKeyEscape, Key_Escape}, - {EKeySpace, Key_Space}, - {EKeyDelete, Key_Delete}, - {EKeyPrintScreen, Key_SysReq}, - {EKeyPause, Key_Pause}, - {EKeyHome, Key_Home}, - {EKeyEnd, Key_End}, - {EKeyPageUp, Key_PageUp}, - {EKeyPageDown, Key_PageDown}, - {EKeyInsert, Key_Insert}, - {EKeyLeftArrow, Key_Left}, - {EKeyRightArrow, Key_Right}, - {EKeyUpArrow, Key_Up}, - {EKeyDownArrow, Key_Down}, - {EKeyLeftShift, Key_Shift}, - {EKeyRightShift, Key_Shift}, - {EKeyLeftAlt, Key_Alt}, - {EKeyRightAlt, Key_AltGr}, - {EKeyLeftCtrl, Key_Control}, - {EKeyRightCtrl, Key_Control}, - {EKeyLeftFunc, Key_Super_L}, - {EKeyRightFunc, Key_Super_R}, - {EKeyCapsLock, Key_CapsLock}, - {EKeyNumLock, Key_NumLock}, - {EKeyScrollLock, Key_ScrollLock}, - {EKeyF1, Key_F1}, - {EKeyF2, Key_F2}, - {EKeyF3, Key_F3}, - {EKeyF4, Key_F4}, - {EKeyF5, Key_F5}, - {EKeyF6, Key_F6}, - {EKeyF7, Key_F7}, - {EKeyF8, Key_F8}, - {EKeyF9, Key_F9}, - {EKeyF10, Key_F10}, - {EKeyF11, Key_F11}, - {EKeyF12, Key_F12}, - {EKeyF13, Key_F13}, - {EKeyF14, Key_F14}, - {EKeyF15, Key_F15}, - {EKeyF16, Key_F16}, - {EKeyF17, Key_F17}, - {EKeyF18, Key_F18}, - {EKeyF19, Key_F19}, - {EKeyF20, Key_F20}, - {EKeyF21, Key_F21}, - {EKeyF22, Key_F22}, - {EKeyF23, Key_F23}, - {EKeyF24, Key_F24}, - {EKeyOff, Key_unknown}, - {EKeyIncContrast, Key_unknown}, - {EKeyDecContrast, Key_unknown}, - {EKeyBacklightOn, Key_unknown}, - {EKeyBacklightOff, Key_unknown}, - {EKeyBacklightToggle, Key_unknown}, - {EKeySliderDown, Key_unknown}, - {EKeySliderUp, Key_unknown}, - {EKeyMenu, Key_Menu}, - {EKeyDictaphonePlay, Key_unknown}, - {EKeyDictaphoneStop, Key_unknown}, - {EKeyDictaphoneRecord, Key_unknown}, - {EKeyHelp, Key_unknown}, - {EKeyDial, Key_Call}, - {EKeyScreenDimension0, Key_unknown}, - {EKeyScreenDimension1, Key_unknown}, - {EKeyScreenDimension2, Key_unknown}, - {EKeyScreenDimension3, Key_unknown}, - {EKeyIncVolume, Key_unknown}, - {EKeyDecVolume, Key_unknown}, - {EKeyDevice0, Key_Context1}, // Found by manual testing, left softkey. - {EKeyDevice1, Key_Context2}, // Found by manual testing. - {EKeyDevice2, Key_unknown}, - {EKeyDevice3, Key_Select}, // Found by manual testing. - {EKeyDevice4, Key_unknown}, - {EKeyDevice5, Key_unknown}, - {EKeyDevice6, Key_unknown}, - {EKeyDevice7, Key_unknown}, - {EKeyDevice8, Key_unknown}, - {EKeyDevice9, Key_unknown}, - {EKeyDeviceA, Key_unknown}, - {EKeyDeviceB, Key_unknown}, - {EKeyDeviceC, Key_unknown}, - {EKeyDeviceD, Key_unknown}, - {EKeyDeviceE, Key_unknown}, - {EKeyDeviceF, Key_unknown}, - {EKeyApplication0, Key_Launch0}, - {EKeyApplication1, Key_Launch1}, - {EKeyApplication2, Key_Launch2}, - {EKeyApplication3, Key_Launch3}, - {EKeyApplication4, Key_Launch4}, - {EKeyApplication5, Key_Launch5}, - {EKeyApplication6, Key_Launch6}, - {EKeyApplication7, Key_Launch7}, - {EKeyApplication8, Key_Launch8}, - {EKeyApplication9, Key_Launch9}, - {EKeyApplicationA, Key_LaunchA}, - {EKeyApplicationB, Key_LaunchB}, - {EKeyApplicationC, Key_LaunchC}, - {EKeyApplicationD, Key_LaunchD}, - {EKeyApplicationE, Key_LaunchE}, - {EKeyApplicationF, Key_LaunchF}, - {EKeyYes, Key_Yes}, - {EKeyNo, Key_No}, - {EKeyIncBrightness, Key_unknown}, - {EKeyDecBrightness, Key_unknown}, - {EKeyKeyboardExtend, Key_unknown}, - {EKeyDevice10, Key_unknown}, - {EKeyDevice11, Key_unknown}, - {EKeyDevice12, Key_unknown}, - {EKeyDevice13, Key_unknown}, - {EKeyDevice14, Key_unknown}, - {EKeyDevice15, Key_unknown}, - {EKeyDevice16, Key_unknown}, - {EKeyDevice17, Key_unknown}, - {EKeyDevice18, Key_unknown}, - {EKeyDevice19, Key_unknown}, - {EKeyDevice1A, Key_unknown}, - {EKeyDevice1B, Key_unknown}, - {EKeyDevice1C, Key_unknown}, - {EKeyDevice1D, Key_unknown}, - {EKeyDevice1E, Key_unknown}, - {EKeyDevice1F, Key_unknown}, - {EKeyApplication10, Key_unknown}, - {EKeyApplication11, Key_unknown}, - {EKeyApplication12, Key_unknown}, - {EKeyApplication13, Key_unknown}, - {EKeyApplication14, Key_unknown}, - {EKeyApplication15, Key_unknown}, - {EKeyApplication16, Key_unknown}, - {EKeyApplication17, Key_unknown}, - {EKeyApplication18, Key_unknown}, - {EKeyApplication19, Key_unknown}, - {EKeyApplication1A, Key_unknown}, - {EKeyApplication1B, Key_unknown}, - {EKeyApplication1C, Key_unknown}, - {EKeyApplication1D, Key_unknown}, - {EKeyApplication1E, Key_unknown}, - {EKeyApplication1F, Key_unknown} - }; - const int mapSize = int(sizeof(map)/sizeof(map[0])); - s60ToQtKeyMap.reserve(mapSize + 5); // +5? docs: Ideally, slightly more than number of items - for (int i = 0; i < mapSize; ++i) - s60ToQtKeyMap.insert(map[i].s60Key, map[i].qtKey); + int res = Qt::Key_unknown; + for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) { + if (keyMapping[i].s60KeyCode == s60key) { + res = keyMapping[i].qtKey; + break; + } + } + return res; } -int QKeyMapperPrivate::mapS60KeyToQt(TUint s60key) +int QKeyMapperPrivate::mapS60ScanCodesToQt(TUint s60scanCode) { - QHash<TUint, int>::const_iterator mapping; - mapping = s60ToQtKeyMap.find(s60key); - if (mapping != s60ToQtKeyMap.end()) { - return *mapping; - } else { - return Qt::Key_unknown; + int res = Qt::Key_unknown; + for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) { + if (keyMapping[i].s60ScanCode == s60scanCode) { + res = keyMapping[i].qtKey; + break; + } } + return res; } +int QKeyMapperPrivate::mapQtToS60Key(int qtKey) +{ + int res = KErrUnknown; + for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) { + if (keyMapping[i].qtKey == qtKey) { + res = keyMapping[i].s60KeyCode; + break; + } + } + return res; +} + +int QKeyMapperPrivate::mapQtToS60ScanCodes(int qtKey) +{ + int res = KErrUnknown; + for (int i = 0; keyMapping[i].s60KeyCode != 0; i++) { + if (keyMapping[i].qtKey == qtKey) { + res = keyMapping[i].s60ScanCode; + break; + } + } + return res; +} QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 1e9b1d9..2f6ec6b 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -118,6 +118,10 @@ #include "private/qgraphicssystem_p.h" #include "private/qgesturemanager_p.h" +#ifdef QT_KEYPAD_NAVIGATION +#include "qtabwidget.h" // Needed in inTabWidget() +#endif // QT_KEYPAD_NAVIGATION + // widget/widget data creation count //#define QWIDGET_EXTRA_DEBUG //#define ALIEN_DEBUG @@ -11641,6 +11645,45 @@ QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction) } return targetWidget; } + +/*! + \internal + + Tells us if it there is currently a reachable widget by keypad navigation in + a certain \a orientation. + If no navigation is possible, occuring key events in that \a orientation may + be used to interact with the value in the focussed widget, even though it + currently has not the editFocus. + + \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus() +*/ +bool QWidgetPrivate::canKeypadNavigate(Qt::Orientation orientation) +{ + return orientation == Qt::Horizontal? + (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast) + || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest)) + :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth) + || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth)); +} +/*! + \internal + + Checks, if the \a widget is inside a QTabWidget. If is is inside + one, left/right key events will be used to switch between tabs in keypad + navigation. If there is no QTabWidget, the horizontal key events can be used +to + interact with the value in the focussed widget, even though it currently has + not the editFocus. + + \sa QWidget::hasEditFocus() +*/ +bool QWidgetPrivate::inTabWidget(QWidget *widget) +{ + for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget()) + if (qobject_cast<const QTabWidget*>(tabWidget)) + return true; + return false; +} #endif /*! diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index da9e9eb..dcb87fc 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -4543,8 +4543,20 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) } } + // ### Scroll the dirty regions as well, the following is not correct. + QRegion displayRegion = r.isNull() ? dirtyOnWidget : (dirtyOnWidget & r); + const QVector<QRect> &rects = dirtyOnWidget.rects(); + const QVector<QRect>::const_iterator end = rects.end(); + QVector<QRect>::const_iterator it = rects.begin(); + while (it != end) { + const QRect rect = *it; + const NSRect dirtyRect = NSMakeRect(rect.x() + dx, rect.y() + dy, + rect.width(), rect.height()); + [view setNeedsDisplayInRect:dirtyRect]; + ++it; + } + NSSize deltaSize = NSMakeSize(dx, dy); - [view translateRectsNeedingDisplayInRect:scrollRect by:deltaSize]; [view scrollRect:scrollRect by:deltaSize]; [view setNeedsDisplayInRect:deltaXRect]; [view setNeedsDisplayInRect:deltaYRect]; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 75b4c12..efd9a0a 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -475,6 +475,8 @@ public: #ifdef QT_KEYPAD_NAVIGATION static bool navigateToDirection(Direction direction); static QWidget *widgetInNavigationDirection(Direction direction); + static bool canKeypadNavigate(Qt::Orientation orientation); + static bool inTabWidget(QWidget *widget); #endif void setWindowIconText_sys(const QString &cap); diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 1f9fc32..bc1bece 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -5749,6 +5749,13 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c return positionRect(w, subRule, subRule2, pe, opt->rect, opt->direction); } +#ifndef QT_NO_TOOLBAR + case SE_ToolBarHandle: + if (hasStyleRule(w, PseudoElement_ToolBarHandle)) + return ParentStyle::subElementRect(se, opt, w); + break; +#endif //QT_NO_TOOLBAR + default: break; } diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp index 4bd7b5a..2888490 100644 --- a/src/gui/widgets/qabstractslider.cpp +++ b/src/gui/widgets/qabstractslider.cpp @@ -47,9 +47,6 @@ #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" #endif -#ifdef QT_KEYPAD_NAVIGATION -#include "qtabwidget.h" // Needed in inTabWidget() -#endif // QT_KEYPAD_NAVIGATION #include <limits.h> QT_BEGIN_NAMESPACE @@ -702,7 +699,7 @@ bool QAbstractSliderPrivate::scrollByDelta(Qt::Orientation orientation, Qt::Keyb stepsToScroll = qBound(-pageStep, int(offset * pageStep), pageStep); offset_accumulated = 0; } else { - // Calculate how many lines to scroll. Depending on what delta is (and + // Calculate how many lines to scroll. Depending on what delta is (and // offset), we might end up with a fraction (e.g. scroll 1.3 lines). We can // only scroll whole lines, so we keep the reminder until next event. qreal stepsToScrollF = @@ -749,45 +746,7 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e) } #endif -#ifdef QT_KEYPAD_NAVIGATION -/*! - \internal - - Tells us if it there is currently a reachable widget by keypad navigation in - a certain \a orientation. - If no navigation is possible, occuring key events in that \a orientation may - be used to interact with the value in the focussed widget, even though it - currently has not the editFocus. - \sa QWidgetPrivate::widgetInNavigationDirection(), QWidget::hasEditFocus() -*/ -inline static bool canKeypadNavigate(Qt::Orientation orientation) -{ - return orientation == Qt::Horizontal? - (QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionEast) - || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionWest)) - :(QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionNorth) - || QWidgetPrivate::widgetInNavigationDirection(QWidgetPrivate::DirectionSouth)); -} -/*! - \internal - - Checks, if the \a widget is inside a QTabWidget. If is is inside - one, left/right key events will be used to switch between tabs in keypad - navigation. If there is no QTabWidget, the horizontal key events can be used to - interact with the value in the focussed widget, even though it currently has - not the editFocus. - - \sa QWidget::hasEditFocus() -*/ -inline static bool inTabWidget(QWidget *widget) -{ - for (QWidget *tabWidget = widget; tabWidget; tabWidget = tabWidget->parentWidget()) - if (qobject_cast<const QTabWidget*>(tabWidget)) - return true; - return false; -} -#endif // QT_KEYPAD_NAVIGATION /*! \reimp */ @@ -853,7 +812,8 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) if (QApplication::keypadNavigationEnabled() && (!hasEditFocus() && QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder || d->orientation == Qt::Vertical - || !hasEditFocus() && (canKeypadNavigate(Qt::Horizontal) || inTabWidget(this)))) { + || !hasEditFocus() + && (QWidgetPrivate::canKeypadNavigate(Qt::Horizontal) || QWidgetPrivate::inTabWidget(this)))) { ev->ignore(); return; } @@ -872,7 +832,8 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) if (QApplication::keypadNavigationEnabled() && (!hasEditFocus() && QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder || d->orientation == Qt::Vertical - || !hasEditFocus() && (canKeypadNavigate(Qt::Horizontal) || inTabWidget(this)))) { + || !hasEditFocus() + && (QWidgetPrivate::canKeypadNavigate(Qt::Horizontal) || QWidgetPrivate::inTabWidget(this)))) { ev->ignore(); return; } @@ -892,7 +853,7 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) if (QApplication::keypadNavigationEnabled() && (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder || d->orientation == Qt::Horizontal - || !hasEditFocus() && canKeypadNavigate(Qt::Vertical))) { + || !hasEditFocus() && QWidgetPrivate::canKeypadNavigate(Qt::Vertical))) { ev->ignore(); break; } @@ -905,7 +866,7 @@ void QAbstractSlider::keyPressEvent(QKeyEvent *ev) if (QApplication::keypadNavigationEnabled() && (QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder || d->orientation == Qt::Horizontal - || !hasEditFocus() && canKeypadNavigate(Qt::Vertical))) { + || !hasEditFocus() && QWidgetPrivate::canKeypadNavigate(Qt::Vertical))) { ev->ignore(); break; } diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp index 1aa7a2b..2c76a5c 100644 --- a/src/gui/widgets/qlineedit_p.cpp +++ b/src/gui/widgets/qlineedit_p.cpp @@ -129,7 +129,7 @@ void QLineEditPrivate::_q_editFocusChange(bool e) void QLineEditPrivate::_q_selectionChanged() { Q_Q(QLineEdit); - if (control->preeditAreaText().isEmpty()) { + if (!control->text().isEmpty() && control->preeditAreaText().isEmpty()) { QStyleOptionFrameV2 opt; q->initStyleOption(&opt); bool showCursor = control->hasSelectedText() ? diff --git a/src/multimedia/audio/qaudioinput.cpp b/src/multimedia/audio/qaudioinput.cpp index 45cafc1..fd892dd 100644 --- a/src/multimedia/audio/qaudioinput.cpp +++ b/src/multimedia/audio/qaudioinput.cpp @@ -190,18 +190,18 @@ QAudioInput::~QAudioInput() Passing a QIODevice allows the data to be transfered without any extra code. All that is required is to open the QIODevice. + If able to successfully get audio data from the systems audio device the + state() is set to either QAudio::ActiveState or QAudio::IdleState, + error() is set to QAudio::NoError and the stateChanged() signal is emitted. + + If a problem occurs during this process the error() is set to QAudio::OpenError, + state() is set to QAudio::StoppedState and stateChanged() signal is emitted. + \sa QIODevice */ void QAudioInput::start(QIODevice* device) { - /* - -If currently not StoppedState, stop - -If previous start was push mode, delete internal QIODevice. - -open audio input. - If ok, NoError and ActiveState, else OpenError and StoppedState. - -emit stateChanged() - */ d->start(device); } @@ -210,19 +210,18 @@ void QAudioInput::start(QIODevice* device) transfer. This QIODevice can be used to read() audio data directly. + If able to access the systems audio device the state() is set to + QAudio::IdleState, error() is set to QAudio::NoError + and the stateChanged() signal is emitted. + + If a problem occurs during this process the error() is set to QAudio::OpenError, + state() is set to QAudio::StoppedState and stateChanged() signal is emitted. + \sa QIODevice */ QIODevice* QAudioInput::start() { - /* - -If currently not StoppedState, stop - -If no internal QIODevice, create one. - -open audio input. - -If ok, NoError and IdleState, else OpenError and StoppedState - -emit stateChanged() - -return internal QIODevice - */ return d->start(0); } @@ -236,17 +235,14 @@ QAudioFormat QAudioInput::format() const } /*! - Stops the audio input. + Stops the audio input, detaching from the system resource. + + Sets error() to QAudio::NoError, state() to QAudio::StoppedState and + emit stateChanged() signal. */ void QAudioInput::stop() { - /* - -If StoppedState, return - -set to StoppedState - -detach from audio device - -emit stateChanged() - */ d->stop(); } @@ -256,42 +252,32 @@ void QAudioInput::stop() void QAudioInput::reset() { - /* - -drop all buffered audio, set buffers to zero. - -call stop() - */ d->reset(); } /*! Stops processing audio data, preserving buffered audio data. + + Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and + emit stateChanged() signal. */ void QAudioInput::suspend() { - /* - -If not ActiveState|IdleState, return - -stop processing audio, saving all buffered audio data - -set NoError and SuspendedState - -emit stateChanged() - */ d->suspend(); } /*! Resumes processing audio data after a suspend(). + + Sets error() to QAudio::NoError. + Sets state() to QAudio::ActiveState if you previously called start(QIODevice*). + Sets state() to QAudio::IdleState if you previously called start(). + emits stateChanged() signal. */ void QAudioInput::resume() { - /* - -If SuspendedState, return - -resume audio - -(PULL MODE): set ActiveState, NoError - -(PUSH MODE): set IdleState, NoError - -kick start audio if needed - -emit stateChanged() - */ d->resume(); } @@ -327,6 +313,9 @@ int QAudioInput::bufferSize() const /*! Returns the amount of audio data available to read in bytes. + + NOTE: returned value is only valid while in QAudio::ActiveState or QAudio::IdleState + state, otherwise returns zero. */ int QAudioInput::bytesReady() const @@ -352,7 +341,10 @@ int QAudioInput::periodSize() const /*! Sets the interval for notify() signal to be emitted. This is based on the \a ms of audio data processed - not on actual real-time. The resolution of the timer is platform specific. + not on actual real-time. + The minimum resolution of the timer is platform specific and values + should be checked with notifyInterval() to confirm actual value + being used. */ void QAudioInput::setNotifyInterval(int ms) diff --git a/src/multimedia/audio/qaudioinput_alsa_p.cpp b/src/multimedia/audio/qaudioinput_alsa_p.cpp index 26e46b3..6010f3c 100644 --- a/src/multimedia/audio/qaudioinput_alsa_p.cpp +++ b/src/multimedia/audio/qaudioinput_alsa_p.cpp @@ -217,9 +217,11 @@ QIODevice* QAudioInputPrivate::start(QIODevice* device) //set to pull mode pullMode = true; audioSource = device; + deviceState = QAudio::ActiveState; } else { //set to push mode pullMode = false; + deviceState = QAudio::IdleState; audioSource = new InputPrivate(this); audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered); } @@ -413,7 +415,6 @@ bool QAudioInputPrivate::open() timer->start(period_time*chunks/2000); errorState = QAudio::NoError; - deviceState = QAudio::ActiveState; totalTimeValue = 0; @@ -439,7 +440,7 @@ int QAudioInputPrivate::bytesReady() const if(resuming) return period_size; - if(deviceState != QAudio::ActiveState) + if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return 0; int frames = snd_pcm_avail_update(handle); if((int)frames > (int)buffer_frames) @@ -450,8 +451,8 @@ int QAudioInputPrivate::bytesReady() const qint64 QAudioInputPrivate::read(char* data, qint64 len) { - Q_UNUSED(data) Q_UNUSED(len) + // Read in some audio data and write it to QIODevice, pull mode if ( !handle ) return 0; @@ -468,7 +469,7 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) if (readFrames >= 0) { err = snd_pcm_frames_to_bytes(handle, readFrames); #ifdef DEBUG_AUDIO - qDebug()<<QString::fromLatin1("PULL: read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData(); + qDebug()<<QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData(); #endif break; } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) { @@ -489,28 +490,46 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) if(err > 0) { // got some send it onward #ifdef DEBUG_AUDIO - qDebug()<<"PULL: frames to write to QIODevice = "<< + qDebug()<<"frames to write to QIODevice = "<< snd_pcm_bytes_to_frames( handle, (int)err )<<" ("<<err<<") bytes"; #endif - if(deviceState != QAudio::ActiveState) + if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return 0; + if (pullMode) { + qint64 l = audioSource->write(audioBuffer,err); + if(l < 0) { + close(); + errorState = QAudio::IOError; + deviceState = QAudio::StoppedState; + emit stateChanged(deviceState); + } else if(l == 0) { + if (deviceState != QAudio::IdleState) { + errorState = QAudio::NoError; + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } + } else { + totalTimeValue += err; + resuming = false; + if (deviceState != QAudio::ActiveState) { + errorState = QAudio::NoError; + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } + } + return l; - qint64 l = audioSource->write(audioBuffer,err); - if(l < 0) { - close(); - errorState = QAudio::IOError; - deviceState = QAudio::StoppedState; - emit stateChanged(deviceState); - } else if(l == 0) { - errorState = QAudio::NoError; - deviceState = QAudio::IdleState; } else { - totalTimeValue += snd_pcm_bytes_to_frames(handle, err)*1000000/settings.frequency(); + memcpy(data,audioBuffer,err); + totalTimeValue += err; resuming = false; - errorState = QAudio::NoError; - deviceState = QAudio::ActiveState; + if (deviceState != QAudio::ActiveState) { + errorState = QAudio::NoError; + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } + return err; } - return l; } return 0; } @@ -569,7 +588,7 @@ int QAudioInputPrivate::notifyInterval() const qint64 QAudioInputPrivate::processedUSecs() const { - return totalTimeValue; + return qint64(1000000) * totalTimeValue / settings.frequency(); } void QAudioInputPrivate::suspend() @@ -617,34 +636,10 @@ bool QAudioInputPrivate::deviceReady() qint64 QAudioInputPrivate::elapsedUSecs() const { - if(!handle) - return 0; - if (deviceState == QAudio::StoppedState) return 0; -#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) - snd_pcm_status_t* status; - snd_pcm_status_alloca(&status); - - snd_timestamp_t t1,t2; - if( snd_pcm_status(handle, status) >= 0) { - snd_pcm_status_get_tstamp(status,&t1); - snd_pcm_status_get_trigger_tstamp(status,&t2); - t1.tv_sec-=t2.tv_sec; - - signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec; - if(l < 0) { - t1.tv_sec--; - l = -l; - l %= 1000000; - } - return ((t1.tv_sec * 1000000)+l); - } else - return 0; -#else return clockStamp.elapsed()*1000; -#endif } void QAudioInputPrivate::reset() @@ -670,43 +665,7 @@ InputPrivate::~InputPrivate() qint64 InputPrivate::readData( char* data, qint64 len) { - // push mode, user read() called - if((audioDevice->state() != QAudio::ActiveState) && !audioDevice->resuming) - return 0; - - int readFrames; - int count=0, err = 0; - - while(count < 5) { - int frames = snd_pcm_bytes_to_frames(audioDevice->handle, len); - readFrames = snd_pcm_readi(audioDevice->handle, data, frames); - if (readFrames >= 0) { - err = snd_pcm_frames_to_bytes(audioDevice->handle, readFrames); -#ifdef DEBUG_AUDIO - qDebug()<<QString::fromLatin1("PUSH: read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData(); -#endif - break; - } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) { - audioDevice->errorState = QAudio::IOError; - err = 0; - break; - } else { - if(readFrames == -EPIPE) { - audioDevice->errorState = QAudio::UnderrunError; - err = snd_pcm_prepare(audioDevice->handle); - } else if(readFrames == -ESTRPIPE) { - err = snd_pcm_prepare(audioDevice->handle); - } - if(err != 0) break; - } - count++; - } - if(err > 0 && readFrames > 0) { - audioDevice->totalTimeValue += readFrames*1000/audioDevice->settings.frequency()*1000; - audioDevice->deviceState = QAudio::ActiveState; - return err; - } - return 0; + return audioDevice->read(data,len); } qint64 InputPrivate::writeData(const char* data, qint64 len) diff --git a/src/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/audio/qaudioinput_win32_p.cpp index cc4fdee..594f6ca 100644 --- a/src/multimedia/audio/qaudioinput_win32_p.cpp +++ b/src/multimedia/audio/qaudioinput_win32_p.cpp @@ -192,9 +192,11 @@ QIODevice* QAudioInputPrivate::start(QIODevice* device) //set to pull mode pullMode = true; audioSource = device; + deviceState = QAudio::ActiveState; } else { //set to push mode pullMode = false; + deviceState = QAudio::IdleState; audioSource = new InputPrivate(this); audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered); } @@ -311,7 +313,6 @@ bool QAudioInputPrivate::open() elapsedTimeOffset = 0; totalTimeValue = 0; errorState = QAudio::NoError; - deviceState = QAudio::ActiveState; return true; } @@ -320,9 +321,9 @@ void QAudioInputPrivate::close() if(deviceState == QAudio::StoppedState) return; + deviceState = QAudio::StoppedState; waveInReset(hWaveIn); waveInClose(hWaveIn); - deviceState = QAudio::StoppedState; int count = 0; while(!finished && count < 500) { @@ -357,7 +358,6 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) char* p = data; qint64 l = 0; qint64 written = 0; - while(!done) { // Read in some audio data if(waveBlocks[header].dwBytesRecorded > 0 && waveBlocks[header].dwFlags & WHDR_DONE) { @@ -378,11 +378,12 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) errorState = QAudio::IOError; } else { - totalTimeValue += waveBlocks[header].dwBytesRecorded - /((settings.channels()*settings.sampleSize()/8)) - *10000/settings.frequency()*100; + totalTimeValue += waveBlocks[header].dwBytesRecorded; errorState = QAudio::NoError; - deviceState = QAudio::ActiveState; + if (deviceState != QAudio::ActiveState) { + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } resuming = false; } } else { @@ -392,16 +393,17 @@ qint64 QAudioInputPrivate::read(char* data, qint64 len) #ifdef DEBUG_AUDIO qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l; #endif - totalTimeValue += waveBlocks[header].dwBytesRecorded - /((settings.channels()*settings.sampleSize()/8)) - *10000/settings.frequency()*100; + totalTimeValue += waveBlocks[header].dwBytesRecorded; errorState = QAudio::NoError; - deviceState = QAudio::ActiveState; + if (deviceState != QAudio::ActiveState) { + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } resuming = false; } } else { //no data, not ready yet, next time - return 0; + break; } waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); @@ -510,7 +512,13 @@ int QAudioInputPrivate::notifyInterval() const qint64 QAudioInputPrivate::processedUSecs() const { - return totalTimeValue; + if (deviceState == QAudio::StoppedState) + return 0; + qint64 result = qint64(1000000) * totalTimeValue / + (settings.channels()*(settings.sampleSize()/8)) / + settings.frequency(); + + return result; } void QAudioInputPrivate::suspend() @@ -540,6 +548,9 @@ bool QAudioInputPrivate::deviceReady() QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT"; #endif + if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) + return true; + if(pullMode) { // reads some audio data and writes it to QIODevice read(0,0); @@ -548,8 +559,6 @@ bool QAudioInputPrivate::deviceReady() InputPrivate* a = qobject_cast<InputPrivate*>(audioSource); a->trigger(); } - if(deviceState != QAudio::ActiveState) - return true; if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { emit notify(); @@ -582,7 +591,8 @@ InputPrivate::~InputPrivate() {} qint64 InputPrivate::readData( char* data, qint64 len) { // push mode, user read() called - if(audioDevice->deviceState != QAudio::ActiveState) + if(audioDevice->deviceState != QAudio::ActiveState && + audioDevice->deviceState != QAudio::IdleState) return 0; // Read in some audio data return audioDevice->read(data,len); diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp index afd8a84..b0b5244 100644 --- a/src/multimedia/audio/qaudiooutput.cpp +++ b/src/multimedia/audio/qaudiooutput.cpp @@ -202,18 +202,18 @@ QAudioFormat QAudioOutput::format() const Passing a QIODevice allows the data to be transfered without any extra code. All that is required is to open the QIODevice. + If able to successfully output audio data to the systems audio device the + state() is set to QAudio::ActiveState, error() is set to QAudio::NoError + and the stateChanged() signal is emitted. + + If a problem occurs during this process the error() is set to QAudio::OpenError, + state() is set to QAudio::StoppedState and stateChanged() signal is emitted. + \sa QIODevice */ void QAudioOutput::start(QIODevice* device) { - /* - -If currently not StoppedState, stop. - -If previous start was push mode, delete internal QIODevice. - -open audio output. - -If ok, NoError and ActiveState, else OpenError and StoppedState - -emit stateChanged() - */ d->start(device); } @@ -221,34 +221,30 @@ void QAudioOutput::start(QIODevice* device) Returns a pointer to the QIODevice being used to handle the data transfer. This QIODevice can be used to write() audio data directly. + If able to access the systems audio device the state() is set to + QAudio::IdleState, error() is set to QAudio::NoError + and the stateChanged() signal is emitted. + + If a problem occurs during this process the error() is set to QAudio::OpenError, + state() is set to QAudio::StoppedState and stateChanged() signal is emitted. + \sa QIODevice */ QIODevice* QAudioOutput::start() { - /* - -If currently not StoppedState, stop. - -If no internal QIODevice, create one. - -open audio output. - -If ok, NoError and IdleState, else OpenError and StoppedState - -emit stateChanged() - -return internal QIODevice - */ return d->start(0); } /*! - Stops the audio output. + Stops the audio output, detaching from the system resource. + + Sets error() to QAudio::NoError, state() to QAudio::StoppedState and + emit stateChanged() signal. */ void QAudioOutput::stop() { - /* - -If StoppedState, return - -set to StoppedState - -detach from audio device - -emit stateChanged() - */ d->stop(); } @@ -258,55 +254,44 @@ void QAudioOutput::stop() void QAudioOutput::reset() { - /* - -drop all buffered audio, set buffers to zero. - -call stop() - */ d->reset(); } /*! Stops processing audio data, preserving buffered audio data. + + Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and + emit stateChanged() signal. */ void QAudioOutput::suspend() { - /* - -If not ActiveState|IdleState, return - -stop processing audio, saving all buffered audio data - -set NoError and SuspendedState - -emit stateChanged() - */ d->suspend(); } /*! Resumes processing audio data after a suspend(). + + Sets error() to QAudio::NoError. + Sets state() to QAudio::ActiveState if you previously called start(QIODevice*). + Sets state() to QAudio::IdleState if you previously called start(). + emits stateChanged() signal. */ void QAudioOutput::resume() { - /* - -If SuspendedState, return - -resume audio - -(PULL MODE): set ActiveState, NoError - -(PUSH MODE): set IdleState, NoError - -kick start audio if needed - -emit stateChanged() - */ d->resume(); } /*! Returns the free space available in bytes in the audio buffer. + + NOTE: returned value is only valid while in QAudio::ActiveState or QAudio::IdleState + state, otherwise returns zero. */ int QAudioOutput::bytesFree() const { - /* - -If not ActiveState|IdleState, return 0 - -return space available in audio buffer in bytes - */ return d->bytesFree(); } @@ -353,7 +338,10 @@ int QAudioOutput::bufferSize() const /*! Sets the interval for notify() signal to be emitted. This is based on the \a ms of audio data processed - not on actual real-time. The resolution of the timer is platform specific. + not on actual real-time. + The minimum resolution of the timer is platform specific and values + should be checked with notifyInterval() to confirm actual value + being used. */ void QAudioOutput::setNotifyInterval(int ms) diff --git a/src/multimedia/audio/qaudiooutput_alsa_p.cpp b/src/multimedia/audio/qaudiooutput_alsa_p.cpp index 7b89cef..b127103 100644 --- a/src/multimedia/audio/qaudiooutput_alsa_p.cpp +++ b/src/multimedia/audio/qaudiooutput_alsa_p.cpp @@ -259,6 +259,7 @@ void QAudioOutputPrivate::stop() { if(deviceState == QAudio::StoppedState) return; + errorState = QAudio::NoError; deviceState = QAudio::StoppedState; close(); emit stateChanged(deviceState); @@ -494,10 +495,13 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) err = snd_pcm_writei( handle, data, frames ); } if(err > 0) { - totalTimeValue += err*1000000/settings.frequency(); + totalTimeValue += err; resuming = false; errorState = QAudio::NoError; - deviceState = QAudio::ActiveState; + if (deviceState != QAudio::ActiveState) { + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } return snd_pcm_frames_to_bytes( handle, err ); } else err = xrun_recovery(err); @@ -542,7 +546,7 @@ int QAudioOutputPrivate::notifyInterval() const qint64 QAudioOutputPrivate::processedUSecs() const { - return totalTimeValue; + return qint64(1000000) * totalTimeValue / settings.frequency(); } void QAudioOutputPrivate::resume() @@ -562,10 +566,8 @@ void QAudioOutputPrivate::resume() bytesAvailable = (int)snd_pcm_frames_to_bytes(handle, buffer_frames); } resuming = true; - if(pullMode) - deviceState = QAudio::ActiveState; - else - deviceState = QAudio::IdleState; + + deviceState = QAudio::ActiveState; errorState = QAudio::NoError; timer->start(period_time/1000); @@ -637,7 +639,9 @@ bool QAudioOutputPrivate::deviceReady() // Got some data to output if(deviceState != QAudio::ActiveState) return true; - write(audioBuffer,l); + qint64 bytesWritten = write(audioBuffer,l); + if (bytesWritten != l) + audioSource->seek(audioSource->pos()-(l-bytesWritten)); bytesAvailable = bytesFree(); } else if(l == 0) { @@ -645,9 +649,11 @@ bool QAudioOutputPrivate::deviceReady() bytesAvailable = bytesFree(); if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) { // Underrun - errorState = QAudio::UnderrunError; - deviceState = QAudio::IdleState; - emit stateChanged(deviceState); + if (deviceState != QAudio::IdleState) { + errorState = QAudio::UnderrunError; + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } } } else if(l < 0) { @@ -655,8 +661,17 @@ bool QAudioOutputPrivate::deviceReady() errorState = QAudio::IOError; emit stateChanged(deviceState); } - } else + } else { bytesAvailable = bytesFree(); + if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) { + // Underrun + if (deviceState != QAudio::IdleState) { + errorState = QAudio::UnderrunError; + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } + } + } if(deviceState != QAudio::ActiveState) return true; @@ -671,35 +686,10 @@ bool QAudioOutputPrivate::deviceReady() qint64 QAudioOutputPrivate::elapsedUSecs() const { - if(!handle) - return 0; - if (deviceState == QAudio::StoppedState) return 0; -#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) - snd_pcm_status_t* status; - snd_pcm_status_alloca(&status); - - snd_timestamp_t t1,t2; - if( snd_pcm_status(handle, status) >= 0) { - snd_pcm_status_get_tstamp(status,&t1); - snd_pcm_status_get_trigger_tstamp(status,&t2); - t1.tv_sec-=t2.tv_sec; - - signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec; - if(l < 0) { - t1.tv_sec--; - l = -l; - l %= 1000000; - } - return ((t1.tv_sec * 1000000)+l); - } else - return 0; -#else return clockStamp.elapsed()*1000; -#endif - return 0; } void QAudioOutputPrivate::reset() diff --git a/src/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/audio/qaudiooutput_win32_p.cpp index bce45c1..6200160 100644 --- a/src/multimedia/audio/qaudiooutput_win32_p.cpp +++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp @@ -211,6 +211,13 @@ bool QAudioOutputPrivate::open() QTime now(QTime::currentTime()); qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; #endif + if (!(settings.frequency() >= 8000 && settings.frequency() <= 48000)) { + errorState = QAudio::OpenError; + deviceState = QAudio::StoppedState; + emit stateChanged(deviceState); + qWarning("QAudioOutput: open error, frequency out of range."); + return false; + } if(buffer_size == 0) { // Default buffer size, 200ms, default period size is 40ms buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2; @@ -289,6 +296,7 @@ void QAudioOutputPrivate::close() return; deviceState = QAudio::StoppedState; + errorState = QAudio::NoError; int delay = (buffer_size-bytesFree())*1000/(settings.frequency() *settings.channels()*(settings.sampleSize()/8)); waveOutReset(hWaveOut); @@ -340,12 +348,20 @@ int QAudioOutputPrivate::notifyInterval() const qint64 QAudioOutputPrivate::processedUSecs() const { - return totalTimeValue; + if (deviceState == QAudio::StoppedState) + return 0; + qint64 result = qint64(1000000) * totalTimeValue / + (settings.channels()*(settings.sampleSize()/8)) / + settings.frequency(); + + return result; } qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) { // Write out some audio data + if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) + return 0; char* p = (char*)data; int l = (int)len; @@ -385,13 +401,16 @@ qint64 QAudioOutputPrivate::write( const char *data, qint64 len ) current->dwBufferLength,waveFreeBlockCount); LeaveCriticalSection(&waveOutCriticalSection); #endif - totalTimeValue += current->dwBufferLength - /(settings.channels()*(settings.sampleSize()/8)) - *1000000/settings.frequency();; + totalTimeValue += current->dwBufferLength; waveCurrentBlock++; waveCurrentBlock %= buffer_size/period_size; current = &waveBlocks[waveCurrentBlock]; current->dwUser = 0; + errorState = QAudio::NoError; + if (deviceState != QAudio::ActiveState) { + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } } return (len-l); } @@ -409,8 +428,11 @@ void QAudioOutputPrivate::resume() void QAudioOutputPrivate::suspend() { - if(deviceState == QAudio::ActiveState) { + if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState) { + int delay = (buffer_size-bytesFree())*1000/(settings.frequency() + *settings.channels()*(settings.sampleSize()/8)); waveOutPause(hWaveOut); + Sleep(delay+10); deviceState = QAudio::SuspendedState; errorState = QAudio::NoError; emit stateChanged(deviceState); @@ -465,8 +487,16 @@ bool QAudioOutputPrivate::deviceReady() int l = audioSource->read(audioBuffer,input); if(l > 0) { int out= write(audioBuffer,l); - if(out > 0) - deviceState = QAudio::ActiveState; + if(out > 0) { + if (deviceState != QAudio::ActiveState) { + deviceState = QAudio::ActiveState; + emit stateChanged(deviceState); + } + } + if ( out < l) { + // Didnt write all data + audioSource->seek(audioSource->pos()-(l-out)); + } if(startup) waveOutRestart(hWaveOut); } else if(l == 0) { @@ -478,16 +508,28 @@ bool QAudioOutputPrivate::deviceReady() LeaveCriticalSection(&waveOutCriticalSection); if(check == buffer_size/period_size) { errorState = QAudio::UnderrunError; - deviceState = QAudio::IdleState; - emit stateChanged(deviceState); + if (deviceState != QAudio::IdleState) { + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } } } else if(l < 0) { bytesAvailable = bytesFree(); errorState = QAudio::IOError; } + } else { + int buffered; + EnterCriticalSection(&waveOutCriticalSection); + buffered = waveFreeBlockCount; + LeaveCriticalSection(&waveOutCriticalSection); + errorState = QAudio::UnderrunError; + if (buffered >= buffer_size/period_size && deviceState == QAudio::ActiveState) { + deviceState = QAudio::IdleState; + emit stateChanged(deviceState); + } } - if(deviceState != QAudio::ActiveState) + if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) return true; if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 62aa2d7..a887449 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -416,13 +416,25 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor lowPriorityQueue.prepend(pair); break; } + // this used to be called via invokeMethod and a QueuedConnection + // It is the only place _q_startNextRequest is called directly without going + // through the event loop using a QueuedConnection. + // This is dangerous because of recursion that might occur when emitting + // signals as DirectConnection from this code path. Therefore all signal + // emissions that can come out from this code path need to + // be QueuedConnection. + // We are currently trying to fine-tune this. _q_startNextRequest(); + + return reply; } void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair) { + Q_Q(QHttpNetworkConnection); + QHttpNetworkRequest request = pair.first; switch (request.priority()) { case QHttpNetworkRequest::HighPriority: @@ -433,8 +445,8 @@ void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair) lowPriorityQueue.prepend(pair); break; } - // this used to be called via invokeMethod and a QueuedConnection - _q_startNextRequest(); + + QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); } void QHttpNetworkConnectionPrivate::dequeueAndSendRequest(QAbstractSocket *socket) @@ -682,6 +694,8 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply) +// This function must be called from the event loop. The only +// exception is documented in QHttpNetworkConnectionPrivate::queueRequest void QHttpNetworkConnectionPrivate::_q_startNextRequest() { //resend the necessary ones. diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index dbee72a..e92b2f3 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -459,6 +459,8 @@ void QHttpNetworkConnectionChannel::handleUnexpectedEOF() } else { reconnectAttempts--; reply->d_func()->clear(); + reply->d_func()->connection = connection; + reply->d_func()->connectionChannel = this; closeAndResendCurrentRequest(); } } diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index b9bd52a..5876ee2 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -110,7 +110,8 @@ static void ensureInitialized() object, which holds the common configuration and settings for the requests it sends. It contains the proxy and cache configuration, as well as the signals related to such issues, and reply signals that can be used to - monitor the progress of a network operation. + monitor the progress of a network operation. One QNetworkAccessManager + should be enough for the whole Qt application. Once a QNetworkAccessManager object has been created, the application can use it to send requests over the network. A group of standard functions @@ -121,6 +122,7 @@ static void ensureInitialized() A simple download off the network could be accomplished with: \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 0 + QNetworkAccessManager has an asynchronous API. When the \tt replyFinished slot above is called, the parameter it takes is the QNetworkReply object containing the downloaded data as well as meta-data (headers, etc.). @@ -130,6 +132,11 @@ static void ensureInitialized() delete it inside the slot connected to finished(). You can use the deleteLater() function. + \note QNetworkAccessManager queues the requests it receives. The number + of requests executed in parallel is dependent on the protocol. + Currently, for the HTTP protocol on desktop platforms, 6 requests are + executed in parallel for one host/port combination. + A more involved example, assuming the manager is already existent, can be: \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 1 diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index e563f4e..61c116d 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -138,6 +138,8 @@ QT_BEGIN_NAMESPACE default follow redirections: it's up to the application to determine if the requested redirection should be allowed, according to its security policies. + The returned URL might be relative. Use QUrl::resolved() + to create an absolute URL out of it. \value ConnectionEncryptedAttribute Replies only, type: QVariant::Bool (default: false) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 829df89..275c436 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -155,6 +155,9 @@ See the \l network/fortuneclient and \l network/blockingfortuneclient examples for an overview of both approaches. + \note We discourage the use of the blocking functions together + with signals. One of the two possibilities should be used. + QAbstractSocket can be used with QTextStream and QDataStream's stream operators (operator<<() and operator>>()). There is one issue to be aware of, though: You must make sure that enough data @@ -1682,9 +1685,12 @@ static int qt_timeout_value(int msecs, int elapsed) If msecs is -1, this function will not time out. - Note: This function may wait slightly longer than \a msecs, + \note This function may wait slightly longer than \a msecs, depending on the time it takes to complete the host lookup. + \note Multiple calls to this functions do not accumulate the time. + If the function times out, the connecting process will be aborted. + \sa connectToHost(), connected() */ bool QAbstractSocket::waitForConnected(int msecs) @@ -1722,7 +1728,7 @@ bool QAbstractSocket::waitForConnected(int msecs) d->_q_startConnecting(QHostInfo::fromName(d->hostName)); } if (state() == UnconnectedState) - return false; + return false; // connect not im progress anymore! bool timedOut = true; #if defined (QABSTRACTSOCKET_DEBUG) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 2ed185f..73cd6a8 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -5559,7 +5559,7 @@ QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len) quint32 level = 0; quint32 width = pvrHeader->width; quint32 height = pvrHeader->height; - while (bufferSize > 0 && level < pvrHeader->mipMapCount) { + while (bufferSize > 0 && level <= pvrHeader->mipMapCount) { quint32 size = (qMax(width, minWidth) * qMax(height, minHeight) * pvrHeader->bitsPerPixel) / 8; diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index bc9f0c9..35f552e 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -130,8 +130,9 @@ public: void draw(VGPath path, const QPen& pen, const QBrush& brush, VGint rule = VG_EVEN_ODD); void stroke(VGPath path, const QPen& pen); void fill(VGPath path, const QBrush& brush, VGint rule = VG_EVEN_ODD); - VGPath vectorPathToVGPath(const QVectorPath& path); - VGPath painterPathToVGPath(const QPainterPath& path); + inline void releasePath(VGPath path); + VGPath vectorPathToVGPath(const QVectorPath& path, bool forceNewPath = false); + VGPath painterPathToVGPath(const QPainterPath& path, bool forceNewPath = false); VGPath roundedRectPath(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode); VGPaintType setBrush (VGPaint paint, const QBrush& brush, VGMatrixMode mode, @@ -177,6 +178,8 @@ public: VGPath roundRectPath; // Cached path for quick drawing of rounded rects. #endif + VGPath reusablePath; // Reusable path for vectorPathToVGPath(), etc. + QTransform transform; // Currently active transform. bool simpleTransform; // True if the transform is simple (non-projective). qreal penScale; // Pen scaling factor from "transform". @@ -349,6 +352,8 @@ void QVGPaintEnginePrivate::init() roundRectPath = 0; #endif + reusablePath = 0; + simpleTransform = true; pathTransformSet = false; penScale = 1.0; @@ -445,6 +450,15 @@ void QVGPaintEnginePrivate::initObjects() VG_PATH_CAPABILITY_ALL); vgAppendPathData(linePath, 2, segments, coords); #endif + + // This path can be reused over and over by calling vgClearPath(). + reusablePath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + 32 + 1, // segmentCapacityHint + 32 * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); } void QVGPaintEnginePrivate::destroy() @@ -464,6 +478,8 @@ void QVGPaintEnginePrivate::destroy() if (roundRectPath) vgDestroyPath(roundRectPath); #endif + if (reusablePath) + vgDestroyPath(reusablePath); #if !defined(QVG_NO_DRAW_GLYPHS) QVGFontCache::Iterator it; @@ -540,19 +556,32 @@ void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) qt_scaleForTransform(transform, &penScale); } -VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path) +inline void QVGPaintEnginePrivate::releasePath(VGPath path) +{ + if (path == reusablePath) + vgClearPath(path, VG_PATH_CAPABILITY_ALL); + else + vgDestroyPath(path); +} + +VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path, bool forceNewPath) { int count = path.elementCount(); const qreal *points = path.points(); const QPainterPath::ElementType *elements = path.elements(); - VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - count + 1, // segmentCapacityHint - count * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath vgpath; + if (forceNewPath) { + vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + count + 1, // segmentCapacityHint + count * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + } else { + vgpath = reusablePath; + } // Size is sufficient segments for drawRoundedRect() paths. QVarLengthArray<VGubyte, 20> segments; @@ -724,17 +753,22 @@ VGPath QVGPaintEnginePrivate::vectorPathToVGPath(const QVectorPath& path) return vgpath; } -VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path) +VGPath QVGPaintEnginePrivate::painterPathToVGPath(const QPainterPath& path, bool forceNewPath) { int count = path.elementCount(); - VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - count + 1, // segmentCapacityHint - count * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath vgpath; + if (forceNewPath) { + vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + count + 1, // segmentCapacityHint + count * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + } else { + vgpath = reusablePath; + } if (count == 0) return vgpath; @@ -953,13 +987,7 @@ VGPath QVGPaintEnginePrivate::roundedRectPath(const QRectF &rect, qreal xRadius, vgModifyPathCoords(vgpath, 0, 9, pts); } #else - VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - 10, // segmentCapacityHint - 17 * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath vgpath = reusablePath; vgAppendPathData(vgpath, 10, roundedrect_types, pts); #endif @@ -1512,7 +1540,7 @@ void QVGPaintEngine::draw(const QVectorPath &path) d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD); else d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO); - vgDestroyPath(vgpath); + d->releasePath(vgpath); } void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush) @@ -1523,7 +1551,7 @@ void QVGPaintEngine::fill(const QVectorPath &path, const QBrush &brush) d->fill(vgpath, brush, VG_EVEN_ODD); else d->fill(vgpath, brush, VG_NON_ZERO); - vgDestroyPath(vgpath); + d->releasePath(vgpath); } void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen) @@ -1531,7 +1559,7 @@ void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen) Q_D(QVGPaintEngine); VGPath vgpath = d->vectorPathToVGPath(path); d->stroke(vgpath, pen); - vgDestroyPath(vgpath); + d->releasePath(vgpath); } // Determine if a co-ordinate transform is simple enough to allow @@ -1727,7 +1755,7 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) default: break; } - vgDestroyPath(vgpath); + d->releasePath(vgpath); vgSeti(VG_MASKING, VG_TRUE); d->maskValid = true; @@ -2044,7 +2072,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) default: break; } - vgDestroyPath(vgpath); + d->releasePath(vgpath); vgSeti(VG_MASKING, VG_TRUE); d->maskValid = true; @@ -2395,7 +2423,7 @@ void QVGPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) return; // Check to see if we can use vgClear() for faster filling. - if (brush.style() == Qt::SolidPattern && + if (brush.style() == Qt::SolidPattern && brush.isOpaque() && clipTransformIsSimple(d->transform) && d->opacity == 1.0f && clearRect(rect, brush.color())) { return; @@ -2438,7 +2466,7 @@ void QVGPaintEngine::fillRect(const QRectF &rect, const QColor &color) Q_D(QVGPaintEngine); // Check to see if we can use vgClear() for faster filling. - if (clipTransformIsSimple(d->transform) && d->opacity == 1.0f && + if (clipTransformIsSimple(d->transform) && d->opacity == 1.0f && color.alpha() == 255 && clearRect(rect, color)) { return; } @@ -2483,7 +2511,7 @@ void QVGPaintEngine::drawRoundedRect(const QRectF &rect, qreal xrad, qreal yrad, VGPath vgpath = d->roundedRectPath(rect, xrad, yrad, mode); d->draw(vgpath, s->pen, s->brush); #if defined(QVG_NO_MODIFY_PATH) - vgDestroyPath(vgpath); + d->releasePath(vgpath); #endif } else { QPaintEngineEx::drawRoundedRect(rect, xrad, yrad, mode); @@ -2632,13 +2660,7 @@ void QVGPaintEngine::drawEllipse(const QRectF &r) Q_D(QVGPaintEngine); if (d->simpleTransform) { QVGPainterState *s = state(); - VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - 4, // segmentCapacityHint - 12, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath path = d->reusablePath; static VGubyte segments[4] = { VG_MOVE_TO_ABS, VG_SCCWARC_TO_REL, @@ -2662,7 +2684,7 @@ void QVGPaintEngine::drawEllipse(const QRectF &r) coords[11] = 0.0f; vgAppendPathData(path, 4, segments, coords); d->draw(path, s->pen, s->brush); - vgDestroyPath(path); + d->releasePath(path); } else { // The projective transform version of an ellipse is difficult. // Generate a QVectorPath containing cubic curves and transform that. @@ -2686,7 +2708,7 @@ void QVGPaintEngine::drawPath(const QPainterPath &path) d->draw(vgpath, s->pen, s->brush, VG_EVEN_ODD); else d->draw(vgpath, s->pen, s->brush, VG_NON_ZERO); - vgDestroyPath(vgpath); + d->releasePath(vgpath); } void QVGPaintEngine::drawPoints(const QPointF *points, int pointCount) @@ -2761,13 +2783,7 @@ void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonD { Q_D(QVGPaintEngine); QVGPainterState *s = state(); - VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - pointCount + 1, // segmentCapacityHint - pointCount * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath path = d->reusablePath; QVarLengthArray<VGfloat, 16> coords; QVarLengthArray<VGubyte, 10> segments; for (int i = 0; i < pointCount; ++i, ++points) { @@ -2801,20 +2817,14 @@ void QVGPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonD d->draw(path, s->pen, s->brush, VG_EVEN_ODD); break; } - vgDestroyPath(path); + d->releasePath(path); } void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) { Q_D(QVGPaintEngine); QVGPainterState *s = state(); - VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, - VG_PATH_DATATYPE_F, - 1.0f, // scale - 0.0f, // bias - pointCount + 1, // segmentCapacityHint - pointCount * 2, // coordCapacityHint - VG_PATH_CAPABILITY_ALL); + VGPath path = d->reusablePath; QVarLengthArray<VGfloat, 16> coords; QVarLengthArray<VGubyte, 10> segments; for (int i = 0; i < pointCount; ++i, ++points) { @@ -2848,7 +2858,7 @@ void QVGPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDr d->draw(path, s->pen, s->brush, VG_EVEN_ODD); break; } - vgDestroyPath(path); + d->releasePath(path); } void QVGPaintEnginePrivate::setImageOptions() @@ -3245,7 +3255,7 @@ void QVGFontGlyphCache::cacheGlyphs(QVGPaintEnginePrivate *d, fontEngine->getUnscaledGlyph(glyph, &path, &metrics); VGPath vgPath; if (!path.isEmpty()) { - vgPath = d->painterPathToVGPath(path); + vgPath = d->painterPathToVGPath(path, true); } else { // Probably a "space" character with no visible outline. vgPath = VG_INVALID_HANDLE; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index cd4d5c2..cffd4e3 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1126,6 +1126,8 @@ bool QDirectFBScreen::connect(const QString &displaySpec) if (displayArgs.contains(QLatin1String("boundingrectflip"), Qt::CaseInsensitive)) { d_ptr->directFBFlags |= BoundingRectFlip; + } else if (displayArgs.contains(QLatin1String("nopartialflip"), Qt::CaseInsensitive)) { + d_ptr->directFBFlags |= NoPartialFlip; } #ifdef QT_DIRECTFB_IMAGECACHE @@ -1139,6 +1141,8 @@ bool QDirectFBScreen::connect(const QString &displaySpec) #endif d_ptr->dfb->SetCooperativeLevel(d_ptr->dfb, DFSCL_FULLSCREEN); + const bool forcePremultiplied = displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive); + DFBSurfaceDescription description; memset(&description, 0, sizeof(DFBSurfaceDescription)); IDirectFBSurface *surface; @@ -1167,7 +1171,7 @@ bool QDirectFBScreen::connect(const QString &displaySpec) description.caps |= capabilities[i].cap; } - if (displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive)) { + if (forcePremultiplied) { description.caps |= DSCAPS_PREMULTIPLIED; } @@ -1217,6 +1221,8 @@ bool QDirectFBScreen::connect(const QString &displaySpec) d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied; break; case QImage::Format_ARGB32: + if (forcePremultiplied) + d_ptr->alphaPixmapFormat = pixelFormat = QImage::Format_ARGB32_Premultiplied; case QImage::Format_ARGB32_Premultiplied: case QImage::Format_ARGB4444_Premultiplied: case QImage::Format_ARGB8555_Premultiplied: @@ -1674,7 +1680,7 @@ bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *d uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl) { - void *mem; + void *mem = 0; const DFBResult result = surface->Lock(surface, flags, &mem, bpl); if (result != DFB_OK) { DirectFBError("QDirectFBScreen::lockSurface()", result); @@ -1683,11 +1689,22 @@ uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFla return reinterpret_cast<uchar*>(mem); } +static inline bool isFullUpdate(IDirectFBSurface *surface, const QRegion ®ion, const QPoint &offset) +{ + if (offset == QPoint(0, 0) && region.rectCount() == 1) { + QSize size; + surface->GetSize(surface, &size.rwidth(), &size.rheight()); + if (region.boundingRect().size() == size) + return true; + } + return false; +} void QDirectFBScreen::flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags, const QRegion ®ion, const QPoint &offset) { - if (!(flipFlags & DSFLIP_BLIT)) { + if (d_ptr->directFBFlags & NoPartialFlip + || (!(flipFlags & DSFLIP_BLIT) && QT_PREPEND_NAMESPACE(isFullUpdate(surface, region, offset)))) { surface->Flip(surface, 0, flipFlags); } else { if (!(d_ptr->directFBFlags & BoundingRectFlip) && region.rectCount() > 1) { diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index a8c4b43..c483020 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -144,7 +144,8 @@ public: NoFlags = 0x00, VideoOnly = 0x01, SystemOnly = 0x02, - BoundingRectFlip = 0x04 + BoundingRectFlip = 0x04, + NoPartialFlip = 0x08 }; Q_DECLARE_FLAGS(DirectFBFlags, DirectFBFlag); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 6764e75..a8bdb65 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -92,10 +92,6 @@ QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirect mode = Offscreen; flags = Buffered; } -#else - noSystemBackground = widget && widget->testAttribute(Qt::WA_NoSystemBackground); - if (noSystemBackground) - flags &= ~Opaque; #endif setSurfaceFlags(flags); #ifdef QT_DIRECTFB_TIMING @@ -134,33 +130,35 @@ void QDirectFBWindowSurface::createWindow(const QRect &rect) if (!layer) qFatal("QDirectFBWindowSurface: Unable to get primary display layer!"); + updateIsOpaque(); + DFBWindowDescription description; memset(&description, 0, sizeof(DFBWindowDescription)); + description.flags = DWDESC_CAPS|DWDESC_HEIGHT|DWDESC_WIDTH|DWDESC_POSX|DWDESC_POSY|DWDESC_SURFACE_CAPS|DWDESC_PIXELFORMAT; description.caps = DWCAPS_NODECORATION; - description.flags = DWDESC_CAPS|DWDESC_SURFACE_CAPS|DWDESC_PIXELFORMAT|DWDESC_HEIGHT|DWDESC_WIDTH|DWDESC_POSX|DWDESC_POSY; -#if (Q_DIRECTFB_VERSION >= 0x010200) - description.flags |= DWDESC_OPTIONS; -#endif + description.surface_caps = DSCAPS_NONE; + imageFormat = screen->pixelFormat(); - if (noSystemBackground) { + if (!(surfaceFlags() & Opaque)) { + imageFormat = screen->alphaPixmapFormat(); description.caps |= DWCAPS_ALPHACHANNEL; #if (Q_DIRECTFB_VERSION >= 0x010200) + description.flags |= DWDESC_OPTIONS; description.options |= DWOP_ALPHACHANNEL; #endif } - + description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(imageFormat); description.posx = rect.x(); description.posy = rect.y(); description.width = rect.width(); description.height = rect.height(); - description.surface_caps = DSCAPS_NONE; + + if (QDirectFBScreen::isPremultiplied(imageFormat)) + description.surface_caps = DSCAPS_PREMULTIPLIED; + if (screen->directFBFlags() & QDirectFBScreen::VideoOnly) description.surface_caps |= DSCAPS_VIDEOONLY; - const QImage::Format format = (noSystemBackground ? screen->alphaPixmapFormat() : screen->pixelFormat()); - description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); - if (QDirectFBScreen::isPremultiplied(format)) - description.surface_caps = DSCAPS_PREMULTIPLIED; DFBResult result = layer->CreateWindow(layer, &description, &dfbWindow); @@ -182,7 +180,6 @@ void QDirectFBWindowSurface::createWindow(const QRect &rect) Q_ASSERT(!dfbSurface); dfbWindow->GetSurface(dfbWindow, &dfbSurface); - updateFormat(); } static DFBResult setWindowGeometry(IDirectFBWindow *dfbWindow, const QRect &old, const QRect &rect) @@ -267,15 +264,17 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect) } } else { // mode == Offscreen if (!dfbSurface) { - dfbSurface = screen->createDFBSurface(rect.size(), screen->pixelFormat(), QDirectFBScreen::DontTrackSurface); + dfbSurface = screen->createDFBSurface(rect.size(), surfaceFlags() & Opaque ? screen->pixelFormat() : screen->alphaPixmapFormat(), + QDirectFBScreen::DontTrackSurface); } } if (result != DFB_OK) DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result); #endif } - if (oldSurface != dfbSurface) - updateFormat(); + if (oldSurface != dfbSurface) { + imageFormat = dfbSurface ? QDirectFBScreen::getImageFormat(dfbSurface) : QImage::Format_Invalid; + } if (oldRect.size() != rect.size()) { QWSWindowSurface::setGeometry(rect); @@ -296,7 +295,7 @@ void QDirectFBWindowSurface::setPermanentState(const QByteArray &state) if (state.size() == sizeof(this)) { sibling = *reinterpret_cast<QDirectFBWindowSurface *const*>(state.constData()); Q_ASSERT(sibling); - sibling->setSurfaceFlags(surfaceFlags()); + setSurfaceFlags(sibling->surfaceFlags()); } } @@ -359,8 +358,6 @@ void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, const quint8 windowOpacity = quint8(win->windowOpacity() * 0xff); const QRect windowGeometry = geometry(); #ifdef QT_DIRECTFB_WM - const bool wasNoSystemBackground = noSystemBackground; - noSystemBackground = win->testAttribute(Qt::WA_NoSystemBackground); quint8 currentOpacity; Q_ASSERT(dfbWindow); dfbWindow->GetOpacity(dfbWindow, ¤tOpacity); @@ -368,18 +365,9 @@ void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, dfbWindow->SetOpacity(dfbWindow, windowOpacity); } - setOpaque(noSystemBackground || windowOpacity != 0xff); - if (wasNoSystemBackground != noSystemBackground) { - releaseSurface(); - dfbWindow->Release(dfbWindow); - dfbWindow = 0; - createWindow(windowGeometry); - win->update(); - return; - } screen->flipSurface(dfbSurface, flipFlags, region, offset); #else - setOpaque(windowOpacity != 0xff); + setOpaque(windowOpacity == 0xff); if (mode == Offscreen) { screen->exposeRegion(region.translated(offset + geometry().topLeft()), 0); } else { @@ -442,11 +430,6 @@ IDirectFBSurface *QDirectFBWindowSurface::surfaceForWidget(const QWidget *widget return dfbSurface; } -void QDirectFBWindowSurface::updateFormat() -{ - imageFormat = dfbSurface ? QDirectFBScreen::getImageFormat(dfbSurface) : QImage::Format_Invalid; -} - void QDirectFBWindowSurface::releaseSurface() { if (dfbSurface) { @@ -465,9 +448,37 @@ void QDirectFBWindowSurface::releaseSurface() } } +void QDirectFBWindowSurface::updateIsOpaque() +{ + const QWidget *win = window(); + Q_ASSERT(win); + if (win->testAttribute(Qt::WA_OpaquePaintEvent) || win->testAttribute(Qt::WA_PaintOnScreen)) { + setOpaque(true); + return; + } -QT_END_NAMESPACE + if (qFuzzyCompare(static_cast<float>(win->windowOpacity()), 1.0f)) { + const QPalette &pal = win->palette(); -#endif // QT_NO_QWS_DIRECTFB + if (win->autoFillBackground()) { + const QBrush &autoFillBrush = pal.brush(win->backgroundRole()); + if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) { + setOpaque(true); + return; + } + } + + if (win->isWindow() && !win->testAttribute(Qt::WA_NoSystemBackground)) { + const QBrush &windowBrush = win->palette().brush(QPalette::Window); + if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) { + setOpaque(true); + return; + } + } + } + setOpaque(false); +} +QT_END_NAMESPACE +#endif // QT_NO_QWS_DIRECTFB diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index 9568067..a6138f6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -97,8 +97,8 @@ public: IDirectFBWindow *directFBWindow() const; #endif private: + void updateIsOpaque(); void setOpaque(bool opaque); - void updateFormat(); void releaseSurface(); QDirectFBWindowSurface *sibling; @@ -113,7 +113,6 @@ private: #endif DFBSurfaceFlipFlags flipFlags; - bool noSystemBackground; bool boundingRectFlip; #ifdef QT_DIRECTFB_TIMING int frames; diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 98a24d0..d2e96d1 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -844,7 +844,7 @@ static QScriptValue __setupPackage__(QScriptContext *ctx, QScriptEngine *eng) } // namespace QScript QScriptEnginePrivate::QScriptEnginePrivate() - : registeredScriptValues(0), freeScriptValues(0), + : registeredScriptValues(0), freeScriptValues(0), freeScriptValuesCount(0), registeredScriptStrings(0), inEval(false) { qMetaTypeId<QScriptValue>(); diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 79294fe..d0d020a 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -354,6 +354,8 @@ public: int agentLineNumber; QScriptValuePrivate *registeredScriptValues; QScriptValuePrivate *freeScriptValues; + static const int maxFreeScriptValues = 256; + int freeScriptValuesCount; QScriptStringPrivate *registeredScriptStrings; QHash<int, QScriptTypeInfo*> m_typeInfos; int processEventsInterval; @@ -521,6 +523,7 @@ inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(siz if (freeScriptValues) { QScriptValuePrivate *p = freeScriptValues; freeScriptValues = p->next; + --freeScriptValuesCount; return p; } return reinterpret_cast<QScriptValuePrivate*>(qMalloc(size)); @@ -528,8 +531,13 @@ inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(siz inline void QScriptEnginePrivate::freeScriptValuePrivate(QScriptValuePrivate *p) { - p->next = freeScriptValues; - freeScriptValues = p; + if (freeScriptValuesCount < maxFreeScriptValues) { + p->next = freeScriptValues; + freeScriptValues = p; + ++freeScriptValuesCount; + } else { + qFree(p); + } } inline void QScriptEnginePrivate::registerScriptValue(QScriptValuePrivate *value) diff --git a/src/svg/qgraphicssvgitem.cpp b/src/svg/qgraphicssvgitem.cpp index 7e80e50..69ff7a3 100644 --- a/src/svg/qgraphicssvgitem.cpp +++ b/src/svg/qgraphicssvgitem.cpp @@ -267,6 +267,7 @@ int QGraphicsSvgItem::type() const /*! \property QGraphicsSvgItem::maximumCacheSize + \since 4.6 This property holds the maximum size of the device coordinate cache for this item. @@ -312,7 +313,8 @@ QSize QGraphicsSvgItem::maximumCacheSize() const /*! \property QGraphicsSvgItem::elementId - + \since 4.6 + This property holds the element's XML ID. */ |