Possibility to change custom Drag&Drop cursors while dragging something. Implementati...
authorCyril Oblikov <munknex@gmail.com>
Thu, 27 Sep 2012 14:55:16 +0000 (17:55 +0300)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 26 Oct 2012 15:08:03 +0000 (17:08 +0200)
Additional checks to figure out if new Drag&Drop cursors where set. This means it is possible now to keep QDrag object in your program and call setDragCursor() method every time we need to change cursor depending on context.

Change-Id: I4be69e44b2863371a7ffbb29efc17c18210d6cde
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Gatis Paeglis <gatis.paeglis@digia.com>
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
src/platformsupport/dnd/qsimpledrag.cpp
src/plugins/platforms/windows/qwindowsdrag.cpp

index d8ef17e..18e6b97 100644 (file)
@@ -253,8 +253,19 @@ void QBasicDrag::updateCursor(Qt::DropAction action)
     }
 
     QCursor *cursor = qApp->overrideCursor();
-    if (cursor && cursorShape != cursor->shape()) {
-        qApp->changeOverrideCursor(QCursor(cursorShape));
+    QPixmap pixmap = m_drag->dragCursor(action);
+    if (!cursor) {
+        qApp->changeOverrideCursor((pixmap.isNull()) ? QCursor(cursorShape) : QCursor(pixmap));
+    } else {
+        if (!pixmap.isNull()) {
+            if ((cursor->pixmap().cacheKey() != pixmap.cacheKey())) {
+                qApp->changeOverrideCursor(QCursor(pixmap));
+            }
+        } else {
+            if (cursorShape != cursor->shape()) {
+                qApp->changeOverrideCursor(QCursor(cursorShape));
+            }
+        }
     }
     updateAction(action);
 }
index ad2ff22..a0434fb 100644 (file)
@@ -301,9 +301,15 @@ public:
     STDMETHOD(GiveFeedback)(DWORD dwEffect);
 
 private:
-    typedef QMap <Qt::DropAction, HCURSOR> ActionCursorMap;
-
-    inline void clearCursors();
+    class DragCursorHandle {
+        Q_DISABLE_COPY(DragCursorHandle)
+    public:
+        DragCursorHandle(HCURSOR c, quint64 k) :  cursor(c), cacheKey(k) {}
+        ~DragCursorHandle() { DestroyCursor(cursor); }
+        HCURSOR cursor;
+        quint64 cacheKey;
+    };
+    typedef QMap <Qt::DropAction, QSharedPointer<DragCursorHandle> > ActionCursorMap;
 
     QWindowsDrag *m_drag;
     Qt::MouseButtons m_currentButtons;
@@ -322,7 +328,7 @@ QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag) :
 
 QWindowsOleDropSource::~QWindowsOleDropSource()
 {
-    clearCursors();
+    m_cursors.clear();
     if (QWindowsContext::verboseOLE)
         qDebug("%s", __FUNCTION__);
 }
@@ -347,10 +353,14 @@ void QWindowsOleDropSource::createCursors()
         QPixmap cpm = drag->dragCursor(action);
         if (cpm.isNull())
             cpm = m_drag->defaultCursor(action);
+        QSharedPointer<DragCursorHandle> cursorHandler = m_cursors.value(action);
+        if (!cursorHandler.isNull() && cpm.cacheKey() == cursorHandler->cacheKey)
+            continue;
         if (cpm.isNull()) {
             qWarning("%s: Unable to obtain drag cursor for %d.", __FUNCTION__, action);
             continue;
         }
+
         int w = cpm.width();
         int h = cpm.height();
 
@@ -380,23 +390,14 @@ void QWindowsOleDropSource::createCursors()
         const int hotX = hasPixmap ? qMax(0,newHotSpot.x()) : 0;
         const int hotY = hasPixmap ? qMax(0,newHotSpot.y()) : 0;
 
-        if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newCursor, hotX, hotY))
-            m_cursors.insert(actions.at(cnum), sysCursor);
+        if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newCursor, hotX, hotY)) {
+            m_cursors.insert(action, QSharedPointer<DragCursorHandle>(new DragCursorHandle(sysCursor, cpm.cacheKey())));
+        }
     }
     if (QWindowsContext::verboseOLE)
         qDebug("%s %d cursors", __FUNCTION__, m_cursors.size());
 }
 
-void QWindowsOleDropSource::clearCursors()
-{
-    if (!m_cursors.isEmpty()) {
-        const ActionCursorMap::const_iterator cend = m_cursors.constEnd();
-        for (ActionCursorMap::const_iterator it = m_cursors.constBegin(); it != cend; ++it)
-            DestroyCursor(it.value());
-        m_cursors.clear();
-    }
-}
-
 //---------------------------------------------------------------------
 //                    IUnknown Methods
 //---------------------------------------------------------------------
@@ -488,9 +489,14 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
     if (QWindowsContext::verboseOLE > 2)
         qDebug("%s dwEffect=%lu, action=%d", __FUNCTION__, dwEffect, action);
 
+    QSharedPointer<DragCursorHandle> cursorHandler = m_cursors.value(action);
+    quint64 currentCacheKey = m_drag->currentDrag()->dragCursor(action).cacheKey();
+    if (cursorHandler.isNull() || currentCacheKey != cursorHandler->cacheKey)
+        createCursors();
+
     const ActionCursorMap::const_iterator it = m_cursors.constFind(action);
     if (it != m_cursors.constEnd()) {
-        SetCursor(it.value());
+        SetCursor(it.value()->cursor);
         return ResultFromScode(S_OK);
     }