R: [calligra] /: FEATURE: Isolated Mode for Krita nodes
silvio grosso
grossosilvio at yahoo.it
Thu May 23 17:45:48 UTC 2013
Hi Dmitry,
> FEATURE: Isolated Mode for Krita nodes
Quite Interesting feature indeed :-)
My best regards,
Silvio Grosso
--- Gio 23/5/13, Dmitry Kazakov <dimula73 at gmail.com> ha scritto:
Da: Dmitry Kazakov <dimula73 at gmail.com>
Oggetto: [calligra] /: FEATURE: Isolated Mode for Krita nodes
A: kde-commits at kde.org
Cc: kimageshop at kde.org
Data: Giovedì 23 maggio 2013, 18:07
Git commit e1e85dea054bf7718a05a6e63cec83b59ffe0315 by Dmitry Kazakov.
Committed on 23/05/2013 at 18:06.
Pushed by dkazakov into branch 'master'.
FEATURE: Isolated Mode for Krita nodes
Implemented a mode, which allow a user to limit visible layers by
a subtree of a graph. It means you can look at a layer or mask or
a group in isolated environment, without other nodes seen.
To switch on the mode, you can select a context menu item in the
Layers Docker. To switch off, just select another layer or just use
the same context menu.
CCMAIL:kimageshop at kde.org
M +52 -9 krita/image/kis_image.cc
M +15 -16 krita/image/kis_image.h
M +10 -0 krita/image/kis_mask.cc
M +10 -0 krita/image/kis_mask.h
M +8 -6 krita/plugins/extensions/dockers/defaultdockers/kis_layer_box.cpp
M +1 -1 krita/plugins/paintops/libpaintop/kis_custom_brush_widget.cpp
M +56 -0 krita/ui/kis_node_manager.cpp
M +4 -0 krita/ui/kis_node_manager.h
M +45 -2 krita/ui/kis_node_model.cpp
M +6 -0 krita/ui/kis_node_model.h
M +2 -2 libs/main/KoDocumentSectionDelegate.cpp
M +1 -1 libs/main/KoDocumentSectionDelegate.h
http://commits.kde.org/calligra/e1e85dea054bf7718a05a6e63cec83b59ffe0315
diff --git a/krita/image/kis_image.cc b/krita/image/kis_image.cc
index 0c5fc22..ad6cceb 100644
--- a/krita/image/kis_image.cc
+++ b/krita/image/kis_image.cc
@@ -112,6 +112,7 @@ public:
KisGroupLayerSP rootLayer; // The layers are contained in here
QList<KisLayer*> dirtyLayers; // for thumbnails
QList<KisLayerComposition*> compositions;
+ KisNodeSP isolatedRootNode;
KisNameServer *nserver;
@@ -177,6 +178,13 @@ KisImage::~KisImage()
disconnect(); // in case Qt gets confused
}
+void KisImage::aboutToAddANode(KisNode *parent, int index)
+{
+ KisNodeGraphListener::aboutToAddANode(parent, index);
+ SANITY_CHECK_LOCKED("aboutToAddANode");
+ stopIsolatedMode();
+}
+
void KisImage::nodeHasBeenAdded(KisNode *parent, int index)
{
KisNodeGraphListener::nodeHasBeenAdded(parent, index);
@@ -187,6 +195,7 @@ void KisImage::nodeHasBeenAdded(KisNode *parent, int index)
void KisImage::aboutToRemoveANode(KisNode *parent, int index)
{
+ stopIsolatedMode();
KisNodeGraphListener::aboutToRemoveANode(parent, index);
SANITY_CHECK_LOCKED("aboutToRemoveANode");
@@ -807,6 +816,11 @@ KisGroupLayerSP KisImage::rootLayer() const
KisPaintDeviceSP KisImage::projection()
{
+ if (m_d->isolatedRootNode) {
+ return m_d->isolatedRootNode->projection();
+ }
+
+
Q_ASSERT(m_d->rootLayer);
KisPaintDeviceSP projection = m_d->rootLayer->projection();
Q_ASSERT(projection);
@@ -1059,7 +1073,7 @@ QImage KisImage::convertToQImage(qint32 x,
qint32 h,
const KoColorProfile * profile)
{
- KisPaintDeviceSP dev = m_d->rootLayer->projection();
+ KisPaintDeviceSP dev = projection();
if (!dev) return QImage();
QImage image = dev->convertToQImage(const_cast<KoColorProfile*>(profile), x, y, w, h,
KoColorConversionTransformation::InternalRenderingIntent,
@@ -1114,7 +1128,7 @@ QImage KisImage::convertToQImage(const QRect& scaledRect, const QSize& scaledIma
srcRect.setTop(static_cast<int>(scaledRect.top() * yScale));
srcRect.setBottom(static_cast<int>(ceil((scaledRect.bottom() + 1) * yScale)) - 1);
- KisPaintDeviceSP mergedImage = m_d->rootLayer->projection();
+ KisPaintDeviceSP mergedImage = projection();
quint8 *scaledImageData = new quint8[scaledRect.width() * scaledRect.height() * pixelSize];
quint8 *imageRow = new quint8[srcRect.width() * pixelSize];
@@ -1173,13 +1187,6 @@ QImage KisImage::convertToQImage(const QRect& scaledRect, const QSize& scaledIma
return image;
}
-
-KisPaintDeviceSP KisImage::mergedImage()
-{
- refreshGraph();
- return m_d->rootLayer->projection();
-}
-
void KisImage::notifyLayersChanged()
{
m_d->signalRouter->emitNotification(LayersChangedSignal);
@@ -1221,6 +1228,8 @@ KisActionRecorder* KisImage::actionRecorder() const
void KisImage::setRootLayer(KisGroupLayerSP rootLayer)
{
+ stopIsolatedMode();
+
if (m_d->rootLayer) {
m_d->rootLayer->setGraphListener(0);
m_d->rootLayer->disconnect();
@@ -1348,6 +1357,40 @@ KisStrokeId KisImage::startStroke(KisStrokeStrategy *strokeStrategy)
return id;
}
+void KisImage::startIsolatedMode(KisNodeSP node)
+{
+ barrierLock();
+ unlock();
+
+ m_d->isolatedRootNode = node;
+ emit sigIsolatedModeChanged();
+
+ notifyProjectionUpdated(bounds());
+}
+
+void KisImage::stopIsolatedMode()
+{
+ if (!m_d->isolatedRootNode) return;
+
+ KisNodeSP oldRootNode = m_d->isolatedRootNode;
+ m_d->isolatedRootNode = 0;
+
+ emit sigIsolatedModeChanged();
+
+ notifyProjectionUpdated(bounds());
+
+ // TODO: Substitute notifyProjectionUpdated() with this code
+ // when update optimization is implemented
+ //
+ // QRect updateRect = bounds() | oldRootNode->extent();
+ // oldRootNode->setDirty(updateRect);
+}
+
+KisNodeSP KisImage::isolatedModeRoot() const
+{
+ return m_d->isolatedRootNode;
+}
+
void KisImage::addJob(KisStrokeId id, KisStrokeJobData *data)
{
if (m_d->scheduler) {
diff --git a/krita/image/kis_image.h b/krita/image/kis_image.h
index 11e17ca..7988df5 100644
--- a/krita/image/kis_image.h
+++ b/krita/image/kis_image.h
@@ -84,6 +84,7 @@ public:
public: // KisNodeGraphListener implementation
+ void aboutToAddANode(KisNode *parent, int index);
void nodeHasBeenAdded(KisNode *parent, int index);
void aboutToRemoveANode(KisNode *parent, int index);
void nodeChanged(KisNode * node);
@@ -387,22 +388,6 @@ public:
}
/**
- * Starting form 2.3 mergedImage() is declared deprecated.
- * If you want to get a projection of the image, please use
- * something like:
- *
- * image->lock();
- * read_something_from_the_image(image->projection());
- * image->unlock();
- *
- * or if you want to get a full refresh of the image graph
- * performed beforehand (do you really want it?) (sure?) then
- * you can add a call to image->refreshGraph() before locking
- * the image.
- */
- KDE_DEPRECATED KisPaintDeviceSP mergedImage();
-
- /**
* @return the root node of the image node graph
*/
KisGroupLayerSP rootLayer() const;
@@ -503,6 +488,11 @@ public:
*/
void removeComposition(KisLayerComposition* composition);
+public:
+ void startIsolatedMode(KisNodeSP node);
+ void stopIsolatedMode();
+ KisNodeSP isolatedModeRoot() const;
+
signals:
/**
@@ -622,6 +612,15 @@ signals:
*/
void sigStrokeEndRequested();
+ /**
+ * Emitted when the isolated mode status has changed.
+ *
+ * Can be used by the recievers to catch a fact of forcefully
+ * stopping the isolated mode by the image when some complex
+ * action was requested
+ */
+ void sigIsolatedModeChanged();
+
public slots:
KisCompositeProgressProxy* compositeProgressProxy();
diff --git a/krita/image/kis_mask.cc b/krita/image/kis_mask.cc
index d4ba755..c3953a6 100644
--- a/krita/image/kis_mask.cc
+++ b/krita/image/kis_mask.cc
@@ -179,6 +179,16 @@ KisPaintDeviceSP KisMask::paintDevice() const
return selection()->getOrCreatePixelSelection();
}
+KisPaintDeviceSP KisMask::original() const
+{
+ return paintDevice();
+}
+
+KisPaintDeviceSP KisMask::projection() const
+{
+ return paintDevice();
+}
+
void KisMask::setSelection(KisSelectionSP selection)
{
m_d->selection = selection;
diff --git a/krita/image/kis_mask.h b/krita/image/kis_mask.h
index 056ec68..92c2eaf 100644
--- a/krita/image/kis_mask.h
+++ b/krita/image/kis_mask.h
@@ -119,6 +119,16 @@ public:
KisPaintDeviceSP paintDevice() const;
/**
+ * @return the same as paintDevice()
+ */
+ KisPaintDeviceSP original() const;
+
+ /**
+ * @return the same as paintDevice()
+ */
+ KisPaintDeviceSP projection() const;
+
+ /**
* Change the selection to the specified selection object. The
* selection is deep copied.
*/
diff --git a/krita/plugins/extensions/dockers/defaultdockers/kis_layer_box.cpp b/krita/plugins/extensions/dockers/defaultdockers/kis_layer_box.cpp
index 00755a3..81e1b78 100644
--- a/krita/plugins/extensions/dockers/defaultdockers/kis_layer_box.cpp
+++ b/krita/plugins/extensions/dockers/defaultdockers/kis_layer_box.cpp
@@ -454,14 +454,16 @@ void KisLayerBox::slotContextMenuRequested(const QPoint &pos, const QModelIndex
QAction* mergeLayerDown = menu.addAction(i18n("&Merge with Layer Below"), this, SLOT(slotMergeLayer()));
if (!index.sibling(index.row() + 1, 0).isValid()) mergeLayerDown->setEnabled(false);
menu.addSeparator();
+
+ QMenu *convertToMenu = menu.addMenu(i18n("&Convert"));
+ addActionToMenu(convertToMenu, "convert_to_paint_layer");
+ addActionToMenu(convertToMenu, "convert_to_transparency_mask");
+ addActionToMenu(convertToMenu, "convert_to_filter_mask");
+ addActionToMenu(convertToMenu, "convert_to_selection_mask");
+
+ addActionToMenu(&menu, "isolate_layer");
}
menu.addSeparator();
- QMenu *convertToMenu = menu.addMenu(i18n("&Convert"));
- addActionToMenu(convertToMenu, "convert_to_paint_layer");
- addActionToMenu(convertToMenu, "convert_to_transparency_mask");
- addActionToMenu(convertToMenu, "convert_to_filter_mask");
- addActionToMenu(convertToMenu, "convert_to_selection_mask");
- menu.addSeparator();
addActionToMenu(&menu, "add_new_transparency_mask");
addActionToMenu(&menu, "add_new_filter_mask");
addActionToMenu(&menu, "add_new_selection_mask");
diff --git a/krita/plugins/paintops/libpaintop/kis_custom_brush_widget.cpp b/krita/plugins/paintops/libpaintop/kis_custom_brush_widget.cpp
index ac1601c..0d77ccd 100644
--- a/krita/plugins/paintops/libpaintop/kis_custom_brush_widget.cpp
+++ b/krita/plugins/paintops/libpaintop/kis_custom_brush_widget.cpp
@@ -189,7 +189,7 @@ void KisCustomBrushWidget::createBrush()
KisSelectionSP selection = m_image->globalSelection();
// create copy of the data
m_image->lock();
- KisPaintDeviceSP dev = new KisPaintDevice(*m_image->mergedImage());
+ KisPaintDeviceSP dev = new KisPaintDevice(*m_image->projection());
m_image->unlock();
if (!selection){
diff --git a/krita/ui/kis_node_manager.cpp b/krita/ui/kis_node_manager.cpp
index 1a7b650..1604ea5 100644
--- a/krita/ui/kis_node_manager.cpp
+++ b/krita/ui/kis_node_manager.cpp
@@ -270,6 +270,16 @@ void KisNodeManager::setup(KActionCollection * actionCollection, KisActionManage
connect(&m_d->nodeConversionSignalMapper, SIGNAL(mapped(const QString &)),
this, SLOT(convertNode(const QString &)));
+ action = new KisAction(koIcon("view-filter"), i18n("&Isolate Layer"), this);
+ action->setCheckable(true);
+ action->setActivationFlags(KisAction::ACTIVE_NODE);
+ actionManager->addAction("isolate_layer", action, actionCollection);
+ connect(action, SIGNAL(triggered(bool)), this, SLOT(toggleIsolateMode(bool)));
+
+ connect(m_d->view->image(), SIGNAL(sigIsolatedModeChanged()),
+ this, SLOT(slotUpdateIsolateModeAction()));
+ connect(this, SIGNAL(sigNodeActivated(KisNodeSP)), SLOT(slotUpdateIsolateModeAction()));
+ connect(this, SIGNAL(sigNodeActivated(KisNodeSP)), SLOT(slotTryFinishIsolatedMode()));
}
void KisNodeManager::updateGUI()
@@ -333,6 +343,52 @@ void KisNodeManager::moveNodeDirect(KisNodeSP node, KisNodeSP parent, KisNodeSP
m_d->commandsAdapter->moveNode(node, parent, aboveThis);
}
+void KisNodeManager::toggleIsolateMode(bool checked)
+{
+ KisImageWSP image = m_d->view->image();
+
+ if (checked) {
+ KisNodeSP activeNode = this->activeNode();
+ Q_ASSERT(activeNode);
+
+ image->startIsolatedMode(activeNode);
+ } else {
+ image->stopIsolatedMode();
+ }
+}
+
+void KisNodeManager::slotUpdateIsolateModeAction()
+{
+ KisAction *action = m_d->view->actionManager()->actionByName("isolate_layer");
+ Q_ASSERT(action);
+
+ KisNodeSP activeNode = this->activeNode();
+ KisNodeSP isolatedRootNode = m_d->view->image()->isolatedModeRoot();
+
+ action->setChecked(isolatedRootNode && isolatedRootNode == activeNode);
+}
+
+void KisNodeManager::slotTryFinishIsolatedMode()
+{
+ KisNodeSP isolatedRootNode = m_d->view->image()->isolatedModeRoot();
+ if (!isolatedRootNode) return;
+
+ bool belongsToIsolatedGroup = false;
+
+ KisNodeSP node = this->activeNode();
+ while(node) {
+ if (node == isolatedRootNode) {
+ belongsToIsolatedGroup = true;
+ break;
+ }
+ node = node->parent();
+ }
+
+ if (!belongsToIsolatedGroup) {
+ m_d->view->image()->stopIsolatedMode();
+ }
+}
+
void KisNodeManager::createNode(const QString & nodeType)
{
KisNodeSP activeNode = this->activeNode();
diff --git a/krita/ui/kis_node_manager.h b/krita/ui/kis_node_manager.h
index 9e8596b..1f81239 100644
--- a/krita/ui/kis_node_manager.h
+++ b/krita/ui/kis_node_manager.h
@@ -138,6 +138,10 @@ public slots:
*/
void moveNodeDirect(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis);
+ void toggleIsolateMode(bool checked);
+ void slotUpdateIsolateModeAction();
+ void slotTryFinishIsolatedMode();
+
void moveNodeAt(KisNodeSP node, KisNodeSP parent, int index);
void createNode(const QString &node);
void convertNode(const QString &nodeType);
diff --git a/krita/ui/kis_node_model.cpp b/krita/ui/kis_node_model.cpp
index 8d64888..1b354c3 100644
--- a/krita/ui/kis_node_model.cpp
+++ b/krita/ui/kis_node_model.cpp
@@ -99,6 +99,26 @@ QModelIndex KisNodeModel::indexFromNode(KisNodeSP node) const
return m_d->indexConverter->indexFromDummy(dummy);
}
+bool KisNodeModel::belongsToIsolatedGroup(KisNodeSP node) const
+{
+ KisNodeSP isolatedRoot = m_d->image->isolatedModeRoot();
+ if (!isolatedRoot) return true;
+
+ KisNodeDummy *isolatedRootDummy =
+ m_d->dummiesFacade->dummyForNode(isolatedRoot);
+ KisNodeDummy *dummy =
+ m_d->dummiesFacade->dummyForNode(node);
+
+ while (dummy) {
+ if (dummy == isolatedRootDummy) {
+ return true;
+ }
+ dummy = dummy->parent();
+ }
+
+ return false;
+}
+
void KisNodeModel::resetIndexConverter()
{
delete m_d->indexConverter;
@@ -116,6 +136,23 @@ void KisNodeModel::resetIndexConverter()
}
}
+void KisNodeModel::regenerateItems(KisNodeDummy *dummy)
+{
+ const QModelIndex &index = m_d->indexConverter->indexFromDummy(dummy);
+ emit dataChanged(index, index);
+
+ dummy = dummy->firstChild();
+ while (dummy) {
+ regenerateItems(dummy);
+ dummy = dummy->nextSibling();
+ }
+}
+
+void KisNodeModel::slotIsolatedModeChanged()
+{
+ regenerateItems(m_d->dummiesFacade->rootDummy());
+}
+
void KisNodeModel::updateSettings()
{
KisConfig cfg;
@@ -163,14 +200,16 @@ void KisNodeModel::connectDummies(KisNodeDummy *dummy, bool needConnect)
void KisNodeModel::setDummiesFacade(KisDummiesFacadeBase *dummiesFacade, KisImageWSP image, KisShapeController *shapeController)
{
- m_d->image = image;
+
m_d->shapeController = shapeController;
if(m_d->dummiesFacade) {
+ m_d->image->disconnect(this);
m_d->dummiesFacade->disconnect(this);
connectDummies(m_d->dummiesFacade->rootDummy(), false);
}
+ m_d->image = image;
m_d->dummiesFacade = dummiesFacade;
resetIndexConverter();
@@ -191,6 +230,8 @@ void KisNodeModel::setDummiesFacade(KisDummiesFacadeBase *dummiesFacade, KisImag
connect(m_d->dummiesFacade, SIGNAL(sigDummyChanged(KisNodeDummy*)),
SLOT(slotDummyChanged(KisNodeDummy*)));
+
+ connect(m_d->image, SIGNAL(sigIsolatedModeChanged()), SLOT(slotIsolatedModeChanged()));
}
reset();
@@ -320,6 +361,8 @@ QVariant KisNodeModel::data(const QModelIndex &index, int role) const
case Qt::DecorationRole: return node->icon();
case Qt::EditRole: return node->name();
case Qt::SizeHintRole: return m_d->image->size(); // FIXME
+ case Qt::TextColorRole:
+ return belongsToIsolatedGroup(node) ? QVariant() : Qt::gray;
case PropertiesRole: return QVariant::fromValue(node->sectionModelProperties());
case AspectRatioRole: return double(m_d->image->width()) / m_d->image->height();
case ProgressRole: {
@@ -327,7 +370,7 @@ QVariant KisNodeModel::data(const QModelIndex &index, int role) const
return proxy ? proxy->percentage() : -1;
}
default:
- if (role >= int(BeginThumbnailRole))
+ if (role >= int(BeginThumbnailRole) && belongsToIsolatedGroup(node))
return node->createThumbnail(role - int(BeginThumbnailRole), role - int(BeginThumbnailRole));
else
return QVariant();
diff --git a/krita/ui/kis_node_model.h b/krita/ui/kis_node_model.h
index 6352853..76d04eb 100644
--- a/krita/ui/kis_node_model.h
+++ b/krita/ui/kis_node_model.h
@@ -79,6 +79,8 @@ private slots:
void slotEndRemoveDummy();
void slotDummyChanged(KisNodeDummy *dummy);
+ void slotIsolatedModeChanged();
+
void updateSettings();
void processUpdateQueue();
void progressPercentageChanged(int, const KisNodeSP);
@@ -95,6 +97,10 @@ private:
bool correctNewNodeLocation(KisNodeSP node,
KisNodeDummy* &parentDummy,
KisNodeDummy* &aboveThisDummy);
+
+ void regenerateItems(KisNodeDummy *dummy);
+ bool belongsToIsolatedGroup(KisNodeSP node) const;
+
private:
struct Private;
diff --git a/libs/main/KoDocumentSectionDelegate.cpp b/libs/main/KoDocumentSectionDelegate.cpp
index 13d6100..81ae7b1 100644
--- a/libs/main/KoDocumentSectionDelegate.cpp
+++ b/libs/main/KoDocumentSectionDelegate.cpp
@@ -264,9 +264,9 @@ bool KoDocumentSectionDelegate::eventFilter(QObject *object, QEvent *event)
// PRIVATE
-QStyleOptionViewItem KoDocumentSectionDelegate::getOptions(const QStyleOptionViewItem &o, const QModelIndex &index)
+QStyleOptionViewItemV4 KoDocumentSectionDelegate::getOptions(const QStyleOptionViewItem &o, const QModelIndex &index)
{
- QStyleOptionViewItem option = o;
+ QStyleOptionViewItemV4 option = o;
QVariant v = index.data(Qt::FontRole);
if (v.isValid()) {
option.font = v.value<QFont>();
diff --git a/libs/main/KoDocumentSectionDelegate.h b/libs/main/KoDocumentSectionDelegate.h
index e804f5d..ad4b9f1 100644
--- a/libs/main/KoDocumentSectionDelegate.h
+++ b/libs/main/KoDocumentSectionDelegate.h
@@ -57,7 +57,7 @@ private:
class Private;
Private* const d;
- static QStyleOptionViewItem getOptions(const QStyleOptionViewItem &option, const QModelIndex &index);
+ static QStyleOptionViewItemV4 getOptions(const QStyleOptionViewItem &option, const QModelIndex &index);
int thumbnailHeight(const QStyleOptionViewItem &option, const QModelIndex &index) const;
int availableWidth() const;
int textBoxHeight(const QStyleOptionViewItem &option) const;
_______________________________________________
Krita mailing list
kimageshop at kde.org
https://mail.kde.org/mailman/listinfo/kimageshop
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.kde.org/pipermail/kimageshop/attachments/20130523/4ff8847c/attachment-0001.html>
More information about the kimageshop
mailing list