From e866577453334f528fdf289ab825af1911586e47 Mon Sep 17 00:00:00 2001 From: Kavindra Devi Palaraja Date: Fri, 21 Aug 2009 14:31:32 +0200 Subject: Doc - Clarified the use of layoutChanged() in relation to persistent model indexes Reviewed-By: Olivier Goffart Task: 231608 --- src/corelib/kernel/qabstractitemmodel.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 17af60d..3b7059b 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -1216,7 +1216,16 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent, layoutChanged() after changing the layout. Subclasses should update any persistent model indexes before emitting - layoutChanged(). + layoutChanged(). In other words, when the structure changes: + + \list + \o Call beginLayoutChanged() + \o Remember the QModelIndex that will change + \o Update your internal data + \o Call changePersistentIndex() + \o Call endLayoutChanged() + \endlist + \sa layoutAboutToBeChanged(), dataChanged(), headerDataChanged(), reset(), changePersistentIndex() -- cgit v0.12 From 09878f0d63000a2920458884d5ae0d765939395e Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Wed, 19 Aug 2009 13:49:32 +0200 Subject: Dont create native windows when setting up gestures. The code used to create native window handle even before checking if the widget subscribes to gestures, basically breaking alien widgets. Check the position of the gesture instead when the WM_GESTURE message is received in the GID_BEGIN state. This will work properly in most cases - but not always as the position that we get with the WM_GESTURE message is the center point of the multitouch gesture, which might be outside of the widget depending on positions of fingers. Reviewed-by: trustme --- src/gui/kernel/qapplication_p.h | 12 ++++ src/gui/kernel/qapplication_win.cpp | 128 ++++++++++++++++++------------------ src/gui/kernel/qwidget_win.cpp | 6 +- 3 files changed, 82 insertions(+), 64 deletions(-) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 5d409f4..70646a8 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -248,6 +248,17 @@ typedef struct tagGESTURECONFIG #endif // WM_GESTURE +#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES) +#undef GID_ZOOM +#define GID_ZOOM 0xf000 +#undef GID_ROTATE +#define GID_ROTATE 0xf001 +#undef GID_TWOFINGERTAP +#define GID_TWOFINGERTAP 0xf002 +#undef GID_ROLLOVER +#define GID_ROLLOVER 0xf003 +#endif + #endif // Q_WS_WIN class QPanGesture; @@ -531,6 +542,7 @@ public: PtrBeginPanningFeedback BeginPanningFeedback; PtrUpdatePanningFeedback UpdatePanningFeedback; PtrEndPanningFeedback EndPanningFeedback; + QWidget *gestureWidget; #endif #ifdef QT_RX71_MULTITOUCH diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 7d9e6ea..12cd879 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -452,7 +452,7 @@ public: bool translateConfigEvent(const MSG &msg); bool translateCloseEvent(const MSG &msg); bool translateTabletEvent(const MSG &msg, PACKET *localPacketBuf, int numPackets); - bool translateGestureEvent(const MSG &msg); + bool translateGestureEvent(const MSG &msg, const GESTUREINFO &gi); void repolishStyle(QStyle &style); inline void showChildren(bool spontaneous) { d_func()->showChildren(spontaneous); } inline void hideChildren(bool spontaneous) { d_func()->hideChildren(spontaneous); } @@ -848,6 +848,7 @@ void qt_init(QApplicationPrivate *priv, int) (PtrEndPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"), "EndPanningFeedback"); #endif + priv->gestureWidget = 0; } /***************************************************************************** @@ -2513,10 +2514,38 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam } result = false; break; - case WM_GESTURE: - widget->translateGestureEvent(msg); + case WM_GESTURE: { + GESTUREINFO gi; + memset(&gi, 0, sizeof(GESTUREINFO)); + gi.cbSize = sizeof(GESTUREINFO); + + QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); + BOOL bResult = false; + if (qAppPriv->GetGestureInfo) + bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi); + if (bResult) { + if (gi.dwID == GID_BEGIN) { + // find the alien widget for the gesture position. + // This might not be accurate as the position is the center + // point of two fingers for multi-finger gestures. + QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y); + QWidget *w = widget->childAt(widget->mapFromGlobal(pt)); + qAppPriv->gestureWidget = w ? w : widget; + } + if (qAppPriv->gestureWidget) + static_cast(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi); + if (qAppPriv->CloseGestureInfoHandle) + qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam); + if (gi.dwID == GID_END) + qAppPriv->gestureWidget = 0; + } else { + DWORD dwErr = GetLastError(); + if (dwErr > 0) + qWarning() << "translateGestureEvent: error = " << dwErr; + } result = true; break; + } default: result = false; // event was not processed break; @@ -3725,69 +3754,42 @@ bool QETWidget::translateCloseEvent(const MSG &) return d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); } -bool QETWidget::translateGestureEvent(const MSG &msg) +bool QETWidget::translateGestureEvent(const MSG &, const GESTUREINFO &gi) { - GESTUREINFO gi; - memset(&gi, 0, sizeof(GESTUREINFO)); - gi.cbSize = sizeof(GESTUREINFO); + const QPoint widgetPos = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); + QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos); + if (alienWidget && alienWidget->internalWinId()) + alienWidget = 0; + QWidget *widget = alienWidget ? alienWidget : this; - QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); -#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES) -#undef GID_ZOOM -#define GID_ZOOM 0xf000 -#undef GID_ROTATE -#define GID_ROTATE 0xf001 -#undef GID_TWOFINGERTAP -#define GID_TWOFINGERTAP 0xf002 -#undef GID_ROLLOVER -#define GID_ROLLOVER 0xf003 -#endif - BOOL bResult = false; - if (qAppPriv->GetGestureInfo) - bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi); - - if (bResult) { - const QPoint widgetPos = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); - QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos); - if (alienWidget && alienWidget->internalWinId()) - alienWidget = 0; - QWidget *widget = alienWidget ? alienWidget : this; - - QNativeGestureEvent event; - event.sequenceId = gi.dwSequenceID; - event.position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); - event.argument = gi.ullArguments; - - switch (gi.dwID) { - case GID_BEGIN: - event.gestureType = QNativeGestureEvent::GestureBegin; - break; - case GID_END: - event.gestureType = QNativeGestureEvent::GestureEnd; - break; - case GID_ZOOM: - event.gestureType = QNativeGestureEvent::Zoom; - break; - case GID_PAN: - event.gestureType = QNativeGestureEvent::Pan; - break; - case GID_ROTATE: - event.gestureType = QNativeGestureEvent::Rotate; - break; - case GID_TWOFINGERTAP: - case GID_ROLLOVER: - default: - break; - } - if (qAppPriv->CloseGestureInfoHandle) - qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam); - if (event.gestureType != QNativeGestureEvent::None) - qt_sendSpontaneousEvent(widget, &event); - } else { - DWORD dwErr = GetLastError(); - if (dwErr > 0) - qWarning() << "translateGestureEvent: error = " << dwErr; + QNativeGestureEvent event; + event.sequenceId = gi.dwSequenceID; + event.position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); + event.argument = gi.ullArguments; + + switch (gi.dwID) { + case GID_BEGIN: + event.gestureType = QNativeGestureEvent::GestureBegin; + break; + case GID_END: + event.gestureType = QNativeGestureEvent::GestureEnd; + break; + case GID_ZOOM: + event.gestureType = QNativeGestureEvent::Zoom; + break; + case GID_PAN: + event.gestureType = QNativeGestureEvent::Pan; + break; + case GID_ROTATE: + event.gestureType = QNativeGestureEvent::Rotate; + break; + case GID_TWOFINGERTAP: + case GID_ROLLOVER: + default: + break; } + if (event.gestureType != QNativeGestureEvent::None) + qt_sendSpontaneousEvent(widget, &event); return true; } diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index ea334b6..bf2abc8 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -2066,7 +2066,11 @@ void QWidgetPrivate::winSetupGestures() bool needh = false; bool needv = false; bool singleFingerPanEnabled = false; - QStandardGestures gestures = qAppPriv->widgetGestures[q]; + QApplicationPrivate::WidgetStandardGesturesMap::const_iterator it = + qAppPriv->widgetGestures.find(q); + if (it == qAppPriv->widgetGestures.end()) + return; + const QStandardGestures &gestures = it.value(); WId winid = 0; if (QAbstractScrollArea *asa = qobject_cast(q)) { -- cgit v0.12 From 1a78099a6b5523ad913caf9d1700a4f6ffbea485 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 21 Aug 2009 11:14:33 +0200 Subject: Fixed gesture handling on Windows when there are no alien widgets Use the proper winid to set gesture configuration to. Reviewed-by: trustme --- src/gui/kernel/qwidget_win.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index bf2abc8..ef0fe6a 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -2074,7 +2074,13 @@ void QWidgetPrivate::winSetupGestures() WId winid = 0; if (QAbstractScrollArea *asa = qobject_cast(q)) { - winid = asa->viewport()->winId(); + winid = asa->viewport()->internalWinId(); + if (!winid) { + QWidget *nativeParent = asa->viewport()->nativeParentWidget(); + if (!nativeParent) + return; + winid = nativeParent->internalWinId(); + } QScrollBar *hbar = asa->horizontalScrollBar(); QScrollBar *vbar = asa->verticalScrollBar(); Qt::ScrollBarPolicy hbarpolicy = asa->horizontalScrollBarPolicy(); @@ -2085,9 +2091,13 @@ void QWidgetPrivate::winSetupGestures() (vbarpolicy == Qt::ScrollBarAsNeeded && vbar->minimum() < vbar->maximum())); singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled; } else { - winid = q->winId(); + winid = q->internalWinId(); + if (!winid) { + if (QWidget *nativeParent = q->nativeParentWidget()) + winid = nativeParent->internalWinId(); + } } - if (qAppPriv->SetGestureConfig) { + if (winid && qAppPriv->SetGestureConfig) { GESTURECONFIG gc[3]; memset(gc, 0, sizeof(gc)); gc[0].dwID = GID_PAN; @@ -2116,7 +2126,6 @@ void QWidgetPrivate::winSetupGestures() else gc[2].dwBlock = GC_ROTATE; - Q_ASSERT(winid); qAppPriv->SetGestureConfig(winid, 0, sizeof(gc)/sizeof(gc[0]), gc, sizeof(gc[0])); } } -- cgit v0.12 From b69bc882acdc445c5ef2334697f7eec9cb73f16d Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 21 Aug 2009 11:16:16 +0200 Subject: Improved the QPanGesture implementation. When Pan is implemented with touch events, make sure it pans only when two fingers are used. Reviewed-by: trustme --- src/gui/kernel/qstandardgestures.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index 10689ba..8c50c78 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -179,27 +179,29 @@ bool QPanGesture::filterEvent(QEvent *event) d->lastOffset = d->totalOffset = QSize(); } else if (event->type() == QEvent::TouchEnd) { if (state() != Qt::NoGesture) { - if (!ev->touchPoints().isEmpty()) { - QTouchEvent::TouchPoint p = ev->touchPoints().at(0); - const QPoint pos = p.pos().toPoint(); - const QPoint lastPos = p.lastPos().toPoint(); - const QPoint startPos = p.startPos().toPoint(); - d->lastOffset = QSize(pos.x() - lastPos.x(), pos.y() - lastPos.y()); - d->totalOffset = QSize(pos.x() - startPos.x(), pos.y() - startPos.y()); + if (ev->touchPoints().size() == 2) { + QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); + QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + d->lastOffset = + QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), + p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; + d->totalOffset += d->lastOffset; } updateState(Qt::GestureFinished); } reset(); } else if (event->type() == QEvent::TouchUpdate) { - QTouchEvent::TouchPoint p = ev->touchPoints().at(0); - const QPoint pos = p.pos().toPoint(); - const QPoint lastPos = p.lastPos().toPoint(); - const QPoint startPos = p.startPos().toPoint(); - d->lastOffset = QSize(pos.x() - lastPos.x(), pos.y() - lastPos.y()); - d->totalOffset = QSize(pos.x() - startPos.x(), pos.y() - startPos.y()); - if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || - d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { - updateState(Qt::GestureUpdated); + if (ev->touchPoints().size() == 2) { + QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0); + QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1); + d->lastOffset = + QSize(p1.pos().x() - p1.lastPos().x() + p2.pos().x() - p2.lastPos().x(), + p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2; + d->totalOffset += d->lastOffset; + if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || + d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { + updateState(Qt::GestureUpdated); + } } } #ifdef Q_OS_MAC -- cgit v0.12 From f13908359f08d856c2825988e65651dbf744c0e4 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 21 Aug 2009 13:57:18 +0200 Subject: Improved a QGesture api a little bit. Changed the constructor of the QGesture to separate the gesture target (the object/widget that the gesture filters events for), and the parent object. Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qgesture.cpp | 37 ++++++++++++--- src/gui/kernel/qgesture.h | 8 +++- src/gui/kernel/qgesture_p.h | 5 +- src/gui/kernel/qstandardgestures.cpp | 92 ++++++++++++++++-------------------- src/gui/kernel/qstandardgestures.h | 4 +- src/gui/kernel/qstandardgestures_p.h | 5 ++ 6 files changed, 88 insertions(+), 63 deletions(-) diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 79dcae1..eeb6528 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -149,20 +149,18 @@ private: \sa setGraphicsItem() */ -QGesture::QGesture(QObject *parent) +QGesture::QGesture(QObject *gestureTarget, QObject *parent) : QObject(*new QGesturePrivate, parent) { - if (parent) - parent->installEventFilter(this); + setGestureTarget(gestureTarget); } /*! \internal */ -QGesture::QGesture(QGesturePrivate &dd, QObject *parent) +QGesture::QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent) : QObject(dd, parent) { - if (parent) - parent->installEventFilter(this); + setGestureTarget(gestureTarget); } /*! @@ -172,6 +170,33 @@ QGesture::~QGesture() { } +/*! + \property QGesture::gestureTarget + + Gesture target is the object that the gesture will observe for events. + Typically this means that the gesture installs an event filter on the + target object. +*/ +void QGesture::setGestureTarget(QObject *object) +{ + d_func()->setupGestureTarget(object); +} + +QObject* QGesture::gestureTarget() const +{ + return d_func()->gestureTarget; +} + +void QGesturePrivate::setupGestureTarget(QObject *object) +{ + Q_Q(QGesture); + if (gestureTarget) + gestureTarget->removeEventFilter(q); + if (object) + object->installEventFilter(q); + gestureTarget = object; +} + /*! \internal */ bool QGesture::eventFilter(QObject *receiver, QEvent *event) diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index ee28ea4..1d2fa6d 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -63,20 +63,24 @@ class Q_GUI_EXPORT QGesture : public QObject Q_DECLARE_PRIVATE(QGesture) Q_PROPERTY(Qt::GestureState state READ state) + Q_PROPERTY(QObject* gestureTarget READ gestureTarget WRITE setGestureTarget) public: - explicit QGesture(QObject *parent = 0); + explicit QGesture(QObject *gestureTarget = 0, QObject *parent = 0); ~QGesture(); virtual bool filterEvent(QEvent *event) = 0; + void setGestureTarget(QObject *object); + QObject* gestureTarget() const; + void setGraphicsItem(QGraphicsItem *); QGraphicsItem *graphicsItem() const; Qt::GestureState state() const; protected: - QGesture(QGesturePrivate &dd, QObject *parent); + QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent); bool eventFilter(QObject*, QEvent*); virtual void reset(); diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 37f3146..f584713 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -69,11 +69,14 @@ class QGesturePrivate : public QObjectPrivate public: QGesturePrivate() - : graphicsItem(0), eventFilterProxyGraphicsItem(0), state(Qt::NoGesture) + : gestureTarget(0), graphicsItem(0), eventFilterProxyGraphicsItem(0), + state(Qt::NoGesture) { } + virtual void setupGestureTarget(QObject *o); + QPointer gestureTarget; QGraphicsItem *graphicsItem; QGraphicsItem *eventFilterProxyGraphicsItem; diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index 8c50c78..d798d32 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -69,42 +69,35 @@ QWidgetPrivate *qt_widget_private(QWidget *widget); On some platform like Windows it's necessary to provide a non-null widget as \a parent to get native gesture support. */ -QPanGesture::QPanGesture(QWidget *parent) - : QGesture(*new QPanGesturePrivate, parent) +QPanGesture::QPanGesture(QWidget *gestureTarget, QObject *parent) + : QGesture(*new QPanGesturePrivate, gestureTarget, parent) { - if (parent) { - QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); - qAppPriv->widgetGestures[parent].pan = this; -#ifdef Q_WS_WIN - qt_widget_private(parent)->winSetupGestures(); -#endif - } } -/*! \internal */ -bool QPanGesture::event(QEvent *event) +void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget) { - switch (event->type()) { - case QEvent::ParentAboutToChange: - if (QWidget *w = qobject_cast(parent())) { - QApplicationPrivate::instance()->widgetGestures[w].pan = 0; + Q_Q(QPanGesture); + if (gestureTarget && gestureTarget->isWidgetType()) { + QWidget *w = static_cast(gestureTarget.data()); + QApplicationPrivate::instance()->widgetGestures[w].pan = 0; #ifdef Q_WS_WIN - qt_widget_private(w)->winSetupGestures(); + qt_widget_private(w)->winSetupGestures(); #endif - } - break; - case QEvent::ParentChange: - if (QWidget *w = qobject_cast(parent())) { - QApplicationPrivate::instance()->widgetGestures[w].pan = this; + } + + if (newGestureTarget && newGestureTarget->isWidgetType()) { + QWidget *w = static_cast(newGestureTarget); + QApplicationPrivate::instance()->widgetGestures[w].pan = q; #ifdef Q_WS_WIN - qt_widget_private(w)->winSetupGestures(); + qt_widget_private(w)->winSetupGestures(); #endif - } - break; - default: - break; } + QGesturePrivate::setupGestureTarget(newGestureTarget); +} +/*! \internal */ +bool QPanGesture::event(QEvent *event) +{ #if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA) Q_D(QPanGesture); if (event->type() == QEvent::Timer) { @@ -289,41 +282,35 @@ QSize QPanGesture::lastOffset() const On some platform like Windows it's necessary to provide a non-null widget as \a parent to get native gesture support. */ -QPinchGesture::QPinchGesture(QWidget *parent) - : QGesture(*new QPinchGesturePrivate, parent) +QPinchGesture::QPinchGesture(QWidget *gestureTarget, QObject *parent) + : QGesture(*new QPinchGesturePrivate, gestureTarget, parent) { - if (parent) { - QApplicationPrivate *qAppPriv = QApplicationPrivate::instance(); - qAppPriv->widgetGestures[parent].pinch = this; -#ifdef Q_WS_WIN - qt_widget_private(parent)->winSetupGestures(); -#endif - } } -/*! \internal */ -bool QPinchGesture::event(QEvent *event) +void QPinchGesturePrivate::setupGestureTarget(QObject *newGestureTarget) { - switch (event->type()) { - case QEvent::ParentAboutToChange: - if (QWidget *w = qobject_cast(parent())) { - QApplicationPrivate::instance()->widgetGestures[w].pinch = 0; + Q_Q(QPinchGesture); + if (gestureTarget && gestureTarget->isWidgetType()) { + QWidget *w = static_cast(gestureTarget.data()); + QApplicationPrivate::instance()->widgetGestures[w].pinch = 0; #ifdef Q_WS_WIN - qt_widget_private(w)->winSetupGestures(); + qt_widget_private(w)->winSetupGestures(); #endif - } - break; - case QEvent::ParentChange: - if (QWidget *w = qobject_cast(parent())) { - QApplicationPrivate::instance()->widgetGestures[w].pinch = this; + } + + if (newGestureTarget && newGestureTarget->isWidgetType()) { + QWidget *w = static_cast(newGestureTarget); + QApplicationPrivate::instance()->widgetGestures[w].pinch = q; #ifdef Q_WS_WIN - qt_widget_private(w)->winSetupGestures(); + qt_widget_private(w)->winSetupGestures(); #endif - } - break; - default: - break; } + QGesturePrivate::setupGestureTarget(newGestureTarget); +} + +/*! \internal */ +bool QPinchGesture::event(QEvent *event) +{ return QObject::event(event); } @@ -401,6 +388,7 @@ bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event) return QGesture::eventFilter(receiver, event); } + /*! \internal */ bool QPinchGesture::filterEvent(QEvent *event) { diff --git a/src/gui/kernel/qstandardgestures.h b/src/gui/kernel/qstandardgestures.h index 8b5421b..0eb9d92 100644 --- a/src/gui/kernel/qstandardgestures.h +++ b/src/gui/kernel/qstandardgestures.h @@ -63,7 +63,7 @@ class Q_GUI_EXPORT QPanGesture : public QGesture Q_PROPERTY(QSize lastOffset READ lastOffset) public: - QPanGesture(QWidget *parent); + QPanGesture(QWidget *gestureTarget, QObject *parent = 0); bool filterEvent(QEvent *event); @@ -97,7 +97,7 @@ class Q_GUI_EXPORT QPinchGesture : public QGesture Q_PROPERTY(QPoint centerPoint READ centerPoint) public: - QPinchGesture(QWidget *parent); + QPinchGesture(QWidget *gestureTarget, QObject *parent = 0); bool filterEvent(QEvent *event); void reset(); diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h index c52d16b..5fbcc5d 100644 --- a/src/gui/kernel/qstandardgestures_p.h +++ b/src/gui/kernel/qstandardgestures_p.h @@ -76,6 +76,8 @@ public: #endif } + void setupGestureTarget(QObject *o); + QSize totalOffset; QSize lastOffset; QPoint lastPosition; @@ -98,6 +100,9 @@ public: #endif { } + + void setupGestureTarget(QObject *o); + qreal scaleFactor; qreal lastScaleFactor; qreal rotationAngle; -- cgit v0.12 From 02ef8fab7e511f50e901676eac15229eb456b01c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 25 Nov 2008 16:44:11 +0100 Subject: Add a new class for handling a process's environment variables. First of all, make it a lot easier to access individual variables by having them in an associative container (a QHash). This fixes task 232427, albeit one release later than I had originally planned. On Windows, the variable names in the environment are case-insensitive, so a direct QHash isn't a good solution. Implement code that does the uppercasing on Windows and leaves untransformed on other platforms. Since we're doing this anyways, use QByteArray on Unix systems, since, in theory, the environment could contain any random binary data, which is not representable in QString. Task-number: 232427 --- doc/src/snippets/qprocess-environment/main.cpp | 6 +- src/corelib/io/qprocess.cpp | 242 +++++++++++++++++++------ src/corelib/io/qprocess.h | 44 ++++- src/corelib/io/qprocess_p.h | 17 +- src/corelib/io/qprocess_unix.cpp | 26 +-- src/corelib/io/qprocess_win.cpp | 14 +- tests/auto/qprocess/tst_qprocess.cpp | 37 +++- 7 files changed, 300 insertions(+), 86 deletions(-) diff --git a/doc/src/snippets/qprocess-environment/main.cpp b/doc/src/snippets/qprocess-environment/main.cpp index a143bf8..0fa0896 100644 --- a/doc/src/snippets/qprocess-environment/main.cpp +++ b/doc/src/snippets/qprocess-environment/main.cpp @@ -57,10 +57,10 @@ process.start("myapp"); { //! [1] QProcess process; -QHash env = QProcess::systemEnvironmentHash(); +QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); env.insert("TMPDIR", "C:\\MyApp\\temp"); // Add an environment variable -env["PATH"] += ";C:\\Bin"; -process.setEnvironment(env); +env.insert("PATH", env.value("Path") + ";C:\\Bin"); +process.setProcessEnvironment(env); process.start("myapp"); //! [1] } diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index ccc16b2..3d143e9 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -101,27 +101,169 @@ QT_END_NAMESPACE QT_BEGIN_NAMESPACE -static QHash environmentHashFromList(const QStringList &environment) +#ifdef Q_OS_WIN +static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name) +{ return name.toUpper(); } +static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name) +{ return QString::fromLocal8Bit(name).toUpper(); } +static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name) +{ return name; } +static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value) +{ return value; } +static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value) +{ return QString::fromLocal8Bit(value); } +static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value) +{ return value; } +static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value) +{ return value.toLocal8Bit(); } +#else +static inline QProcessEnvironmentPrivate::Unit prepareName(const QByteArray &name) +{ return name; } +static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name) +{ return name.toLocal8Bit(); } +static inline QString nameToString(const QProcessEnvironmentPrivate::Unit &name) +{ return QString::fromLocal8Bit(name); } +static inline QProcessEnvironmentPrivate::Unit prepareValue(const QByteArray &value) +{ return value; } +static inline QProcessEnvironmentPrivate::Unit prepareValue(const QString &value) +{ return value.toLocal8Bit(); } +static inline QString valueToString(const QProcessEnvironmentPrivate::Unit &value) +{ return QString::fromLocal8Bit(value); } +static inline QByteArray valueToByteArray(const QProcessEnvironmentPrivate::Unit &value) +{ return value; } +#endif + +template<> void QSharedDataPointer::detach() { - QHash result; - QStringList::ConstIterator it = environment.constBegin(), - end = environment.constEnd(); + if (d && d->ref == 1) + return; + QProcessEnvironmentPrivate *x = (d ? new QProcessEnvironmentPrivate(*d) + : new QProcessEnvironmentPrivate); + x->ref.ref(); + if (d && !d->ref.deref()) + delete d; + d = x; +} + +QStringList QProcessEnvironmentPrivate::toList() const +{ + QStringList result; + QHash::ConstIterator it = hash.constBegin(), + end = hash.constEnd(); for ( ; it != end; ++it) { - int equals = it->indexOf(QLatin1Char('=')); + QString data = nameToString(it.key()); + QString value = valueToString(it.value()); + data.reserve(data.length() + value.length() + 1); + data.append(QLatin1Char('=')); + data.append(value); + result << data; + } + return result; +} + +QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list) +{ + QProcessEnvironment env; + QStringList::ConstIterator it = list.constBegin(), + end = list.constEnd(); + for ( ; it != end; ++it) { + int pos = it->indexOf(QLatin1Char('=')); + if (pos < 1) + continue; + QString value = it->mid(pos + 1); QString name = *it; - QString value; - if (equals != -1) { - name.truncate(equals); -#ifdef Q_OS_WIN - name = name.toUpper(); -#endif - value = it->mid(equals + 1); - } - result.insert(name, value); + name.truncate(pos); + env.insert(name, value); } + return env; +} - return result; +QProcessEnvironment::QProcessEnvironment() + : d(0) +{ +} + +QProcessEnvironment::~QProcessEnvironment() +{ +} + +QProcessEnvironment::QProcessEnvironment(const QProcessEnvironment &other) + : d(other.d) +{ +} + +QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &other) +{ + d = other.d; + return *this; +} + +bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const +{ + return d->hash == other.d->hash; +} + +bool QProcessEnvironment::isEmpty() const +{ + return d ? d->hash.isEmpty() : true; +} + +void QProcessEnvironment::clear() +{ + d->hash.clear(); +} + +bool QProcessEnvironment::contains(const QString &name) const +{ + return d ? d->hash.contains(prepareName(name)) : false; +} + +void QProcessEnvironment::insert(const QString &name, const QString &value) +{ + d->hash.insert(prepareName(name), prepareValue(value)); +} + +void QProcessEnvironment::remove(const QString &name) +{ + d->hash.remove(prepareName(name)); +} + +QString QProcessEnvironment::value(const QString &name, const QString &defaultValue) const +{ + if (!d) + return defaultValue; + + QProcessEnvironmentPrivate::Unit result = d->hash.value(prepareName(name), prepareValue(defaultValue)); + return valueToString(result); +} + +bool QProcessEnvironment::containsRaw(const QByteArray &name) const +{ + return d ? d->hash.contains(prepareName(name)) : false; +} + +void QProcessEnvironment::insertRaw(const QByteArray &name, const QByteArray &value) +{ + d->hash.insert(prepareName(name), prepareValue(value)); +} + +void QProcessEnvironment::removeRaw(const QByteArray &name) +{ + d->hash.remove(prepareName(name)); +} + +QByteArray QProcessEnvironment::valueRaw(const QByteArray &name, const QByteArray &defaultValue) const +{ + if (!d) + return defaultValue; + QProcessEnvironmentPrivate::Unit result = d->hash.value(prepareName(name), prepareValue(defaultValue)); + return valueToByteArray(result); +} + +QStringList QProcessEnvironment::toStringList() const +{ + return d ? d->toList() : QStringList(); } void QProcessPrivate::Channel::clear() @@ -446,7 +588,6 @@ QProcessPrivate::QProcessPrivate() sequenceNumber = 0; exitCode = 0; exitStatus = QProcess::NormalExit; - environment = 0; startupSocketNotifier = 0; deathNotifier = 0; notifier = 0; @@ -473,7 +614,6 @@ QProcessPrivate::QProcessPrivate() */ QProcessPrivate::~QProcessPrivate() { - delete environment; if (stdinChannel.process) stdinChannel.process->stdoutChannel.clear(); if (stdoutChannel.process) @@ -1215,6 +1355,7 @@ QProcess::ProcessState QProcess::state() const } /*! + \deprecated Sets the environment that QProcess will use when starting a process to the \a environment specified which consists of a list of key=value pairs. @@ -1223,14 +1364,15 @@ QProcess::ProcessState QProcess::state() const \snippet doc/src/snippets/qprocess-environment/main.cpp 0 - \sa environment(), systemEnvironment(), setEnvironmentHash() + \sa environment(), setProcessEnvironment(), systemEnvironment() */ void QProcess::setEnvironment(const QStringList &environment) { - setEnvironmentHash(environmentHashFromList(environment)); + setProcessEnvironment(QProcessEnvironmentPrivate::fromList(environment)); } /*! + \deprecated Returns the environment that QProcess will use when starting a process, or an empty QStringList if no environment has been set using setEnvironment() or setEnvironmentHash(). If no environment @@ -1239,67 +1381,50 @@ void QProcess::setEnvironment(const QStringList &environment) \note The environment settings are ignored on Windows CE, as there is no concept of an environment. - \sa environmentHash(), setEnvironment(), systemEnvironment() + \sa processEnvironment(), setEnvironment(), systemEnvironment() */ QStringList QProcess::environment() const { Q_D(const QProcess); - - QStringList result; - if (!d->environment) - return result; - - QHash::ConstIterator it = d->environment->constBegin(), - end = d->environment->constEnd(); - for ( ; it != end; ++it) { - QString data = it.key(); - data.reserve(data.length() + it.value().length() + 1); - data.append(QLatin1Char('=')); - data.append(it.value()); - result << data; - } - return result; + return d->environment.toStringList(); } /*! \since 4.5 Sets the environment that QProcess will use when starting a process to the - \a environment hash map. + \a environment object. For example, the following code adds the \c{C:\\BIN} directory to the list of executable paths (\c{PATHS}) on Windows and sets \c{TMPDIR}: \snippet doc/src/snippets/qprocess-environment/main.cpp 1 - \sa environment(), systemEnvironmentHash(), setEnvironment() + Note how, on Windows, environment variable names are case-insensitive. + + \sa processEnvironment(), QProcessEnvironment::systemEnvironment(), setEnvironment() */ -void QProcess::setEnvironmentHash(const QHash &environment) +void QProcess::setProcessEnvironment(const QProcessEnvironment &environment) { Q_D(QProcess); - if (!d->environment) - d->environment = new QHash(environment); - else - *d->environment = environment; + d->environment = environment; } /*! \since 4.5 Returns the environment that QProcess will use when starting a - process, or an empty QHash if no environment has been set using - setEnvironment() or setEnvironmentHash(). If no environment has + process, or an empty object if no environment has been set using + setEnvironment() or setProcessEnvironment(). If no environment has been set, the environment of the calling process will be used. \note The environment settings are ignored on Windows CE, as there is no concept of an environment. - \sa setEnvironmentHash(), setEnvironment(), systemEnvironmentHash() + \sa setProcessEnvironment(), setEnvironment(), QProcessEnvironment::isValid() */ -QHash QProcess::environmentHash() const +QProcessEnvironment QProcess::processEnvironment() const { Q_D(const QProcess); - if (d->environment) - return *d->environment; - return QHash(); + return d->environment; } /*! @@ -1898,7 +2023,7 @@ QT_END_INCLUDE_NAMESPACE \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8 - \sa systemEnvironmentHash(), environment(), setEnvironment() + \sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment() */ QStringList QProcess::systemEnvironment() { @@ -1915,11 +2040,22 @@ QStringList QProcess::systemEnvironment() Returns the environment of the calling process as a QHash. - \sa systemEnvironment(), environmentHash(), setEnvironmentHash() + \sa QProcess::systemEnvironment() */ -QHash QProcess::systemEnvironmentHash() +QProcessEnvironment QProcessEnvironment::systemEnvironment() { - return environmentHashFromList(systemEnvironment()); + QProcessEnvironment env; + const char *entry; + for (int count = 0; (entry = environ[count]); ++count) { + const char *equal = strchr(entry, '='); + if (!equal) + continue; + + QByteArray name(entry, equal - entry); + QByteArray value(equal + 1); + env.insertRaw(name, value); + } + return env; } /*! diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index 096f625..116168b 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -44,6 +44,7 @@ #include #include +#include QT_BEGIN_HEADER @@ -53,8 +54,6 @@ QT_MODULE(Core) #ifndef QT_NO_PROCESS -template class QHash; - #if (!defined(Q_OS_WIN32) && !defined(Q_OS_WINCE)) || defined(qdoc) typedef qint64 Q_PID; #else @@ -64,6 +63,42 @@ QT_BEGIN_NAMESPACE #endif class QProcessPrivate; +class QProcessEnvironmentPrivate; + +class Q_CORE_EXPORT QProcessEnvironment +{ +public: + QProcessEnvironment(); + QProcessEnvironment(const QProcessEnvironment &other); + ~QProcessEnvironment(); + QProcessEnvironment &operator=(const QProcessEnvironment &other); + + bool operator==(const QProcessEnvironment &other) const; + inline bool operator!=(const QProcessEnvironment &other) const + { return !(*this == other); } + + bool isEmpty() const; + void clear(); + + bool contains(const QString &name) const; + void insert(const QString &name, const QString &value); + void remove(const QString &name); + QString value(const QString &name, const QString &defaultValue = QString()) const; + + bool containsRaw(const QByteArray &name) const; + void insertRaw(const QByteArray &name, const QByteArray &value); + void removeRaw(const QByteArray &name); + QByteArray valueRaw(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; + + QStringList toStringList() const; + + static QProcessEnvironment systemEnvironment(); + +private: + friend class QProcessPrivate; + friend class QProcessEnvironmentPrivate; + QSharedDataPointer d; +}; class Q_CORE_EXPORT QProcess : public QIODevice { @@ -123,8 +158,8 @@ public: void setEnvironment(const QStringList &environment); QStringList environment() const; - void setEnvironmentHash(const QHash &environment); - QHash environmentHash() const; + void setProcessEnvironment(const QProcessEnvironment &environment); + QProcessEnvironment processEnvironment() const; QProcess::ProcessError error() const; QProcess::ProcessState state() const; @@ -160,7 +195,6 @@ public: static bool startDetached(const QString &program); static QStringList systemEnvironment(); - static QHash systemEnvironmentHash(); public Q_SLOTS: void terminate(); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 5482871..3b04d88 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -55,6 +55,7 @@ #include "QtCore/qprocess.h" #include "QtCore/qstringlist.h" +#include "QtCore/qhash.h" #include "private/qringbuffer_p.h" #include "private/qiodevice_p.h" @@ -76,6 +77,20 @@ class QWindowsPipeWriter; class QWinEventNotifier; class QTimer; +class QProcessEnvironmentPrivate: public QSharedData +{ +public: +#ifdef Q_OS_WIN + typedef QString Unit; +#else + typedef QByteArray Unit; +#endif + QHash hash; + + static QProcessEnvironment fromList(const QStringList &list); + QStringList toList() const; +}; + class QProcessPrivate : public QIODevicePrivate { public: @@ -161,7 +176,7 @@ public: QString program; QStringList arguments; - QHash *environment; + QProcessEnvironment environment; QRingBuffer outputReadBuffer; QRingBuffer errorReadBuffer; diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index d28cdc4..dfeeb71 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -458,11 +458,11 @@ bool QProcessPrivate::createChannel(Channel &channel) } } -static char **_q_dupEnvironment(const QHash *environment, int *envc) +static char **_q_dupEnvironment(const QHash &environment, int *envc) { *envc = 0; - if (!environment) - return 0; // use the default environment + if (environment.isEmpty()) + return 0; // if LD_LIBRARY_PATH exists in the current environment, but // not in the environment list passed by the programmer, then @@ -474,17 +474,17 @@ static char **_q_dupEnvironment(const QHash *environment, int #endif const QByteArray envLibraryPath = qgetenv(libraryPath); bool needToAddLibraryPath = !envLibraryPath.isEmpty() && - !environment->contains(QLatin1String(libraryPath)); + !environment.contains(libraryPath); - char **envp = new char *[environment->count() + 2]; - envp[environment->count()] = 0; - envp[environment->count() + 1] = 0; + char **envp = new char *[environment.count() + 2]; + envp[environment.count()] = 0; + envp[environment.count() + 1] = 0; - QHash::ConstIterator it = environment->constBegin(); - const QHash::ConstIterator end = environment->constEnd(); + QHash::ConstIterator it = environment.constBegin(); + const QHash::ConstIterator end = environment.constEnd(); for ( ; it != end; ++it) { - QByteArray key = it.key().toLocal8Bit(); - QByteArray value = it.value().toLocal8Bit(); + QByteArray key = it.key(); + QByteArray value = it.value(); key.reserve(key.length() + 1 + value.length()); key.append('='); key.append(value); @@ -590,7 +590,9 @@ void QProcessPrivate::startProcess() // Duplicate the environment. int envc = 0; - char **envp = _q_dupEnvironment(environment, &envc); + char **envp = 0; + if (environment.d.constData()) + envp = _q_dupEnvironment(environment.d.constData()->hash, &envc); // Encode the working directory if it's non-empty, otherwise just pass 0. const char *workingDirPtr = 0; diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index acb169f..50a4a00 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -278,17 +278,17 @@ static QString qt_create_commandline(const QString &program, const QStringList & return args; } -static QByteArray qt_create_environment(const QHash *environment) +static QByteArray qt_create_environment(const QHash &environment) { QByteArray envlist; - if (environment) { - QHash copy = *environment; + if (!environment.isEmpty()) { + QHash copy = environment; // add PATH if necessary (for DLL loading) if (!copy.contains(QLatin1String("PATH"))) { QByteArray path = qgetenv("PATH"); if (!path.isEmpty()) - copy.insert(QLatin1String("PATH"), QString::fromLocal8Bit(path)); + copy.insert(QLatin1String("PATH"), QString::fromLocal8Bit(path)); } // add systemroot if needed @@ -362,7 +362,9 @@ void QProcessPrivate::startProcess() QString args = qt_create_commandline(QString(), arguments); #else QString args = qt_create_commandline(program, arguments); - QByteArray envlist = qt_create_environment(environment); + QByteArray envlist; + if (environment.d.constData()) + envlist = qt_create_environment(environment.d.constData()->hash); #endif #if defined QPROCESS_DEBUG @@ -393,7 +395,7 @@ void QProcessPrivate::startProcess() }; success = CreateProcess(0, (wchar_t*)args.utf16(), 0, 0, TRUE, dwCreationFlags, - environment ? envlist.data() : 0, + environment.isEmpty() ? 0 : envlist.data(), workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), &startupInfo, pid); diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index b57139b..d2af86a 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -130,6 +130,8 @@ private slots: void exitCodeTest(); void setEnvironment_data(); void setEnvironment(); + void setProcessEnvironment_data(); + void setProcessEnvironment(); void systemEnvironment(); void spaceInName(); void lockupsInStartDetached(); @@ -1697,16 +1699,39 @@ void tst_QProcess::setEnvironment() QCOMPARE(process.readAll(), value.toLocal8Bit()); } +#endif +} + +//----------------------------------------------------------------------------- +void tst_QProcess::setProcessEnvironment_data() +{ + setEnvironment_data(); +} + +void tst_QProcess::setProcessEnvironment() +{ +#if !defined (Q_OS_WINCE) + // there is no concept of system variables on Windows CE as there is no console + + // make sure our environment variables are correct + QVERIFY(qgetenv("tst_QProcess").isEmpty()); + QVERIFY(!qgetenv("PATH").isEmpty()); +#ifdef Q_OS_WIN + QVERIFY(!qgetenv("PROMPT").isEmpty()); +#endif + + QFETCH(QString, name); + QFETCH(QString, value); + QString executable = QDir::currentPath() + "/testProcessEnvironment/testProcessEnvironment"; - // use the hash variant now { QProcess process; - QHash environment = QProcess::systemEnvironmentHash(); + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); if (value.isNull()) environment.remove(name); else environment.insert(name, value); - process.setEnvironmentHash(environment); + process.setProcessEnvironment(environment); process.start(executable, QStringList() << name); QVERIFY(process.waitForFinished()); @@ -1725,12 +1750,12 @@ void tst_QProcess::systemEnvironment() #if defined (Q_OS_WINCE) // there is no concept of system variables on Windows CE as there is no console QVERIFY(QProcess::systemEnvironment().isEmpty()); - QVERIFY(QProcess::systemEnvironmentHash().isEmpty()); + QVERIFY(QProcessEnvironment::systemEnvironment().isEmpty()); #else QVERIFY(!QProcess::systemEnvironment().isEmpty()); - QVERIFY(!QProcess::systemEnvironmentHash().isEmpty()); + QVERIFY(!QProcessEnvironment::systemEnvironment().isEmpty()); - QVERIFY(QProcess::systemEnvironmentHash().contains("PATH")); + QVERIFY(QProcessEnvironment::systemEnvironment().contains("PATH")); QVERIFY(!QProcess::systemEnvironment().filter(QRegExp("^PATH=", Qt::CaseInsensitive)).isEmpty()); #endif } -- cgit v0.12 From 06b1759e694f57056454506ed10b14eb2639d07c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 25 Nov 2008 19:48:22 +0100 Subject: Add the reason for a process's failure to start to the errorString It would have been of great help to find this out when I was debugging the previous commit. --- src/corelib/io/qprocess_win.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 50a4a00..8ece6ec 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -398,6 +398,10 @@ void QProcessPrivate::startProcess() environment.isEmpty() ? 0 : envlist.data(), workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), &startupInfo, pid); + if (!success) { + // Capture the error string before we do CloseHandle below + q->setErrorString(QProcess::tr("Process failed to start: %1").arg(qt_error_string())); + } if (stdinChannel.pipe[0] != INVALID_Q_PIPE) { CloseHandle(stdinChannel.pipe[0]); @@ -416,7 +420,6 @@ void QProcessPrivate::startProcess() if (!success) { cleanup(); processError = QProcess::FailedToStart; - q->setErrorString(QProcess::tr("Process failed to start")); emit q->error(processError); q->setProcessState(QProcess::NotRunning); return; -- cgit v0.12 From e2b1ab498d0e3b194d5aaa9dd8d6a7112d1a0201 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 13 May 2009 16:15:31 +0200 Subject: Remove the xxxRaw versions of the QProcessEnvironment functions. If we ever decide we need them later, we can readd. For the moment, let's keep the QString versions only. --- src/corelib/io/qprocess.cpp | 27 ++------------------------- src/corelib/io/qprocess.h | 5 ----- 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 3d143e9..b9dd9d7 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -238,29 +238,6 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa return valueToString(result); } -bool QProcessEnvironment::containsRaw(const QByteArray &name) const -{ - return d ? d->hash.contains(prepareName(name)) : false; -} - -void QProcessEnvironment::insertRaw(const QByteArray &name, const QByteArray &value) -{ - d->hash.insert(prepareName(name), prepareValue(value)); -} - -void QProcessEnvironment::removeRaw(const QByteArray &name) -{ - d->hash.remove(prepareName(name)); -} - -QByteArray QProcessEnvironment::valueRaw(const QByteArray &name, const QByteArray &defaultValue) const -{ - if (!d) - return defaultValue; - QProcessEnvironmentPrivate::Unit result = d->hash.value(prepareName(name), prepareValue(defaultValue)); - return valueToByteArray(result); -} - QStringList QProcessEnvironment::toStringList() const { return d ? d->toList() : QStringList(); @@ -2038,7 +2015,7 @@ QStringList QProcess::systemEnvironment() /*! \since 4.5 - Returns the environment of the calling process as a QHash. + Returns the environment of the calling process as a QProcessEnvironment. \sa QProcess::systemEnvironment() */ @@ -2053,7 +2030,7 @@ QProcessEnvironment QProcessEnvironment::systemEnvironment() QByteArray name(entry, equal - entry); QByteArray value(equal + 1); - env.insertRaw(name, value); + env.insert(QString::fromLocal8Bit(name), QString::fromLocal8Bit(value)); } return env; } diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index 116168b..0498d1e 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -85,11 +85,6 @@ public: void remove(const QString &name); QString value(const QString &name, const QString &defaultValue = QString()) const; - bool containsRaw(const QByteArray &name) const; - void insertRaw(const QByteArray &name, const QByteArray &value); - void removeRaw(const QByteArray &name); - QByteArray valueRaw(const QByteArray &name, const QByteArray &defaultValue = QByteArray()) const; - QStringList toStringList() const; static QProcessEnvironment systemEnvironment(); -- cgit v0.12 From 0375a941dcd45b71a9397dbd405c9c055ab9a81a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 13 May 2009 16:54:03 +0200 Subject: Document the new QProcessEnvironment class --- src/corelib/io/qprocess.cpp | 168 +++++++++++++++++++++++++++++++++++++++++++- src/corelib/io/qprocess_p.h | 1 + 2 files changed, 166 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index b9dd9d7..7c13bf0 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -101,6 +101,44 @@ QT_END_NAMESPACE QT_BEGIN_NAMESPACE +/*! + \class QProcessEnvironment + + \brief The QProcessEnvironment class holds the environment variables that + can be passed to a program. + + \ingroup io + \ingroup misc + \mainclass + \reentrant + \since 4.6 + + A process's environment is composed of a set of key=value pairs known as + environment variables. The QProcessEnvironment class wraps that concept + and allows easy manipulation of those variables. It's meant to be used + along with QProcess, to set the environment for child processes. It + cannot be used to change the current process's environment. + + The environment of the calling process can be obtained using + QProcessEnvironment::systemEnvironment(). + + On Unix systems, the variable names are case-sensitive. For that reason, + this class will not touch the names of the variables. Note as well that + Unix environment allows both variable names and contents to contain arbitrary + binary data (except for the NUL character), but this is not supported by + QProcessEnvironment. This class only supports names and values that are + encodable by the current locale settings (see QTextCodec::codecForLocale). + + On Windows, the variable names are case-insensitive. Therefore, + QProcessEnvironment will always uppercase the names and do case-insensitive + comparisons. + + On Windows CE, the concept of environment does not exist. This class will + keep the values set for compatibility with other platforms, but the values + set will have no effect on the processes being created. + + \sa QProcess, QProcess::systemEnvironment(), QProcess::setProcessEnvironment() +*/ #ifdef Q_OS_WIN static inline QProcessEnvironmentPrivate::Unit prepareName(const QString &name) { return name.toUpper(); } @@ -179,56 +217,148 @@ QProcessEnvironment QProcessEnvironmentPrivate::fromList(const QStringList &list return env; } +/*! + Creates a new QProcessEnvironment object. This constructor creates an + empty environment. If set on a QProcess, this will cause the current + environment variables to be removed. +*/ QProcessEnvironment::QProcessEnvironment() : d(0) { } +/*! + Frees the resources associated with this QProcessEnvironment object. +*/ QProcessEnvironment::~QProcessEnvironment() { } +/*! + Creates a QProcessEnvironment object that is a copy of \a other. +*/ QProcessEnvironment::QProcessEnvironment(const QProcessEnvironment &other) : d(other.d) { } +/*! + Copies the contents of the \a other QProcessEnvironment object into this + one. +*/ QProcessEnvironment &QProcessEnvironment::operator=(const QProcessEnvironment &other) { d = other.d; return *this; } +/*! + \fn bool QProcessEnvironment::operator !=(const QProcessEnvironment &other) const + + Returns true if this and the \a other QProcessEnvironment objects are different. + + \sa operator==() +*/ + +/*! + Returns true if this and the \a other QProcessEnvironment objects are equal. + + Two QProcessEnvironment objects are considered equal if they have the same + set of key=value pairs. The comparison of keys is done case-sensitive on + platforms where the environment is case-sensitive. + + \sa operator!=(), contains() +*/ bool QProcessEnvironment::operator==(const QProcessEnvironment &other) const { return d->hash == other.d->hash; } +/*! + Returns true if this QProcessEnvironment object is empty: that is + there are no key=value pairs set. + + \sa clear(), systemEnvironment(), insert() +*/ bool QProcessEnvironment::isEmpty() const { return d ? d->hash.isEmpty() : true; } +/*! + Removes all key=value pairs from this QProcessEnvironment object, making + it empty. + + \sa isEmpty(), systemEnvironment() +*/ void QProcessEnvironment::clear() { d->hash.clear(); } +/*! + Returns true if the environment variable of name \a name is found in + this QProcessEnvironment object. + + On Windows, variable names are case-insensitive, so the key is converted + to uppercase before searching. On other systems, names are case-sensitive + so no trasformation is applied. + + \sa insert(), value() +*/ bool QProcessEnvironment::contains(const QString &name) const { return d ? d->hash.contains(prepareName(name)) : false; } +/*! + Inserts the environment variable of name \a name and contents \a value + into this QProcessEnvironment object. If that variable already existed, + it is replaced by the new value. + + On Windows, variable names are case-insensitive, so this function always + uppercases the variable name before inserting. On other systems, names + are case-sensitive, so no transformation is applied. + + On most systems, inserting a variable with no contents will have the + same effect for applications as if the variable had not been set at all. + However, to guarantee that there are no incompatibilities, to remove a + variable, please use the remove() function. + + \sa contains(), remove(), value() +*/ void QProcessEnvironment::insert(const QString &name, const QString &value) { d->hash.insert(prepareName(name), prepareValue(value)); } +/*! + Removes the environment variable identified by \a name from this + QProcessEnvironment object. If that variable did not exist before, + nothing happens. + + On Windows, variable names are case-insensitive, so the key is converted + to uppercase before searching. On other systems, names are case-sensitive + so no trasformation is applied. + + \sa contains(), insert(), value() +*/ void QProcessEnvironment::remove(const QString &name) { d->hash.remove(prepareName(name)); } +/*! + Searches this QProcessEnvironment object for a variable identified by + \a name and returns its value. If the variable is not found in this object, + then \a defaultValue is returned instead. + + On Windows, variable names are case-insensitive, so the key is converted + to uppercase before searching. On other systems, names are case-sensitive + so no trasformation is applied. + + \sa contains(), insert(), remove() +*/ QString QProcessEnvironment::value(const QString &name, const QString &defaultValue) const { if (!d) @@ -238,6 +368,19 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa return valueToString(result); } +/*! + Converts this QProcessEnvironment object into a list of strings, one for + each environment variable that is set. The environment variable's name + and its value are separated by an equal character ('='). + + The QStringList contents returned by this function are suitable for use + with the QProcess::setEnvironment function. However, it is recommended + to use QProcess::setProcessEnvironment instead since that will avoid + unnecessary copying of the data. + + \sa systemEnvironment(), QProcess::systemEnvironment(), QProcess::environment(), + QProcess::setEnvironment() +*/ QStringList QProcessEnvironment::toStringList() const { return d ? d->toList() : QStringList(); @@ -1341,6 +1484,9 @@ QProcess::ProcessState QProcess::state() const \snippet doc/src/snippets/qprocess-environment/main.cpp 0 + \note This function is less efficient than the setProcessEnvironment() + function. + \sa environment(), setProcessEnvironment(), systemEnvironment() */ void QProcess::setEnvironment(const QStringList &environment) @@ -1367,7 +1513,7 @@ QStringList QProcess::environment() const } /*! - \since 4.5 + \since 4.6 Sets the environment that QProcess will use when starting a process to the \a environment object. @@ -1387,7 +1533,7 @@ void QProcess::setProcessEnvironment(const QProcessEnvironment &environment) } /*! - \since 4.5 + \since 4.6 Returns the environment that QProcess will use when starting a process, or an empty object if no environment has been set using setEnvironment() or setProcessEnvironment(). If no environment has @@ -2000,6 +2146,15 @@ QT_END_INCLUDE_NAMESPACE \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8 + This function does not cache the system environment. Therefore, it's + possible to obtain an updated version of the environment if low-level C + library functions like \tt setenv ot \tt putenv have been called. + + However, note that repeated calls to this function will recreate the + list of environment variables, which is a non-trivial operation. + + \note For new code, it is recommended to use QProcessEvironment::systemEnvironment() + \sa QProcessEnvironment::systemEnvironment(), environment(), setEnvironment() */ QStringList QProcess::systemEnvironment() @@ -2013,10 +2168,17 @@ QStringList QProcess::systemEnvironment() } /*! - \since 4.5 + \since 4.6 Returns the environment of the calling process as a QProcessEnvironment. + This function does not cache the system environment. Therefore, it's + possible to obtain an updated version of the environment if low-level C + library functions like \tt setenv ot \tt putenv have been called. + + However, note that repeated calls to this function will recreate the + QProcessEnvironment object, which is a non-trivial operation. + \sa QProcess::systemEnvironment() */ QProcessEnvironment QProcessEnvironment::systemEnvironment() diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 3b04d88..1e2979b 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -56,6 +56,7 @@ #include "QtCore/qprocess.h" #include "QtCore/qstringlist.h" #include "QtCore/qhash.h" +#include "QtCore/qshareddata.h" #include "private/qringbuffer_p.h" #include "private/qiodevice_p.h" -- cgit v0.12 From 48d4baca5becf0966ad02f3f316cd9894ef6d5c3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 13 May 2009 16:54:14 +0200 Subject: Execute some small performance improvements in QProcessEnvironment If d == 0, then we know we have no items. Therefore, removing or clearing is an idempotent action. So instead of detaching, leave d == 0. In the search function, avoid converting the defaultValue to the internal representation. --- src/corelib/io/qprocess.cpp | 13 +++++++++---- src/corelib/io/qprocess_p.h | 3 ++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 7c13bf0..733887a 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -293,7 +293,8 @@ bool QProcessEnvironment::isEmpty() const */ void QProcessEnvironment::clear() { - d->hash.clear(); + if (d) + d->hash.clear(); } /*! @@ -345,7 +346,8 @@ void QProcessEnvironment::insert(const QString &name, const QString &value) */ void QProcessEnvironment::remove(const QString &name) { - d->hash.remove(prepareName(name)); + if (d) + d->hash.remove(prepareName(name)); } /*! @@ -364,8 +366,11 @@ QString QProcessEnvironment::value(const QString &name, const QString &defaultVa if (!d) return defaultValue; - QProcessEnvironmentPrivate::Unit result = d->hash.value(prepareName(name), prepareValue(defaultValue)); - return valueToString(result); + QProcessEnvironmentPrivate::Hash::ConstIterator it = d->hash.constFind(prepareName(name)); + if (it == d->hash.constEnd()) + return defaultValue; + + return valueToString(it.value()); } /*! diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 1e2979b..b581e91 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -86,7 +86,8 @@ public: #else typedef QByteArray Unit; #endif - QHash hash; + typedef QHash Hash; + Hash hash; static QProcessEnvironment fromList(const QStringList &list); QStringList toList() const; -- cgit v0.12 From 7ce08a2058daadf27dcd145bd7ce61b5fd73eee6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 21 Aug 2009 14:42:06 +0200 Subject: Oops: fix compilerSupportsFlag: must return $ret, not $? --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 8ad5823..593c316 100755 --- a/configure +++ b/configure @@ -103,7 +103,7 @@ EOF "$TEST_COMPILER" "$@" -o /dev/null conftest.cpp ret=$? rm -f conftest.cpp conftest.o - return $? + return $ret } # relies on $TEST_COMPILER being set correctly -- cgit v0.12 From bc58c9d33c3e333dd51f2aa60fd4bdcb296b2649 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Fri, 21 Aug 2009 14:52:02 +0200 Subject: QFSFileEngine: fix inverted logic for return values Merge-request: 833 Reviewed-by: Joerg Bornemann --- src/corelib/io/qfsfileengine_unix.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index dc7fafd..9cd187d 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -913,18 +913,18 @@ bool QFSFileEngine::setPermissions(uint perms) if (perms & ExeOtherPerm) mode |= S_IXOTH; if (d->fd != -1) - return !fchmod(d->fd, mode); - return !::chmod(d->nativeFilePath.constData(), mode); + return fchmod(d->fd, mode) == 0; + return ::chmod(d->nativeFilePath.constData(), mode) == 0; } bool QFSFileEngine::setSize(qint64 size) { Q_D(QFSFileEngine); if (d->fd != -1) - return !QT_FTRUNCATE(d->fd, size); + return QT_FTRUNCATE(d->fd, size) == 0; if (d->fh) - return !QT_FTRUNCATE(QT_FILENO(d->fh), size); - return !QT_TRUNCATE(d->nativeFilePath.constData(), size); + return QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0; + return QT_TRUNCATE(d->nativeFilePath.constData(), size) == 0; } QDateTime QFSFileEngine::fileTime(FileTime time) const -- cgit v0.12 From 48758257c77ab6698e8f11b1d7acfdaa93158054 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Fri, 21 Aug 2009 14:52:05 +0200 Subject: QFile: use fileEngine's errorString() instead of errno/GetLastError() QFile behaves like wrapper for file engine in most operations, so proper error reporting must be implemented in file engine backends. Merge-request: 833 Reviewed-by: Joerg Bornemann --- src/corelib/io/qfile.cpp | 16 ++++----------- src/corelib/io/qfsfileengine_unix.cpp | 38 ++++++++++++++++++++++++++--------- src/corelib/io/qfsfileengine_win.cpp | 36 +++++++++++++++++++++++++-------- 3 files changed, 61 insertions(+), 29 deletions(-) diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index aa704d3..daadad7 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -52,10 +52,6 @@ # include "qcoreapplication.h" #endif -#if !defined(Q_OS_WINCE) -#include -#endif - #ifdef QT_NO_QOBJECT #define tr(X) QString::fromLatin1(X) #endif @@ -654,11 +650,7 @@ QFile::remove() unsetError(); return true; } -#if defined(Q_OS_WIN) - d->setError(QFile::RemoveError, GetLastError()); -#else - d->setError(QFile::RemoveError, errno); -#endif + d->setError(QFile::RemoveError, fileEngine()->errorString()); } return false; } @@ -809,7 +801,7 @@ QFile::link(const QString &linkName) unsetError(); return true; } - d->setError(QFile::RenameError, errno); + d->setError(QFile::RenameError, fileEngine()->errorString()); return false; } @@ -1255,7 +1247,7 @@ QFile::resize(qint64 sz) unsetError(); return true; } - d->setError(QFile::ResizeError, errno); + d->setError(QFile::ResizeError, fileEngine()->errorString()); return false; } @@ -1319,7 +1311,7 @@ QFile::setPermissions(Permissions permissions) unsetError(); return true; } - d->setError(QFile::PermissionsError, errno); + d->setError(QFile::PermissionsError, fileEngine()->errorString()); return false; } diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 9cd187d..592f792 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -373,25 +373,35 @@ bool QFSFileEnginePrivate::nativeIsSequential() const bool QFSFileEngine::remove() { Q_D(QFSFileEngine); - return unlink(d->nativeFilePath.constData()) == 0; + bool ret = unlink(d->nativeFilePath.constData()) == 0; + if (!ret) + setError(QFile::RemoveError, qt_error_string(errno)); + return ret; } bool QFSFileEngine::copy(const QString &) { // ### Add copy code for Unix here + setError(QFile::UnspecifiedError, QLatin1String("Not implemented!")); return false; } bool QFSFileEngine::rename(const QString &newName) { Q_D(QFSFileEngine); - return ::rename(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; + bool ret = ::rename(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; + if (!ret) + setError(QFile::RenameError, qt_error_string(errno)); + return ret; } bool QFSFileEngine::link(const QString &newName) { Q_D(QFSFileEngine); - return ::symlink(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; + bool ret = ::symlink(d->nativeFilePath.constData(), QFile::encodeName(newName).constData()) == 0; + if (!ret) + setError(QFile::RenameError, qt_error_string(errno)); + return ret; } qint64 QFSFileEnginePrivate::nativeSize() const @@ -887,6 +897,7 @@ QString QFSFileEngine::owner(FileOwner own) const bool QFSFileEngine::setPermissions(uint perms) { Q_D(QFSFileEngine); + bool ret = false; mode_t mode = 0; if (perms & ReadOwnerPerm) mode |= S_IRUSR; @@ -913,18 +924,27 @@ bool QFSFileEngine::setPermissions(uint perms) if (perms & ExeOtherPerm) mode |= S_IXOTH; if (d->fd != -1) - return fchmod(d->fd, mode) == 0; - return ::chmod(d->nativeFilePath.constData(), mode) == 0; + ret = fchmod(d->fd, mode) == 0; + else + ret = ::chmod(d->nativeFilePath.constData(), mode) == 0; + if (!ret) + setError(QFile::PermissionsError, qt_error_string(errno)); + return ret; } bool QFSFileEngine::setSize(qint64 size) { Q_D(QFSFileEngine); + bool ret = false; if (d->fd != -1) - return QT_FTRUNCATE(d->fd, size) == 0; - if (d->fh) - return QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0; - return QT_TRUNCATE(d->nativeFilePath.constData(), size) == 0; + ret = QT_FTRUNCATE(d->fd, size) == 0; + else if (d->fh) + ret = QT_FTRUNCATE(QT_FILENO(d->fh), size) == 0; + else + ret = QT_TRUNCATE(d->nativeFilePath.constData(), size) == 0; + if (!ret) + setError(QFile::ResizeError, qt_error_string(errno)); + return ret; } QDateTime QFSFileEngine::fileTime(FileTime time) const diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 4bae9f4..c7510f2 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -780,21 +780,30 @@ bool QFSFileEnginePrivate::nativeIsSequential() const bool QFSFileEngine::remove() { Q_D(QFSFileEngine); - return ::DeleteFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0; + bool ret = ::DeleteFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0; + if (!ret) + setError(QFile::RemoveError, qt_error_string()); + return ret; } bool QFSFileEngine::copy(const QString ©Name) { Q_D(QFSFileEngine); - return ::CopyFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (wchar_t*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0; + bool ret = ::CopyFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), + (wchar_t*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0; + if (!ret) + setError(QFile::CopyError, qt_error_string()); + return ret; } bool QFSFileEngine::rename(const QString &newName) { Q_D(QFSFileEngine); - return ::MoveFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (wchar_t*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0; + bool ret = ::MoveFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), + (wchar_t*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0; + if (!ret) + setError(QFile::RenameError, qt_error_string()); + return ret; } static inline bool mkDir(const QString &path) @@ -1303,6 +1312,9 @@ bool QFSFileEngine::link(const QString &newName) } psl->Release(); } + if (!ret) + setError(QFile::RenameError, qt_error_string()); + if(neededCoInit) CoUninitialize(); @@ -1319,7 +1331,10 @@ bool QFSFileEngine::link(const QString &newName) // Need to append on our own orgName.prepend(QLatin1Char('"')); orgName.append(QLatin1Char('"')); - return SUCCEEDED(SHCreateShortcut((wchar_t*)linkName.utf16(), (wchar_t*)orgName.utf16())); + bool ret = SUCCEEDED(SHCreateShortcut((wchar_t*)linkName.utf16(), (wchar_t*)orgName.utf16())); + if (!ret) + setError(QFile::RenameError, qt_error_string()); + return ret; #endif // Q_OS_WINCE } @@ -1643,7 +1658,9 @@ bool QFSFileEngine::setPermissions(uint perms) if (mode == 0) // not supported return false; - ret = ::_wchmod((wchar_t*)d->longFileName(d->filePath).utf16(), mode) == 0; + ret = ::_wchmod((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), mode) == 0; + if (!ret) + setError(QFile::PermissionsError, qt_error_string(errno)); return ret; } @@ -1675,7 +1692,10 @@ bool QFSFileEngine::setSize(qint64 size) // resize file on disk QFile file(d->filePath); if (file.open(QFile::ReadWrite)) { - return file.resize(size); + bool ret = file.resize(size); + if (!ret) + setError(QFile::ResizeError, file.errorString()); + return ret; } } return false; -- cgit v0.12 From 4209fa5809f5a0a8de2a346c56a0640cc15193ee Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Fri, 21 Aug 2009 14:52:09 +0200 Subject: QFile: unset errorString as well as error Prefer using unsetError() since it unsets both error and errorString. Merge-request: 833 Reviewed-by: Joerg Bornemann --- src/corelib/io/qfile.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index daadad7..ab45bf7 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -1467,7 +1467,7 @@ bool QFile::seek(qint64 off) d->setError(err, fileEngine()->errorString()); return false; } - d->error = NoError; + unsetError(); return true; } @@ -1495,7 +1495,7 @@ qint64 QFile::readLineData(char *data, qint64 maxlen) qint64 QFile::readData(char *data, qint64 len) { Q_D(QFile); - d->error = NoError; + unsetError(); if (!d->ensureFlushed()) return -1; @@ -1577,7 +1577,7 @@ qint64 QFile::writeData(const char *data, qint64 len) { Q_D(QFile); - d->error = NoError; + unsetError(); d->lastWasWrite = true; bool buffered = !(d->openMode & Unbuffered); -- cgit v0.12 From 2e27e9b38766b4c0a2c9ec20539cf808de01f2dd Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Fri, 21 Aug 2009 14:52:12 +0200 Subject: improve error reporting for map/unmap of files and resources Merge-request: 833 Reviewed-by: Joerg Bornemann --- src/corelib/io/qfsfileengine_unix.cpp | 8 ++++---- src/corelib/io/qfsfileengine_win.cpp | 6 +++--- src/corelib/io/qresource.cpp | 6 +----- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 592f792..96ea96e 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -966,14 +966,14 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla { Q_Q(QFSFileEngine); Q_UNUSED(flags); - if (offset < 0) { - q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL))); - return 0; - } if (openMode == QIODevice::NotOpen) { q->setError(QFile::PermissionsError, qt_error_string(int(EACCES))); return 0; } + if (offset < 0) { + q->setError(QFile::UnspecifiedError, qt_error_string(int(EINVAL))); + return 0; + } int access = 0; if (openMode & QIODevice::ReadOnly) access |= PROT_READ; if (openMode & QIODevice::WriteOnly) access |= PROT_WRITE; diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index c7510f2..e524e8e 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -1798,11 +1798,11 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, Q_Q(QFSFileEngine); Q_UNUSED(flags); if (openMode == QFile::NotOpen) { - q->setError(QFile::PermissionsError, qt_error_string()); + q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); return 0; } if (offset == 0 && size == 0) { - q->setError(QFile::UnspecifiedError, qt_error_string()); + q->setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER)); return 0; } @@ -1884,7 +1884,7 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr) { Q_Q(QFSFileEngine); if (!maps.contains(ptr)) { - q->setError(QFile::PermissionsError, qt_error_string()); + q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED)); return false; } uchar *start = ptr - maps[ptr].first; diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 212f153..242af61 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1488,11 +1488,7 @@ uchar *QResourceFileEnginePrivate::map(qint64 offset, qint64 size, QFile::Memory { Q_Q(QResourceFileEngine); Q_UNUSED(flags); - if (!resource.isValid() - || offset < 0 - || size < 0 - || offset + size > resource.size() - || (size == 0)) { + if (offset < 0 || size <= 0 || !resource.isValid() || offset + size > resource.size()) { q->setError(QFile::UnspecifiedError, QString()); return 0; } -- cgit v0.12 From 00ba962d428dcdff70fcde74a9e5cb316545cef6 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 21 Aug 2009 15:08:54 +0200 Subject: adjust auto.pro to the recent split of qstringbuilder tests Reviewed-by: cduclos --- tests/auto/auto.pro | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index e9e1c8a..0f3c099 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -300,7 +300,10 @@ SUBDIRS += \ qstatusbar \ qstl \ qstring \ - qstringbuilder \ + qstringbuilder1 \ + qstringbuilder2 \ + qstringbuilder3 \ + qstringbuilder4 \ qstringmatcher \ qstringlist \ qstringlistmodel \ -- cgit v0.12