[krita] krita: FEATURE: add import/export of GBR and GIH brush files

Boudewijn Rempt boud at valdyas.org
Mon Jan 11 11:02:54 UTC 2016


Git commit 7d68f4ab6010ed742091587499c46c8934ecb7ac by Boudewijn Rempt.
Committed on 11/01/2016 at 10:59.
Pushed by rempt into branch 'master'.

FEATURE: add import/export of GBR and GIH brush files

The import/export is limited to what Krita already supported when
creating new brushes, i.e., not the whole GIH spec is implemented.

CCMAIL:kimageshop at kde.org
Implements T125

M  +4    -1    krita/data/CMakeLists.txt
A  +7    -0    krita/data/x-gimp-brush-animated.xml
A  +8    -0    krita/data/x-gimp-brush.xml
M  +1    -1    krita/libbrush/CMakeLists.txt
M  +1    -2    krita/libbrush/kis_brush.h
M  +1    -1    krita/libbrush/kis_brushes_pipe.h
M  +26   -11   krita/libbrush/kis_imagepipe_brush.cpp
M  +9    -2    krita/libbrush/kis_imagepipe_brush.h
R  +7    -1    krita/libbrush/kis_pipebrush_parasite.cpp [from: krita/libbrush/kis_imagepipe_brush_p.cpp - 097% similarity]
R  +3    -2    krita/libbrush/kis_pipebrush_parasite.h [from: krita/libbrush/kis_imagepipe_brush_p.h - 097% similarity]
M  +4    -4    krita/libbrush/tests/kis_imagepipe_brush_test.cpp
M  +1    -6    krita/plugins/extensions/dockers/palettedocker/CMakeLists.txt
M  +4    -4    krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.cpp
M  +4    -4    krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.h
M  +1    -0    krita/plugins/formats/CMakeLists.txt
A  +26   -0    krita/plugins/formats/brush/CMakeLists.txt
A  +36   -0    krita/plugins/formats/brush/KisAnimatedBrushAnnotation.cpp     [License: GPL (v2+)]
A  +33   -0    krita/plugins/formats/brush/KisAnimatedBrushAnnotation.h     [License: GPL (v2+)]
A  +214  -0    krita/plugins/formats/brush/kis_brush_export.cpp     [License: GPL (v2+)]
A  +37   -0    krita/plugins/formats/brush/kis_brush_export.h     [License: GPL (v2+)]
A  +149  -0    krita/plugins/formats/brush/kis_brush_import.cpp     [License: GPL (v2+)]
A  +37   -0    krita/plugins/formats/brush/kis_brush_import.h     [License: GPL (v2+)]
A  +72   -0    krita/plugins/formats/brush/krita_brush.desktop
A  +11   -0    krita/plugins/formats/brush/krita_brush_export.json
A  +11   -0    krita/plugins/formats/brush/krita_brush_import.json
A  +205  -0    krita/plugins/formats/brush/wdg_export_gih.ui
M  +2    -1    krita/plugins/paintops/libpaintop/kis_spacing_selection_widget.h
M  +17   -0    krita/plugins/tools/selectiontools/kis_selection_modifier_mapper.cc
M  +3    -0    krita/ui/CMakeLists.txt
R  +5    -5    krita/ui/KisColorsetChooser.cpp [from: krita/plugins/extensions/dockers/palettedocker/colorsetchooser.cpp - 095% similarity]
R  +8    -5    krita/ui/KisColorsetChooser.h [from: krita/plugins/extensions/dockers/palettedocker/colorsetchooser.h - 085% similarity]
M  +1    -0    krita/ui/KisDocument.cpp
R  +11   -11   krita/ui/KisPaletteModel.cpp [from: krita/plugins/extensions/dockers/palettedocker/palettemodel.cpp - 079% similarity]
R  +7    -6    krita/ui/KisPaletteModel.h [from: krita/plugins/extensions/dockers/palettedocker/palettemodel.h - 088% similarity]

http://commits.kde.org/krita/7d68f4ab6010ed742091587499c46c8934ecb7ac

diff --git a/krita/data/CMakeLists.txt b/krita/data/CMakeLists.txt
index fdb194e..b8722d3 100644
--- a/krita/data/CMakeLists.txt
+++ b/krita/data/CMakeLists.txt
@@ -22,7 +22,10 @@ install( FILES
 
 install( FILES
     krita.xml
-    DESTINATION ${XDG_MIME_INSTALL_DIR})
+    x-gimp-brush-animated.xml
+    x-gimp-brush.xml
+    DESTINATION ${XDG_MIME_INSTALL_DIR}
+)
 if (SHARED_MIME_INFO_FOUND)
     update_xdg_mimetypes(${XDG_MIME_INSTALL_DIR})
 endif()
diff --git a/krita/data/x-gimp-brush-animated.xml b/krita/data/x-gimp-brush-animated.xml
new file mode 100644
index 0000000..dfa1901
--- /dev/null
+++ b/krita/data/x-gimp-brush-animated.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+  <mime-type type="image/x-gimp-brush-animated">
+    <comment>Gimp Image Hose Brush</comment>
+    <glob pattern="*.gih"/>
+  </mime-type>
+</mime-info>
diff --git a/krita/data/x-gimp-brush.xml b/krita/data/x-gimp-brush.xml
new file mode 100644
index 0000000..8bbb9c6
--- /dev/null
+++ b/krita/data/x-gimp-brush.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+  <mime-type type="image/x-gimp-brush">
+    <comment>Gimp Brush</comment>
+    <glob pattern="*.gbr"/>
+    <glob pattern="*.vbr"/>
+  </mime-type>
+</mime-info>
diff --git a/krita/libbrush/CMakeLists.txt b/krita/libbrush/CMakeLists.txt
index 99c97c1..b78357f 100644
--- a/krita/libbrush/CMakeLists.txt
+++ b/krita/libbrush/CMakeLists.txt
@@ -11,7 +11,7 @@ set(kritalibbrush_LIB_SRCS
     kis_abr_brush.cpp
     kis_abr_brush_collection.cpp
     kis_imagepipe_brush.cpp
-    kis_imagepipe_brush_p.cpp
+    kis_pipebrush_parasite.cpp
     kis_png_brush.cpp
     kis_svg_brush.cpp
     kis_qimage_pyramid.cpp
diff --git a/krita/libbrush/kis_brush.h b/krita/libbrush/kis_brush.h
index f80e20a..1ca7684 100644
--- a/krita/libbrush/kis_brush.h
+++ b/krita/libbrush/kis_brush.h
@@ -45,8 +45,7 @@ enum enumBrushType {
     MASK,
     IMAGE,
     PIPE_MASK,
-    PIPE_IMAGE,
-    AIRBRUSH
+    PIPE_IMAGE
 };
 
 static const qreal DEFAULT_SOFTNESS_FACTOR = 1.0;
diff --git a/krita/libbrush/kis_brushes_pipe.h b/krita/libbrush/kis_brushes_pipe.h
index e8b8e50..97e2031 100644
--- a/krita/libbrush/kis_brushes_pipe.h
+++ b/krita/libbrush/kis_brushes_pipe.h
@@ -127,7 +127,7 @@ public:
         return device;
     }
 
-    QVector<BrushType*> testingGetBrushes() {
+    QVector<BrushType*> brushes() {
         return m_brushes;
     }
 
diff --git a/krita/libbrush/kis_imagepipe_brush.cpp b/krita/libbrush/kis_imagepipe_brush.cpp
index fdd6dfd..f6f731e 100644
--- a/krita/libbrush/kis_imagepipe_brush.cpp
+++ b/krita/libbrush/kis_imagepipe_brush.cpp
@@ -17,7 +17,7 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 #include "kis_imagepipe_brush.h"
-#include "kis_imagepipe_brush_p.h"
+#include "kis_pipebrush_parasite.h"
 #include "kis_brushes_pipe.h"
 
 
@@ -206,11 +206,8 @@ KisImagePipeBrush::KisImagePipeBrush(const QString& name, int w, int h,
 
     parasite.setBrushesCount();
 
-    m_d->brushesPipe.setParasite(parasite);
-    for (int i = 0; i < devices.at(0).count(); i++) {
-        m_d->brushesPipe.addBrush(new KisGbrBrush(devices.at(0).at(i), 0, 0, w, h));
-    }
-
+    setParasite(parasite);
+    setDevices(devices, w, h);
     setBrushTipImage(m_d->brushesPipe.firstBrush()->brushTipImage());
 }
 
@@ -363,6 +360,11 @@ void KisImagePipeBrush::generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceS
     m_d->brushesPipe.generateMaskAndApplyMaskOrCreateDab(dst, coloringInformation, scaleX, scaleY, angle, info, subPixelX, subPixelY, softnessFactor);
 }
 
+QVector<KisGbrBrush *> KisImagePipeBrush::brushes() const
+{
+    return m_d->brushesPipe.brushes();
+}
+
 KisFixedPaintDeviceSP KisImagePipeBrush::paintDevice(const KoColorSpace * colorSpace, double scale, double angle, const KisPaintInformation& info, double subPixelX, double subPixelY) const
 {
     return m_d->brushesPipe.paintDevice(colorSpace, scale, angle, info, subPixelX, subPixelY);
@@ -450,7 +452,7 @@ void KisImagePipeBrush::setBrushType(enumBrushType type)
 {
     Q_UNUSED(type);
     qFatal("FATAL: protected member setBrushType has no meaning for KisImagePipeBrush");
-    // brushType() is a finction of hasColor() and useColorAsMask()
+    // brushType() is a function of hasColor() and useColorAsMask()
 }
 
 void KisImagePipeBrush::setHasColor(bool hasColor)
@@ -465,12 +467,25 @@ KisGbrBrush* KisImagePipeBrush::testingGetCurrentBrush(const KisPaintInformation
     return m_d->brushesPipe.currentBrush(info);
 }
 
-QVector<KisGbrBrush*> KisImagePipeBrush::testingGetBrushes() const
-{
-    return m_d->brushesPipe.testingGetBrushes();
-}
 
 void KisImagePipeBrush::testingSelectNextBrush(const KisPaintInformation& info) const
 {
     return m_d->brushesPipe.testingSelectNextBrush(info);
 }
+
+const KisPipeBrushParasite& KisImagePipeBrush::parasite() const {
+    return m_d->brushesPipe.parasite();
+}
+
+void KisImagePipeBrush::setParasite(const KisPipeBrushParasite &parasite)
+{
+    m_d->brushesPipe.setParasite(parasite);
+}
+
+void KisImagePipeBrush::setDevices(QVector<QVector<KisPaintDevice *> > devices, int w, int h)
+{
+
+    for (int i = 0; i < devices.at(0).count(); i++) {
+        m_d->brushesPipe.addBrush(new KisGbrBrush(devices.at(0).at(i), 0, 0, w, h));
+    }
+}
diff --git a/krita/libbrush/kis_imagepipe_brush.h b/krita/libbrush/kis_imagepipe_brush.h
index b85aa4e..7516c70 100644
--- a/krita/libbrush/kis_imagepipe_brush.h
+++ b/krita/libbrush/kis_imagepipe_brush.h
@@ -27,6 +27,7 @@
 #include "kis_gbr_brush.h"
 #include "kis_global.h"
 
+class KisPipeBrushParasite;
 
 /**
  * Velocity won't be supported, atm Tilt isn't either,
@@ -105,6 +106,13 @@ public:
             double subPixelX = 0, double subPixelY = 0, qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR) const;
 
 
+    QVector<KisGbrBrush*> brushes() const;
+
+
+    const KisPipeBrushParasite &parasite() const;
+
+    void setParasite(const KisPipeBrushParasite& parasite);
+    void setDevices(QVector< QVector<KisPaintDevice*> > devices, int w, int h);
 
 protected:
     void setBrushType(enumBrushType type);
@@ -119,11 +127,10 @@ private:
     friend class KisImagePipeBrushTest;
 
     KisGbrBrush* testingGetCurrentBrush(const KisPaintInformation& info) const;
-    QVector<KisGbrBrush*> testingGetBrushes() const;
     void testingSelectNextBrush(const KisPaintInformation& info) const;
 
     bool initFromData(const QByteArray &data);
-    void sanitize(); // Force some default values in case the ones read in don't make sense
+
 private:
     struct Private;
     Private * const m_d;
diff --git a/krita/libbrush/kis_imagepipe_brush_p.cpp b/krita/libbrush/kis_pipebrush_parasite.cpp
similarity index 97%
rename from krita/libbrush/kis_imagepipe_brush_p.cpp
rename to krita/libbrush/kis_pipebrush_parasite.cpp
index 78f1169..1ff78d1 100644
--- a/krita/libbrush/kis_imagepipe_brush_p.cpp
+++ b/krita/libbrush/kis_pipebrush_parasite.cpp
@@ -16,7 +16,7 @@
  *  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_imagepipe_brush_p.h"
+#include "kis_pipebrush_parasite.h"
 
 KisPipeBrushParasite::KisPipeBrushParasite(const QString& source)
 {
@@ -169,3 +169,9 @@ bool KisPipeBrushParasite::saveToDevice(QIODevice* dev) const
 
     return true;
 }
+
+bool loadFromDevice(QIODevice *dev)
+{
+    // XXX: implement...
+    return true;;
+}
diff --git a/krita/libbrush/kis_imagepipe_brush_p.h b/krita/libbrush/kis_pipebrush_parasite.h
similarity index 97%
rename from krita/libbrush/kis_imagepipe_brush_p.h
rename to krita/libbrush/kis_pipebrush_parasite.h
index 7f78f20..a3bffb3 100644
--- a/krita/libbrush/kis_imagepipe_brush_p.h
+++ b/krita/libbrush/kis_pipebrush_parasite.h
@@ -40,6 +40,7 @@
 #include "kis_paint_device.h"
 #include "kis_layer.h"
 
+#include "kritabrush_export.h"
 
 /**
  * The parasite info that gets loaded from the terribly documented gimp pipe brush parasite.
@@ -62,7 +63,7 @@
  * until we have reached dimension dim. Or at least, that is how it looks like, we'll know
  * for sure when we can test it better with >1 dim brushes and Angular selectionMode.
  **/
-class KisPipeBrushParasite
+class BRUSH_EXPORT KisPipeBrushParasite
 {
 public:
     /// Set some default values
@@ -86,7 +87,7 @@ public:
      * Saves a GIMP-compatible representation of this parasite to the device. Also writes the
      * number of brushes (== ncells) (no trailing '\n') */
     bool saveToDevice(QIODevice* dev) const;
-
+    bool loadFromDevice(QIODevice *dev);
 
     enum Placement { DefaultPlacement, ConstantPlacement, RandomPlacement };
 
diff --git a/krita/libbrush/tests/kis_imagepipe_brush_test.cpp b/krita/libbrush/tests/kis_imagepipe_brush_test.cpp
index 5c403d2..96b986b 100644
--- a/krita/libbrush/tests/kis_imagepipe_brush_test.cpp
+++ b/krita/libbrush/tests/kis_imagepipe_brush_test.cpp
@@ -33,11 +33,11 @@
 #include <kis_painter.h>
 
 #define COMPARE_ALL(brush, method)                                      \
-    Q_FOREACH (KisGbrBrush *child, brush->testingGetBrushes()) {           \
+    Q_FOREACH (KisGbrBrush *child, brush->brushes()) {           \
         if(brush->method() != child->method()) {                        \
             dbgKrita << "Failing method:" << #method                    \
                      << "brush index:"                                  \
-                     << brush->testingGetBrushes().indexOf(child);      \
+                     << brush->brushes().indexOf(child);      \
             QCOMPARE(brush->method(), child->method());                 \
         }                                                               \
     }
@@ -45,7 +45,7 @@
 inline void KisImagePipeBrushTest::checkConsistency(KisImagePipeBrush *brush)
 {
     qreal scale = 0.5; Q_UNUSED(scale);
-    KisGbrBrush *firstBrush = brush->testingGetBrushes().first();
+    KisGbrBrush *firstBrush = brush->brushes().first();
 
     /**
      * This set of values is supposed to be constant, so
@@ -216,7 +216,7 @@ void KisImagePipeBrushTest::testColoredDabWash()
     KisPainter painter(layer);
     painter.setCompositeOp(COMPOSITE_ALPHA_DARKEN);
 
-    const QVector<KisGbrBrush*> gbrs = brush->testingGetBrushes();
+    const QVector<KisGbrBrush*> gbrs = brush->brushes();
 
     KisFixedPaintDeviceSP dab = gbrs.at(0)->paintDevice(cs, 2.0, 0.0, info);
     painter.bltFixed(0, 0, dab, 0, 0, dab->bounds().width(), dab->bounds().height());
diff --git a/krita/plugins/extensions/dockers/palettedocker/CMakeLists.txt b/krita/plugins/extensions/dockers/palettedocker/CMakeLists.txt
index f20ee99..efc0019 100644
--- a/krita/plugins/extensions/dockers/palettedocker/CMakeLists.txt
+++ b/krita/plugins/extensions/dockers/palettedocker/CMakeLists.txt
@@ -1,9 +1,4 @@
-set(KRITA_PALETTEDOCKER_SOURCES 
-    colorsetchooser.cpp 
-    palettemodel.cpp 
-    palettedocker.cpp 
-    palettedocker_dock.cpp 
-)
+set(KRITA_PALETTEDOCKER_SOURCES palettedocker.cpp palettedocker_dock.cpp )
 
 ki18n_wrap_ui(KRITA_PALETTEDOCKER_SOURCES
     wdgpalettedock.ui
diff --git a/krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.cpp b/krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.cpp
index 321d4ab..be3ba79 100644
--- a/krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.cpp
+++ b/krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.cpp
@@ -43,8 +43,8 @@
 #include <kis_display_color_converter.h>
 #include <kis_canvas2.h>
 
-#include "palettemodel.h"
-#include "colorsetchooser.h"
+#include "KisPaletteModel.h"
+#include "KisColorsetChooser.h"
 #include "ui_wdgpalettedock.h"
 
 /// The resource item delegate for rendering the resource preview
@@ -137,7 +137,7 @@ PaletteDockerDock::PaletteDockerDock( )
     connect(m_wdgPaletteDock->bnAddDialog, SIGNAL(clicked(bool)), this, SLOT(addColor()));
     connect(m_wdgPaletteDock->bnRemove, SIGNAL(clicked(bool)), this, SLOT(removeColor()));
 
-    m_model = new PaletteModel(this);
+    m_model = new KisPaletteModel(this);
     m_wdgPaletteDock->paletteView->setModel(m_model);
     m_wdgPaletteDock->paletteView->setShowGrid(false);
     m_wdgPaletteDock->paletteView->horizontalHeader()->setVisible(false);
@@ -159,7 +159,7 @@ PaletteDockerDock::PaletteDockerDock( )
     m_serverAdapter->connectToResourceServer();
     rServer->addObserver(this);
 
-    m_colorSetChooser = new ColorSetChooser(this);
+    m_colorSetChooser = new KisColorsetChooser(this);
     connect(m_colorSetChooser, SIGNAL(paletteSelected(KoColorSet*)), this, SLOT(setColorSet(KoColorSet*)));
 
     m_wdgPaletteDock->bnColorSets->setIcon(KisIconUtils::loadIcon("hi16-palette_library"));
diff --git a/krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.h b/krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.h
index 10a07bb..c0f8ebb 100644
--- a/krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.h
+++ b/krita/plugins/extensions/dockers/palettedocker/palettedocker_dock.h
@@ -33,8 +33,8 @@ class KisViewManager;
 class KisCanvasResourceProvider;
 class KisCanvas2;
 class KisWorkspaceResource;
-class ColorSetChooser;
-class PaletteModel;
+class KisColorsetChooser;
+class KisPaletteModel;
 class Ui_WdgPaletteDock;
 
 
@@ -72,10 +72,10 @@ private Q_SLOTS:
 
 private:    
     Ui_WdgPaletteDock* m_wdgPaletteDock;
-    PaletteModel *m_model;
+    KisPaletteModel *m_model;
     QSharedPointer<KoAbstractResourceServerAdapter> m_serverAdapter;
     KoColorSet *m_currentColorSet;
-    ColorSetChooser *m_colorSetChooser;
+    KisColorsetChooser *m_colorSetChooser;
     KisCanvasResourceProvider *m_resourceProvider;
     KisCanvas2 *m_canvas;
 };
diff --git a/krita/plugins/formats/CMakeLists.txt b/krita/plugins/formats/CMakeLists.txt
index 9592728..29f9dc8 100644
--- a/krita/plugins/formats/CMakeLists.txt
+++ b/krita/plugins/formats/CMakeLists.txt
@@ -41,3 +41,4 @@ add_subdirectory(odg)
 add_subdirectory(qml)
 add_subdirectory(tga)
 add_subdirectory(heightmap)
+add_subdirectory(brush)
diff --git a/krita/plugins/formats/brush/CMakeLists.txt b/krita/plugins/formats/brush/CMakeLists.txt
new file mode 100644
index 0000000..616eb6f
--- /dev/null
+++ b/krita/plugins/formats/brush/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(kritabrushexport_PART_SRCS
+    kis_brush_export.cpp
+    KisAnimatedBrushAnnotation.cpp
+    )
+
+ki18n_wrap_ui(kritabrushexport_PART_SRCS  wdg_export_gih.ui)
+
+add_library(kritabrushexport MODULE ${kritabrushexport_PART_SRCS})
+
+target_link_libraries(kritabrushexport kritalibbrush kritalibpaintop kritaui)
+
+install(TARGETS kritabrushexport  DESTINATION ${CALLIGRA_PLUGIN_INSTALL_DIR})
+
+set(kritabrushimport_PART_SRCS
+    kis_brush_import.cpp
+    KisAnimatedBrushAnnotation.cpp
+    )
+
+ki18n_wrap_ui(kritabrushimport_PART_SRCS )
+
+add_library(kritabrushimport MODULE ${kritabrushimport_PART_SRCS})
+
+target_link_libraries(kritabrushimport kritalibbrush kritaui)
+
+install(TARGETS kritabrushimport  DESTINATION ${CALLIGRA_PLUGIN_INSTALL_DIR})
+install( PROGRAMS  krita_brush.desktop  DESTINATION ${XDG_APPS_INSTALL_DIR})
diff --git a/krita/plugins/formats/brush/KisAnimatedBrushAnnotation.cpp b/krita/plugins/formats/brush/KisAnimatedBrushAnnotation.cpp
new file mode 100644
index 0000000..0f8ae80
--- /dev/null
+++ b/krita/plugins/formats/brush/KisAnimatedBrushAnnotation.cpp
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2015 Boudewijn Rempt <boud at valdyas.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 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 "KisAnimatedBrushAnnotation.h"
+
+#include <QByteArray>
+#include <QBuffer>
+
+#include <kis_pipebrush_parasite.h>
+
+KisAnimatedBrushAnnotation::KisAnimatedBrushAnnotation(const KisPipeBrushParasite &parasite)
+    : KisAnnotation("ImagePipe Parasite",
+                    i18n("Brush selection information for animated brushes"),
+                    QByteArray())
+{
+    QBuffer buf(&m_annotation);
+    buf.open(QBuffer::WriteOnly);
+    parasite.saveToDevice(&buf);
+    buf.close();
+}
diff --git a/krita/plugins/formats/brush/KisAnimatedBrushAnnotation.h b/krita/plugins/formats/brush/KisAnimatedBrushAnnotation.h
new file mode 100644
index 0000000..64fa5cd
--- /dev/null
+++ b/krita/plugins/formats/brush/KisAnimatedBrushAnnotation.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2015 Boudewijn Rempt <boud at valdyas.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 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 KISANIMATEDBRUSHANNOTATION_H
+#define KISANIMATEDBRUSHANNOTATION_H
+
+#include <kis_annotation.h>
+
+class KisPipeBrushParasite;
+
+class KisAnimatedBrushAnnotation : public KisAnnotation
+{
+public:
+    KisAnimatedBrushAnnotation(const KisPipeBrushParasite &parasite);
+};
+
+#endif // KISANIMATEDBRUSHANNOTATION_H
diff --git a/krita/plugins/formats/brush/kis_brush_export.cpp b/krita/plugins/formats/brush/kis_brush_export.cpp
new file mode 100644
index 0000000..6cacbda
--- /dev/null
+++ b/krita/plugins/formats/brush/kis_brush_export.cpp
@@ -0,0 +1,214 @@
+/*
+ *  Copyright (c) 2016 Boudewijn Rempt <boud at valdyas.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 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_brush_export.h"
+
+#include <QCheckBox>
+#include <QSlider>
+#include <QBuffer>
+
+#include <KoProperties.h>
+#include <KoDialog.h>
+#include <kpluginfactory.h>
+#include <QUrl>
+
+#include <KisFilterChain.h>
+
+#include <kis_paint_device.h>
+#include <KisDocument.h>
+#include <kis_image.h>
+#include <kis_paint_layer.h>
+#include <kis_spacing_selection_widget.h>
+#include <kis_gbr_brush.h>
+#include <kis_imagepipe_brush.h>
+#include <kis_pipebrush_parasite.h>
+#include <KisAnimatedBrushAnnotation.h>
+#include <KisImportExportManager.h>
+
+#include <ui_wdg_export_gih.h>
+
+struct KisBrushExportOptions {
+    qreal spacing;
+    bool mask;
+    int brushStyle;
+    int selectionMode;
+    QString name;
+};
+
+
+K_PLUGIN_FACTORY_WITH_JSON(KisBrushExportFactory, "krita_brush_export.json", registerPlugin<KisBrushExport>();)
+
+KisBrushExport::KisBrushExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent)
+{
+}
+
+KisBrushExport::~KisBrushExport()
+{
+}
+
+KisImportExportFilter::ConversionStatus KisBrushExport::convert(const QByteArray& from, const QByteArray& to)
+{
+    KisDocument *input = m_chain->inputDocument();
+    QString filename = m_chain->outputFile();
+
+    if (!input)
+        return KisImportExportFilter::NoDocumentCreated;
+
+    if (filename.isEmpty()) return KisImportExportFilter::FileNotFound;
+
+    if (from != "application/x-krita")
+        return KisImportExportFilter::NotImplemented;
+
+    KisAnnotationSP annotation = input->image()->annotation("ImagePipe Parasite");
+    KisPipeBrushParasite parasite;
+    if (annotation) {
+        QBuffer buf(const_cast<QByteArray*>(&annotation->annotation()));
+        buf.open(QBuffer::ReadOnly);
+        //parasite.loadFromDevice(&buf);
+        buf.close();
+    }
+
+    KisBrushExportOptions exportOptions;
+    exportOptions.spacing = 1.0;
+    exportOptions.name = input->image()->objectName();
+    exportOptions.mask = true;
+    exportOptions.selectionMode = 0;
+    exportOptions.brushStyle = 0;
+
+
+    if (input->image()->dynamicPropertyNames().contains("brushspacing")) {
+        exportOptions.spacing = input->image()->property("brushspacing").toFloat();
+    }
+    KisGbrBrush *brush;
+
+    if (!m_chain->manager()->getBatchMode()) {
+
+        KoDialog* dlgBrushExportOptions = new KoDialog(0);
+        dlgBrushExportOptions->setWindowTitle(i18n("Brush Tip Export Options"));
+        dlgBrushExportOptions->setButtons(KoDialog::Ok | KoDialog::Cancel);
+
+        Ui::WdgExportGih wdgUi;
+        QWidget* wdg = new QWidget(dlgBrushExportOptions);
+        wdgUi.setupUi(wdg);
+        wdgUi.spacingWidget->setSpacing(false, exportOptions.spacing);
+        wdgUi.nameLineEdit->setText(exportOptions.name);
+        dlgBrushExportOptions->setMainWidget(wdg);
+
+
+        if (to == "image/x-gimp-brush") {
+            brush = new KisGbrBrush(filename);
+            wdgUi.groupBox->setVisible(false);
+        }
+        else if (to == "image/x-gimp-brush-animated") {
+            brush = new KisImagePipeBrush(filename);
+            wdgUi.groupBox->setVisible(true);
+        }
+        else {
+            delete dlgBrushExportOptions;
+            return KisImportExportFilter::BadMimeType;
+        }
+
+        if (dlgBrushExportOptions->exec() == QDialog::Rejected) {
+            delete dlgBrushExportOptions;
+            return KisImportExportFilter::UserCancelled;
+        }
+        else {
+            exportOptions.spacing = wdgUi.spacingWidget->spacing();
+            exportOptions.name = wdgUi.brushNameLbl->text();
+            exportOptions.mask = wdgUi.colorAsMask->isChecked();
+            exportOptions.brushStyle = wdgUi.brushStyle->currentIndex();
+            exportOptions.selectionMode = wdgUi.cmbSelectionMode->currentIndex();
+            delete dlgBrushExportOptions;
+        }
+    }
+    else {
+        qApp->processEvents(); // For vector layers to be updated
+    }
+
+
+    input->image()->waitForDone();
+    QRect rc = input->image()->bounds();
+    input->image()->refreshGraph();
+    input->image()->lock();
+
+    brush->setName(exportOptions.name);
+    brush->setSpacing(exportOptions.spacing);
+    brush->setUseColorAsMask(exportOptions.mask);
+
+    int w = input->image()->width();
+    int h = input->image()->height();
+
+    KisImagePipeBrush *pipeBrush = dynamic_cast<KisImagePipeBrush*>(brush);
+    if (pipeBrush) {
+        // Create parasite. XXX: share with KisCustomBrushWidget
+        QVector< QVector<KisPaintDevice*> > devices;
+        devices.push_back(QVector<KisPaintDevice*>());
+
+        KoProperties properties;
+        properties.setProperty("visible", true);
+        QList<KisNodeSP> layers = input->image()->root()->childNodes(QStringList("KisLayer"), properties);
+        KisNodeSP node;
+        Q_FOREACH (KisNodeSP node, layers) {
+            devices[0].push_back(node->projection().data());
+        }
+
+
+        QVector<KisParasite::SelectionMode > modes;
+        switch (exportOptions.selectionMode) {
+        case 0: modes.push_back(KisParasite::Constant); break;
+        case 1: modes.push_back(KisParasite::Random); break;
+        case 2: modes.push_back(KisParasite::Incremental); break;
+        case 3: modes.push_back(KisParasite::Pressure); break;
+        case 4: modes.push_back(KisParasite::Angular); break;
+        default: modes.push_back(KisParasite::Incremental);
+        }
+
+        KisPipeBrushParasite parasite;
+
+        // XXX: share code with KisImagePipeBrush, when we figure out how to support more gih features
+        parasite.dim = devices.count();
+        // XXX Change for multidim! :
+        parasite.ncells = devices.at(0).count();
+        parasite.rank[0] = parasite.ncells; // ### This can mask some bugs, be careful here in the future
+        parasite.selection[0] = modes.at(0);
+        // XXX needsmovement!
+        parasite.setBrushesCount();
+        pipeBrush->setParasite(parasite);
+        pipeBrush->setDevices(devices, w, h);
+    }
+    else {
+        QImage image = input->image()->projection()->convertToQImage(0, 0, 0, rc.width(), rc.height(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
+        brush->setImage(image);
+    }
+
+    brush->setWidth(w);
+    brush->setHeight(h);
+
+    input->image()->unlock();
+
+    QFile f(filename);
+    f.open(QIODevice::WriteOnly);
+    brush->saveToDevice(&f);
+    f.close();
+
+    return KisImportExportFilter::OK;
+}
+
+#include "kis_brush_export.moc"
+
diff --git a/krita/plugins/formats/brush/kis_brush_export.h b/krita/plugins/formats/brush/kis_brush_export.h
new file mode 100644
index 0000000..2693387
--- /dev/null
+++ b/krita/plugins/formats/brush/kis_brush_export.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (c) 2016 Boudewijn Rempt <boud at valdyas.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 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 _KIS_Brush_EXPORT_H_
+#define _KIS_Brush_EXPORT_H_
+
+#include <QVariant>
+
+#include <KisImportExportFilter.h>
+
+class KisBrushExport : public KisImportExportFilter
+{
+    Q_OBJECT
+public:
+    KisBrushExport(QObject *parent, const QVariantList &);
+    virtual ~KisBrushExport();
+public:
+    virtual KisImportExportFilter::ConversionStatus convert(const QByteArray& from, const QByteArray& to);
+};
+
+#endif
diff --git a/krita/plugins/formats/brush/kis_brush_import.cpp b/krita/plugins/formats/brush/kis_brush_import.cpp
new file mode 100644
index 0000000..f08054f
--- /dev/null
+++ b/krita/plugins/formats/brush/kis_brush_import.cpp
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (c) 2016 Boudewijn Rempt <boud at valdyas.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 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_brush_import.h"
+
+#include <QCheckBox>
+#include <QBuffer>
+#include <QSlider>
+#include <QApplication>
+
+#include <kpluginfactory.h>
+#include <QUrl>
+
+#include <KoColorSpace.h>
+#include <KoColorSpaceRegistry.h>
+#include <KoColorModelStandardIds.h>
+
+#include <KisFilterChain.h>
+#include <KisDocument.h>
+
+#include <kis_transaction.h>
+#include <kis_paint_device.h>
+#include <kis_image.h>
+#include <kis_paint_layer.h>
+#include <kis_node.h>
+#include <kis_group_layer.h>
+
+#include <kis_gbr_brush.h>
+#include <kis_imagepipe_brush.h>
+#include <KisAnimatedBrushAnnotation.h>
+
+K_PLUGIN_FACTORY_WITH_JSON(KisBrushImportFactory, "krita_brush_import.json", registerPlugin<KisBrushImport>();)
+
+KisBrushImport::KisBrushImport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent)
+{
+}
+
+KisBrushImport::~KisBrushImport()
+{
+}
+
+
+KisImportExportFilter::ConversionStatus KisBrushImport::convert(const QByteArray& from, const QByteArray& to)
+{
+    if (to != "application/x-krita")
+        return KisImportExportFilter::BadMimeType;
+
+    QString filename = m_chain->inputFile();
+
+    if (!filename.isEmpty()) {
+
+        if (!QFile(filename).exists()) {
+            return KisImportExportFilter::FileNotFound;
+        }
+
+
+        KisBrush *brush;
+
+        if (from == "image/x-gimp-brush") {
+            brush = new KisGbrBrush(filename);
+        }
+        else if (from == "image/x-gimp-brush-animated") {
+            brush = new KisImagePipeBrush(filename);
+        }
+        else {
+            return KisImportExportFilter::BadMimeType;
+        }
+
+
+        if (!brush->load()) {
+            delete brush;
+            return KisImportExportFilter::InvalidFormat;
+        }
+
+        if (!brush->valid()) {
+            delete brush;
+            return KisImportExportFilter::InvalidFormat;
+        }
+
+        KisDocument * doc = m_chain->outputDocument();
+
+        if (!doc) {
+            delete brush;
+            return KisImportExportFilter::NoDocumentCreated;
+        }
+
+        doc->prepareForImport();
+
+        const KoColorSpace *colorSpace = 0;
+        if (brush->hasColor()) {
+            colorSpace = KoColorSpaceRegistry::instance()->rgb8();
+        }
+        else {
+            colorSpace = KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer8BitsColorDepthID.id(), "");
+        }
+
+        KisImageWSP image = new KisImage(doc->createUndoStore(), brush->width(), brush->height(), colorSpace, brush->name());
+        image->setProperty("brushspacing", brush->spacing());
+
+        KisImagePipeBrush *pipeBrush = dynamic_cast<KisImagePipeBrush*>(brush);
+        if (pipeBrush) {
+            QVector<KisGbrBrush*> brushes = pipeBrush->brushes();
+            for(int i = brushes.size(); i > 0; i--) {
+                KisGbrBrush *subbrush = brushes.at(i - 1);
+                const KoColorSpace *subColorSpace = 0;
+                if (brush->hasColor()) {
+                    subColorSpace = KoColorSpaceRegistry::instance()->rgb8();
+                }
+                else {
+                    subColorSpace = KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer8BitsColorDepthID.id(), "");
+                }
+                KisPaintLayerSP layer = new KisPaintLayer(image, image->nextLayerName(), 255, subColorSpace);
+                layer->paintDevice()->convertFromQImage(subbrush->brushTipImage(), 0, 0, 0);
+                image->addNode(layer, image->rootLayer());
+            }
+            KisAnnotationSP ann = new KisAnimatedBrushAnnotation(pipeBrush->parasite());
+            image->addAnnotation(ann);
+        }
+        else {
+            KisPaintLayerSP layer = new KisPaintLayer(image, image->nextLayerName(), 255, colorSpace);
+            layer->paintDevice()->convertFromQImage(brush->brushTipImage(), 0, 0, 0);
+            image->addNode(layer, image->rootLayer(), 0);
+        }
+
+        doc->setCurrentImage(image);
+        delete brush;
+        return KisImportExportFilter::OK;
+    }
+
+    return KisImportExportFilter::StorageCreationError;
+
+}
+#include "kis_brush_import.moc"
diff --git a/krita/plugins/formats/brush/kis_brush_import.h b/krita/plugins/formats/brush/kis_brush_import.h
new file mode 100644
index 0000000..d6b85ec
--- /dev/null
+++ b/krita/plugins/formats/brush/kis_brush_import.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (c) 2016 Boudewijn Rempt <boud at valdyas.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 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 _KIS_Brush_IMPORT_H_
+#define _KIS_Brush_IMPORT_H_
+
+#include <QVariant>
+
+#include <KisImportExportFilter.h>
+
+class KisBrushImport : public KisImportExportFilter
+{
+    Q_OBJECT
+public:
+    KisBrushImport(QObject *parent, const QVariantList &);
+    virtual ~KisBrushImport();
+public:
+    virtual KisImportExportFilter::ConversionStatus convert(const QByteArray& from, const QByteArray& to);
+};
+
+#endif
diff --git a/krita/plugins/formats/brush/krita_brush.desktop b/krita/plugins/formats/brush/krita_brush.desktop
new file mode 100644
index 0000000..0718313
--- /dev/null
+++ b/krita/plugins/formats/brush/krita_brush.desktop
@@ -0,0 +1,72 @@
+[Desktop Entry]
+Name=Krita
+Name[af]=Krita
+Name[bg]=Krita
+Name[br]=Krita
+Name[bs]=Krita
+Name[ca]=Krita
+Name[ca at valencia]=Krita
+Name[cy]=Krita
+Name[da]=Krita
+Name[de]=Krita
+Name[el]=Krita
+Name[en_GB]=Krita
+Name[eo]=Krita
+Name[es]=Krita
+Name[et]=Krita
+Name[eu]=Krita
+Name[fi]=Krita
+Name[fr]=Krita
+Name[fy]=Krita
+Name[ga]=Krita
+Name[gl]=Krita
+Name[he]=Krita
+Name[hi]=केरिता
+Name[hne]=केरिता
+Name[hr]=Krita
+Name[hu]=Krita
+Name[ia]=Krita
+Name[is]=Krita
+Name[it]=Krita
+Name[kk]=Krita
+Name[ko]=Krita
+Name[lt]=Krita
+Name[lv]=Krita
+Name[mr]=क्रिटा
+Name[ms]=Krita
+Name[nb]=Krita
+Name[nds]=Krita
+Name[ne]=क्रिता
+Name[nl]=Krita
+Name[pl]=Krita
+Name[pt]=Krita
+Name[pt_BR]=Krita
+Name[ro]=Krita
+Name[ru]=Krita
+Name[se]=Krita
+Name[sk]=Krita
+Name[sl]=Krita
+Name[sv]=Krita
+Name[ta]=கிரிட்டா
+Name[tg]=Krita
+Name[tr]=Krita
+Name[ug]=Krita
+Name[uk]=Krita
+Name[uz]=Krita
+Name[uz at cyrillic]=Krita
+Name[wa]=Krita
+Name[xh]=Krita
+Name[x-test]=xxKritaxx
+Name[zh_CN]=Krita
+Name[zh_TW]=繪圖_Krita
+Exec=krita %u
+MimeType=image/x-tga;
+Type=Application
+Icon=calligrakrita
+Categories=Qt;KDE;Office;Graphics;
+StartupNotify=true
+X-KDE-ServiceTypes=Calligra/Application
+X-Calligra-DefaultMimeTypes=image/x-gimp-brush,image/x-gimp-brush-animated
+X-DBUS-StartupType=Multi
+X-DBUS-ServiceName=org.krita.krita
+NoDisplay=true
diff --git a/krita/plugins/formats/brush/krita_brush_export.json b/krita/plugins/formats/brush/krita_brush_export.json
new file mode 100644
index 0000000..3cca14e
--- /dev/null
+++ b/krita/plugins/formats/brush/krita_brush_export.json
@@ -0,0 +1,11 @@
+{
+    "Id": "Krita Brush Export Filter",
+    "X-KDE-ServiceTypes": [
+        "Krita/FileFilter"
+    ],
+    "NoDisplay": "true",
+    "X-KDE-Export": "image/x-gimp-brush,image/x-gimp-brush-animated",
+    "X-KDE-Import": "application/x-krita",
+    "X-KDE-Weight": "1",
+    "X-KDE-Extensions" : "gih,gbr"
+}
diff --git a/krita/plugins/formats/brush/krita_brush_import.json b/krita/plugins/formats/brush/krita_brush_import.json
new file mode 100644
index 0000000..05ac641
--- /dev/null
+++ b/krita/plugins/formats/brush/krita_brush_import.json
@@ -0,0 +1,11 @@
+{
+    "Id": "Krita Brush Import Filter",
+    "X-KDE-ServiceTypes": [
+        "Krita/FileFilter"
+    ],
+    "NoDisplay": "true",
+    "X-KDE-Export": "application/x-krita",
+    "X-KDE-Import": "image/x-gimp-brush,image/x-gimp-brush-animated",
+    "X-KDE-Weight": "1",
+    "X-KDE-Extensions" : "gih,gbr"
+}
diff --git a/krita/plugins/formats/brush/wdg_export_gih.ui b/krita/plugins/formats/brush/wdg_export_gih.ui
new file mode 100644
index 0000000..bf8de6b
--- /dev/null
+++ b/krita/plugins/formats/brush/wdg_export_gih.ui
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WdgExportGih</class>
+ <widget class="QWidget" name="WdgExportGih">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>468</width>
+    <height>318</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout_3">
+   <item row="0" column="0">
+    <layout class="QVBoxLayout" name="verticalLayout">
+     <item>
+      <layout class="QGridLayout" name="gridLayout">
+       <item row="0" column="1">
+        <widget class="QLineEdit" name="nameLineEdit"/>
+       </item>
+       <item row="1" column="1">
+        <widget class="KisSpacingSelectionWidget" name="spacingWidget" native="true"/>
+       </item>
+       <item row="1" column="0">
+        <widget class="QLabel" name="spacingLbl">
+         <property name="text">
+          <string>Spacing:</string>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="0">
+        <widget class="QLabel" name="brushNameLbl">
+         <property name="text">
+          <string>Name:</string>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+         </property>
+        </widget>
+       </item>
+       <item row="2" column="1">
+        <widget class="QCheckBox" name="colorAsMask">
+         <property name="text">
+          <string>Create mask from color</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="groupBox">
+       <property name="minimumSize">
+        <size>
+         <width>0</width>
+         <height>110</height>
+        </size>
+       </property>
+       <property name="title">
+        <string>Brush Style</string>
+       </property>
+       <property name="checkable">
+        <bool>false</bool>
+       </property>
+       <layout class="QGridLayout" name="gridLayout_4">
+        <item row="0" column="0">
+         <layout class="QGridLayout" name="gridLayout_2">
+          <property name="spacing">
+           <number>3</number>
+          </property>
+          <item row="0" column="0">
+           <widget class="QLabel" name="textLabel2">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>Style:</string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+            </property>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QComboBox" name="brushStyle">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <item>
+             <property name="text">
+              <string>Regular</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Animated</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+          <item row="1" column="0">
+           <widget class="QLabel" name="textLabel3">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string>Selection mode:</string>
+            </property>
+            <property name="alignment">
+             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+            </property>
+           </widget>
+          </item>
+          <item row="1" column="1">
+           <widget class="QComboBox" name="cmbSelectionMode">
+            <property name="enabled">
+             <bool>false</bool>
+            </property>
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="currentIndex">
+             <number>2</number>
+            </property>
+            <item>
+             <property name="text">
+              <string>Constant</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Random</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Incremental</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Pressure</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Angular</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <layout class="QHBoxLayout" name="horizontalLayout">
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KisSpacingSelectionWidget</class>
+   <extends>QWidget</extends>
+   <header>kis_spacing_selection_widget.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/krita/plugins/paintops/libpaintop/kis_spacing_selection_widget.h b/krita/plugins/paintops/libpaintop/kis_spacing_selection_widget.h
index 7625170..8f6a68f 100644
--- a/krita/plugins/paintops/libpaintop/kis_spacing_selection_widget.h
+++ b/krita/plugins/paintops/libpaintop/kis_spacing_selection_widget.h
@@ -22,8 +22,9 @@
 #include <QWidget>
 #include <QScopedPointer>
 
+#include <kritapaintop_export.h>
 
-class KisSpacingSelectionWidget : public QWidget
+class PAINTOP_EXPORT KisSpacingSelectionWidget : public QWidget
 {
     Q_OBJECT
 public:
diff --git a/krita/plugins/tools/selectiontools/kis_selection_modifier_mapper.cc b/krita/plugins/tools/selectiontools/kis_selection_modifier_mapper.cc
index f83f33a..f314a8e 100644
--- a/krita/plugins/tools/selectiontools/kis_selection_modifier_mapper.cc
+++ b/krita/plugins/tools/selectiontools/kis_selection_modifier_mapper.cc
@@ -17,6 +17,23 @@
  * Boston, MA 02110-1301, USA.
  */
 
+/**
+ * This is a basic template to create selection tools from basic path based drawing tools.
+ * The template overrides the ability to execute alternate actions correctly.
+ * Modifier keys are overridden with the following behavior:
+ *
+ * Shift: add to selection
+ * Alt: subtract from selection
+ * Shift+Alt: intersect current selection
+ * Ctrl: replace selection
+ *
+ * Certain tools also use modifier keys to alter their behavior, e.g. forcing square proportions with the rectangle tool.
+ * The template enables the following rules for forwarding keys:
+ * 1) Any modifier keys held *when the tool is first activated* will determine the new selection method.
+ * 2) If the underlying tool *does not take modifier keys*, pressing modifier keys in the middle of a stroke will change the selection method.  This applies to the lasso tool and polygon tool.
+ * 3) If the underlying tool *takes modifier keys,* they will always be forwarded to the underlying tool, and it is not possible to change the selection method in the middle of a stroke.
+ */
+
 #include "kis_selection.h"
 #include "kis_selection_modifier_mapper.h"
 #include "kis_config_notifier.h"
diff --git a/krita/ui/CMakeLists.txt b/krita/ui/CMakeLists.txt
index ec1b1ed..3ed2390 100644
--- a/krita/ui/CMakeLists.txt
+++ b/krita/ui/CMakeLists.txt
@@ -337,6 +337,9 @@ set(kritaui_LIB_SRCS
     KisNetworkAccessManager.cpp
     KisWelcomeScreen.cpp
     KisMultiFeedRSSModel.cpp
+
+    KisPaletteModel.cpp
+    KisColorsetChooser.cpp
 )
 
 if(WIN32)
diff --git a/krita/plugins/extensions/dockers/palettedocker/colorsetchooser.cpp b/krita/ui/KisColorsetChooser.cpp
similarity index 95%
rename from krita/plugins/extensions/dockers/palettedocker/colorsetchooser.cpp
rename to krita/ui/KisColorsetChooser.cpp
index f7e0827..2b58ca4 100644
--- a/krita/plugins/extensions/dockers/palettedocker/colorsetchooser.cpp
+++ b/krita/ui/KisColorsetChooser.cpp
@@ -17,7 +17,7 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#include "colorsetchooser.h"
+#include "KisColorsetChooser.h"
 
 #include <QVBoxLayout>
 #include <QAbstractItemDelegate>
@@ -82,7 +82,7 @@ void ColorSetDelegate::paint(QPainter * painter, const QStyleOptionViewItem & op
     painter->restore();
 }
 
-ColorSetChooser::ColorSetChooser(QWidget* parent): QWidget(parent)
+KisColorsetChooser::KisColorsetChooser(QWidget* parent): QWidget(parent)
 {
     KoResourceServer<KoColorSet> * rserver = KoResourceServerProvider::instance()->paletteServer(false);
     QSharedPointer<KoAbstractResourceServerAdapter> adapter(new KoResourceServerAdapter<KoColorSet>(rserver));
@@ -115,16 +115,16 @@ ColorSetChooser::ColorSetChooser(QWidget* parent): QWidget(parent)
     layout->setColumnStretch(1, 1);
 }
 
-ColorSetChooser::~ColorSetChooser()
+KisColorsetChooser::~KisColorsetChooser()
 {
 }
 
-void ColorSetChooser::resourceSelected(KoResource* resource)
+void KisColorsetChooser::resourceSelected(KoResource* resource)
 {
     emit paletteSelected(static_cast<KoColorSet*>(resource));
 }
 
-void ColorSetChooser::slotSave()
+void KisColorsetChooser::slotSave()
 {
     KoResourceServer<KoColorSet> * rserver = KoResourceServerProvider::instance()->paletteServer();
 
diff --git a/krita/plugins/extensions/dockers/palettedocker/colorsetchooser.h b/krita/ui/KisColorsetChooser.h
similarity index 85%
rename from krita/plugins/extensions/dockers/palettedocker/colorsetchooser.h
rename to krita/ui/KisColorsetChooser.h
index 61741ac..dca0cf3 100644
--- a/krita/plugins/extensions/dockers/palettedocker/colorsetchooser.h
+++ b/krita/ui/KisColorsetChooser.h
@@ -18,8 +18,8 @@
  */
 
 
-#ifndef COLORSET_CHOOSER_H
-#define COLORSET_CHOOSER_H
+#ifndef KIS_COLORSET_CHOOSER_H
+#define KIS_COLORSET_CHOOSER_H
 
 #include <QWidget>
 
@@ -29,12 +29,15 @@ class QLineEdit;
 class KoResourceItemChooser;
 class KoResource;
 
-class ColorSetChooser : public QWidget
+#include "kritaui_export.h"
+
+
+class KRITAUI_EXPORT KisColorsetChooser : public QWidget
 {
     Q_OBJECT
 public:
-    ColorSetChooser(QWidget* parent = 0);
-    virtual ~ColorSetChooser();
+    KisColorsetChooser(QWidget* parent = 0);
+    virtual ~KisColorsetChooser();
 
 Q_SIGNALS:
     void paletteSelected(KoColorSet* colorSet);
diff --git a/krita/ui/KisDocument.cpp b/krita/ui/KisDocument.cpp
index b333a27..2e24d83 100644
--- a/krita/ui/KisDocument.cpp
+++ b/krita/ui/KisDocument.cpp
@@ -921,6 +921,7 @@ QString KisDocument::checkImageMimeTypes(const QString &mimeType, const QUrl &ur
                    << "image/png"
                    << "image/bmp" << "image/x-xpixmap" << "image/gif" << "image/x-xbitmap"
                    << "image/tiff"
+                   << "image/x-gimp-brush" << "image/x-gimp-brush-animated"
                    << "image/jp2";
 
     if (!imageMimeTypes.contains(mimeType)) return mimeType;
diff --git a/krita/plugins/extensions/dockers/palettedocker/palettemodel.cpp b/krita/ui/KisPaletteModel.cpp
similarity index 79%
rename from krita/plugins/extensions/dockers/palettedocker/palettemodel.cpp
rename to krita/ui/KisPaletteModel.cpp
index 5ea280d..32cbd5e 100644
--- a/krita/plugins/extensions/dockers/palettedocker/palettemodel.cpp
+++ b/krita/ui/KisPaletteModel.cpp
@@ -16,7 +16,7 @@
  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#include "palettemodel.h"
+#include "KisPaletteModel.h"
 
 #include <QBrush>
 
@@ -27,18 +27,18 @@
 #include <kis_layer.h>
 #include <kis_paint_layer.h>
 
-PaletteModel::PaletteModel(QObject* parent)
+KisPaletteModel::KisPaletteModel(QObject* parent)
     : QAbstractTableModel(parent),
       m_colorSet(0),
       m_displayRenderer(KoDumbColorDisplayRenderer::instance())
 {
 }
 
-PaletteModel::~PaletteModel()
+KisPaletteModel::~KisPaletteModel()
 {
 }
 
-void PaletteModel::setDisplayRenderer(KoColorDisplayRendererInterface *displayRenderer)
+void KisPaletteModel::setDisplayRenderer(KoColorDisplayRendererInterface *displayRenderer)
 {
     if (displayRenderer) {
         if (m_displayRenderer) {
@@ -52,12 +52,12 @@ void PaletteModel::setDisplayRenderer(KoColorDisplayRendererInterface *displayRe
     }
 }
 
-void PaletteModel::slotDisplayConfigurationChanged()
+void KisPaletteModel::slotDisplayConfigurationChanged()
 {
     reset();
 }
 
-QVariant PaletteModel::data(const QModelIndex& index, int role) const
+QVariant KisPaletteModel::data(const QModelIndex& index, int role) const
 {
     if (m_colorSet) {
         int i = index.row()*columnCount()+index.column();
@@ -74,7 +74,7 @@ QVariant PaletteModel::data(const QModelIndex& index, int role) const
     return QVariant();
 }
 
-int PaletteModel::rowCount(const QModelIndex& /*parent*/) const
+int KisPaletteModel::rowCount(const QModelIndex& /*parent*/) const
 {
     if (!m_colorSet) {
         return 0;
@@ -85,7 +85,7 @@ int PaletteModel::rowCount(const QModelIndex& /*parent*/) const
     return m_colorSet->nColors()/15 + 1;
 }
 
-int PaletteModel::columnCount(const QModelIndex& /*parent*/) const
+int KisPaletteModel::columnCount(const QModelIndex& /*parent*/) const
 {
     if (m_colorSet && m_colorSet->columnCount() > 0) {
         return m_colorSet->columnCount();
@@ -93,13 +93,13 @@ int PaletteModel::columnCount(const QModelIndex& /*parent*/) const
     return 15;
 }
 
-Qt::ItemFlags PaletteModel::flags(const QModelIndex& /*index*/) const
+Qt::ItemFlags KisPaletteModel::flags(const QModelIndex& /*index*/) const
 {
     Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
     return flags;
 }
 
-QModelIndex PaletteModel::index(int row, int column, const QModelIndex& parent) const
+QModelIndex KisPaletteModel::index(int row, int column, const QModelIndex& parent) const
 {
     int index = row*columnCount()+column;
     if (m_colorSet && index < m_colorSet->nColors()) {
@@ -109,7 +109,7 @@ QModelIndex PaletteModel::index(int row, int column, const QModelIndex& parent)
 }
 
 
-void PaletteModel::setColorSet(KoColorSet* colorSet)
+void KisPaletteModel::setColorSet(KoColorSet* colorSet)
 {
     m_colorSet = colorSet;
     reset();
diff --git a/krita/plugins/extensions/dockers/palettedocker/palettemodel.h b/krita/ui/KisPaletteModel.h
similarity index 88%
rename from krita/plugins/extensions/dockers/palettedocker/palettemodel.h
rename to krita/ui/KisPaletteModel.h
index e392b92..bfb4201 100644
--- a/krita/plugins/extensions/dockers/palettedocker/palettemodel.h
+++ b/krita/ui/KisPaletteModel.h
@@ -17,22 +17,23 @@
  */
 
 
-#ifndef PALETTEMODEL_H
-#define PALETTEMODEL_H
+#ifndef KIS_PALETTEMODEL_H
+#define KIS_PALETTEMODEL_H
 
 #include <QModelIndex>
 
 #include <kis_types.h>
+#include "kritaui_export.h"
 
 class KoColorSet;
 class KoColorDisplayRendererInterface;
 
-class PaletteModel : public QAbstractTableModel
+class KRITAUI_EXPORT KisPaletteModel : public QAbstractTableModel
 {
     Q_OBJECT
 public:
-    PaletteModel(QObject* parent = 0);
-    virtual ~PaletteModel();
+    KisPaletteModel(QObject* parent = 0);
+    virtual ~KisPaletteModel();
     
     virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
     virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
@@ -57,4 +58,4 @@ private:
     KoColorDisplayRendererInterface *m_displayRenderer;
 };
 
-#endif // PALETTEMODEL_H
+#endif


More information about the kimageshop mailing list