[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [calligra] krita/plugins/extensions/dockers: Add image docker again
From:       Silvio Heinrich <plassy () web ! de>
Date:       2011-08-17 15:03:50
Message-ID: 20110817150350.3824DA60A4 () git ! kde ! org
[Download RAW message or body]

Git commit 21ec0724af1706fdefa02f77622cc875026a4b69 by Silvio Heinrich.
Committed on 17/08/2011 at 17:02.
Pushed by heinrich into branch 'master'.

Add image docker again to master. Was removed... Why??

A  +99   -0    krita/plugins/extensions/dockers/imagedocker/imagedocker_dock.h     \
[License: LGPL (v2)] M  +1    -0    krita/plugins/extensions/dockers/CMakeLists.txt
A  +255  -0    krita/plugins/extensions/dockers/imagedocker/forms/wdgimagedocker.ui
A  +486  -0    krita/plugins/extensions/dockers/imagedocker/imagedocker_dock.cpp     \
[License: LGPL (v2)] A  +177  -0    \
krita/plugins/extensions/dockers/imagedocker/kis_image_strip_scene.cpp     [License: \
LGPL (v2)] A  +261  -0    \
krita/plugins/extensions/dockers/imagedocker/kis_image_view.cpp     [License: LGPL \
(v2)] A  +31   -0    krita/plugins/extensions/dockers/imagedocker/imagedocker.h     \
[License: LGPL (v2)] A  +9    -0    \
krita/plugins/extensions/dockers/imagedocker/kritaimagedocker.desktop A  +94   -0    \
krita/plugins/extensions/dockers/imagedocker/kis_image_view.h     [License: LGPL \
(v2)] A  +121  -0    \
krita/plugins/extensions/dockers/imagedocker/kis_image_strip_scene.h     [License: \
LGPL (v2)] A  +60   -0    \
krita/plugins/extensions/dockers/imagedocker/imagedocker.cpp     [License: LGPL (v2)] \
A  +114  -0    krita/plugins/extensions/dockers/imagedocker/forms/wdgImageViewPopup.ui
 A  +15   -0    krita/plugins/extensions/dockers/imagedocker/CMakeLists.txt

http://commits.kde.org/calligra/21ec0724af1706fdefa02f77622cc875026a4b69

diff --git a/krita/plugins/extensions/dockers/CMakeLists.txt \
b/krita/plugins/extensions/dockers/CMakeLists.txt index 51690c0..d06930a 100644
--- a/krita/plugins/extensions/dockers/CMakeLists.txt
+++ b/krita/plugins/extensions/dockers/CMakeLists.txt
@@ -6,3 +6,4 @@ add_subdirectory(advancedcolorselector)
 add_subdirectory(presetdocker)
 add_subdirectory(historydocker)
 add_subdirectory(channeldocker)
+add_subdirectory(imagedocker)
\ No newline at end of file
diff --git a/krita/plugins/extensions/dockers/imagedocker/CMakeLists.txt \
b/krita/plugins/extensions/dockers/imagedocker/CMakeLists.txt new file mode 100644
index 0000000..ad23303
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+set(kritaimagedocker_PART_SRCS
+    imagedocker.cpp
+    imagedocker_dock.cpp
+    kis_image_strip_scene.cpp
+    kis_image_view.cpp
+)
+
+kde4_add_ui_files(kritaimagedocker_PART_SRCS forms/wdgimagedocker.ui \
forms/wdgImageViewPopup.ui) +
+kde4_add_plugin(kritaimagedocker ${kritaimagedocker_PART_SRCS})
+target_link_libraries(kritaimagedocker kritaui)
+
+install(TARGETS kritaimagedocker DESTINATION ${PLUGIN_INSTALL_DIR})
+install(FILES kritaimagedocker.desktop DESTINATION ${SERVICES_INSTALL_DIR})
diff --git a/krita/plugins/extensions/dockers/imagedocker/forms/wdgImageViewPopup.ui \
b/krita/plugins/extensions/dockers/imagedocker/forms/wdgImageViewPopup.ui new file \
mode 100644 index 0000000..e45986e
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/forms/wdgImageViewPopup.ui
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>wdgImageViewPopup</class>
+ <widget class="QWidget" name="wdgImageViewPopup">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>340</width>
+    <height>59</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QPushButton" name="bnZoomFit">
+       <property name="text">
+        <string>Fit</string>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <property name="autoDefault">
+        <bool>false</bool>
+       </property>
+       <property name="flat">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="bnZoomAdjust">
+       <property name="text">
+        <string>Adjust</string>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <property name="flat">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="bnZoom100">
+       <property name="text">
+        <string>100%</string>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <property name="flat">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="bnZoom75">
+       <property name="text">
+        <string>75%</string>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <property name="flat">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="bnZoom50">
+       <property name="text">
+        <string>50%</string>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <property name="flat">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="bnZoom25">
+       <property name="text">
+        <string>25%</string>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <property name="flat">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="KisSliderSpinBox" name="zoomSlider" native="true"/>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KisSliderSpinBox</class>
+   <extends>QWidget</extends>
+   <header location="global">kis_slider_spin_box.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/krita/plugins/extensions/dockers/imagedocker/forms/wdgimagedocker.ui \
b/krita/plugins/extensions/dockers/imagedocker/forms/wdgimagedocker.ui new file mode \
100644 index 0000000..a6e5341
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/forms/wdgimagedocker.ui
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>wdgImageDocker</class>
+ <widget class="QWidget" name="wdgImageDocker">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>399</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QTabWidget" name="tabWidget">
+     <property name="tabPosition">
+      <enum>QTabWidget::North</enum>
+     </property>
+     <property name="tabShape">
+      <enum>QTabWidget::Rounded</enum>
+     </property>
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <property name="elideMode">
+      <enum>Qt::ElideNone</enum>
+     </property>
+     <property name="usesScrollButtons">
+      <bool>true</bool>
+     </property>
+     <property name="documentMode">
+      <bool>true</bool>
+     </property>
+     <property name="tabsClosable">
+      <bool>false</bool>
+     </property>
+     <widget class="QWidget" name="imgBrowserTab">
+      <attribute name="title">
+       <string>Browse</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <property name="spacing">
+        <number>0</number>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <item>
+        <widget class="QSplitter" name="splitter">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <widget class="QWidget" name="verticalLayoutWidget">
+          <layout class="QVBoxLayout" name="verticalLayout">
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout">
+             <item>
+              <widget class="QComboBox" name="cmbPath">
+               <property name="editable">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QToolButton" name="bnBack">
+               <property name="text">
+                <string>Back</string>
+               </property>
+               <property name="autoRaise">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QToolButton" name="bnUp">
+               <property name="text">
+                <string>Up</string>
+               </property>
+               <property name="autoRaise">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QToolButton" name="bnHome">
+               <property name="text">
+                <string>Home</string>
+               </property>
+               <property name="autoRaise">
+                <bool>true</bool>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+           <item>
+            <widget class="QTreeView" name="treeView">
+             <property name="alternatingRowColors">
+              <bool>true</bool>
+             </property>
+             <property name="rootIsDecorated">
+              <bool>true</bool>
+             </property>
+             <property name="uniformRowHeights">
+              <bool>true</bool>
+             </property>
+             <property name="itemsExpandable">
+              <bool>true</bool>
+             </property>
+             <property name="expandsOnDoubleClick">
+              <bool>false</bool>
+             </property>
+             <attribute name="headerVisible">
+              <bool>true</bool>
+             </attribute>
+             <attribute name="headerCascadingSectionResizes">
+              <bool>false</bool>
+             </attribute>
+             <attribute name="headerDefaultSectionSize">
+              <number>200</number>
+             </attribute>
+             <attribute name="headerHighlightSections">
+              <bool>false</bool>
+             </attribute>
+             <attribute name="headerStretchLastSection">
+              <bool>false</bool>
+             </attribute>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+         <widget class="QGraphicsView" name="thumbView">
+          <property name="minimumSize">
+           <size>
+            <width>50</width>
+            <height>50</height>
+           </size>
+          </property>
+         </widget>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QWidget" name="imgViewTab">
+      <attribute name="title">
+       <string>Images</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,1">
+       <property name="spacing">
+        <number>0</number>
+       </property>
+       <property name="margin">
+        <number>0</number>
+       </property>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="0,1,0,0,0">
+         <item>
+          <widget class="KisPopupButton" name="bnPopup">
+           <property name="enabled">
+            <bool>false</bool>
+           </property>
+           <property name="text">
+            <string/>
+           </property>
+           <property name="flat">
+            <bool>false</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="cmbImg">
+           <property name="frame">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QToolButton" name="bnImgPrev">
+           <property name="enabled">
+            <bool>false</bool>
+           </property>
+           <property name="text">
+            <string>Prev</string>
+           </property>
+           <property name="autoRaise">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QToolButton" name="bnImgNext">
+           <property name="enabled">
+            <bool>false</bool>
+           </property>
+           <property name="text">
+            <string>Next</string>
+           </property>
+           <property name="autoRaise">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QToolButton" name="bnImgClose">
+           <property name="enabled">
+            <bool>false</bool>
+           </property>
+           <property name="text">
+            <string>Close</string>
+           </property>
+           <property name="autoRaise">
+            <bool>true</bool>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="KisImageView" name="imgView">
+         <property name="frameShape">
+          <enum>QFrame::StyledPanel</enum>
+         </property>
+         <property name="frameShadow">
+          <enum>QFrame::Plain</enum>
+         </property>
+         <property name="lineWidth">
+          <number>0</number>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KisImageView</class>
+   <extends>QFrame</extends>
+   <header>kis_image_view.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>KisPopupButton</class>
+   <extends>QPushButton</extends>
+   <header location="global">kis_popup_button.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/krita/plugins/extensions/dockers/imagedocker/imagedocker.cpp \
b/krita/plugins/extensions/dockers/imagedocker/imagedocker.cpp new file mode 100644
index 0000000..4643016
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/imagedocker.cpp
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "imagedocker.h"
+#include "imagedocker_dock.h"
+
+#include <kpluginfactory.h>
+#include <klocale.h>
+#include <KoDockFactoryBase.h>
+#include <KoDockRegistry.h>
+
+K_PLUGIN_FACTORY(ImageDockerPluginFactory, registerPlugin<ImageDockerPlugin>();)
+K_EXPORT_PLUGIN(ImageDockerPluginFactory("krita"))
+
+class ImageDockerDockFactory: public KoDockFactoryBase {
+public:
+    ImageDockerDockFactory() { }
+
+    virtual QString id() const
+    {
+        return QString("ImageDocker");
+    }
+
+    virtual Qt::DockWidgetArea defaultDockWidgetArea() const
+    {
+        return Qt::RightDockWidgetArea;
+    }
+
+    virtual QDockWidget* createDockWidget()
+    {
+        ImageDockerDock* dockWidget = new ImageDockerDock();
+        dockWidget->setObjectName(id());
+        return dockWidget;
+    }
+
+    DockPosition defaultDockPosition() const
+    {
+        return DockMinimized;
+    }
+};
+
+ImageDockerPlugin::ImageDockerPlugin(QObject* parent, const QVariantList&):
+    QObject(parent)
+{
+    KoDockRegistry::instance()->add(new ImageDockerDockFactory());
+}
diff --git a/krita/plugins/extensions/dockers/imagedocker/imagedocker.h \
b/krita/plugins/extensions/dockers/imagedocker/imagedocker.h new file mode 100644
index 0000000..8810313
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/imagedocker.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef H_IMAGEDOCKER_H_
+#define H_IMAGEDOCKER_H_
+
+#include <QObject>
+#include <QVariantList>
+
+class ImageDockerPlugin: public QObject
+{
+    Q_OBJECT
+public:
+    ImageDockerPlugin(QObject* parent, const QVariantList&);
+};
+
+#endif // H_IMAGEDOCKER_H_
diff --git a/krita/plugins/extensions/dockers/imagedocker/imagedocker_dock.cpp \
b/krita/plugins/extensions/dockers/imagedocker/imagedocker_dock.cpp new file mode \
100644 index 0000000..7c3294d
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/imagedocker_dock.cpp
@@ -0,0 +1,486 @@
+/*
+ *  Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "imagedocker_dock.h"
+#include "kis_image_strip_scene.h"
+#include "kis_image_view.h"
+
+#include <klocale.h>
+#include <KoResourceManager.h>
+#include <KoCanvasBase.h>
+#include <KoColorSpaceRegistry.h>
+
+#include <QFileSystemModel>
+#include <QImageReader>
+#include <QSortFilterProxyModel>
+#include <QFileInfo>
+#include <QMouseEvent>
+#include <QDir>
+#include <QLineEdit>
+#include <QLabel>
+#include <QIcon>
+#include <QAbstractListModel>
+#include <QButtonGroup>
+
+#include "ui_wdgimagedocker.h"
+#include "ui_wdgImageViewPopup.h"
+
+///////////////////////////////////////////////////////////////////////////////
+// --------- ImageFilter --------------------------------------------------- //
+
+class ImageFilter: public QSortFilterProxyModel
+{
+    virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) \
const { +        QFileSystemModel* model = \
static_cast<QFileSystemModel*>(sourceModel()); +        QModelIndex       index = \
sourceModel()->index(source_row, 0, source_parent); +        
+        if(model->isDir(index))
+            return true;
+        
+        m_reader.setFileName(model->filePath(index));
+        return m_reader.canRead();
+    }
+    
+    virtual bool filterAcceptsColumn(int source_column, const QModelIndex& \
source_parent) const { +        Q_UNUSED(source_parent);
+        return source_column == 0;
+    }
+    
+    mutable QImageReader m_reader;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// --------- ImageListModel ------------------------------------------------ //
+
+class ImageListModel: public QAbstractListModel
+{
+    struct Data
+    {
+        QPixmap icon;
+        QString text;
+        qint64  id;
+    };
+    
+public:
+    void addImage(const QPixmap& pixmap, const QString& text, qint64 id) {
+        Data data;
+        data.icon = pixmap.scaled(70, 70, Qt::KeepAspectRatio);
+        data.text = text;
+        data.id   = id;
+        emit layoutAboutToBeChanged();
+        m_data.push_back(data);
+        emit layoutChanged();
+    }
+    
+    qint64 imageID(int index) const { return m_data[index].id; }
+    
+    void removeImage(qint64 id) {
+        typedef QList<Data>::iterator Iterator;
+        
+        for(Iterator data=m_data.begin(); data!=m_data.end(); ++data) {
+            if(data->id == id) {
+                emit layoutAboutToBeChanged();
+                m_data.erase(data);
+                emit layoutChanged();
+                return;
+            }
+        }
+    }
+    
+    int indexFromID(qint64 id) {
+        for(int i=0; i<m_data.size(); ++i) {
+            if(m_data[i].id == id)
+                return i;
+        }
+        return -1;
+    }
+    
+    virtual int rowCount(const QModelIndex& parent=QModelIndex()) const {
+        Q_UNUSED(parent);
+        return m_data.size();
+    }
+    
+    virtual QVariant data(const QModelIndex& index, int role=Qt::DisplayRole) const \
{ +        if(index.isValid() && index.row() < m_data.size()) {
+            switch(role)
+            {
+            case Qt::DisplayRole:
+                return m_data[index.row()].text;
+            case Qt::DecorationRole:
+                return m_data[index.row()].icon;
+            }
+        }
+        return QVariant();
+    }
+    
+private:
+    QList<Data> m_data;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// --------- ImageDockerUI ------------------------------------------------- //
+
+struct ImageDockerUI: public QWidget, public Ui_wdgImageDocker
+{
+    ImageDockerUI() {
+        setupUi(this);
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// --------- PopupWidgetUI ------------------------------------------------- //
+
+struct PopupWidgetUI: public QWidget, public Ui_wdgImageViewPopup
+{
+    PopupWidgetUI() {
+        setupUi(this);
+    }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// --------- ImageDockerDock ----------------------------------------------- //
+
+ImageDockerDock::ImageDockerDock():
+    QDockWidget(i18n("Image Docker")),
+    m_canvas(0),
+    m_currImageID(-1)
+{
+    m_ui           = new ImageDockerUI();
+    m_popupUi      = new PopupWidgetUI();
+    m_zoomButtons  = new QButtonGroup();
+    m_imgListModel = new ImageListModel();
+    m_thumbModel   = new KisImageStripScene();
+    m_model        = new QFileSystemModel();
+    m_proxyModel   = new ImageFilter();
+    m_proxyModel->setSourceModel(m_model);
+    m_proxyModel->setDynamicSortFilter(true);
+    
+    m_ui->bnBack->setIcon(QIcon::fromTheme("go-previous"));
+    m_ui->bnUp->setIcon(QIcon::fromTheme("go-up"));
+    m_ui->bnHome->setIcon(QIcon::fromTheme("go-home"));
+    m_ui->bnImgPrev->setIcon(QIcon::fromTheme("go-previous"));
+    m_ui->bnImgNext->setIcon(QIcon::fromTheme("go-next"));
+    m_ui->bnImgClose->setIcon(QIcon::fromTheme("window-close"));
+    m_ui->thumbView->setScene(m_thumbModel);
+    m_ui->treeView->setModel(m_proxyModel);
+    m_ui->cmbImg->setModel(m_imgListModel);
+    m_ui->bnPopup->setIcon(QIcon::fromTheme("zoom-original"));
+    m_ui->bnPopup->setPopupWidget(m_popupUi);
+    
+    m_popupUi->zoomSlider->setRange(5, 500);
+    m_popupUi->zoomSlider->setValue(100);
+    
+    m_zoomButtons->addButton(m_popupUi->bnZoomFit   , KisImageView::VIEW_MODE_FIT);
+    m_zoomButtons->addButton(m_popupUi->bnZoomAdjust, \
KisImageView::VIEW_MODE_ADJUST); +    m_zoomButtons->addButton(m_popupUi->bnZoom25    \
, 25); +    m_zoomButtons->addButton(m_popupUi->bnZoom50    , 50);
+    m_zoomButtons->addButton(m_popupUi->bnZoom75    , 75);
+    m_zoomButtons->addButton(m_popupUi->bnZoom100   , 100);
+    
+    m_model->setRootPath(QDir::rootPath());
+    m_ui->treeView->setRootIndex(m_proxyModel->mapFromSource(m_model->index(QDir::homePath())));
 +    updatePath(QDir::homePath());
+    
+    connect(m_ui->treeView           , SIGNAL(doubleClicked(const QModelIndex&))     \
, SLOT(slotItemDoubleClicked(const QModelIndex&))); +    connect(m_ui->bnBack         \
, SIGNAL(clicked(bool))                          , SLOT(slotBackButtonClicked())); +  \
connect(m_ui->bnHome             , SIGNAL(clicked(bool))                          , \
SLOT(slotHomeButtonClicked())); +    connect(m_ui->bnUp               , \
SIGNAL(clicked(bool))                          , SLOT(slotUpButtonClicked())); +    \
connect(m_thumbModel             , SIGNAL(sigImageActivated(const QString&))      , \
SLOT(slotOpenImage(QString))); +    connect(m_ui->bnImgNext          , \
SIGNAL(clicked(bool))                          , SLOT(slotNextImage())); +    \
connect(m_ui->bnImgPrev          , SIGNAL(clicked(bool))                          , \
SLOT(slotPrevImage())); +    connect(m_ui->bnImgClose         , SIGNAL(clicked(bool)) \
, SLOT(slotCloseCurrentImage())); +    connect(m_ui->cmbImg             , \
SIGNAL(activated(int))                         , \
SLOT(slotImageChoosenFromComboBox(int))); +    connect(m_ui->imgView            , \
SIGNAL(sigColorSelected(const QColor&))        , SLOT(slotColorSelected(const \
QColor))); +    connect(m_ui->imgView            , SIGNAL(sigViewModeChanged(int, \
qreal))         , SLOT(slotViewModeChanged(int, qreal))); +    \
connect(m_popupUi->zoomSlider    , SIGNAL(valueChanged(int))                      , \
SLOT(slotZoomChanged(int))); +    connect(m_zoomButtons            , \
SIGNAL(buttonClicked(int))                     , SLOT(slotZoomChanged(int))); +    \
connect(m_zoomButtons            , SIGNAL(buttonClicked(int))                     , \
SLOT(slotCloseZoomPopup())); +    connect(this                     , \
SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), \
SLOT(slotDockLocationChanged(Qt::DockWidgetArea))); +    connect(this                 \
, SIGNAL(topLevelChanged(bool))                  , SLOT(slotTopLevelChanged(bool))); \
+ +    setWidget(m_ui);
+}
+
+ImageDockerDock::~ImageDockerDock()
+{
+    delete m_proxyModel;
+    delete m_model;
+    delete m_thumbModel;
+    delete m_imgListModel;
+    delete m_zoomButtons;
+}
+
+void ImageDockerDock::setCanvas(KoCanvasBase* canvas)
+{
+    // "Every connection you make emits a signal, so duplicate connections emit two \
signals" +    if(m_canvas)
+        m_canvas->disconnectCanvasObserver(this);
+
+    m_canvas = canvas;
+}
+
+void ImageDockerDock::addCurrentPathToHistory()
+{
+    m_history.push_back(m_model->filePath(m_proxyModel->mapToSource(m_ui->treeView->rootIndex())));
 +}
+
+void ImageDockerDock::updatePath(const QString& path)
+{
+    m_ui->cmbPath->lineEdit()->setText(path);
+    m_ui->bnBack->setDisabled(m_history.empty());
+    m_thumbModel->setCurrentDirectory(path);
+}
+
+qint64 ImageDockerDock::generateImageID() const
+{
+    static qint64 id = 0;
+    return ++id;
+}
+
+void ImageDockerDock::setCurrentImage(qint64 imageID)
+{
+    if(m_imgInfoMap.contains(m_currImageID))
+        m_imgInfoMap[m_currImageID].scrollPos = m_ui->imgView->getScrollPos();
+    
+    m_ui->bnImgClose->setDisabled(imageID < 0);
+    m_ui->bnPopup->setDisabled(imageID < 0);
+    
+    if(imageID < 0) {
+        m_currImageID = -1;
+        m_ui->imgView->setPixmap(QPixmap());
+    }
+    else if(m_imgInfoMap.contains(imageID)) {
+        ImageInfoIter info = m_imgInfoMap.find(imageID);
+        
+        m_ui->imgView->blockSignals(true);
+        m_ui->imgView->setPixmap(info->pixmap);
+        setZoom(*info);
+        m_ui->imgView->blockSignals(false);
+        
+        m_ui->bnImgPrev->setDisabled(info == m_imgInfoMap.begin());
+        m_ui->bnImgNext->setDisabled((info+1) == m_imgInfoMap.end());
+        
+        m_ui->cmbImg->blockSignals(true);
+        m_ui->cmbImg->setCurrentIndex(m_imgListModel->indexFromID(imageID));
+        m_ui->cmbImg->blockSignals(false);
+        
+        m_currImageID = imageID;
+    }
+}
+
+void ImageDockerDock::setZoom(const ImageInfo& info)
+{
+    m_ui->imgView->setViewMode(info.viewMode, info.scale);
+    m_ui->imgView->setScrollPos(info.scrollPos);
+    
+    int zoom = qRound(m_ui->imgView->getScale() * 100.0f);
+    
+    m_popupUi->zoomSlider->blockSignals(true);
+    m_popupUi->zoomSlider->setValue(zoom);
+    m_popupUi->zoomSlider->blockSignals(false);
+}
+
+
+// ------------ slots ------------------------------------------------- //
+
+void ImageDockerDock::slotItemDoubleClicked(const QModelIndex& index)
+{
+    QModelIndex mappedIndex = m_proxyModel->mapToSource(index);
+    mappedIndex = m_model->index(mappedIndex.row(), 0, mappedIndex.parent());
+    QString path(m_model->filePath(mappedIndex));
+    
+    if(m_model->isDir(mappedIndex)) {
+        addCurrentPathToHistory();
+        updatePath(path);
+        m_ui->treeView->setRootIndex(m_proxyModel->mapFromSource(mappedIndex));
+    }
+    else slotOpenImage(path);
+}
+
+void ImageDockerDock::slotBackButtonClicked()
+{
+    if(!m_history.empty()) {
+        QString     path  = m_history.last();
+        QModelIndex index = m_proxyModel->mapFromSource(m_model->index(path));
+        m_ui->treeView->setRootIndex(index);
+        m_history.pop_back();
+        updatePath(path);
+    }
+}
+
+void ImageDockerDock::slotHomeButtonClicked()
+{
+    addCurrentPathToHistory();
+    QModelIndex index = \
m_proxyModel->mapFromSource(m_model->index(QDir::homePath())); +    \
m_ui->treeView->setRootIndex(index); +    updatePath(QDir::homePath());
+}
+
+void ImageDockerDock::slotUpButtonClicked()
+{
+    addCurrentPathToHistory();
+    
+    QModelIndex index = m_proxyModel->mapToSource(m_ui->treeView->rootIndex());
+    QDir        dir(m_model->filePath(index));
+    dir.makeAbsolute();
+    
+    if(dir.cdUp()) {
+        index = m_proxyModel->mapFromSource(m_model->index(dir.path()));
+        m_ui->treeView->setRootIndex(index);
+        updatePath(dir.path());
+    }
+}
+
+void ImageDockerDock::slotOpenImage(const QString& path)
+{
+    QPixmap pixmap(path);
+    
+    if(!pixmap.isNull()) {
+        QFileInfo fileInfo(path);
+        ImageInfo imgInfo;
+        imgInfo.id        = generateImageID();
+        imgInfo.name      = fileInfo.fileName();
+        imgInfo.path      = fileInfo.absoluteFilePath();
+        imgInfo.viewMode  = KisImageView::VIEW_MODE_FIT;
+        imgInfo.scale     = 1.0f;
+        imgInfo.pixmap    = pixmap;
+        imgInfo.scrollPos = QPoint(0, 0);
+        
+        m_imgInfoMap[imgInfo.id] = imgInfo;
+        m_imgListModel->addImage(imgInfo.pixmap, imgInfo.name, imgInfo.id);
+        setCurrentImage(imgInfo.id);
+        m_ui->tabWidget->setCurrentIndex(1);
+    }
+}
+
+void ImageDockerDock::slotCloseCurrentImage()
+{
+    ImageInfoIter info = m_imgInfoMap.find(m_currImageID);
+    
+    if(info != m_imgInfoMap.end()) {
+        ImageInfoIter next = info + 1;
+        ImageInfoIter prev = info - 1;
+        qint64        id   = -1;
+        
+        if(next != m_imgInfoMap.end())
+            id = next->id;
+        else if(info != m_imgInfoMap.begin())
+            id = prev->id;
+        
+        m_imgListModel->removeImage(info->id);
+        m_imgInfoMap.erase(info);
+        setCurrentImage(id);
+        
+        if(id < 0)
+            m_ui->tabWidget->setCurrentIndex(0);
+    }
+}
+
+void ImageDockerDock::slotNextImage()
+{
+    ImageInfoIter info = m_imgInfoMap.find(m_currImageID);
+    
+    if(info != m_imgInfoMap.end()) {
+        ++info;
+        if(info != m_imgInfoMap.end())
+            setCurrentImage(info->id);
+    }
+}
+
+void ImageDockerDock::slotPrevImage()
+{
+    ImageInfoIter info = m_imgInfoMap.find(m_currImageID);
+    
+    if(info != m_imgInfoMap.end() && info != m_imgInfoMap.begin()) {
+        --info;
+        setCurrentImage(info->id);
+    }
+}
+
+void ImageDockerDock::slotImageChoosenFromComboBox(int index)
+{
+    setCurrentImage(m_imgListModel->imageID(index));
+}
+
+void ImageDockerDock::slotZoomChanged(int zoom)
+{
+    if(isImageLoaded()) {
+        ImageInfoIter info = m_imgInfoMap.find(m_currImageID);
+        
+        switch(zoom)
+        {
+        case KisImageView::VIEW_MODE_FIT:
+        case KisImageView::VIEW_MODE_ADJUST:
+            info->viewMode = zoom;
+            break;
+            
+        default:
+            info->viewMode = KisImageView::VIEW_MODE_FREE;
+            info->scale    = float(zoom) / 100.0f;
+            break;
+        }
+        
+        setZoom(*info);
+    }
+}
+
+void ImageDockerDock::slotColorSelected(const QColor& color)
+{
+    m_canvas->resourceManager()->setForegroundColor(
+        KoColor(color, KoColorSpaceRegistry::instance()->rgb8())
+    );
+}
+
+void ImageDockerDock::slotDockLocationChanged(Qt::DockWidgetArea area)
+{
+    if(area == Qt::AllDockWidgetAreas)
+        m_ui->tabWidget->setTabPosition(QTabWidget::North);
+    else if(area & Qt::LeftDockWidgetArea)
+        m_ui->tabWidget->setTabPosition(QTabWidget::East);
+    else if(area & Qt::RightDockWidgetArea)
+        m_ui->tabWidget->setTabPosition(QTabWidget::West);
+    else
+        m_ui->tabWidget->setTabPosition(QTabWidget::North);
+}
+
+void ImageDockerDock::slotTopLevelChanged(bool topLevel)
+{
+    if(topLevel)
+        m_ui->tabWidget->setTabPosition(QTabWidget::North);
+}
+
+void ImageDockerDock::slotViewModeChanged(int viewMode, qreal scale)
+{
+    if(isImageLoaded()) {
+        m_imgInfoMap[m_currImageID].viewMode = viewMode;
+        m_imgInfoMap[m_currImageID].scale    = scale;
+        
+        int zoom = qRound(scale * 100.0);
+        
+        m_popupUi->zoomSlider->blockSignals(true);
+        m_popupUi->zoomSlider->setValue(zoom);
+        m_popupUi->zoomSlider->blockSignals(false);
+    }
+}
+
+void ImageDockerDock::slotCloseZoomPopup()
+{
+    m_ui->bnPopup->hidePopupWidget();
+}
diff --git a/krita/plugins/extensions/dockers/imagedocker/imagedocker_dock.h \
b/krita/plugins/extensions/dockers/imagedocker/imagedocker_dock.h new file mode \
100644 index 0000000..0501a3a
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/imagedocker_dock.h
@@ -0,0 +1,99 @@
+/*
+ *  Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef H_IMAGEDOCKER_DOCK_H_
+#define H_IMAGEDOCKER_DOCK_H_
+
+#include <QDockWidget>
+#include <KoCanvasObserverBase.h>
+#include <QStringList>
+#include <QPixmap>
+#include <QMap>
+
+class QModelIndex;
+class QFileSystemModel;
+class QButtonGroup;
+class KoCanvasBase;
+class ImageFilter;
+class KisImageStripScene;
+class ImageListModel;
+struct ImageDockerUI;
+struct PopupWidgetUI;
+
+class ImageDockerDock: public QDockWidget, public KoCanvasObserverBase
+{
+    Q_OBJECT
+    
+    struct ImageInfo
+    {
+        qint64  id;
+        int     viewMode;
+        QString path;
+        QString name;
+        float   scale;
+        QPixmap pixmap;
+        QPoint  scrollPos;
+    };
+    
+    typedef QMap<qint64,ImageInfo>::iterator ImageInfoIter;
+    
+public:
+    ImageDockerDock();
+    virtual ~ImageDockerDock();
+    virtual void setCanvas(KoCanvasBase* canvas);
+    virtual void unsetCanvas() { m_canvas = 0; }
+    
+private slots:
+    void slotItemDoubleClicked(const QModelIndex& index);
+    void slotBackButtonClicked();
+    void slotUpButtonClicked();
+    void slotHomeButtonClicked();
+    void slotCloseCurrentImage();
+    void slotNextImage();
+    void slotPrevImage();
+    void slotOpenImage(const QString& path);
+    void slotImageChoosenFromComboBox(int index);
+    void slotZoomChanged(int zoom);
+    void slotColorSelected(const QColor& color);
+    void slotDockLocationChanged(Qt::DockWidgetArea area);
+    void slotTopLevelChanged(bool topLevel);
+    void slotViewModeChanged(int viewMode, qreal scale);
+    void slotCloseZoomPopup();
+    
+private:
+    void addCurrentPathToHistory();
+    void updatePath(const QString& path);
+    qint64 generateImageID() const;
+    void setCurrentImage(qint64 imageID);
+    bool isImageLoaded() const { return m_currImageID != -1; }
+    void setZoom(const ImageInfo& info);
+    
+private:
+    QFileSystemModel*      m_model;
+    QButtonGroup*          m_zoomButtons;
+    KoCanvasBase*          m_canvas;
+    ImageFilter*           m_proxyModel;
+    ImageListModel*        m_imgListModel;
+    QStringList            m_history;
+    KisImageStripScene*    m_thumbModel;
+    ImageDockerUI*         m_ui;
+    PopupWidgetUI*         m_popupUi;
+    QMap<qint64,ImageInfo> m_imgInfoMap;
+    qint64                 m_currImageID;
+};
+
+#endif // H_IMAGEDOCKER_DOCK_H_
diff --git a/krita/plugins/extensions/dockers/imagedocker/kis_image_strip_scene.cpp \
b/krita/plugins/extensions/dockers/imagedocker/kis_image_strip_scene.cpp new file \
mode 100644 index 0000000..b92a847
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/kis_image_strip_scene.cpp
@@ -0,0 +1,177 @@
+/*
+ *  Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_image_strip_scene.h"
+
+#include <QDir>
+#include <QPainter>
+#include <QHash>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsLinearLayout>
+#include <QGraphicsWidget>
+#include <QMutexLocker>
+#include <QIcon>
+
+/////////////////////////////////////////////////////////////////////////////////////////////
 +// ------------- KisImageLoader \
---------------------------------------------------------- // +
+void KisImageLoader::run()
+{
+    typedef QHash<KisImageItem*,Data>::iterator Iterator;
+    
+    QImageReader reader;
+    
+    for(Iterator data=m_data.begin(); data!=m_data.end() && m_run; ++data) {
+        reader.setFileName(data->path);
+        qreal w = m_size;
+        qreal h = m_size;
+        
+        if(reader.supportsOption(QImageIOHandler::Size)) {
+            QSizeF imgSize = reader.size();
+            
+            if(imgSize.width() > imgSize.height()) {
+                qreal div = m_size / imgSize.width();
+                h = imgSize.height() * div;
+            }
+            else {
+                qreal div = m_size / imgSize.height();
+                w = imgSize.width() * div;
+            }
+        }
+        
+        reader.setScaledSize(QSize(w,h));
+        data->image    = reader.read();
+        data->isLoaded = true;
+        emit sigItemContentChanged(data.key());
+    }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
 +// ------------- KisImageItem \
------------------------------------------------------------ // +
+void KisImageItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, \
QWidget* widget) +{
+    Q_UNUSED(option);
+    Q_UNUSED(widget);
+    
+    if(m_loader->isImageLoaded(this)) {
+        QImage  image = m_loader->getImage(this);
+        
+        if(!image.isNull()) {
+            QPointF offset((m_size-image.width()) / 2.0, (m_size-image.height()) / \
2.0); +            painter->drawImage(offset, image);
+        }
+        else {
+            QIcon   icon = QIcon::fromTheme("image-missing");
+            QRect   rect = boundingRect().toRect();
+            QPixmap img  = icon.pixmap(rect.size());
+            painter->drawPixmap(rect, img, img.rect());
+        }
+    }
+    else {
+        QIcon   icon = QIcon::fromTheme("image-loading");
+        QRect   rect = boundingRect().toRect();
+        QPixmap img  = icon.pixmap(rect.size());
+        painter->drawPixmap(rect, img, img.rect());
+    }
+    
+    if(isSelected())
+        painter->fillRect(boundingRect(), Qt::Dense5Pattern);
+    
+    painter->drawRect(boundingRect());
+}
+
+QSizeF KisImageItem::sizeHint(Qt::SizeHint which, const QSizeF& constraint) const
+{
+    return QSizeF(m_size, m_size);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////
 +// ------------- KisImageStripScene \
------------------------------------------------------ // +
+KisImageStripScene::KisImageStripScene():
+    m_imgSize(80), m_loader(0) { }
+
+bool KisImageStripScene::setCurrentDirectory(const QString& path)
+{
+    QMutexLocker locker(&m_mutex);
+    QDir         directory(path);
+    QImageReader reader;
+    
+    if(directory.exists()) {
+        clear();
+        
+        if(m_loader) {
+            m_loader->disconnect(this);
+            m_loader->stopExecution();
+            
+            if(!m_loader->wait(500)) {
+                m_loader->terminate();
+                m_loader->wait();
+            }
+        }
+        
+        delete m_loader;
+        
+        m_numItems = 0;
+        m_loader   = new KisImageLoader(m_imgSize);
+        connect(m_loader, SIGNAL(sigItemContentChanged(KisImageItem*)), \
SLOT(slotItemContentChanged(KisImageItem*))); +        
+        QStringList            files  = directory.entryList(QDir::Files);
+        QGraphicsLinearLayout* layout = new QGraphicsLinearLayout();
+        
+        for(QStringList::iterator name=files.begin(); name!=files.end(); ++name) {
+            QString path = directory.absoluteFilePath(*name);
+            reader.setFileName(path);
+            
+            if(reader.canRead()) {
+                KisImageItem* item = new KisImageItem(m_imgSize, path, m_loader);
+                m_loader->addPath(item, path);
+                layout->addItem(item);
+                ++m_numItems;
+            }
+        }
+        
+        QGraphicsWidget* widget = new QGraphicsWidget();
+        widget->setLayout(layout);
+        widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+        
+        addItem(widget);
+        setSceneRect(widget->boundingRect());
+        
+        m_loader->start(QThread::LowPriority);
+        return true;
+    }
+    
+    return false;
+}
+
+void KisImageStripScene::slotItemContentChanged(KisImageItem* item)
+{
+    QMutexLocker locker(&m_mutex);
+    item->update();
+}
+
+void KisImageStripScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
+{
+    KisImageItem* item = static_cast<KisImageItem*>(itemAt(event->scenePos()));
+    
+    if(item)
+        emit sigImageActivated(item->path());
+}
diff --git a/krita/plugins/extensions/dockers/imagedocker/kis_image_strip_scene.h \
b/krita/plugins/extensions/dockers/imagedocker/kis_image_strip_scene.h new file mode \
100644 index 0000000..d9dc8b9
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/kis_image_strip_scene.h
@@ -0,0 +1,121 @@
+/*
+ *  Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef H_IMAGE_STRIP_SCENE_H_
+#define H_IMAGE_STRIP_SCENE_H_
+
+#include <QGraphicsScene>
+#include <QGraphicsWidget>
+#include <QImageReader>
+#include <QThread>
+#include <QAtomicInt>
+#include <QMutex>
+
+class KisImageItem;
+
+class KisImageLoader: public QThread
+{
+    Q_OBJECT
+    
+    struct Data
+    {
+        Data() { }
+        Data(const QString& p):
+            path(p), isLoaded(false) { };
+        Data(const Data& d):
+            image(d.image), path(d.path), isLoaded(d.isLoaded) { };
+        
+        QImage     image;
+        QString    path;
+        QAtomicInt isLoaded;
+    };
+    
+signals:
+    void sigItemContentChanged(KisImageItem* item);
+    
+public:
+    KisImageLoader(float size): m_size(size), m_run(true) { }
+    
+    void addPath(KisImageItem* item, const QString& path) {
+        m_data[item] = Data(path);
+    }
+    
+    bool isImageLoaded(KisImageItem* item) const {
+        return m_data[item].isLoaded != false;
+    }
+    
+    QImage getImage(KisImageItem* item) const {
+        return m_data[item].image;
+    }
+    
+    void stopExecution() {
+        m_run = false;
+    }
+    
+    virtual void run();
+    
+private:
+    float                     m_size;
+    QHash<KisImageItem*,Data> m_data;
+    QAtomicInt                m_run;
+};
+
+class KisImageItem: public QGraphicsWidget
+{
+public:
+    KisImageItem(float size, const QString& path, KisImageLoader* loader):
+        m_size(size), m_loader(loader), m_path(path)
+    {
+        setFlag(QGraphicsItem::ItemIsSelectable, true);
+    }
+    
+    const QString& path() const { return m_path; }
+    
+    virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF& constraint=QSizeF()) \
const; +    virtual void   paint(QPainter* painter, const QStyleOptionGraphicsItem* \
option, QWidget* widget=0); +    
+private:
+    float           m_size;
+    KisImageLoader* m_loader;
+    QString         m_path;
+};
+
+class KisImageStripScene: public QGraphicsScene
+{
+    Q_OBJECT
+    
+public:
+    KisImageStripScene();
+    bool setCurrentDirectory(const QString& path);
+    
+signals:
+    void sigImageActivated(const QString& path);
+    
+private:
+    virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event);
+    
+private slots:
+    void slotItemContentChanged(KisImageItem* item);
+    
+private:
+    float           m_imgSize;
+    quint32         m_numItems;
+    KisImageLoader* m_loader;
+    QMutex          m_mutex;
+};
+
+#endif // H_IMAGE_STRIP_SCENE_H_
diff --git a/krita/plugins/extensions/dockers/imagedocker/kis_image_view.cpp \
b/krita/plugins/extensions/dockers/imagedocker/kis_image_view.cpp new file mode \
100644 index 0000000..c138fca
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/kis_image_view.cpp
@@ -0,0 +1,261 @@
+/*
+ *  Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kis_image_view.h"
+
+#include <QPaintEvent>
+#include <QMouseEvent>
+#include <QResizeEvent>
+#include <QPainter>
+#include <QScrollBar>
+
+//////////////////////////////////////////////////////////////////////////////
+// -------- KisImageViewport ---------------------------------------------- //
+
+KisImageViewport::KisImageViewport():
+    m_scale(1.0f),
+    m_mousePressed(false),
+    m_rubberBand(QRubberBand::Rectangle, this)
+{
+    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+}
+
+void KisImageViewport::paintEvent(QPaintEvent* event)
+{
+    Q_UNUSED(event);
+    QPainter painter(this);
+    painter.drawPixmap(imageRect().topLeft(), m_cachedPixmap);
+}
+
+void KisImageViewport::setImage(const QPixmap& pixmap, qreal scale)
+{
+    m_scale        = scale;
+    m_pixmap       = pixmap;
+    m_cachedPixmap = pixmap.scaled(imageRect().size(), Qt::IgnoreAspectRatio, \
Qt::FastTransformation); +}
+
+void KisImageViewport::setScale(qreal scale)
+{
+    if(!qFuzzyCompare(scale, m_scale)) {
+        m_scale        = scale;
+        m_cachedPixmap = m_pixmap.scaled(imageRect().size(), Qt::IgnoreAspectRatio, \
Qt::FastTransformation); +    }
+}
+
+QColor KisImageViewport::imageColor(const QPoint& pos) const
+{
+    return m_cachedPixmap.copy(pos.x(), pos.y(), 1, 1).toImage().pixel(0,0);
+}
+
+QSize KisImageViewport::sizeHint() const
+{
+    return imageRect().size();
+}
+
+QRect KisImageViewport::imageRect() const
+{
+    int w = int(m_scale * m_pixmap.width());
+    int h = int(m_scale * m_pixmap.height());
+    int x = (width()  - w) / 2;
+    int y = (height() - h) / 2;
+    return QRect(x, y, w, h);
+}
+
+QSize KisImageViewport::imageSize() const
+{
+    return m_pixmap.size();
+}
+
+void KisImageViewport::mousePressEvent(QMouseEvent* event)
+{
+    m_mousePressed = true;
+    m_selection    = QRect(event->pos(), QSize(0,0));
+    m_rubberBand.setGeometry(m_selection);
+    m_rubberBand.show();
+}
+
+void KisImageViewport::mouseMoveEvent(QMouseEvent* event)
+{
+    if(m_mousePressed) {
+        QPoint size = event->pos() - m_selection.topLeft();
+        m_selection.setSize(QSize(size.x(), size.y()));
+        m_rubberBand.setGeometry(m_selection.normalized());
+    }
+}
+
+void KisImageViewport::mouseReleaseEvent(QMouseEvent* event)
+{
+    m_selection = m_selection.normalized();
+    
+    if(m_selection.width() > 5 && m_selection.height() > 5) {
+        QRect imgRect = imageRect();
+        QRect rect    = \
imgRect.intersected(m_selection).translated(-imgRect.topLeft()); +        emit \
sigRegionSelected(rect); +    }
+    else if(imageRect().contains(event->pos(), true)) {
+        emit sigImageClicked(event->pos() - imageRect().topLeft());
+    }
+    
+    m_mousePressed = false;
+    m_rubberBand.hide();
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+// -------- KisImageView -------------------------------------------------- //
+
+KisImageView::KisImageView(QWidget* parent):
+    QScrollArea(parent),
+    m_viewMode(VIEW_MODE_FIT),
+    m_minScale(0.05),
+    m_maxScale(5.00)
+{
+    m_imgViewport = new KisImageViewport();
+    QScrollArea::setWidgetResizable(true);
+    QScrollArea::setWidget(m_imgViewport);
+    
+    connect(m_imgViewport, SIGNAL(sigImageClicked(const QPoint&)) , \
SLOT(slotImageClicked(const QPoint&))); +    connect(m_imgViewport, \
SIGNAL(sigRegionSelected(const QRect&)), SLOT(slotRegionSelected(const QRect&))); +}
+
+void KisImageView::setPixmap(const QPixmap& pixmap, int viewMode, qreal scale)
+{
+    m_viewMode = viewMode;
+    m_scale    = calcScale(scale, viewMode, pixmap.size());
+    m_imgViewport->setImage(pixmap, m_scale);
+    m_imgViewport->setMinimumSize(m_imgViewport->sizeHint());
+    m_imgViewport->adjustSize();
+    
+    emit sigViewModeChanged(m_viewMode, m_scale);
+}
+
+void KisImageView::setViewMode(int viewMode, qreal scale)
+{
+    m_viewMode = viewMode;
+    m_scale    = calcScale(scale, viewMode, m_imgViewport->imageSize());
+    m_imgViewport->setScale(m_scale);
+    m_imgViewport->setMinimumSize(m_imgViewport->sizeHint());
+    m_imgViewport->adjustSize();
+    
+    emit sigViewModeChanged(m_viewMode, m_scale);
+}
+
+void KisImageView::setScrollPos(const QPoint& pos)
+{
+    horizontalScrollBar()->setValue(pos.x());
+    verticalScrollBar()->setValue(pos.y());
+}
+
+QPoint KisImageView::getScrollPos() const
+{
+    return QPoint(horizontalScrollBar()->value(), verticalScrollBar()->value());
+}
+
+qreal KisImageView::getScale() const
+{
+    return m_scale;
+}
+
+qreal KisImageView::calcScale(qreal scale, int viewMode, const QSizeF& imgSize) \
const +{
+    QSizeF viewSize  = viewportSize(viewMode == VIEW_MODE_ADJUST);
+    qreal  wdgAspect = viewSize.width() / viewSize.height();
+    qreal  imgAspect = imgSize.width() / imgSize.height();
+    
+    switch(viewMode)
+    {
+    case VIEW_MODE_FIT:
+        if(wdgAspect > imgAspect) { scale = viewSize.height() / imgSize.height(); }
+        else                      { scale = viewSize.width()  / imgSize.width();  }
+        break;
+        
+    case VIEW_MODE_ADJUST:
+        if(wdgAspect > imgAspect) { scale = viewSize.width()  / imgSize.width();  }
+        else                      { scale = viewSize.height() / imgSize.height(); }
+        break;
+    }
+    
+    return qBound(m_minScale, scale, m_maxScale);
+}
+
+QSize KisImageView::viewportSize(bool withScrollbars) const
+{
+    int width  = viewport()->width();
+    int height = viewport()->height();
+    int xAdd   = verticalScrollBar()->width();
+    int yAdd   = horizontalScrollBar()->height();
+    
+    if(withScrollbars) {
+        width  -= verticalScrollBar()->isVisible()   ? 0 : xAdd;
+        height -= horizontalScrollBar()->isVisible() ? 0 : yAdd;
+    }
+    else {
+        width  += verticalScrollBar()->isVisible()   ? xAdd : 0;
+        height += horizontalScrollBar()->isVisible() ? yAdd : 0;
+    }
+    
+    return QSize(width, height);
+}
+
+void KisImageView::slotImageClicked(const QPoint& pos)
+{
+    emit sigColorSelected(m_imgViewport->imageColor(pos));
+}
+
+void KisImageView::slotRegionSelected(const QRect& rect)
+{
+    QSizeF viewSize = viewportSize(true);
+    QSizeF imgSize  = m_imgViewport->imageSize();
+    QRectF selRect  = rect;
+        
+    selRect = QRectF(selRect.topLeft() / m_scale, selRect.size() / m_scale);
+    
+    qreal wdgAspect = viewSize.width() / viewSize.height();
+    qreal selAspect = selRect.width() / selRect.height();
+    
+    if(wdgAspect > selAspect)
+        m_scale = viewSize.height() / selRect.height();
+    else
+        m_scale = viewSize.width() / selRect.width();
+    
+    m_scale    = qBound(m_minScale, m_scale, m_maxScale);
+    m_viewMode = VIEW_MODE_FREE;
+    m_imgViewport->setScale(m_scale);
+    m_imgViewport->setMinimumSize(m_imgViewport->sizeHint());
+    m_imgViewport->adjustSize();
+    
+    selRect = QRectF(selRect.topLeft() * m_scale, selRect.size() * m_scale);
+    
+    QSize  offset    = ((viewSize - selRect.size()) / 2.0).toSize();
+    QPoint scrollPos = selRect.topLeft().toPoint() - QPoint(offset.width(), \
offset.height()); +    setScrollPos(scrollPos);
+    
+    emit sigViewModeChanged(m_viewMode, m_scale);
+}
+
+void KisImageView::resizeEvent(QResizeEvent* event)
+{
+    QScrollArea::resizeEvent(event);
+    
+    m_scale = calcScale(m_scale, m_viewMode, m_imgViewport->imageSize());
+    m_imgViewport->setScale(m_scale);
+    m_imgViewport->setMinimumSize(m_imgViewport->sizeHint());
+    m_imgViewport->adjustSize();
+    
+    emit sigViewModeChanged(m_viewMode, m_scale);
+}
+
diff --git a/krita/plugins/extensions/dockers/imagedocker/kis_image_view.h \
b/krita/plugins/extensions/dockers/imagedocker/kis_image_view.h new file mode 100644
index 0000000..f55b7a2
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/kis_image_view.h
@@ -0,0 +1,94 @@
+/*
+ *  Copyright (c) 2011 Silvio Heinrich <plassy@web.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef H_KIS_IMAGE_VIEW_H
+#define H_KIS_IMAGE_VIEW_H
+
+#include <QScrollArea>
+#include <QPixmap>
+#include <QRubberBand>
+
+class KisImageViewport: public QWidget
+{
+    Q_OBJECT
+    
+public:
+    KisImageViewport();
+    
+    QRect  imageRect() const;
+    QColor imageColor(const QPoint& pos) const;
+    QSize  imageSize() const;
+    
+    void setImage(const QPixmap& pixmap, qreal scale);
+    void setScale(qreal scale);
+    
+    virtual QSize sizeHint() const;
+    virtual void paintEvent(QPaintEvent* event);
+    virtual void mousePressEvent(QMouseEvent* event);
+    virtual void mouseMoveEvent(QMouseEvent* event);
+    virtual void mouseReleaseEvent(QMouseEvent* event);
+    
+private:
+    qreal       m_scale;
+    QPixmap     m_pixmap;
+    QPixmap     m_cachedPixmap;
+    bool        m_mousePressed;
+    QRubberBand m_rubberBand;
+    QRect       m_selection;
+    
+signals:
+    void sigImageClicked(const QPoint& pos);
+    void sigRegionSelected(const QRect& rect);
+};
+
+class KisImageView: public QScrollArea
+{
+    Q_OBJECT
+    
+public:
+    enum { VIEW_MODE_FREE=0, VIEW_MODE_ADJUST=1, VIEW_MODE_FIT=2 };
+    
+    KisImageView(QWidget* parent=0);
+    
+    void setPixmap(const QPixmap& pixmap, int viewMode=VIEW_MODE_FIT, qreal \
scale=1.0); +    void setViewMode(int viewMode, qreal scale=1.0);
+    void setScrollPos(const QPoint& pos);
+    QPoint getScrollPos() const;
+    qreal getScale() const;
+    
+signals:
+    void sigColorSelected(const QColor& color);
+    void sigViewModeChanged(int viewMode, qreal scale);
+    
+private slots:
+    void slotImageClicked(const QPoint& pos);
+    void slotRegionSelected(const QRect& rect);
+    
+private:
+    qreal calcScale(qreal scale, int viewMode, const QSizeF& imgSize) const;
+    QSize viewportSize(bool withScrollbars) const;
+    virtual void resizeEvent(QResizeEvent* event);
+    
+private:
+    qreal             m_scale;
+    int               m_viewMode;
+    qreal             m_minScale;
+    qreal             m_maxScale;
+    KisImageViewport* m_imgViewport;
+};
+
+#endif // H_KIS_IMAGE_VIEW_H
diff --git a/krita/plugins/extensions/dockers/imagedocker/kritaimagedocker.desktop \
b/krita/plugins/extensions/dockers/imagedocker/kritaimagedocker.desktop new file mode \
100644 index 0000000..d8ce40d
--- /dev/null
+++ b/krita/plugins/extensions/dockers/imagedocker/kritaimagedocker.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=Image Docker
+Name[en_GB]=Image Docker
+Comment=Docker for reference images
+Comment[en_GB]=Docker for reference images
+X-KDE-ServiceTypes=Krita/Dock
+Type=Service
+X-KDE-Library=kritaimagedocker
+X-Krita-Version=4


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic