Commit dea1990c authored by Boudewijn Rempt's avatar Boudewijn Rempt

Use the separate layermodel for the layerbox. There are still

a few bugs: the layerbox is only updated correctly if you switch
between view options and I haven't yet tested deeply nested layers.

svn path=/trunk/koffice/; revision=657109
parent 5d914b28
......@@ -98,6 +98,7 @@ set(kritaimage_LIB_SRCS
kis_image_commands.cc
kis_layer_commands.cc
kis_undo_adapter.cc
kis_reflectivity_mask.cpp
)
add_definitions(${KDE4_ENABLE_EXCEPTIONS})
......
......@@ -74,8 +74,8 @@ QIcon KisAdjustmentLayer::icon() const
KoDocumentSectionModel::PropertyList KisAdjustmentLayer::properties() const
{
PropertyList l = super::properties();
l << Property(i18n("Filter"), KisFilterRegistry::instance()->value(filter()->name())->name());
KoDocumentSectionModel::PropertyList l = KisLayer::properties();
l << KoDocumentSectionModel::Property(i18n("Filter"), KisFilterRegistry::instance()->value(filter()->name())->name());
return l;
}
......@@ -101,7 +101,7 @@ void KisAdjustmentLayer::setFilter(KisFilterConfiguration * filterConfig)
{
Q_ASSERT(filterConfig);
m_filterConfig = filterConfig;
notifyPropertyChanged(this);
notifyPropertyChanged();
}
......
......@@ -41,7 +41,6 @@ class KisFilterConfiguration;
**/
class KRITAIMAGE_EXPORT KisAdjustmentLayer : public KisLayer, public KisIndirectPaintingSupport
{
typedef KisLayer super;
Q_OBJECT
public:
......@@ -55,7 +54,7 @@ public:
virtual QIcon icon() const;
virtual PropertyList properties() const;
virtual KoDocumentSectionModel::PropertyList properties() const;
/// Return a copy of this layer
virtual KisLayerSP clone() const;
......
......@@ -34,7 +34,7 @@
#include "kis_fill_painter.h"
KisGroupLayer::KisGroupLayer(KisImageSP img, const QString &name, quint8 opacity) :
super(img, name, opacity),
KisLayer(img, name, opacity),
m_x(0),
m_y(0)
{
......@@ -42,7 +42,7 @@ KisGroupLayer::KisGroupLayer(KisImageSP img, const QString &name, quint8 opacity
}
KisGroupLayer::KisGroupLayer(const KisGroupLayer &rhs) :
super(rhs),
KisLayer(rhs),
m_x(rhs.m_x),
m_y(rhs.m_y)
{
......@@ -151,25 +151,18 @@ int KisGroupLayer::index(KisLayerSP layer) const
return layer->index();
return -1;
}
#if 0
void KisGroupLayer::setIndex(KisLayerSP layer, int index)
{
if (layer->parent().data() != this)
return;
//TODO optimize
removeLayer(layer);
addLayer(layer, index);
}
#endif
bool KisGroupLayer::addLayer(KisLayerSP newLayer, int x)
{
kDebug() << "KisGroupLayer::addLayer " << name() << ", adding layer " << newLayer->name() << " with parent " << newLayer->parent() << " at pos " << x << endl;
if (x < 0 || qBound(uint(0), uint(x), childCount()) != uint(x) ||
newLayer->parent() || m_layers.contains(newLayer))
{
kWarning() << "invalid input to KisGroupLayer::addLayer(KisLayerSP newLayer, int x)!" << endl;
return false;
}
notifyAboutToAdd(this, x);
if ( image() ) image()->sigAboutToAddALayer(this, x);
uint index(x);
if (index == 0)
m_layers.append(newLayer);
......@@ -185,13 +178,13 @@ bool KisGroupLayer::addLayer(KisLayerSP newLayer, int x)
newLayer->setIndexPrivate( index );
newLayer->setDirty(newLayer->extent());
notifyAdded(this, x);
if ( image() ) image()->sigLayerHasBeenAdded(this, x);
return true;
}
bool KisGroupLayer::addLayer(KisLayerSP newLayer, KisLayerSP aboveThis)
{
kDebug() << "new layer: " << newLayer.data() << endl;
kDebug() << "KisGroupLayer::addLayer new layer: " << newLayer.data() << ", aboveThis " << aboveThis << endl;
if (aboveThis && aboveThis->parent().data() != this)
{
kWarning() << "invalid input to KisGroupLayer::addLayer(KisLayerSP newLayer, KisLayerSP aboveThis)!" << endl;
......@@ -213,7 +206,7 @@ bool KisGroupLayer::removeLayer(int x)
removedLayer->setParentPrivate( 0 );
removedLayer->setIndexPrivate( -1 );
notifyAboutToRemove(this, x);
if ( image() ) image()->sigAboutToRemoveALayer(this, x);
m_layers.erase(m_layers.begin() + reverseIndex(index));
setDirty(removedLayer->extent());
if (childCount() < 1) {
......@@ -221,7 +214,7 @@ bool KisGroupLayer::removeLayer(int x)
m_projection->clear();
setDirty();
}
notifyRemoved(this, x);
if ( image() ) image()->sigALayerHasBeenRemoved(this, x);
return true;
}
kWarning() << "invalid input to KisGroupLayer::removeLayer()!" << endl;
......@@ -241,7 +234,7 @@ bool KisGroupLayer::removeLayer(KisLayerSP layer)
void KisGroupLayer::setImage(KisImageSP image)
{
super::setImage(image);
KisLayer::setImage(image);
for (vKisLayerSP_it it = m_layers.begin(); it != m_layers.end(); ++it)
{
(*it)->setImage(image);
......@@ -450,33 +443,4 @@ void KisGroupLayer::updateProjection(const QRect & rc)
}
}
void KisGroupLayer::notifyAboutToAdd(KisGroupLayer *p, int index)
{
beginInsertRows(indexFromLayer(p), index, index);
if (parent())
parent()->notifyAboutToAdd(p, index);
}
void KisGroupLayer::notifyAdded(KisGroupLayer *p, int index)
{
endInsertRows();
if (parent())
parent()->notifyAdded(p, index);
}
void KisGroupLayer::notifyAboutToRemove(KisGroupLayer *p, int index)
{
beginRemoveRows(indexFromLayer(p), index, index);
if (parent())
parent()->notifyAboutToRemove(p, index);
}
void KisGroupLayer::notifyRemoved(KisGroupLayer *p, int index)
{
endRemoveRows();
if (parent())
parent()->notifyRemoved(p, index);
}
#include "kis_group_layer.moc"
......@@ -36,7 +36,6 @@ class KisMergeVisitor;
* (Implementation detail: internally, the indices are reversed, for speed.)
**/
class KRITAIMAGE_EXPORT KisGroupLayer : public KisLayer {
typedef KisLayer super;
Q_OBJECT
......@@ -189,10 +188,7 @@ public:
private:
friend class KisImage; // Only KisImage is allowed to add layers
#if 0
/// Moves the specified layer to the specified index in the group, if it's already a member of this group.
virtual void setIndex(KisLayerSP layer, int index);
#endif
/** Adds the layer to this group at the specified index. childCount() is a valid index and appends to the end.
Fails and returns false if the layer is already in this group or any other (remove it first.) */
virtual bool addLayer(KisLayerSP newLayer, int index);
......@@ -207,14 +203,6 @@ private:
/// Removes the layer from this group. Fails if there's no such layer in this group.
virtual bool removeLayer(KisLayerSP layer);
protected:
/// these cause QAbstractItemModel::rows{AboutToBe,}{Inserted,Removed} to be emitted and percolated up the tree
void notifyAboutToAdd(KisGroupLayer *parent, int index);
void notifyAdded(KisGroupLayer *parent, int index);
void notifyAboutToRemove(KisGroupLayer *parent, int index);
void notifyRemoved(KisGroupLayer *parent, int index);
private:
inline int reverseIndex(int index) const { return childCount() - 1 - index; };
......
......@@ -625,14 +625,18 @@ KisPaintDeviceSP KisImage::activeDevice()
KisLayerSP KisImage::newLayer(const QString& name, quint8 opacity, const QString & compositeOp, KoColorSpace * cs)
{
kDebug() << "KisImage::newLayer " << name << ", opacity " << opacity << ", compop " << compositeOp << ", cs " << cs << endl;
KisPaintLayer * layer;
if (cs)
if (cs) {
layer = new KisPaintLayer(this, name, opacity, cs);
layer->setCompositeOp(cs->compositeOp(compositeOp));
}
else
layer = new KisPaintLayer(this, name, opacity);
Q_CHECK_PTR(layer);
layer->setCompositeOp(cs->compositeOp(compositeOp));
layer->setVisible(true);
KisLayerSP layerSP(layer);
......@@ -726,24 +730,22 @@ void KisImage::preparePaintLayerAfterAdding( KisLayerSP layer )
emit sigLayerAdded(layer);
activateLayer(layer);
}
if (!layer->temporary()) {
QUndoCommand* cmd = new KisImageLayerAddCommand(KisImageSP(this), layer);
cmd->redo();
}
}
bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent)
{
kDebug() << "KisImage::addLayer " << layer->name() << ", parent: " << parent << endl;
if ( parent )
return addLayer(layer, parent, parent->firstChild());
return addLayer( layer, parent, parent->firstChild() );
else
return addLayer( layer, rootLayer(), rootLayer()->firstChild() );
}
bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
{
kDebug() << "KisImage::addLayer " << layer->name() << ", parent: " << parent << ", abovethis: " << aboveThis << endl;
if (!parent)
return false;
......@@ -755,6 +757,8 @@ bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP abo
bool KisImage::addLayer( KisLayerSP layer, KisGroupLayerSP parent, int index )
{
kDebug() << "KisImage::addLayer " << layer->name() << ", parent: " << parent << ", index: " << index << endl;
if (!parent)
return false;
......
......@@ -483,9 +483,35 @@ signals:
void sigSizeChanged(qint32 w, qint32 h);
void sigProfileChanged(KoColorProfile * profile);
void sigColorSpaceChanged(KoColorSpace* cs);
/// Emitted when any layer's mask info got updated (or when the current layer changes)
void sigMaskInfoChanged();
friend class KisGroupLayer; // Allow the group layer to emit these
// signals for us. This is a bit
// dirty. (BSAR)
/**
* Inform the model that we're going to add a layer.
*/
void sigAboutToAddALayer( KisGroupLayer *parent, int index );
/**
* Inform the model we're done adding a layer.
*/
void sigLayerHasBeenAdded( KisGroupLayer *parent, int index );
/**
* Inform the model we're going to remove a layer.
*/
void sigAboutToRemoveALayer( KisGroupLayer *parent, int index );
/**
* Inform the model we're done removing a layer.
*/
void sigALayerHasBeenRemoved( KisGroupLayer *parent, int index );
public slots:
void slotSelectionChanged();
void slotSelectionChanged(const QRect& r);
......
......@@ -62,7 +62,7 @@ public:
KisLayer::KisLayer(KisImageSP img, const QString &name, quint8 opacity)
: KoDocumentSectionModel(0)
: QObject(0)
, m_d( new Private )
{
m_d->id = getID();
......@@ -79,7 +79,7 @@ KisLayer::KisLayer(KisImageSP img, const QString &name, quint8 opacity)
}
KisLayer::KisLayer(const KisLayer& rhs)
: KoDocumentSectionModel( 0 )
: QObject( 0 )
, KisShared(rhs)
, m_d( new Private() )
{
......@@ -108,15 +108,15 @@ KoColorSpace * KisLayer::colorSpace()
KoDocumentSectionModel::PropertyList KisLayer::properties() const
{
PropertyList l;
l << Property(i18n("Visible"), KIcon("visible"), KIcon("novisible"), visible());
l << Property(i18n("Locked"), KIcon("locked"), KIcon("unlocked"), locked());
l << Property(i18n("Opacity"), i18n("%1%", percentOpacity()));
l << Property(i18n("Composite Mode"), compositeOp()->id());
KoDocumentSectionModel::PropertyList l;
l << KoDocumentSectionModel::Property(i18n("Visible"), KIcon("visible"), KIcon("novisible"), visible());
l << KoDocumentSectionModel::Property(i18n("Locked"), KIcon("locked"), KIcon("unlocked"), locked());
l << KoDocumentSectionModel::Property(i18n("Opacity"), i18n("%1%", percentOpacity()));
l << KoDocumentSectionModel::Property(i18n("Composite Mode"), compositeOp()->id());
return l;
}
void KisLayer::setProperties( const PropertyList &properties )
void KisLayer::setProperties( const KoDocumentSectionModel::PropertyList &properties )
{
setVisible( properties.at( 0 ).state.toBool() );
setLocked( properties.at( 1 ).state.toBool() );
......@@ -136,7 +136,7 @@ QBitArray & KisLayer::channelFlags()
void KisLayer::activate()
{
notifyPropertyChanged(this);
notifyPropertyChanged();
}
void KisLayer::deactivate()
......@@ -267,26 +267,6 @@ bool KisLayer::matchesFlags(int flags) const
return true;
}
KisLayerSP KisLayer::layerFromIndex(const QModelIndex &index)
{
if( !index.isValid() )
return KisLayerSP(0);
Q_ASSERT(index.model() == this);
Q_ASSERT(index.internalPointer());
return KisLayerSP(static_cast<KisLayer*>(index.internalPointer()));
}
vKisLayerSP KisLayer::layersFromIndexes(const QModelIndexList &in)
{
vKisLayerSP out;
for (int i = 0, n = in.count(); i < n; ++i)
if (KisLayerSP layer = layerFromIndex(in.at(i)))
out << layer;
return out;
}
quint8 KisLayer::opacity() const
{
return m_d->opacity;
......@@ -407,143 +387,11 @@ void KisLayer::notifyPropertyChanged()
{
if(image() && !signalsBlocked())
image()->notifyPropertyChanged(KisLayerSP(this));
notifyPropertyChanged(this);
}
void KisLayer::notifyCommandExecuted()
{
notifyPropertyChanged(this);
}
void KisLayer::notifyPropertyChanged(KisLayer *layer)
{
QModelIndex index = indexFromLayer(layer);
emit dataChanged(index, index);
if (parent())
parent()->notifyPropertyChanged(layer); // To make sure the
// group layers
// thumbnails are
// updated, too.
}
QModelIndex KisLayer::indexFromLayer(KisLayer *layer) const
{
Q_ASSERT(layer);
return createIndex(layer->index(), 0, layer);
}
int KisLayer::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid())
return childCount();
Q_ASSERT(parent.model() == this);
Q_ASSERT(parent.internalPointer());
return static_cast<KisLayer*>(parent.internalPointer())->childCount();
}
int KisLayer::columnCount(const QModelIndex&) const
{
return 1;
}
QModelIndex KisLayer::index(int row, int column, const QModelIndex &parent) const
{
if (!parent.isValid())
{
if( static_cast<uint>( row ) < childCount() )
return createIndex(row, column, at(row).data());
else
return QModelIndex();
}
Q_ASSERT(parent.model() == this);
Q_ASSERT(parent.internalPointer());
return createIndex(row, column, static_cast<KisLayer*>(parent.internalPointer())->at(row).data());
}
QModelIndex KisLayer::parent(const QModelIndex &i) const
{
if (!i.isValid())
return QModelIndex();
Q_ASSERT(i.model() == this);
Q_ASSERT(i.internalPointer());
if (static_cast<KisLayer*>(i.internalPointer())->parent().data() == this)
return QModelIndex();
else if (KisGroupLayer *p = static_cast<KisLayer*>(i.internalPointer())->parent().data())
return createIndex(p->KisLayer::index(), 0, p); //gcc--
else
return QModelIndex();
}
QVariant KisLayer::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
Q_ASSERT(index.model() == this);
Q_ASSERT(index.internalPointer());
KisLayer *layer = static_cast<KisLayer*>(index.internalPointer());
switch (role)
{
case Qt::DisplayRole: return layer->name();
case Qt::DecorationRole: return layer->icon();
case Qt::EditRole: return layer->name();
case Qt::SizeHintRole: return layer->image()->size();
case ActiveRole: return layer->isActive();
case PropertiesRole: return QVariant::fromValue(layer->properties());
case AspectRatioRole: return double(layer->image()->width()) / layer->image()->height();
default:
if (role >= int(BeginThumbnailRole))
return layer->createThumbnail(role - int(BeginThumbnailRole), role - int(BeginThumbnailRole));
else
return QVariant();
}
}
Qt::ItemFlags KisLayer::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::ItemIsEnabled;
Q_ASSERT(index.model() == this);
Q_ASSERT(index.internalPointer());
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEditable;
if (qobject_cast<KisGroupLayer*>(static_cast<KisLayer*>(index.internalPointer()))) //gcc--
flags |= Qt::ItemIsDropEnabled;
return flags;
}
bool KisLayer::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return false;
Q_ASSERT(index.model() == this);
Q_ASSERT(index.internalPointer());
KisLayer *layer = static_cast<KisLayer*>(index.internalPointer());
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole:
layer->setName(value.toString());
return true;
case PropertiesRole:
layer->setProperties(value.value<PropertyList>());
return true;
case ActiveRole:
if (value.toBool())
{
layer->setActive();
return true;
}
}
return false;
notifyPropertyChanged();
}
......
......@@ -23,16 +23,20 @@
#include <QRect>
#include <QRegion>
#include <QMetaType>
#include <QObject>
#include "krita_export.h"
#include "KoCompositeOp.h"
#include "KoDocumentSectionModel.h"
#include "kis_shared.h"
#include "kis_types.h"
#include "kis_layer_visitor.h"
#include "KoCompositeOp.h"
#include "KoDocumentSectionModel.h"
#include "kis_paint_device.h"
class QIcon;
class QPainter;
class QBitArray;
......@@ -47,9 +51,9 @@ class KoColorSpace;
* is at the top of the group in the layerlist, using next will iterate to the bottom to last,
* whereas previous will go up to first again.
**/
class KRITAIMAGE_EXPORT KisLayer: public KoDocumentSectionModel, public KisShared
class KRITAIMAGE_EXPORT KisLayer: public QObject, public KisShared
{
typedef KoDocumentSectionModel super;
Q_OBJECT
public:
......@@ -67,8 +71,8 @@ public:
virtual QIcon icon() const = 0;
virtual PropertyList properties() const;
virtual void setProperties( const PropertyList &properties );
virtual KoDocumentSectionModel::PropertyList properties() const;
virtual void setProperties( const KoDocumentSectionModel::PropertyList &properties );
virtual void setChannelFlags( QBitArray & channelFlags );
QBitArray & channelFlags();
......@@ -168,9 +172,6 @@ public:
/// Returns the total number of layers in this layer, its child layers, and their child layers recursively, optionally ones with the specified properties Visible or Locked, which you can OR together.
virtual int numLayers(int type = 0) const;
KisLayerSP layerFromIndex(const QModelIndex &index);
vKisLayerSP layersFromIndexes(const QModelIndexList &list);
public:
/**
* Called when the layer is made active.
......@@ -227,8 +228,6 @@ public:
KisImageSP image() const;
virtual void setImage(KisImageSP image);
// KisUndoAdapter *undoAdapter() const;
/// paints a mask where the selection on this layer resides
virtual void paint(QImage &img, qint32 x, qint32 y, qint32 w, qint32 h);
virtual void paint(QImage &img, const QRect& scaledImageRect, const QSize& scaledImageSize, const QSize& imageSize);
......@@ -243,22 +242,9 @@ public:
/// Accept the KisLayerVisitor (for the Visitor design pattern), should call the correct function on the KisLayerVisitor for this layer type
virtual bool accept(KisLayerVisitor &) = 0;
public: // from QAbstractItemModel
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
virtual QModelIndex parent(const QModelIndex &index) const;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
protected:
QModelIndex indexFromLayer(KisLayer *layer) const;
/// causes QAbstractItemModel::dataChanged() to be emitted and percolated up the tree
void notifyPropertyChanged(KisLayer *layer);
private:
/// ???
bool matchesFlags(int flags) const;
private:
......
......@@ -41,7 +41,7 @@
#include "kis_undo_adapter.h"
#include "kis_effect_mask.h"
#include "kis_transparency_mask.h"
#include "kis_mask.h"
class KisPaintLayer::Private
{
......@@ -64,6 +64,9 @@ public:
foreach( KisEffectMask * mask, effectMasks ) {
delete mask;
}
foreach( KisMask * mask, painterlyOverlays.values() ) {
delete mask;
}
effectMasks.clear();
}
......@@ -79,6 +82,8 @@ public:
QList<KisEffectMask*> effectMasks; // The first mask is the bottom-one in the
// mask stack!
QHash<QString, KisMask*> painterlyOverlays;
bool renderMask;
bool editMask;
};
......@@ -155,10 +160,10 @@ QIcon KisPaintLayer::icon() const
KoDocumentSectionModel::PropertyList KisPaintLayer::properties() const
{
PropertyList l = super::