DlgAnimationRenderer.cpp 11.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 *  Copyright (c) 2016 Boudewijn Rempt <boud@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 "DlgAnimationRenderer.h"

21
#include <QStandardPaths>
22 23
#include <QPluginLoader>
#include <QJsonObject>
24
#include <QMessageBox>
25 26 27 28 29 30 31 32 33

#include <klocalizedstring.h>
#include <kpluginfactory.h>

#include <kis_properties_configuration.h>
#include <kis_debug.h>
#include <KisMimeDatabase.h>
#include <KoJsonTrader.h>
#include <KisImportExportFilter.h>
34 35 36
#include <kis_image.h>
#include <kis_image_animation_interface.h>
#include <kis_time_range.h>
37
#include <KisImportExportManager.h>
38 39 40
#include <kis_config_widget.h>
#include <KisDocument.h>
#include <QHBoxLayout>
41
#include <KisImportExportFilter.h>
42 43
#include <kis_config.h>
#include <kis_file_name_requester.h>
44

45
DlgAnimationRenderer::DlgAnimationRenderer(KisImageWSP image, QWidget *parent)
46
    : KoDialog(parent)
47
    , m_image(image)
48 49 50 51 52 53 54
{
    setCaption(i18n("Render Animation"));
    setButtons(Ok | Cancel);
    setDefaultButton(Ok);

    m_page = new WdgAnimaterionRenderer(this);
    m_page->layout()->setMargin(0);
55
    m_page->dirRequester->setMode(KoFileDialog::OpenDirectory);
56
    m_page->dirRequester->setFileName(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
57 58 59 60 61 62 63 64 65

    m_page->intStart->setMinimum(image->animationInterface()->fullClipRange().start());
    m_page->intStart->setMaximum(image->animationInterface()->fullClipRange().end());
    m_page->intStart->setValue(image->animationInterface()->playbackRange().start());

    m_page->intEnd->setMinimum(image->animationInterface()->fullClipRange().start());
    m_page->intEnd->setMaximum(image->animationInterface()->fullClipRange().end());
    m_page->intEnd->setValue(image->animationInterface()->playbackRange().end());

66
    m_sequenceConfigLayout = new QHBoxLayout(m_page->grpExportOptions);
67
    m_encoderConfigLayout = new QHBoxLayout(m_page->grpRenderOptions);
68

69 70 71 72 73 74 75 76 77 78 79 80 81 82
    QStringList mimes = KisImportExportManager::mimeFilter(KisImportExportManager::Export);
    mimes.sort();
    Q_FOREACH(const QString &mime, mimes) {
        QString description = KisMimeDatabase::descriptionForMimeType(mime);
        if (description.isEmpty()) {
            description = mime;
        }
        m_page->cmbMimetype->addItem(description, mime);
        if (mime == "image/png") {
            m_page->cmbMimetype->setCurrentIndex(m_page->cmbMimetype->count() - 1);
        }

    }

83 84 85 86 87 88 89
    setMainWidget(m_page);
    resize(m_page->sizeHint());

    KoJsonTrader trader;
    QList<QPluginLoader *>list = trader.query("Krita/AnimationExporter", "");
    Q_FOREACH(QPluginLoader *loader, list) {
        QJsonObject json = loader->metaData().value("MetaData").toObject();
90
        Q_FOREACH(const QString &mime, json.value("X-KDE-Export").toString().split(",")) {
91 92 93 94 95 96 97

            KLibFactory *factory = qobject_cast<KLibFactory *>(loader->instance());
            if (!factory) {
                warnUI << loader->errorString();
                continue;
            }

98
            QObject* obj = factory->create<KisImportExportFilter>(0);
99 100 101 102 103
            if (!obj || !obj->inherits("KisImportExportFilter")) {
                delete obj;
                continue;
            }

104
            QSharedPointer<KisImportExportFilter>filter(static_cast<KisImportExportFilter*>(obj));
105 106 107 108 109
            if (!filter) {
                delete obj;
                continue;
            }

Boudewijn Rempt's avatar
Boudewijn Rempt committed
110
            m_renderFilters.append(filter);
111

112 113 114 115 116
            QString description = KisMimeDatabase::descriptionForMimeType(mime);
            if (description.isEmpty()) {
                description = mime;
            }
            m_page->cmbRenderType->addItem(description, mime);
117 118
        }
    }
119
    qDeleteAll(list);
120
    connect(m_page->cmbRenderType, SIGNAL(activated(int)), this, SLOT(selectRenderType(int)));
121
    selectRenderType(m_page->cmbRenderType->currentIndex());
122
    connect(m_page->grpRender, SIGNAL(toggled(bool)), this, SLOT(toggleSequenceType(bool)));
123 124
    connect(m_page->cmbMimetype, SIGNAL(activated(int)), this, SLOT(sequenceMimeTypeSelected(int)));
    sequenceMimeTypeSelected(m_page->cmbMimetype->currentIndex());
125 126 127 128 129

    KisConfig cfg;
    QString ffmpeg = cfg.readEntry<QString>("ffmpeg_location", "");
    m_page->ffmpegLocation->setFileName(ffmpeg);
    connect(m_page->ffmpegLocation, SIGNAL(fileSelected(QString)), this, SLOT(ffmpegLocationChanged(QString)));
130 131
}

132
DlgAnimationRenderer::~DlgAnimationRenderer()
133
{
134 135 136 137 138
    m_encoderConfigWidget->setParent(0);
    m_encoderConfigWidget->deleteLater();
    m_frameExportConfigWidget->setParent(0);
    m_frameExportConfigWidget->deleteLater();

139
    delete m_page;
140

141 142
}

143
KisPropertiesConfigurationSP DlgAnimationRenderer::getSequenceConfiguration() const
144 145 146 147 148 149 150
{
    KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration();
    cfg->setProperty("basename", m_page->txtBasename->text());
    cfg->setProperty("directory", m_page->dirRequester->fileName());
    cfg->setProperty("first_frame", m_page->intStart->value());
    cfg->setProperty("last_frame", m_page->intEnd->value());
    cfg->setProperty("sequence_start", m_page->sequenceStart->value());
151
    cfg->setProperty("mimetype", m_page->cmbMimetype->currentData().toString());
152 153 154
    return cfg;
}

155
void DlgAnimationRenderer::setSequenceConfiguration(KisPropertiesConfigurationSP cfg)
156 157 158 159 160 161
{
    m_page->txtBasename->setText(cfg->getString("basename", "frame"));
    m_page->dirRequester->setFileName(cfg->getString("directory", QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)));
    m_page->intStart->setValue(cfg->getInt("first_frame", m_image->animationInterface()->playbackRange().start()));
    m_page->intEnd->setValue(cfg->getInt("last_frame", m_image->animationInterface()->playbackRange().end()));
    m_page->sequenceStart->setValue(cfg->getInt("sequence_start", m_image->animationInterface()->playbackRange().start()));
162 163 164 165
    QString mimetype = cfg->getString("mimetype");
    for (int i = 0; i < m_page->cmbMimetype->count(); ++i) {
        if (m_page->cmbMimetype->itemData(i).toString() == mimetype) {
            m_page->cmbMimetype->setCurrentIndex(i);
166
            sequenceMimeTypeSelected(i);
167 168 169
            break;
        }
    }
170 171
}

172
KisPropertiesConfigurationSP DlgAnimationRenderer::getFrameExportConfiguration() const
173
{
174 175
    if (m_frameExportConfigWidget) {
        return m_frameExportConfigWidget->configuration();
176 177 178 179
    }
    return 0;
}

180
bool DlgAnimationRenderer::renderToVideo() const
181 182 183 184
{
    return m_page->grpRender->isChecked();
}

185
KisPropertiesConfigurationSP DlgAnimationRenderer::getVideoConfiguration() const
186
{
187
    if (!m_page->grpRender->isChecked()) {
188 189 190 191 192 193 194 195
        return 0;
    }
    KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration();
    cfg->setProperty("filename", m_page->videoFilename->fileName());
    cfg->setProperty("delete_sequence", m_page->chkDeleteSequence->isChecked());
    return cfg;
}

196
void DlgAnimationRenderer::setVideoConfiguration(KisPropertiesConfigurationSP cfg)
197 198 199
{
}

200
KisPropertiesConfigurationSP DlgAnimationRenderer::getEncoderConfiguration() const
201
{
202
    if (!m_page->grpRender->isChecked()) {
203 204 205
        return 0;
    }
    KisPropertiesConfigurationSP cfg = new KisPropertiesConfiguration();
206 207

    cfg->setProperty("mimetype", m_page->cmbRenderType->currentData().toString());
208 209 210
    return cfg;
}

211
void DlgAnimationRenderer::setEncoderConfiguration(KisPropertiesConfigurationSP cfg)
212 213 214 215
{

}

216 217 218 219 220
QSharedPointer<KisImportExportFilter> DlgAnimationRenderer::encoderFilter() const
{
    if (m_page->cmbRenderType->currentIndex() < m_renderFilters.size()) {
        return m_renderFilters[m_page->cmbRenderType->currentIndex()];
    }
Boudewijn Rempt's avatar
Boudewijn Rempt committed
221
    return QSharedPointer<KisImportExportFilter>(0);
222 223
}

224
void DlgAnimationRenderer::selectRenderType(int index)
225
{
226 227 228 229 230 231 232 233 234 235 236
    if (m_encoderConfigWidget) {
        m_encoderConfigLayout->removeWidget(m_encoderConfigWidget);
        m_encoderConfigWidget->hide();
        m_encoderConfigWidget->setParent(0);
        m_encoderConfigWidget->deleteLater();
        m_encoderConfigWidget = 0;
    }

    if (index >= m_renderFilters.size()) return;

    QSharedPointer<KisImportExportFilter> filter = m_renderFilters[index];
237
    QString mimetype = m_page->cmbRenderType->itemData(index).toString();
238 239 240 241 242 243 244 245 246 247 248 249 250

    if (filter) {
        m_encoderConfigWidget = filter->createConfigurationWidget(m_page->grpExportOptions, KisDocument::nativeFormatMimeType(), mimetype.toLatin1());
        if (m_encoderConfigWidget) {
            m_encoderConfigLayout->addWidget(m_encoderConfigWidget);
            m_encoderConfigWidget->setConfiguration(filter->lastSavedConfiguration());
            m_encoderConfigWidget->show();
            resize(sizeHint());
        }
        else {
            m_encoderConfigWidget = 0;
        }
    }
251
}
252

253
void DlgAnimationRenderer::toggleSequenceType(bool toggle)
254 255 256 257 258 259 260 261 262
{
    m_page->cmbMimetype->setEnabled(!toggle);
    for (int i = 0; i < m_page->cmbMimetype->count(); ++i) {
        if (m_page->cmbMimetype->itemData(i).toString() == "image/png") {
            m_page->cmbMimetype->setCurrentIndex(i);
            break;
        }
    }
}
263

264
void DlgAnimationRenderer::sequenceMimeTypeSelected(int index)
265
{
266 267 268 269 270 271
    if (m_frameExportConfigWidget) {
        m_sequenceConfigLayout->removeWidget(m_frameExportConfigWidget);
        m_frameExportConfigWidget->hide();
        m_frameExportConfigWidget->setParent(0);
        m_frameExportConfigWidget->deleteLater();
        m_frameExportConfigWidget = 0;
272 273
    }
    QString mimetype = m_page->cmbMimetype->itemData(index).toString();
274 275
    KisImportExportFilter *filter = KisImportExportManager::filterForMimeType(mimetype, KisImportExportManager::Export);
    if (filter) {
276 277 278 279 280
        m_frameExportConfigWidget = filter->createConfigurationWidget(m_page->grpExportOptions, KisDocument::nativeFormatMimeType(), mimetype.toLatin1());
        if (m_frameExportConfigWidget) {
            m_sequenceConfigLayout->addWidget(m_frameExportConfigWidget);
            m_frameExportConfigWidget->setConfiguration(filter->lastSavedConfiguration());
            m_frameExportConfigWidget->show();
281
            resize(sizeHint());
282
        }
283
        else {
284
            m_frameExportConfigWidget = 0;
285
        }
286
        delete filter;
287 288
    }
}
289

290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
void DlgAnimationRenderer::ffmpegLocationChanged(const QString &s)
{
    KisConfig cfg;
    cfg.writeEntry<QString>("ffmpeg_location", s);
}

void DlgAnimationRenderer::slotButtonClicked(int button)
{

    if (button == KoDialog::Ok && m_page->grpRender->isChecked()) {
        QString ffmpeg = m_page->ffmpegLocation->fileName();
        if (ffmpeg.isEmpty()) {
            QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The location of FFmpeg is unknown. Please install FFmpeg first: Krita cannot render animations without FFmpeg. (<a href=\"https://www.ffmpeg.org\">www.ffmpeg.org</a>)"));
            return;
        }
        else {
            QFileInfo fi(ffmpeg);
            if (!fi.exists()) {
                QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The location of FFmpeg is invalid. Please select the correct location of the FFmpeg executable on your system."));
            }
            return;
        }
    }
    KoDialog::slotButtonClicked(button);
}