kis_layer_box.cpp 21.7 KB
Newer Older
1
2
3
4
5
/*
 *  kis_layer_box.cc - part of Krita aka Krayon aka KimageShop
 *
 *  Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
 *  Copyright (C) 2006 Gábor Lehel <illissius@gmail.com>
Halla Rempt's avatar
Halla Rempt committed
6
 *  Copyright (C) 2007 Thomas Zander <zander@kde.org>
7
 *  Copyright (C) 2007 Boudewijn Rempt <boud@valdyas.org>
José Luis Vergara's avatar
José Luis Vergara committed
8
 *  Copyright (c) 2011 José Luis Vergara <pentalis@gmail.com>
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 *
 *  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_layer_box.h"

Halla Rempt's avatar
Halla Rempt committed
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <QToolButton>
#include <QLayout>
#include <QMouseEvent>
#include <QPainter>
#include <QPoint>
#include <QRect>
#include <QString>
#include <QToolTip>
#include <QWidget>
#include <QComboBox>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QPixmap>
#include <QList>
#include <QVector>

44
#include <kis_debug.h>
45
46
47
48
49
50
51
52
53
#include <kglobal.h>
#include <kmenu.h>
#include <kmessagebox.h>
#include <kpushbutton.h>
#include <kiconloader.h>
#include <kicontheme.h>
#include <klocale.h>
#include <khbox.h>
#include <kicon.h>
54
#include <kaction.h>
55
56

#include <KoDocumentSectionView.h>
57
58
#include <KoColorSpace.h>
#include <KoCompositeOp.h>
59
60
61
62
63
64
65

#include <kis_types.h>
#include <kis_image.h>
#include <kis_paint_device.h>
#include <kis_layer.h>
#include <kis_group_layer.h>
#include <kis_mask.h>
66
#include <kis_node.h>
67
#include <kis_composite_ops_model.h>
68

69
#include "widgets/kis_cmb_composite.h"
70
#include "widgets/kis_slider_spin_box.h"
71
#include "kis_view2.h"
72
#include "kis_node_manager.h"
73
#include "kis_node_model.h"
74
75
#include "canvas/kis_canvas2.h"
#include "kis_doc2.h"
76
77
#include "kis_dummies_facade_base.h"
#include <KoShapeBasedDocumentBase.h>
78

79

80
#include "ui_wdglayerbox.h"
81

82

83
KisLayerBox::KisLayerBox()
Halla Rempt's avatar
Halla Rempt committed
84
85
86
        : QDockWidget(i18n("Layers"))
        , m_canvas(0)
        , m_wdgLayerBox(new Ui_WdgLayerBox)
87
88
89
90
91
{
    setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);

    QWidget* mainWidget = new QWidget(this);
    setWidget(mainWidget);
92
    m_delayTimer.setSingleShot(true);
93

94
    m_wdgLayerBox->setupUi(mainWidget);
95

96
    m_wdgLayerBox->listLayers->setDefaultDropAction(Qt::MoveAction);
97
    m_wdgLayerBox->listLayers->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
98
    m_wdgLayerBox->listLayers->setSelectionBehavior(QAbstractItemView::SelectRows);
Halla Rempt's avatar
Halla Rempt committed
99

100
    connect(m_wdgLayerBox->listLayers, SIGNAL(contextMenuRequested(const QPoint&, const QModelIndex&)),
101
            this, SLOT(slotContextMenuRequested(const QPoint&, const QModelIndex&)));
102
103
    connect(m_wdgLayerBox->listLayers, SIGNAL(collapsed(const QModelIndex&)), SLOT(slotCollapsed(const QModelIndex &)));
    connect(m_wdgLayerBox->listLayers, SIGNAL(expanded(const QModelIndex&)), SLOT(slotExpanded(const QModelIndex &)));
104

Halla Rempt's avatar
Halla Rempt committed
105
106
    m_viewModeMenu = new KMenu(this);
    QActionGroup *group = new QActionGroup(this);
107
108
    QList<QAction*> actions;

109
    actions << m_viewModeMenu->addAction(KIcon("view-list-text"),
Halla Rempt's avatar
Halla Rempt committed
110
                                         i18n("Minimal View"), this, SLOT(slotMinimalView()));
111
    actions << m_viewModeMenu->addAction(KIcon("view-list-details"),
Halla Rempt's avatar
Halla Rempt committed
112
                                         i18n("Detailed View"), this, SLOT(slotDetailedView()));
113
    actions << m_viewModeMenu->addAction(KIcon("view-preview"),
Halla Rempt's avatar
Halla Rempt committed
114
                                         i18n("Thumbnail View"), this, SLOT(slotThumbnailView()));
115

Halla Rempt's avatar
Halla Rempt committed
116
117
118
    for (int i = 0, n = actions.count(); i < n; ++i) {
        actions[i]->setCheckable(true);
        actions[i]->setActionGroup(group);
119
120
121
    }
    actions[1]->trigger(); //TODO save/load previous state

122
123
    m_wdgLayerBox->bnAdd->setIcon(BarIcon("list-add"));

124
125
126
127
    m_wdgLayerBox->bnViewMode->setMenu(m_viewModeMenu);
    m_wdgLayerBox->bnViewMode->setPopupMode(QToolButton::InstantPopup);
    m_wdgLayerBox->bnViewMode->setIcon(KIcon("view-choose"));
    m_wdgLayerBox->bnViewMode->setText(i18n("View mode"));
128

129
130
    m_wdgLayerBox->bnDelete->setIcon(BarIcon("list-remove"));
    m_wdgLayerBox->bnDelete->setIconSize(QSize(22, 22));
Halla Rempt's avatar
Halla Rempt committed
131

132
    m_wdgLayerBox->bnRaise->setEnabled(false);
133
134
135
    m_wdgLayerBox->bnRaise->setIcon(BarIcon("go-up"));
    m_wdgLayerBox->bnRaise->setIconSize(QSize(22, 22));
    
136
    m_wdgLayerBox->bnLower->setEnabled(false);
137
138
    m_wdgLayerBox->bnLower->setIcon(BarIcon("go-down"));
    m_wdgLayerBox->bnLower->setIconSize(QSize(22, 22));
139
140
141
142
143
144
145
146
    
    m_wdgLayerBox->bnLeft->setEnabled(true);
    m_wdgLayerBox->bnLeft->setIcon(BarIcon("arrow-left"));
    m_wdgLayerBox->bnLeft->setIconSize(QSize(22, 22));
    
    m_wdgLayerBox->bnRight->setEnabled(true);
    m_wdgLayerBox->bnRight->setIcon(BarIcon("arrow-right"));
    m_wdgLayerBox->bnRight->setIconSize(QSize(22, 22));
147

148
149
    m_wdgLayerBox->bnProperties->setIcon(BarIcon("document-properties"));
    m_wdgLayerBox->bnProperties->setIconSize(QSize(22, 22));
Halla Rempt's avatar
Halla Rempt committed
150

151
152
    m_wdgLayerBox->bnDuplicate->setIcon(BarIcon("edit-copy"));
    m_wdgLayerBox->bnDuplicate->setIconSize(QSize(22, 22));
153
154
155
156
157
158

    connect(m_wdgLayerBox->bnDelete, SIGNAL(clicked()), SLOT(slotRmClicked()));
    // NOTE: this is _not_ a mistake. The layerbox shows the layers in the reverse order
    connect(m_wdgLayerBox->bnRaise, SIGNAL(clicked()), SLOT(slotLowerClicked()));
    connect(m_wdgLayerBox->bnLower, SIGNAL(clicked()), SLOT(slotRaiseClicked()));
    // END NOTE
159
160
    connect(m_wdgLayerBox->bnLeft, SIGNAL(clicked()), SLOT(slotLeftClicked()));
    connect(m_wdgLayerBox->bnRight, SIGNAL(clicked()), SLOT(slotRightClicked()));
161
162
163
164
165
166
167

    connect(m_wdgLayerBox->bnProperties, SIGNAL(clicked()), SLOT(slotPropertiesClicked()));
    connect(m_wdgLayerBox->bnDuplicate, SIGNAL(clicked()), SLOT(slotDuplicateClicked()));

    connect(m_wdgLayerBox->doubleOpacity, SIGNAL(valueChanged(qreal)), SLOT(slotOpacitySliderMoved(qreal)));
    connect(&m_delayTimer, SIGNAL(timeout()), SLOT(slotOpacityChanged()));

168
    connect(m_wdgLayerBox->cmbComposite, SIGNAL(activated(int)), SLOT(slotCompositeOpChanged(int)));
169
170
171
172
173
174
175
176
177
178
179
    connect(m_wdgLayerBox->bnAdd, SIGNAL(clicked()), SLOT(slotNewPaintLayer()));

    m_newPainterLayerAction = new KAction(KIcon("document-new"), i18n("&Paint Layer"), this);
    connect(m_newPainterLayerAction, SIGNAL(triggered(bool)), this, SLOT(slotNewPaintLayer()));

    m_newGroupLayerAction = new KAction(KIcon("folder-new"), i18n("&Group Layer"), this);
    connect(m_newGroupLayerAction, SIGNAL(triggered(bool)), this, SLOT(slotNewGroupLayer()));

    m_newCloneLayerAction = new KAction(KIcon("edit-copy"), i18n("&Clone Layer"), this);
    connect(m_newCloneLayerAction, SIGNAL(triggered(bool)), this, SLOT(slotNewCloneLayer()));

180
    m_newShapeLayerAction = new KAction(KIcon("bookmark-new"), i18n("&Vector Layer"), this);
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    connect(m_newShapeLayerAction, SIGNAL(triggered(bool)), this, SLOT(slotNewShapeLayer()));

    m_newAdjustmentLayerAction = new KAction(KIcon("view-filter"), i18n("&Filter Layer..."), this);
    connect(m_newAdjustmentLayerAction, SIGNAL(triggered(bool)), this, SLOT(slotNewAdjustmentLayer()));

    m_newGeneratorLayerAction = new KAction(KIcon("view-filter"), i18n("&Generated Layer..."), this);
    connect(m_newGeneratorLayerAction, SIGNAL(triggered(bool)), this, SLOT(slotNewGeneratorLayer()));

    m_newTransparencyMaskAction = new KAction(KIcon("edit-copy"), i18n("&Transparency Mask"), this);
    connect(m_newTransparencyMaskAction, SIGNAL(triggered(bool)), this, SLOT(slotNewTransparencyMask()));

    m_newEffectMaskAction = new KAction(KIcon("bookmarks"), i18n("&Filter Mask..."), this);
    connect(m_newEffectMaskAction, SIGNAL(triggered(bool)), this, SLOT(slotNewEffectMask()));

    m_newSelectionMaskAction = new KAction(KIcon("edit-paste"), i18n("&Local Selection"), this);
    connect(m_newSelectionMaskAction, SIGNAL(triggered(bool)), this, SLOT(slotNewSelectionMask()));

    m_newLayerMenu = new KMenu(this);
    m_wdgLayerBox->bnAdd->setMenu(m_newLayerMenu);
    m_wdgLayerBox->bnAdd->setPopupMode(QToolButton::MenuButtonPopup);

    m_newLayerMenu->addAction(m_newPainterLayerAction);
    m_newLayerMenu->addAction(m_newGroupLayerAction);
    m_newLayerMenu->addAction(m_newCloneLayerAction);
    m_newLayerMenu->addAction(m_newShapeLayerAction);
    m_newLayerMenu->addAction(m_newAdjustmentLayerAction);
    m_newLayerMenu->addAction(m_newGeneratorLayerAction);
    m_newLayerMenu->addSeparator();
    m_newLayerMenu->addAction(m_newTransparencyMaskAction);
    m_newLayerMenu->addAction(m_newEffectMaskAction);
#if 0 // XXX_2.0
    m_newLayerMenu->addAction(KIcon("view-filter"), i18n("&Transformation Mask..."), this, SLOT(slotNewTransformationMa
    sk()));
#endif
    m_newLayerMenu->addAction(m_newSelectionMaskAction);
216

217
    
218
    m_nodeModel = new KisNodeModel(this);
219

220
221
222
223
224
225
    /**
     * Connect model updateUI() to enable/disable controls.
     * Note: nodeActivated() is connected seperately in setImage(), because
     *       it needs particular order of calls: first the connection to the
     *       node manager should be called, then updateUI()
     */
226
227
228
    connect(m_nodeModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SLOT(updateUI()));
    connect(m_nodeModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SLOT(updateUI()));
    connect(m_nodeModel, SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)), SLOT(updateUI()));
229
    connect(m_nodeModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), SLOT(updateUI()));
230
231
    connect(m_nodeModel, SIGNAL(modelReset()), SLOT(updateUI()));

232
    m_wdgLayerBox->listLayers->setModel(m_nodeModel);
233
234
235
236
}

KisLayerBox::~KisLayerBox()
{
Halla Rempt's avatar
Halla Rempt committed
237
    delete m_wdgLayerBox;
238
239
}

240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

void expandNodesRecursively(KisNodeSP root, QPointer<KisNodeModel> nodeModel, KoDocumentSectionView *sectionView)
{
    if (!root) return;
    if (nodeModel.isNull()) return;
    if (!sectionView) return;

    sectionView->blockSignals(true);

    KisNodeSP node = root->firstChild();
    while (node) {
        QModelIndex idx = nodeModel->indexFromNode(node);
        if (idx.isValid()) {
            if (node->collapsed()) {
                sectionView->collapse(idx);
            }
        }
        if (node->childCount() > 0) {
            expandNodesRecursively(node, nodeModel, sectionView);
        }
        node = node->nextSibling();
    }
    sectionView->blockSignals(false);
}

Halla Rempt's avatar
Halla Rempt committed
265
void KisLayerBox::setCanvas(KoCanvasBase *canvas)
266
{
267

268
    if (m_canvas) {
269
        m_canvas->disconnectCanvasObserver(this);
270
        m_nodeModel->setDummiesFacade(0, 0);
271

272
273
274
275
        disconnect(m_image, 0, this, 0);
        disconnect(m_nodeManager, 0, this, 0);
        disconnect(m_nodeModel, 0, m_nodeManager, 0);
        disconnect(m_nodeModel, SIGNAL(nodeActivated(KisNodeSP)), this, SLOT(updateUI()));
Halla Rempt's avatar
Halla Rempt committed
276
    }
277

278
    m_canvas = dynamic_cast<KisCanvas2*>(canvas);
279

280
281
    if (m_canvas) {
        m_image = m_canvas->view()->image();
282

283
        m_nodeManager = m_canvas->view()->nodeManager();
284

285
286
        KisDummiesFacadeBase *kritaDummiesFacade = dynamic_cast<KisDummiesFacadeBase*>(m_canvas->view()->document()->shapeController());
        m_nodeModel->setDummiesFacade(kritaDummiesFacade, m_image);
287

288
        connect(m_image, SIGNAL(sigAboutToBeDeleted()), SLOT(notifyImageDeleted()));
289

290
291
        // cold start
        setCurrentNode(m_nodeManager->activeNode());
292
293

        // Connection KisNodeManager -> KisLayerBox
294
        connect(m_nodeManager, SIGNAL(sigUiNeedChangeActiveNode(KisNodeSP)), this, SLOT(setCurrentNode(KisNodeSP)));
295
296
297

        // Connection KisLayerBox -> KisNodeManager
        // The order of these connections is important! See comment in the ctor
298
        connect(m_nodeModel, SIGNAL(nodeActivated(KisNodeSP)), m_nodeManager, SLOT(slotUiActivatedNode(KisNodeSP)));
299
        connect(m_nodeModel, SIGNAL(nodeActivated(KisNodeSP)), SLOT(updateUI()));
300

301
        // Node manipulation methods are forwarded to the node manager
302
303
304
305
        connect(m_nodeModel, SIGNAL(requestAddNode(KisNodeSP, KisNodeSP, KisNodeSP)),
                m_nodeManager, SLOT(addNodeDirect(KisNodeSP, KisNodeSP, KisNodeSP)));
        connect(m_nodeModel, SIGNAL(requestMoveNode(KisNodeSP, KisNodeSP, KisNodeSP)),
                m_nodeManager, SLOT(moveNodeDirect(KisNodeSP, KisNodeSP, KisNodeSP)));
306
307
308
309

        m_wdgLayerBox->listLayers->expandAll();
        expandNodesRecursively(m_image->rootLayer(), m_nodeModel, m_wdgLayerBox->listLayers);
        m_wdgLayerBox->listLayers->scrollToBottom();
310
    }
311

312
313
}

314
315
316
317
318
319

void KisLayerBox::unsetCanvas()
{
    setCanvas(0);
}

320
321
void KisLayerBox::notifyImageDeleted()
{
322
    setCanvas(0);
323
}
324

325
326
void KisLayerBox::updateUI()
{
327
328
329
    if(!m_canvas) return;

    KisNodeSP active = m_nodeManager->activeNode();
330

331
332
    m_wdgLayerBox->bnDelete->setEnabled(active);
    m_wdgLayerBox->bnRaise->setEnabled(active && (active->nextSibling()
333
334
335
                                       || (active->parent() && active->parent() != m_image->root())));
    m_wdgLayerBox->bnLower->setEnabled(active && (active->prevSibling()
                                       || (active->parent() && active->parent() != m_image->root())));
336
337
    m_wdgLayerBox->bnLeft->setEnabled(active);
    m_wdgLayerBox->bnRight->setEnabled(active);
338
339
    m_wdgLayerBox->bnDuplicate->setEnabled(active);
    m_wdgLayerBox->bnProperties->setEnabled(active);
340

341
    m_wdgLayerBox->doubleOpacity->setEnabled(active);
342
    m_wdgLayerBox->doubleOpacity->setRange(0, 100, 0);
343

344
    m_wdgLayerBox->cmbComposite->setEnabled(active);
345

346
    if (active) {
347
        if (m_nodeManager->activePaintDevice()) {
348
            slotFillCompositeOps(m_nodeManager->activeColorSpace());
349
        } else {
350
            slotFillCompositeOps(m_image->colorSpace());
351
352
        }

353
354
355
356
357
358
        if (active->inherits("KisMask")) {
            active = active->parent(); // We need a layer to set opacity and composite op, which masks don't have
        }
        if (active->inherits("KisLayer")) {
            KisLayerSP l = qobject_cast<KisLayer*>(active.data());
            slotSetOpacity(l->opacity() * 100.0 / 255);
359
360
361
362
363
364
365

            const KoCompositeOp* compositeOp = l->compositeOp();
            if(compositeOp) {
                slotSetCompositeOp(compositeOp);
            } else {
                m_wdgLayerBox->cmbComposite->setEnabled(false);
            }
366
        }
367
    }
368
369
370
    m_newTransparencyMaskAction->setEnabled(active);
    m_newEffectMaskAction->setEnabled(active);
    m_newSelectionMaskAction->setEnabled(active);
371
    m_newCloneLayerAction->setEnabled(active);
372
373
}

374
375
376
377
378

/**
 * This method is callen *only* when non-GUI code requested the
 * change of the current node
 */
Halla Rempt's avatar
Halla Rempt committed
379
void KisLayerBox::setCurrentNode(KisNodeSP node)
380
{
381
382
383
384
    QModelIndex index = node ? m_nodeModel->indexFromNode(node) : QModelIndex();

    m_wdgLayerBox->listLayers->setCurrentIndex(index);
    updateUI();
385
386
387
388
}

void KisLayerBox::slotSetCompositeOp(const KoCompositeOp* compositeOp)
{
389
    KoID cmpOp = KoCompositeOpRegistry::instance().getKoID(compositeOp->id());
390
    int  index = m_wdgLayerBox->cmbComposite->indexOf(cmpOp);
391
    
392
    m_wdgLayerBox->cmbComposite->blockSignals(true);
393
    m_wdgLayerBox->cmbComposite->setCurrentIndex(index);
394
    m_wdgLayerBox->cmbComposite->blockSignals(false);
395
396
}

397
void KisLayerBox::slotFillCompositeOps(const KoColorSpace* colorSpace)
398
{
399
    m_wdgLayerBox->cmbComposite->getModel()->validateCompositeOps(colorSpace);
400
401
402
403
404
}

// range: 0-100
void KisLayerBox::slotSetOpacity(double opacity)
{
Halla Rempt's avatar
Halla Rempt committed
405
    Q_ASSERT(opacity >= 0 && opacity <= 100);
406
407
408
    m_wdgLayerBox->doubleOpacity->blockSignals(true);
    m_wdgLayerBox->doubleOpacity->setValue(opacity);
    m_wdgLayerBox->doubleOpacity->blockSignals(false);
409
410
411
412
413
}

void KisLayerBox::slotContextMenuRequested(const QPoint &pos, const QModelIndex &index)
{
    QMenu menu;
414

Halla Rempt's avatar
Halla Rempt committed
415
    if (index.isValid()) {
416
417
418
        menu.addAction(KIcon("document-properties"), i18n("&Properties..."), this, SLOT(slotPropertiesClicked()));
        menu.addSeparator();
        menu.addAction(KIcon("edit-delete"), i18n("&Remove Layer"), this, SLOT(slotRmClicked()));
419
        menu.addAction(KIcon("edit-duplicate"), i18n("&Duplicate Layer or Mask"), this, SLOT(slotDuplicateClicked()));
420
        QAction* mergeLayerDown = menu.addAction(KIcon("edit-merge"), i18n("&Merge with Layer Below"), this, SLOT(slotMergeLayer()));
421
        if (!index.sibling(index.row() + 1, 0).isValid()) mergeLayerDown->setEnabled(false);
422
        menu.addSeparator();
423
    }
424
425
426
427
    menu.addSeparator();
    menu.addAction(m_newTransparencyMaskAction);
    menu.addAction(m_newEffectMaskAction);
    menu.addAction(m_newSelectionMaskAction);
Halla Rempt's avatar
Halla Rempt committed
428

429
430
431
    menu.exec(pos);
}

432
void KisLayerBox::slotMergeLayer()
433
{
434
    if(!m_canvas) return;
435
    m_nodeManager->mergeLayerDown();
436
437
}

438
439
void KisLayerBox::slotMinimalView()
{
440
    m_wdgLayerBox->listLayers->setDisplayMode(KoDocumentSectionView::MinimalMode);
441
442
443
444
}

void KisLayerBox::slotDetailedView()
{
445
    m_wdgLayerBox->listLayers->setDisplayMode(KoDocumentSectionView::DetailedMode);
446
447
448
449
}

void KisLayerBox::slotThumbnailView()
{
450
    m_wdgLayerBox->listLayers->setDisplayMode(KoDocumentSectionView::ThumbnailMode);
451
452
}

453
void KisLayerBox::slotNewPaintLayer()
454
{
455
    if(!m_canvas) return;
456
    m_nodeManager->createNode("KisPaintLayer");
457
458
459
460
}

void KisLayerBox::slotNewGroupLayer()
{
461
    if(!m_canvas) return;
462
    m_nodeManager->createNode("KisGroupLayer");
463
464
465
466
}

void KisLayerBox::slotNewCloneLayer()
{
467
    if(!m_canvas) return;
468
    m_nodeManager->createNode("KisCloneLayer");
469
470
471
472
473
}


void KisLayerBox::slotNewShapeLayer()
{
474
    if(!m_canvas) return;
475
    m_nodeManager->createNode("KisShapeLayer");
476
477
478
479
480
}


void KisLayerBox::slotNewAdjustmentLayer()
{
481
    if(!m_canvas) return;
482
    m_nodeManager->createNode("KisAdjustmentLayer");
483
484
}

Halla Rempt's avatar
Halla Rempt committed
485
486
void KisLayerBox::slotNewGeneratorLayer()
{
487
    if(!m_canvas) return;
488
    m_nodeManager->createNode("KisGeneratorLayer");
Halla Rempt's avatar
Halla Rempt committed
489
490
}

491
492
void KisLayerBox::slotNewTransparencyMask()
{
493
    if(!m_canvas) return;
494
    m_nodeManager->createNode("KisTransparencyMask");
495
496
497
498
}

void KisLayerBox::slotNewEffectMask()
{
499
    if(!m_canvas) return;
500
    m_nodeManager->createNode("KisFilterMask");
501
502
503
}


504
505
void KisLayerBox::slotNewSelectionMask()
{
506
    if(!m_canvas) return;
507
    m_nodeManager->createNode("KisSelectionMask");
508
509
510
}


511
512
void KisLayerBox::slotRmClicked()
{
513
514
    if(!m_canvas) return;

515
516
    KisNodeSP node = m_nodeManager->activeNode();
    m_nodeManager->removeNode(node);
517
518
519
520
}

void KisLayerBox::slotRaiseClicked()
{
521
    if(!m_canvas) return;
522
    KisNodeSP node = m_nodeManager->activeNode();
523
    KisNodeSP parent = node->parent();
524
525
526
527
528
    KisNodeSP grandParent = parent->parent();

    if (!m_nodeManager->activeNode()->prevSibling()) {
        if (!grandParent) return;  
        if (!grandParent->parent() && node->inherits("KisMask")) return;
529
        m_nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent));
530
531
532
    } else {
        m_nodeManager->raiseNode();
    }
533
534
535
536
}

void KisLayerBox::slotLowerClicked()
{
537
    if(!m_canvas) return;
538
539
540
541
    KisNodeSP node = m_nodeManager->activeNode();
    KisNodeSP parent = node->parent();
    KisNodeSP grandParent = parent->parent();
    
542
    if (!m_nodeManager->activeNode()->nextSibling()) {
543
544
545
        if (!grandParent) return;  
        if (!grandParent->parent() && node->inherits("KisMask")) return;
        m_nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent) + 1);
546
547
548
    } else {
        m_nodeManager->lowerNode();
    }
549
550
}

551
552
void KisLayerBox::slotLeftClicked()
{
553
    if(!m_canvas) return;
554
    KisNodeSP node = m_nodeManager->activeNode();
555
    KisNodeSP parent = node->parent();
José Luis Vergara's avatar
José Luis Vergara committed
556
    KisNodeSP grandParent = parent->parent();
557
    quint16 nodeIndex = parent->index(node);
558
559
560
    
    if (!grandParent) return;  
    if (!grandParent->parent() && node->inherits("KisMask")) return;
José Luis Vergara's avatar
José Luis Vergara committed
561

562
563
564
565
566
    if (nodeIndex <= parent->childCount() / 2) {
        m_nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent));
    } else {
        m_nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent) + 1);
    }
567
568
569
570
}

void KisLayerBox::slotRightClicked()
{
571
    if(!m_canvas) return;
572
573
574
575
576
577
578
579
580
    KisNodeSP node = m_nodeManager->activeNode();
    KisNodeSP parent = m_nodeManager->activeNode()->parent();
    KisNodeSP newParent;
    int nodeIndex = parent->index(node);
    int indexAbove = nodeIndex + 1;
    int indexBelow = nodeIndex - 1;

    if (parent->at(indexBelow) && parent->at(indexBelow)->allowAsChild(node)) {
        newParent = parent->at(indexBelow);
581
        m_nodeManager->moveNodeAt(node, newParent, newParent->childCount());
582
583
    } else if (parent->at(indexAbove) && parent->at(indexAbove)->allowAsChild(node)) {
        newParent = parent->at(indexAbove);
584
        m_nodeManager->moveNodeAt(node, newParent, 0);
585
586
587
    } else {
        return;
    }
588
589
}

590
591
void KisLayerBox::slotPropertiesClicked()
{
592
    if(!m_canvas) return;
593
594
595
    if (KisNodeSP active = m_nodeManager->activeNode()) {
        m_nodeManager->nodeProperties(active);
    }
596
597
598
599
}

void KisLayerBox::slotDuplicateClicked()
{
600
    if(!m_canvas) return;
601
    m_nodeManager->duplicateActiveNode();
602
603
}

604
void KisLayerBox::slotCompositeOpChanged(int index)
605
{
606
607
    if(!m_canvas) return;

608
    KoID compositeOp;
609
    if(m_wdgLayerBox->cmbComposite->entryAt(compositeOp, index))
610
        m_nodeManager->nodeCompositeOpChanged(m_nodeManager->activeColorSpace()->compositeOp(compositeOp.id()));
611
612
}

613
void KisLayerBox::slotOpacityChanged()
614
{
615
    if(!m_canvas) return;
616
    m_nodeManager->nodeOpacityChanged(m_newOpacity, true);
617
618
}

619
620
621
622
623
624
void KisLayerBox::slotOpacitySliderMoved(qreal opacity)
{
    m_newOpacity = opacity;
    m_delayTimer.start(200);
}

625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
void KisLayerBox::slotCollapsed(const QModelIndex &index)
{
    KisNodeSP node = m_nodeModel->nodeFromIndex(index);
    if (node) {
        node->setCollapsed(true);
    }
}

void KisLayerBox::slotExpanded(const QModelIndex &index)
{
    KisNodeSP node = m_nodeModel->nodeFromIndex(index);
    if (node) {
        node->setCollapsed(false);
    }
}
640
641


642
#include "kis_layer_box.moc"