[krita] krita: Fix Drag&Drop of layers in tabbed mode

Dmitry Kazakov dimula73 at gmail.com
Fri Jan 15 14:19:15 UTC 2016


Git commit b7170a05e3697419a3cd14ed905fe8428a1a94dd by Dmitry Kazakov.
Committed on 15/01/2016 at 14:18.
Pushed by dkazakov into branch 'master'.

Fix Drag&Drop of layers in tabbed mode

Now you can drag layers even when Krita works in tabbed mode. Just drag the
layer over the tab, wait for a second and it'll automatically switch to the
tab under the cursor

CC:kimageshop at kde.org

M  +10   -2    krita/image/kis_signal_compressor_with_param.h
M  +66   -2    krita/ui/KisMainWindow.cpp
M  +3    -0    krita/ui/KisMainWindow.h

http://commits.kde.org/krita/b7170a05e3697419a3cd14ed905fe8428a1a94dd

diff --git a/krita/image/kis_signal_compressor_with_param.h b/krita/image/kis_signal_compressor_with_param.h
index 9700e72..94c751a 100644
--- a/krita/image/kis_signal_compressor_with_param.h
+++ b/krita/image/kis_signal_compressor_with_param.h
@@ -93,8 +93,8 @@ public:
     using CallbackFunction = std::function<void (T)>;
 
 public:
-    KisSignalCompressorWithParam(int delay, CallbackFunction function)
-        : m_compressor(delay, KisSignalCompressor::FIRST_ACTIVE),
+KisSignalCompressorWithParam(int delay, CallbackFunction function, KisSignalCompressor::Mode mode = KisSignalCompressor::FIRST_ACTIVE)
+        : m_compressor(delay, mode),
           m_function(function)
     {
         std::function<void ()> callback(
@@ -113,6 +113,14 @@ public:
         m_compressor.start();
     }
 
+    void stop() {
+        m_compressor.stop();
+    }
+
+    bool isActive() const {
+        return m_compressor.isActive();
+    }
+
 private:
     void fakeSlotTimeout() {
         m_function(m_currentParamValue);
diff --git a/krita/ui/KisMainWindow.cpp b/krita/ui/KisMainWindow.cpp
index c47952f..0e5f0cb 100644
--- a/krita/ui/KisMainWindow.cpp
+++ b/krita/ui/KisMainWindow.cpp
@@ -125,6 +125,7 @@
 #include "kis_icon_utils.h"
 #include <KisImportExportFilter.h>
 #include <KisDocumentEntry.h>
+#include "kis_signal_compressor_with_param.h"
 
 class ToolDockerFactory : public KoDockFactoryBase
 {
@@ -150,7 +151,8 @@ class Q_DECL_HIDDEN KisMainWindow::Private
 {
 public:
     Private(KisMainWindow *parent)
-        : viewManager(0)
+        : q(parent)
+        , viewManager(0)
         , firstTime(true)
         , windowSizeDirty(false)
         , readOnly(false)
@@ -198,6 +200,7 @@ public:
         qDeleteAll(toolbarList);
     }
 
+    KisMainWindow *q;
     KisViewManager *viewManager;
 
     QPointer<KisView> activeView;
@@ -269,10 +272,22 @@ public:
 
     QByteArray lastExportedFormat;
     int lastExportSpecialOutputFlag;
+    QScopedPointer<KisSignalCompressorWithParam<int> > tabSwitchCompressor;
 
     KisActionManager * actionManager() {
         return viewManager->actionManager();
     }
+
+    QTabBar* findTabBarHACK() {
+        QObjectList objects = mdiArea->children();
+        Q_FOREACH (QObject *object, objects) {
+            QTabBar *bar = qobject_cast<QTabBar*>(object);
+            if (bar) {
+                return bar;
+            }
+        }
+        return 0;
+    }
 };
 
 KisMainWindow::KisMainWindow()
@@ -460,6 +475,15 @@ KisMainWindow::KisMainWindow()
     d->viewManager->updateIcons();
 
     QTimer::singleShot(1000, this, SLOT(checkSanity()));
+
+    {
+        using namespace std::placeholders; // For _1 placeholder
+        std::function<void (int)> callback(
+            std::bind(&KisMainWindow::switchTab, this, _1));
+
+        d->tabSwitchCompressor.reset(
+            new KisSignalCompressorWithParam<int>(500, callback, KisSignalCompressor::FIRST_INACTIVE));
+    }
 }
 
 void KisMainWindow::setNoCleanup(bool noCleanup)
@@ -1195,7 +1219,10 @@ void KisMainWindow::setActiveView(KisView* view)
 
 void KisMainWindow::dragEnterEvent(QDragEnterEvent *event)
 {
-    if (event->mimeData()->hasUrls()) {
+    if (event->mimeData()->hasUrls() ||
+        event->mimeData()->hasFormat("application/x-krita-node") ||
+        event->mimeData()->hasFormat("application/x-qt-image")) {
+
         event->accept();
     }
 }
@@ -1209,6 +1236,43 @@ void KisMainWindow::dropEvent(QDropEvent *event)
     }
 }
 
+void KisMainWindow::dragMoveEvent(QDragMoveEvent * event)
+{
+    QTabBar *tabBar = d->findTabBarHACK();
+
+    if (!tabBar && d->mdiArea->viewMode() == QMdiArea::TabbedView) {
+        qWarning() << "WARNING!!! Cannot find QTabBar in the main window! Looks like Qt has changed behavior. Drag & Drop between multiple tabs might not work properly (tabs will not switch automatically)!";
+    }
+
+    if (tabBar && tabBar->isVisible()) {
+        QPoint pos = tabBar->mapFromGlobal(mapToGlobal(event->pos()));
+        if (tabBar->rect().contains(pos)) {
+            const int tabIndex = tabBar->tabAt(pos);
+
+            if (tabIndex >= 0 && tabBar->currentIndex() != tabIndex) {
+                d->tabSwitchCompressor->start(tabIndex);
+            }
+        } else if (d->tabSwitchCompressor->isActive()) {
+            d->tabSwitchCompressor->stop();
+        }
+    }
+}
+
+void KisMainWindow::dragLeaveEvent(QDragLeaveEvent * event)
+{
+    if (d->tabSwitchCompressor->isActive()) {
+        d->tabSwitchCompressor->stop();
+    }
+}
+
+void KisMainWindow::switchTab(int index)
+{
+    QTabBar *tabBar = d->findTabBarHACK();
+    if (!tabBar) return;
+
+    tabBar->setCurrentIndex(index);
+}
+
 void KisMainWindow::slotFileNew()
 {
     KisPart::instance()->showStartUpWidget(this, true /*Always show widget*/);
diff --git a/krita/ui/KisMainWindow.h b/krita/ui/KisMainWindow.h
index 8f04a7d..be776d3 100644
--- a/krita/ui/KisMainWindow.h
+++ b/krita/ui/KisMainWindow.h
@@ -368,6 +368,8 @@ protected:
     // QWidget overrides
     virtual void dragEnterEvent(QDragEnterEvent * event);
     virtual void dropEvent(QDropEvent * event);
+    virtual void dragMoveEvent(QDragMoveEvent * event);
+    virtual void dragLeaveEvent(QDragLeaveEvent * event);
 
     void setToolbarList(QList<QAction*> toolbarList);
 
@@ -443,6 +445,7 @@ protected:
 private Q_SLOTS:
     void initializeGeometry();
     void showManual();
+    void switchTab(int index);
 
 private:
     class Private;


More information about the kimageshop mailing list