kis_kra_load_visitor.cpp 20.1 KB
Newer Older
1 2
/*
 *  Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
C. Boemann's avatar
C. Boemann committed
3
 *  Copyright (c) 2005 C. Boemann <cbo@boemann.dk>
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 *  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.
 */

20
#include "kis_kra_load_visitor.h"
21
#include "kis_kra_tags.h"
22
#include "flake/kis_shape_layer.h"
Boudewijn Rempt's avatar
Boudewijn Rempt committed
23

24
#include <QRect>
25 26
#include <QBuffer>
#include <QByteArray>
27 28

#include <KoColorSpaceRegistry.h>
29
#include <KoColorProfile.h>
30
#include <KoStore.h>
31
#include <KoColorSpace.h>
32 33

// kritaimage
34 35
#include <metadata/kis_meta_data_io_backend.h>
#include <metadata/kis_meta_data_store.h>
36 37 38 39 40 41 42 43 44 45 46
#include <kis_types.h>
#include <kis_node_visitor.h>
#include <kis_image.h>
#include <kis_selection.h>
#include <kis_layer.h>
#include <kis_paint_layer.h>
#include <kis_group_layer.h>
#include <kis_adjustment_layer.h>
#include <filter/kis_filter_configuration.h>
#include <kis_datamanager.h>
#include <generator/kis_generator_layer.h>
47
#include <kis_pixel_selection.h>
48 49
#include <kis_clone_layer.h>
#include <kis_filter_mask.h>
50
#include <kis_transform_mask.h>
51
#include <kis_transform_mask_params_interface.h>
52
#include "kis_transform_mask_params_factory_registry.h"
53 54
#include <kis_transparency_mask.h>
#include <kis_selection_mask.h>
55 56
#include <lazybrush/kis_colorize_mask.h>
#include <lazybrush/kis_lazy_fill_tools.h>
57
#include "kis_shape_selection.h"
58
#include "kis_colorize_dom_utils.h"
59
#include "kis_dom_utils.h"
60
#include "kis_raster_keyframe_channel.h"
61
#include "kis_paint_device_frames_interface.h"
62

63
using namespace KRA;
64

65 66 67 68 69 70 71 72 73 74 75 76
QString expandEncodedDirectory(const QString& _intern)
{
    QString intern = _intern;

    QString result;
    int pos;
    while ((pos = intern.indexOf('/')) != -1) {
        if (QChar(intern.at(0)).isDigit())
            result += "part";
        result += intern.left(pos + 1);   // copy numbers (or "pictures") + "/"
        intern = intern.mid(pos + 1);   // remove the dir we just processed
    }
77

78 79 80 81 82
    if (!intern.isEmpty() && QChar(intern.at(0)).isDigit())
        result += "part";
    result += intern;
    return result;
}
Boudewijn Rempt's avatar
Boudewijn Rempt committed
83

84

85
KisKraLoadVisitor::KisKraLoadVisitor(KisImageSP image,
Boudewijn Rempt's avatar
Boudewijn Rempt committed
86 87
                                     KoStore *store,
                                     QMap<KisNode *, QString> &layerFilenames,
88
                                     QMap<KisNode *, QString> &keyframeFilenames,
Boudewijn Rempt's avatar
Boudewijn Rempt committed
89 90 91
                                     const QString & name,
                                     int syntaxVersion) :
        KisNodeVisitor(),
92 93
        m_layerFilenames(layerFilenames),
        m_keyframeFilenames(keyframeFilenames)
94 95
{
    m_external = false;
Boudewijn Rempt's avatar
Boudewijn Rempt committed
96
    m_image = image;
97
    m_store = store;
98
    m_name = name;
99
    m_store->pushDirectory();
100
    if (m_name.startsWith("/")) {
101
        m_name.remove(0, 1);
102
    }
103
    if (!m_store->enterDirectory(m_name)) {
104
        QStringList directories = m_store->directoryList();
105
        dbgKrita << directories;
106 107 108 109 110 111 112 113
        if (directories.size() > 0) {
            dbgFile << "Could not locate the directory, maybe some encoding issue? Grab the first directory, that'll be the image one." << m_name << directories;
            m_name = directories.first();
        }
        else {
            dbgFile << "Could not enter directory" << m_name << ", probably an old-style file with 'part' added.";
            m_name = expandEncodedDirectory(m_name);
        }
114 115 116 117
    }
    else {
        m_store->popDirectory();
    }
118
    m_syntaxVersion = syntaxVersion;
119 120
}

121
void KisKraLoadVisitor::setExternalUri(const QString &uri)
122 123 124 125 126
{
    m_external = true;
    m_uri = uri;
}

127
bool KisKraLoadVisitor::visit(KisExternalLayer * layer)
128
{
129
    bool result = false;
130

Boudewijn Rempt's avatar
Boudewijn Rempt committed
131
    if (KisShapeLayer* shapeLayer = dynamic_cast<KisShapeLayer*>(layer)) {
132

Boudewijn Rempt's avatar
Boudewijn Rempt committed
133
        if (!loadMetaData(layer)) {
134 135 136
            return false;
        }

137
        m_store->pushDirectory();
Boudewijn Rempt's avatar
Boudewijn Rempt committed
138 139
        m_store->enterDirectory(getLocation(layer, DOT_SHAPE_LAYER)) ;
        result =  shapeLayer->loadLayer(m_store);
140 141
        m_store->popDirectory();

142
    }
143 144

    result = visitAll(layer) && result;
145
    return result;
146 147
}

148
bool KisKraLoadVisitor::visit(KisPaintLayer *layer)
149
{
150 151
    loadNodeKeyframes(layer);

152
    dbgFile << "Visit: " << layer->name() << " colorSpace: " << layer->colorSpace()->id();
Boudewijn Rempt's avatar
Boudewijn Rempt committed
153
    if (!loadPaintDevice(layer->paintDevice(), getLocation(layer))) {
154
        return false;
155
    }
Boudewijn Rempt's avatar
Boudewijn Rempt committed
156
    if (!loadProfile(layer->paintDevice(), getLocation(layer, DOT_ICC))) {
157
        return false;
158
    }
Boudewijn Rempt's avatar
Boudewijn Rempt committed
159
    if (!loadMetaData(layer)) {
160 161
        return false;
    }
162

Boudewijn Rempt's avatar
Boudewijn Rempt committed
163
    if (m_syntaxVersion == 1) {
164 165 166
        // Check whether there is a file with a .mask extension in the
        // layer directory, if so, it's an old-style transparency mask
        // that should be converted.
Boudewijn Rempt's avatar
Boudewijn Rempt committed
167
        QString location = getLocation(layer, ".mask");
168

Boudewijn Rempt's avatar
Boudewijn Rempt committed
169
        if (m_store->open(location)) {
170 171

            KisSelectionSP selection = KisSelectionSP(new KisSelection());
172
            KisPixelSelectionSP pixelSelection = selection->pixelSelection();
173
            if (!pixelSelection->read(m_store->device())) {
174
                pixelSelection->disconnect();
Boudewijn Rempt's avatar
Boudewijn Rempt committed
175
            } else {
176
                KisTransparencyMask* mask = new KisTransparencyMask();
Boudewijn Rempt's avatar
Boudewijn Rempt committed
177
                mask->setSelection(selection);
Boudewijn Rempt's avatar
Boudewijn Rempt committed
178
                m_image->addNode(mask, layer, layer->firstChild());
179 180
            }
            m_store->close();
181 182
        }
    }
Sven Langkamp's avatar
Sven Langkamp committed
183 184
    bool result = visitAll(layer);
    return result;
185 186
}

187
bool KisKraLoadVisitor::visit(KisGroupLayer *layer)
188
{
189
    if (*layer->colorSpace() != *m_image->colorSpace()) {
190 191 192
        layer->resetCache(m_image->colorSpace());
    }

Boudewijn Rempt's avatar
Boudewijn Rempt committed
193
    if (!loadMetaData(layer)) {
194 195 196
        return false;
    }

197 198
    bool result = visitAll(layer);
    return result;
199 200
}

201
bool KisKraLoadVisitor::visit(KisAdjustmentLayer* layer)
202
{
203 204
    loadNodeKeyframes(layer);

205 206
    // Adjustmentlayers are tricky: there's the 1.x style and the 2.x
    // style, which has selections with selection components
207
    bool result = true;
Boudewijn Rempt's avatar
Boudewijn Rempt committed
208
    if (m_syntaxVersion == 1) {
209
        KisSelectionSP selection = new KisSelection();
210
        KisPixelSelectionSP pixelSelection = selection->pixelSelection();
211
        result = loadPaintDevice(pixelSelection, getLocation(layer, ".selection"));
212
        layer->setInternalSelection(selection);
Boudewijn Rempt's avatar
Boudewijn Rempt committed
213
    } else if (m_syntaxVersion == 2) {
214
        result = loadSelection(getLocation(layer), layer->internalSelection());
215

Boudewijn Rempt's avatar
Boudewijn Rempt committed
216
    } else {
217
        // We use the default, empty selection
218 219
    }

Boudewijn Rempt's avatar
Boudewijn Rempt committed
220
    if (!loadMetaData(layer)) {
221 222 223
        return false;
    }

224
    loadFilterConfiguration(layer->filter().data(), getLocation(layer, DOT_FILTERCONFIG));
225

226
    result = visitAll(layer);
227
    return result;
228 229
}

Boudewijn Rempt's avatar
Boudewijn Rempt committed
230 231
bool KisKraLoadVisitor::visit(KisGeneratorLayer* layer)
{
Boudewijn Rempt's avatar
Boudewijn Rempt committed
232
    if (!loadMetaData(layer)) {
233 234
        return false;
    }
235
    bool result = true;
236

237 238
    loadNodeKeyframes(layer);

239
    result = loadSelection(getLocation(layer), layer->internalSelection());
Boudewijn Rempt's avatar
Boudewijn Rempt committed
240

241
    result = loadFilterConfiguration(layer->filter().data(), getLocation(layer, DOT_FILTERCONFIG));
Dmitry Kazakov's avatar
Dmitry Kazakov committed
242
    layer->update();
Boudewijn Rempt's avatar
Boudewijn Rempt committed
243

244
    result = visitAll(layer);
Sven Langkamp's avatar
Sven Langkamp committed
245
    return result;
Boudewijn Rempt's avatar
Boudewijn Rempt committed
246
}
Boudewijn Rempt's avatar
Boudewijn Rempt committed
247 248 249

bool KisKraLoadVisitor::visit(KisCloneLayer *layer)
{
Boudewijn Rempt's avatar
Boudewijn Rempt committed
250
    if (!loadMetaData(layer)) {
251 252
        return false;
    }
Dmitry Kazakov's avatar
Dmitry Kazakov committed
253

254 255 256 257 258 259
    // the layer might have already been lazily initialized
    // from the mask loading code
    if (layer->copyFrom()) {
        return true;
    }

260
    KisNodeSP srcNode = layer->copyFromInfo().findNode(m_image->rootLayer());
261
    KisLayerSP srcLayer = qobject_cast<KisLayer*>(srcNode.data());
Dmitry Kazakov's avatar
Dmitry Kazakov committed
262 263 264 265
    Q_ASSERT(srcLayer);

    layer->setCopyFrom(srcLayer);

266 267 268
    // Clone layers have no data except for their masks
    bool result = visitAll(layer);
    return result;
Boudewijn Rempt's avatar
Boudewijn Rempt committed
269 270
}

271 272 273 274 275 276 277 278 279 280
void KisKraLoadVisitor::initSelectionForMask(KisMask *mask)
{
    KisLayer *cloneLayer = dynamic_cast<KisCloneLayer*>(mask->parent().data());
    if (cloneLayer) {
        // the clone layers should be initialized out of order
        // and lazily, because their original() is still not
        // initialized
        cloneLayer->accept(*this);
    }

281
    KisLayer *parentLayer = qobject_cast<KisLayer*>(mask->parent().data());
282 283
    // the KisKraLoader must have already set the parent for us
    Q_ASSERT(parentLayer);
284
    mask->initSelection(parentLayer);
285 286
}

Boudewijn Rempt's avatar
Boudewijn Rempt committed
287 288
bool KisKraLoadVisitor::visit(KisFilterMask *mask)
{
289
    initSelectionForMask(mask);
290 291 292

    loadNodeKeyframes(mask);

293 294 295 296
    bool result = true;
    result = loadSelection(getLocation(mask), mask->selection());
    result = loadFilterConfiguration(mask->filter().data(), getLocation(mask, DOT_FILTERCONFIG));
    return result;
Boudewijn Rempt's avatar
Boudewijn Rempt committed
297 298
}

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
bool KisKraLoadVisitor::visit(KisTransformMask *mask)
{
    QString location = getLocation(mask, DOT_TRANSFORMCONFIG);
    if (m_store->hasFile(location)) {
        QByteArray data;
        m_store->open(location);
        data = m_store->read(m_store->size());
        m_store->close();
        if (!data.isEmpty()) {
            QDomDocument doc;
            doc.setContent(data);

            QDomElement rootElement = doc.documentElement();

            QDomElement main;

            if (!KisDomUtils::findOnlyElement(rootElement, "main", &main/*, &m_errorMessages*/)) {
                return false;
            }

            QString id = main.attribute("id", "not-valid");

            if (id == "not-valid") {
                m_errorMessages << i18n("Could not load \"id\" of the transform mask");
                return false;
            }

            QDomElement data;

            if (!KisDomUtils::findOnlyElement(rootElement, "data", &data, &m_errorMessages)) {
                return false;
            }

            KisTransformMaskParamsInterfaceSP params =
                KisTransformMaskParamsFactoryRegistry::instance()->createParams(id, data);

            if (!params) {
                m_errorMessages << i18n("Could not create transform mask params");
                return false;
            }

            mask->setTransformParams(params);
341 342 343 344

            loadNodeKeyframes(mask);
            params->clearChangedFlag();

345 346 347 348 349 350 351
            return true;
        }
    }

    return false;
}

Boudewijn Rempt's avatar
Boudewijn Rempt committed
352 353
bool KisKraLoadVisitor::visit(KisTransparencyMask *mask)
{
354
    initSelectionForMask(mask);
355

356 357
    loadNodeKeyframes(mask);

358
    return loadSelection(getLocation(mask), mask->selection());
Boudewijn Rempt's avatar
Boudewijn Rempt committed
359 360 361 362
}

bool KisKraLoadVisitor::visit(KisSelectionMask *mask)
{
363
    initSelectionForMask(mask);
364
    return loadSelection(getLocation(mask), mask->selection());
Boudewijn Rempt's avatar
Boudewijn Rempt committed
365
}
366

367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398
bool KisKraLoadVisitor::visit(KisColorizeMask *mask)
{
    m_store->pushDirectory();
    QString location = getLocation(mask, DOT_COLORIZE_MASK);
    m_store->enterDirectory(location) ;

    QByteArray data;
    if (!m_store->extractFile("content.xml", data))
        return false;

    QDomDocument doc;
    if (!doc.setContent(data))
        return false;

    QVector<KisLazyFillTools::KeyStroke> strokes;
    if (!KisDomUtils::loadValue(doc.documentElement(), COLORIZE_KEYSTROKES_SECTION, &strokes, mask->colorSpace()))
        return false;

    int i = 0;
    Q_FOREACH (const KisLazyFillTools::KeyStroke &stroke, strokes) {
        const QString fileName = QString("%1_%2").arg(COLORIZE_KEYSTROKE).arg(i++);
        loadPaintDevice(stroke.dev, fileName);
    }

    mask->setKeyStrokesDirect(QList<KisLazyFillTools::KeyStroke>::fromVector(strokes));

    loadPaintDevice(mask->coloringProjection(), COLORIZE_COLORING_DEVICE);

    m_store->popDirectory();
    return true;
}

399 400 401 402 403
QStringList KisKraLoadVisitor::errorMessages() const
{
    return m_errorMessages;
}

404 405 406 407 408 409
struct SimpleDevicePolicy
{
    bool read(KisPaintDeviceSP dev, QIODevice *stream) {
        return dev->read(stream);
    }

410
    void setDefaultPixel(KisPaintDeviceSP dev, const KoColor &defaultPixel) const {
411 412 413 414 415 416 417 418 419 420 421 422 423
        return dev->setDefaultPixel(defaultPixel);
    }
};

struct FramedDevicePolicy
{
    FramedDevicePolicy(int frameId)
        :  m_frameId(frameId) {}

    bool read(KisPaintDeviceSP dev, QIODevice *stream) {
        return dev->framesInterface()->readFrame(stream, m_frameId);
    }

424
    void setDefaultPixel(KisPaintDeviceSP dev, const KoColor &defaultPixel) const {
425 426 427 428 429 430
        return dev->framesInterface()->setFrameDefaultPixel(defaultPixel, m_frameId);
    }

    int m_frameId;
};

Boudewijn Rempt's avatar
Boudewijn Rempt committed
431
bool KisKraLoadVisitor::loadPaintDevice(KisPaintDeviceSP device, const QString& location)
432 433
{
    // Layer data
434

435 436 437 438 439 440 441 442
    KisPaintDeviceFramesInterface *frameInterface = device->framesInterface();
    QList<int> frames;

    if (frameInterface) {
        frames = device->framesInterface()->frames();
    }

    if (!frameInterface || frames.count() <= 1) {
443
        return loadPaintDeviceFrame(device, location, SimpleDevicePolicy());
444 445 446 447 448 449 450 451
    } else {
        KisRasterKeyframeChannel *keyframeChannel = device->keyframeChannel();

        for (int i = 0; i < frames.count(); i++) {
            int id = frames[i];
            QString frameFilename = getLocation(keyframeChannel->frameFilename(id));
            Q_ASSERT(!frameFilename.isEmpty());

452
            if (!loadPaintDeviceFrame(device, frameFilename, FramedDevicePolicy(id))) {
453 454 455 456 457 458 459 460
                return false;
            }
        }
    }

    return true;
}

461 462
template<class DevicePolicy>
bool KisKraLoadVisitor::loadPaintDeviceFrame(KisPaintDeviceSP device, const QString &location, DevicePolicy policy)
463
{
464
    if (m_store->open(location)) {
465
        if (!policy.read(device, m_store->device())) {
466
            m_errorMessages << i18n("Could not read pixel data: %1.", location);
467 468 469 470 471 472
            device->disconnect();
            m_store->close();
            return false;
        }
        m_store->close();
    } else {
473
        m_errorMessages << i18n("Could not load pixel data: %1.", location);
474 475
        return false;
    }
Cyrille Berger's avatar
Cyrille Berger committed
476 477 478
    if (m_store->open(location + ".defaultpixel")) {
        int pixelSize = device->colorSpace()->pixelSize();
        if (m_store->size() == pixelSize) {
479 480 481
            KoColor color(Qt::transparent, device->colorSpace());
            m_store->read((char*)color.data(), pixelSize);
            policy.setDefaultPixel(device, color);
Cyrille Berger's avatar
Cyrille Berger committed
482 483 484
        }
        m_store->close();
    }
485

486
    return true;
487 488 489
}


Boudewijn Rempt's avatar
Boudewijn Rempt committed
490
bool KisKraLoadVisitor::loadProfile(KisPaintDeviceSP device, const QString& location)
491 492 493 494
{

    if (m_store->hasFile(location)) {
        m_store->open(location);
Cyrille Berger's avatar
Cyrille Berger committed
495
        QByteArray data; data.resize(m_store->size());
496
        dbgFile << "Data to load: " << m_store->size() << " from " << location << " with color space " << device->colorSpace()->id();
Boudewijn Rempt's avatar
Boudewijn Rempt committed
497
        int read = m_store->read(data.data(), m_store->size());
Cyrille Berger's avatar
Cyrille Berger committed
498
        dbgFile << "Profile size: " << data.size() << " " << m_store->atEnd() << " " << m_store->device()->bytesAvailable() << " " << read;
499 500
        m_store->close();
        // Create a colorspace with the embedded profile
501
        const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(device->colorSpace()->colorModelId().id(), device->colorSpace()->colorDepthId().id(), data);
502
        if (device->setProfile(profile)) {
503 504
            return true;
        }
505
    }
506
    m_errorMessages << i18n("Could not load profile %1.", location);
507
    return false;
508 509
}

510
bool KisKraLoadVisitor::loadFilterConfiguration(KisFilterConfigurationSP kfc, const QString& location)
511
{
Boudewijn Rempt's avatar
Boudewijn Rempt committed
512
    if (m_store->hasFile(location)) {
513 514 515 516 517
        QByteArray data;
        m_store->open(location);
        data = m_store->read(m_store->size());
        m_store->close();
        if (!data.isEmpty()) {
518 519 520 521 522 523 524 525 526
            QString xml(data);
            QDomDocument doc;
            doc.setContent(data);
            QDomElement e = doc.documentElement();
            if (e.tagName() == "filterconfig") {
                kfc->fromLegacyXML(e);
            } else {
                kfc->fromXML(e);
            }
527
            return true;
528 529
        }
    }
530
    m_errorMessages << i18n("Could not filter configuration %1.", location);
531
    return false;
532 533
}

Boudewijn Rempt's avatar
Boudewijn Rempt committed
534
bool KisKraLoadVisitor::loadMetaData(KisNode* node)
535
{
536
    dbgFile << "Load metadata for " << node->name();
Boudewijn Rempt's avatar
Boudewijn Rempt committed
537 538
    KisLayer* layer = qobject_cast<KisLayer*>(node);
    if (!layer) return true;
539 540 541 542 543

    bool result = true;

    KisMetaData::IOBackend* backend = KisMetaData::IOBackendRegistry::instance()->get("xmp");

544
    if (!backend || !backend->supportLoading()) {
545 546 547 548
        if (backend)
            dbgFile << "Backend " << backend->id() << " does not support loading.";
        else
            dbgFile << "Could not load the XMP backenda t all";
549
        return true;
550 551
    }

Boudewijn Rempt's avatar
Boudewijn Rempt committed
552
    QString location = getLocation(node, QString(".") + backend->id() +  DOT_METADATA);
553 554
    dbgFile << "going to load " << backend->id() << ", " << backend->name() << " from " << location;

Boudewijn Rempt's avatar
Boudewijn Rempt committed
555
    if (m_store->hasFile(location)) {
556
        QByteArray data;
Boudewijn Rempt's avatar
Boudewijn Rempt committed
557 558
        m_store->open(location);
        data = m_store->read(m_store->size());
559
        m_store->close();
Boudewijn Rempt's avatar
Boudewijn Rempt committed
560 561
        QBuffer buffer(&data);
        if (!backend->loadFrom(layer->metaData(), &buffer)) {
562
            m_errorMessages << i18n("Could not load metadata for layer %1.", layer->name());
563 564 565 566 567 568 569
            result = false;
        }

    }
    return result;
}

570
bool KisKraLoadVisitor::loadSelection(const QString& location, KisSelectionSP dstSelection)
571
{
572
    // Pixel selection
573
    bool result = true;
574
    QString pixelSelectionLocation = location + DOT_PIXEL_SELECTION;
Boudewijn Rempt's avatar
Boudewijn Rempt committed
575
    if (m_store->hasFile(pixelSelectionLocation)) {
576
        KisPixelSelectionSP pixelSelection = dstSelection->pixelSelection();
577
        result = loadPaintDevice(pixelSelection, pixelSelectionLocation);
578 579 580
        if (!result) {
            m_errorMessages << i18n("Could not load raster selection %1.", location);
        }
581
        pixelSelection->invalidateOutlineCache();
582 583 584 585
    }

    // Shape selection
    QString shapeSelectionLocation = location + DOT_SHAPE_SELECTION;
586 587 588
    if (m_store->hasFile(shapeSelectionLocation + "/content.svg") ||
        m_store->hasFile(shapeSelectionLocation + "/content.xml")) {

589
        m_store->pushDirectory();
Boudewijn Rempt's avatar
Boudewijn Rempt committed
590
        m_store->enterDirectory(shapeSelectionLocation) ;
591

592 593
        KisShapeSelection* shapeSelection = new KisShapeSelection(m_image, dstSelection);
        dstSelection->setShapeSelection(shapeSelection);
594
        result = shapeSelection->loadSelection(m_store);
595
        m_store->popDirectory();
596
        if (!result) {
Yuri Chornoivan's avatar
Yuri Chornoivan committed
597
            m_errorMessages << i18n("Could not load vector selection %1.", location);
598
        }
599
    }
600
    return result;
601
}
602

Boudewijn Rempt's avatar
Boudewijn Rempt committed
603
QString KisKraLoadVisitor::getLocation(KisNode* node, const QString& suffix)
604 605 606 607 608
{
    return getLocation(m_layerFilenames[node], suffix);
}

QString KisKraLoadVisitor::getLocation(const QString &filename, const QString& suffix)
609
{
610
    QString location = m_external ? QString() : m_uri;
611
    location += m_name + LAYER_PATH + filename + suffix;
612 613
    return location;
}
614 615 616 617 618

void KisKraLoadVisitor::loadNodeKeyframes(KisNode *node)
{
    if (!m_keyframeFilenames.contains(node)) return;

619 620
    node->enableAnimation();

621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
    const QString &location = getLocation(m_keyframeFilenames[node]);

    if (!m_store->open(location)) {
        m_errorMessages << i18n("Could not load keyframes from %1.", location);
        return;
    }

    QString errorMsg;
    int errorLine;
    int errorColumn;
    KoXmlDocument doc = KoXmlDocument(true);

    bool ok = doc.setContent(m_store->device(), &errorMsg, &errorLine, &errorColumn);
    m_store->close();

    if (!ok) {
        m_errorMessages << i18n("parsing error in the keyframe file %1 at line %2, column %3\nError message: %4", location, errorLine, errorColumn, i18n(errorMsg.toUtf8()));
        return;
    }

    QDomDocument dom;
    KoXml::asQDomElement(dom, doc.documentElement());
    QDomElement root = dom.firstChildElement();

    for (QDomElement child = root.firstChildElement(); !child.isNull(); child = child.nextSiblingElement()) {
        if (child.nodeName().toUpper() == "CHANNEL") {
            QString id = child.attribute("name");
648
            KisKeyframeChannel *channel = node->getKeyframeChannel(id, true);
649 650 651 652 653 654 655 656 657 658

            if (!channel) {
                m_errorMessages << i18n("unknown keyframe channel type: %1 in %2", id, location);
                continue;
            }

            channel->loadXML(child);
        }
    }
}