diff --git a/libs/resources/KoResourceBundle.cpp b/libs/resources/KoResourceBundle.cpp index 47c7b98898..79735398a0 100644 --- a/libs/resources/KoResourceBundle.cpp +++ b/libs/resources/KoResourceBundle.cpp @@ -1,460 +1,445 @@ /* * Copyright (c) 2014 Victor Lafon metabolic.ewilan@hotmail.fr * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoResourceBundle.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "KoResourceBundleManifest.h" #include #include #include #include #include #include "KisStoragePlugin.h" #include "KisResourceLoaderRegistry.h" #include #include #include #include KoResourceBundle::KoResourceBundle(QString const& fileName) : m_filename(fileName), m_bundleVersion("1") { m_metadata[KisResourceStorage::s_meta_generator] = "Krita (" + KritaVersionWrapper::versionString(true) + ")"; } KoResourceBundle::~KoResourceBundle() { } QString KoResourceBundle::defaultFileExtension() const { return QString(".bundle"); } bool KoResourceBundle::load() { if (m_filename.isEmpty()) return false; QScopedPointer resourceStore(KoStore::createStore(m_filename, KoStore::Read, "application/x-krita-resourcebundle", KoStore::Zip)); if (!resourceStore || resourceStore->bad()) { qWarning() << "Could not open store on bundle" << m_filename; return false; } else { m_metadata.clear(); if (resourceStore->open("META-INF/manifest.xml")) { if (!m_manifest.load(resourceStore->device())) { qWarning() << "Could not open manifest for bundle" << m_filename; return false; } resourceStore->close(); Q_FOREACH (KoResourceBundleManifest::ResourceReference ref, m_manifest.files()) { if (!resourceStore->open(ref.resourcePath)) { qWarning() << "Bundle is broken. File" << ref.resourcePath << "is missing"; } else { resourceStore->close(); } } } else { qWarning() << "Could not load META-INF/manifest.xml"; return false; } bool versionFound = false; if (!readMetaData(resourceStore.data())) { qWarning() << "Could not load meta.xml"; return false; } if (resourceStore->open("preview.png")) { // Workaround for some OS (Debian, Ubuntu), where loading directly from the QIODevice // fails with "libpng error: IDAT: CRC error" QByteArray data = resourceStore->device()->readAll(); QBuffer buffer(&data); m_thumbnail.load(&buffer, "PNG"); resourceStore->close(); } else { qWarning() << "Could not open preview.png"; } /* * If no version is found it's an old bundle with md5 hashes to fix, or if some manifest resource entry * doesn't not correspond to a file the bundle is "broken", in both cases we need to recreate the bundle. */ if (!versionFound) { m_metadata.insert(KisResourceStorage::s_meta_version, "1"); } } return true; } bool KoResourceBundle::loadFromDevice(QIODevice *) { return false; } bool saveResourceToStore(KoResourceSP resource, KoStore *store, const QString &resType) { if (!resource) { qWarning() << "No Resource"; return false; } if (!resource->valid()) { qWarning() << "Resource is not valid"; return false; } if (!store || store->bad()) { qWarning() << "No Store or Store is Bad"; return false; } QByteArray ba; QBuffer buf; + buf.open(QFile::ReadWrite); - QFileInfo fi(resource->filename()); - if (fi.exists() && fi.isReadable()) { - - QFile f(resource->filename()); - if (!f.open(QFile::ReadOnly)) { - qWarning() << "Could not open resource" << resource->filename(); - return false; - } - ba = f.readAll(); - if (ba.size() == 0) { - qWarning() << "Resource is empty" << resource->filename(); - return false; - } - f.close(); - buf.setBuffer(&ba); - } - else { - qWarning() << "Could not find the resource " << resource->filename() << " or it isn't readable"; + bool response = resource->saveToDevice(&buf); + if (!response) { + ENTER_FUNCTION() << "Cannot save to device"; return false; } - if (!buf.open(QBuffer::ReadOnly)) { - qWarning() << "Could not open buffer"; - return false; - } - Q_ASSERT(!store->hasFile(resType + "/" + resource->filename())); if (!store->open(resType + "/" + resource->filename())) { qWarning() << "Could not open file in store for resource"; return false; } - bool res = (store->write(buf.data()) == buf.size()); + qint64 size = store->write(buf.data()); store->close(); - return res; - + buf.close(); + if (size != buf.size()) { + ENTER_FUNCTION() << "Cannot save to the store" << size << buf.size(); + } + return size == buf.size(); } bool KoResourceBundle::save() { if (m_filename.isEmpty()) return false; setMetaData(KisResourceStorage::s_meta_dc_date, QDate::currentDate().toString("dd/MM/yyyy")); QDir bundleDir = KoResourcePaths::saveLocation("data", "bundles"); bundleDir.cdUp(); QScopedPointer store(KoStore::createStore(m_filename, KoStore::Write, "application/x-krita-resourcebundle", KoStore::Zip)); if (!store || store->bad()) return false; Q_FOREACH (const QString &resType, m_manifest.types()) { KisResourceModel* model = KisResourceModelProvider::resourceModel(resType); Q_FOREACH (const KoResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { KoResourceSP res = model->resourceForMD5(ref.md5sum); if (!res) res = model->resourceForFilename(QFileInfo(ref.resourcePath).fileName()); + qDebug() << "res is or isn't found: " << (res.isNull() ? "(null)" : res->name()); if (!saveResourceToStore(res, store.data(), resType)) { if (res) { qWarning() << "Could not save resource" << resType << res->name(); } else { qWarning() << "could not find resource for" << QFileInfo(ref.resourcePath).fileName(); } } } } if (!m_thumbnail.isNull()) { QByteArray byteArray; QBuffer buffer(&byteArray); m_thumbnail.save(&buffer, "PNG"); if (!store->open("preview.png")) qWarning() << "Could not open preview.png"; if (store->write(byteArray) != buffer.size()) qWarning() << "Could not write preview.png"; store->close(); } saveManifest(store); saveMetadata(store); store->finalize(); return true; } bool KoResourceBundle::saveToDevice(QIODevice */*dev*/) const { return false; } void KoResourceBundle::setMetaData(const QString &key, const QString &value) { m_metadata.insert(key, value); } const QString KoResourceBundle::metaData(const QString &key, const QString &defaultValue) const { if (m_metadata.contains(key)) { return m_metadata[key]; } else { return defaultValue; } } -void KoResourceBundle::addResource(QString fileType, QString filePath, QVector fileTagList, const QByteArray md5sum) +void KoResourceBundle::addResource(QString resourceType, QString filePath, QVector fileTagList, const QByteArray md5sum) { QStringList tags; Q_FOREACH(KisTagSP tag, fileTagList) { tags << tag->url(); } - m_manifest.addResource(fileType, filePath, tags, md5sum); + m_manifest.addResource(resourceType, filePath, tags, md5sum); } QList KoResourceBundle::getTagsList() { return QList::fromSet(m_bundletags); } QStringList KoResourceBundle::resourceTypes() const { return m_manifest.types(); } void KoResourceBundle::setThumbnail(QString filename) { if (QFileInfo(filename).exists()) { m_thumbnail = QImage(filename); m_thumbnail = m_thumbnail.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation); } else { m_thumbnail = QImage(256, 256, QImage::Format_ARGB32); QPainter gc(&m_thumbnail); gc.fillRect(0, 0, 256, 256, Qt::red); gc.end(); } } void KoResourceBundle::writeMeta(const QString &metaTag, KoXmlWriter *writer) { if (m_metadata.contains(metaTag)) { writer->startElement(metaTag.toUtf8()); writer->addTextNode(m_metadata[metaTag].toUtf8()); writer->endElement(); } } void KoResourceBundle::writeUserDefinedMeta(const QString &metaTag, KoXmlWriter *writer) { if (m_metadata.contains(metaTag)) { writer->startElement("meta:meta-userdefined"); writer->addAttribute("meta:name", metaTag); writer->addAttribute("meta:value", m_metadata[metaTag]); writer->endElement(); } } bool KoResourceBundle::readMetaData(KoStore *resourceStore) { if (resourceStore->open("meta.xml")) { KoXmlDocument doc; if (!doc.setContent(resourceStore->device())) { qWarning() << "Could not parse meta.xml for" << m_filename; return false; } // First find the manifest:manifest node. KoXmlNode n = doc.firstChild(); for (; !n.isNull(); n = n.nextSibling()) { if (!n.isElement()) { continue; } if (n.toElement().tagName() == "meta:meta") { break; } } if (n.isNull()) { qWarning() << "Could not find manifest node for bundle" << m_filename; return false; } const KoXmlElement metaElement = n.toElement(); for (n = metaElement.firstChild(); !n.isNull(); n = n.nextSibling()) { if (n.isElement()) { KoXmlElement e = n.toElement(); if (e.tagName() == "meta:meta-userdefined") { if (e.attribute("meta:name") == "tag") { m_bundletags << e.attribute("meta:value"); } else { m_metadata.insert(e.attribute("meta:name"), e.attribute("meta:value")); } } else { m_metadata.insert(e.tagName(), e.firstChild().toText().data()); } } } resourceStore->close(); return true; } return false; } void KoResourceBundle::saveMetadata(QScopedPointer &store) { QBuffer buf; store->open("meta.xml"); buf.open(QBuffer::WriteOnly); KoXmlWriter metaWriter(&buf); metaWriter.startDocument("office:document-meta"); metaWriter.startElement("meta:meta"); writeMeta(KisResourceStorage::s_meta_generator, &metaWriter); metaWriter.startElement(KisResourceStorage::s_meta_version.toUtf8()); metaWriter.addTextNode(m_bundleVersion.toUtf8()); metaWriter.endElement(); writeMeta(KisResourceStorage::s_meta_author, &metaWriter); writeMeta(KisResourceStorage::s_meta_title, &metaWriter); writeMeta(KisResourceStorage::s_meta_description, &metaWriter); writeMeta(KisResourceStorage::s_meta_initial_creator, &metaWriter); writeMeta(KisResourceStorage::s_meta_creator, &metaWriter); writeMeta(KisResourceStorage::s_meta_creation_date, &metaWriter); writeMeta(KisResourceStorage::s_meta_dc_date, &metaWriter); writeUserDefinedMeta("email", &metaWriter); writeUserDefinedMeta("license", &metaWriter); writeUserDefinedMeta("website", &metaWriter); Q_FOREACH (const QString &tag, m_bundletags) { metaWriter.startElement(KisResourceStorage::s_meta_user_defined.toUtf8()); metaWriter.addAttribute(KisResourceStorage::s_meta_name.toUtf8(), "tag"); metaWriter.addAttribute(KisResourceStorage::s_meta_value.toUtf8(), tag); metaWriter.endElement(); } metaWriter.endElement(); // meta:meta metaWriter.endDocument(); buf.close(); store->write(buf.data()); store->close(); } void KoResourceBundle::saveManifest(QScopedPointer &store) { store->open("META-INF/manifest.xml"); QBuffer buf; buf.open(QBuffer::WriteOnly); m_manifest.save(&buf); buf.close(); store->write(buf.data()); store->close(); } int KoResourceBundle::resourceCount() const { return m_manifest.files().count(); } KoResourceBundleManifest &KoResourceBundle::manifest() { return m_manifest; } KoResourceSP KoResourceBundle::resource(const QString &resourceType, const QString &filepath) { if (m_filename.isEmpty()) return 0; QScopedPointer resourceStore(KoStore::createStore(m_filename, KoStore::Read, "application/x-krita-resourcebundle", KoStore::Zip)); if (!resourceStore || resourceStore->bad()) { qWarning() << "Could not open store on bundle" << m_filename; return 0; } if (!resourceStore->open(filepath)) { qWarning() << "Could not open file in bundle" << filepath; } QString mime = KisMimeDatabase::mimeTypeForSuffix(filepath); KisResourceLoaderBase *loader = KisResourceLoaderRegistry::instance()->loader(resourceType, mime); if (!loader) { qWarning() << "Could not create loader for" << resourceType << filepath << mime; return 0; } KoResourceSP res = loader->load(filepath, *resourceStore->device()); resourceStore->close(); return res; } QImage KoResourceBundle::image() const { return m_thumbnail; } QString KoResourceBundle::filename() const { return m_filename; } diff --git a/libs/store/KoQuaZipStore.cpp b/libs/store/KoQuaZipStore.cpp index 6e09f75921..f95a98eeb9 100644 --- a/libs/store/KoQuaZipStore.cpp +++ b/libs/store/KoQuaZipStore.cpp @@ -1,291 +1,295 @@ /* * Copyright (C) 2019 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KoQuaZipStore.h" #include "KoStore_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct KoQuaZipStore::Private { Private() {} ~Private() {} QuaZip *archive {0}; QuaZipFile *currentFile {0}; int compressionLevel {Z_DEFAULT_COMPRESSION}; bool usingSaveFile {false}; QByteArray cache; QBuffer buffer; }; KoQuaZipStore::KoQuaZipStore(const QString &_filename, KoStore::Mode _mode, const QByteArray &appIdentification, bool writeMimetype) : KoStore(_mode, writeMimetype) , dd(new Private()) { Q_D(KoStore); d->localFileName = _filename; dd->archive = new QuaZip(_filename); init(appIdentification); } KoQuaZipStore::KoQuaZipStore(QIODevice *dev, KoStore::Mode _mode, const QByteArray &appIdentification, bool writeMimetype) : KoStore(_mode, writeMimetype) , dd(new Private()) { dd->archive = new QuaZip(dev); init(appIdentification); } KoQuaZipStore::~KoQuaZipStore() { Q_D(KoStore); if (dd->currentFile && dd->currentFile->isOpen()) { dd->currentFile->close(); } if (!d->finalized) { finalize(); } delete dd->archive; delete dd->currentFile; } void KoQuaZipStore::setCompressionEnabled(bool enabled) { if (enabled) { dd->compressionLevel = Z_BEST_COMPRESSION; } else { dd->compressionLevel = Z_NO_COMPRESSION; } } qint64 KoQuaZipStore::write(const char *_data, qint64 _len) { + qDebug() << "QUAZIP! qint64 KoQuaZipStore::write(const char *_data, qint64 _len)" << _data << _len; Q_D(KoStore); if (_len == 0) return 0; if (!d->isOpen) { + qDebug() << "qint64 KoQuaZipStore::write (1)"; errorStore << "KoStore: You must open before writing" << endl; return 0; } if (d->mode != Write) { + qDebug() << "qint64 KoQuaZipStore::write (2)"; errorStore << "KoStore: Can not write to store that is opened for reading" << endl; return 0; } d->size += _len; + qDebug() << "qint64 KoQuaZipStore::write (3)"; if (dd->buffer.write(_data, _len)) { // writeData returns a bool! return _len; } return 0; } QStringList KoQuaZipStore::directoryList() const { return dd->archive->getFileNameList(); } void KoQuaZipStore::init(const QByteArray &appIdentification) { Q_D(KoStore); bool enableZip64 = false; if (appIdentification == "application/x-krita") { enableZip64 = KSharedConfig::openConfig()->group("").readEntry("UseZip64", false); } dd->archive->setZip64Enabled(enableZip64); dd->archive->setFileNameCodec("UTF-8"); dd->usingSaveFile = dd->archive->getIoDevice() && dd->archive->getIoDevice()->inherits("QSaveFile"); dd->archive->setAutoClose(!dd->usingSaveFile); d->good = dd->archive->open(d->mode == Write ? QuaZip::mdCreate : QuaZip::mdUnzip); if (!d->good) { return; } if (d->mode == Write) { if (d->writeMimetype) { QuaZipFile f(dd->archive); QuaZipNewInfo newInfo("mimetype"); newInfo.setPermissions(QFileDevice::ReadOwner | QFileDevice::ReadGroup | QFileDevice::ReadOther); if (!f.open(QIODevice::WriteOnly, newInfo, 0, 0, Z_DEFLATED, Z_NO_COMPRESSION)) { d->good = false; return; } f.write(appIdentification); f.close(); } } else { debugStore << dd->archive->getEntriesCount() << dd->archive->getFileNameList(); d->good = dd->archive->getEntriesCount(); } } bool KoQuaZipStore::doFinalize() { Q_D(KoStore); d->stream = 0; if (!dd->usingSaveFile) { dd->archive->close(); } return dd->archive->getZipError() == ZIP_OK; } bool KoQuaZipStore::openWrite(const QString &name) { Q_D(KoStore); QString fixedPath = name; fixedPath.replace("//", "/"); delete d->stream; d->stream = 0; // Not used when writing delete dd->currentFile; dd->currentFile = new QuaZipFile(dd->archive); QuaZipNewInfo newInfo(fixedPath); newInfo.setPermissions(QFileDevice::ReadOwner | QFileDevice::ReadGroup | QFileDevice::ReadOther); bool r = dd->currentFile->open(QIODevice::WriteOnly, newInfo, 0, 0, Z_DEFLATED, dd->compressionLevel); if (!r) { qWarning() << "Could not open" << name << dd->currentFile->getZipError(); } dd->cache = QByteArray(); dd->buffer.setBuffer(&dd->cache); dd->buffer.open(QBuffer::WriteOnly); return r; } bool KoQuaZipStore::openRead(const QString &name) { Q_D(KoStore); QString fixedPath = name; fixedPath.replace("//", "/"); delete d->stream; d->stream = 0; delete dd->currentFile; dd->currentFile = 0; if (!currentPath().isEmpty() && !fixedPath.startsWith(currentPath())) { fixedPath = currentPath() + '/' + fixedPath; } if (!d->substituteThis.isEmpty()) { fixedPath = fixedPath.replace(d->substituteThis, d->substituteWith); } if (!dd->archive->setCurrentFile(fixedPath)) { qWarning() << "\t\tCould not set current file" << dd->archive->getZipError() << fixedPath; return false; } dd->currentFile = new QuaZipFile(dd->archive); if (!dd->currentFile->open(QIODevice::ReadOnly)) { qWarning() << "\t\t\tBut could not open!!!" << dd->archive->getZipError(); return false; } d->stream = dd->currentFile; d->size = dd->currentFile->size(); return true; } bool KoQuaZipStore::closeWrite() { Q_D(KoStore); bool r = true; if (!dd->currentFile->write(dd->cache)) { qWarning() << "Could not write buffer to the file"; r = false; } dd->buffer.close(); dd->currentFile->close(); d->stream = 0; return (r && dd->currentFile->getZipError() == ZIP_OK); } bool KoQuaZipStore::closeRead() { Q_D(KoStore); d->stream = 0; return true; } bool KoQuaZipStore::enterRelativeDirectory(const QString & /*path*/) { return true; } bool KoQuaZipStore::enterAbsoluteDirectory(const QString &path) { QString fixedPath = path; fixedPath.replace("//", "/"); if (fixedPath.isEmpty()) { fixedPath = "/"; } QuaZipDir currentDir (dd->archive, fixedPath); return currentDir.exists(); } bool KoQuaZipStore::fileExists(const QString &absPath) const { Q_D(const KoStore); QString fixedPath = absPath; fixedPath.replace("//", "/"); if (!d->substituteThis.isEmpty()) { fixedPath = fixedPath.replace(d->substituteThis, d->substituteWith); } return dd->archive->getFileNameList().contains(fixedPath); } diff --git a/plugins/extensions/resourcemanager/dlg_bundle_manager.cpp b/plugins/extensions/resourcemanager/dlg_bundle_manager.cpp index 066172b469..e801dc4dc4 100644 --- a/plugins/extensions/resourcemanager/dlg_bundle_manager.cpp +++ b/plugins/extensions/resourcemanager/dlg_bundle_manager.cpp @@ -1,87 +1,88 @@ /* * Copyright (c) 2014 Victor Lafon metabolic.ewilan@hotmail.fr * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "dlg_bundle_manager.h" #include "ui_wdgdlgbundlemanager.h" #include "resourcemanager.h" #include "dlg_create_bundle.h" #include #include #include #include #include #include #include #include "kis_action.h" #include #include #include #include #include #include #include DlgBundleManager::DlgBundleManager(QWidget *parent) : KoDialog(parent) , m_page(new QWidget()) , m_ui(new Ui::WdgDlgBundleManager) { setCaption(i18n("Manage Resource Libraries")); m_ui->setupUi(m_page); setMainWidget(m_page); resize(m_page->sizeHint()); m_ui->bnAdd->setIcon(KisIconUtils::loadIcon("list-add")); connect(m_ui->bnAdd, SIGNAL(clicked(bool)), SLOT(addBundle())); m_ui->bnNew->setIcon(KisIconUtils::loadIcon("document-new")); connect(m_ui->bnNew, SIGNAL(clicked(bool)), SLOT(createBundle())); m_ui->bnDelete->setIcon(KisIconUtils::loadIcon("edit-delete")); connect(m_ui->bnDelete, SIGNAL(clicked(bool)), SLOT(deleteBundle())); setButtons(Close); KisStorageFilterProxyModel *proxyModel = new KisStorageFilterProxyModel(this); proxyModel->setSourceModel(KisStorageModel::instance()); proxyModel->setFilter(KisStorageFilterProxyModel::ByStorageType, QStringList() << KisResourceStorage::storageTypeToUntranslatedString(KisResourceStorage::StorageType::Bundle) << KisResourceStorage::storageTypeToUntranslatedString(KisResourceStorage::StorageType::Folder)); m_ui->tableView->setModel(proxyModel); } void DlgBundleManager::addBundle() { } void DlgBundleManager::createBundle() { - + DlgCreateBundle* dlg = new DlgCreateBundle(0, this); + dlg->exec(); } void DlgBundleManager::deleteBundle() { } diff --git a/plugins/extensions/resourcemanager/dlg_create_bundle.cpp b/plugins/extensions/resourcemanager/dlg_create_bundle.cpp index b0564841c6..24562c53f3 100644 --- a/plugins/extensions/resourcemanager/dlg_create_bundle.cpp +++ b/plugins/extensions/resourcemanager/dlg_create_bundle.cpp @@ -1,412 +1,441 @@ /* * Copyright (c) 2014 Victor Lafon metabolic.ewilan@hotmail.fr * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "dlg_create_bundle.h" #include "ui_wdgdlgcreatebundle.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include -#include #include #define ICON_SIZE 48 DlgCreateBundle::DlgCreateBundle(KoResourceBundleSP bundle, QWidget *parent) : KoDialog(parent) , m_ui(new Ui::WdgDlgCreateBundle) , m_bundle(bundle) { m_page = new QWidget(); m_ui->setupUi(m_page); setMainWidget(m_page); setFixedSize(m_page->sizeHint()); setButtons(Ok | Cancel); setDefaultButton(Ok); setButtonText(Ok, i18n("Save")); connect(m_ui->bnSelectSaveLocation, SIGNAL(clicked()), SLOT(selectSaveLocation())); KoDocumentInfo info; info.updateParameters(); if (bundle) { setCaption(i18n("Edit Resource Bundle")); #if 0 m_ui->lblSaveLocation->setText(QFileInfo(bundle->filename()).absolutePath()); m_ui->editBundleName->setText(bundle->name()); m_ui->editAuthor->setText(bundle->getMeta("author")); m_ui->editEmail->setText(bundle->getMeta("email")); m_ui->editLicense->setText(bundle->getMeta("license")); m_ui->editWebsite->setText(bundle->getMeta("website")); m_ui->editDescription->document()->setPlainText(bundle->getMeta("description")); m_ui->lblPreview->setPixmap(QPixmap::fromImage(bundle->image().scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation))); Q_FOREACH (const QString & resType, bundle->resourceTypes()) { if (resType == ResourceType::Gradients) { Q_FOREACH (const KoResourceSP res, bundle->resources(resType)) { if (res) { m_selectedGradients << res->filename(); } } } else if (resType == ResourceType::Patterns) { Q_FOREACH (const KoResourceSP res, bundle->resources(resType)) { if (res) { m_selectedPatterns << res->filename(); } } } else if (resType == ResourceType::Brushes) { Q_FOREACH (const KoResourceSP res, bundle->resources(resType)) { if (res) { m_selectedBrushes << res->filename(); } } } else if (resType == ResourceType::Palettes) { Q_FOREACH (const KoResourceSP res, bundle->resources(resType)) { if (res) { m_selectedPalettes << res->filename(); } } } else if (resType == ResourceType::Workspaces) { Q_FOREACH (const KoResourceSP res, bundle->resources(resType)) { if (res) { m_selectedWorkspaces << res->filename(); } } } else if (resType == ResourceType::PaintOpPresets) { Q_FOREACH (const KoResourceSP res, bundle->resources(resType)) { if (res) { m_selectedPresets << res->filename(); } } } else if (resType == ResourceType::GamutMasks) { Q_FOREACH (const KoResourceSP res, bundle->resources(resType)) { if (res) { m_selectedGamutMasks << res->filename(); } } } } #endif } else { setCaption(i18n("Create Resource Bundle")); KisConfig cfg(true); m_ui->editAuthor->setText(cfg.readEntry("BundleAuthorName", info.authorInfo("creator"))); m_ui->editEmail->setText(cfg.readEntry("BundleAuthorEmail", info.authorInfo("email"))); m_ui->editWebsite->setText(cfg.readEntry("BundleWebsite", "http://")); m_ui->editLicense->setText(cfg.readEntry("BundleLicense", "CC-BY-SA")); m_ui->lblSaveLocation->setText(cfg.readEntry("BundleExportLocation", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation))); } m_ui->bnAdd->setIcon(KisIconUtils::loadIcon("arrow-right")); connect(m_ui->bnAdd, SIGNAL(clicked()), SLOT(addSelected())); m_ui->bnRemove->setIcon(KisIconUtils::loadIcon("arrow-left")); connect(m_ui->bnRemove, SIGNAL(clicked()), SLOT(removeSelected())); m_ui->cmbResourceTypes->addItem(i18n("Brushes"), ResourceType::Brushes); m_ui->cmbResourceTypes->addItem(i18n("Brush Presets"), ResourceType::PaintOpPresets); m_ui->cmbResourceTypes->addItem(i18n("Gradients"), ResourceType::Gradients); m_ui->cmbResourceTypes->addItem(i18n("Gamut Masks"), ResourceType::GamutMasks); m_ui->cmbResourceTypes->addItem(i18n("Patterns"), ResourceType::Patterns); m_ui->cmbResourceTypes->addItem(i18n("Palettes"), ResourceType::Palettes); m_ui->cmbResourceTypes->addItem(i18n("Workspaces"), ResourceType::Workspaces); connect(m_ui->cmbResourceTypes, SIGNAL(activated(int)), SLOT(resourceTypeSelected(int))); m_ui->tableAvailable->setIconSize(QSize(ICON_SIZE, ICON_SIZE)); m_ui->tableAvailable->setSelectionMode(QAbstractItemView::ExtendedSelection); m_ui->tableSelected->setIconSize(QSize(ICON_SIZE, ICON_SIZE)); m_ui->tableSelected->setSelectionMode(QAbstractItemView::ExtendedSelection); connect(m_ui->bnGetPreview, SIGNAL(clicked()), SLOT(getPreviewImage())); resourceTypeSelected(0); } DlgCreateBundle::~DlgCreateBundle() { delete m_ui; } QString DlgCreateBundle::bundleName() const { return m_ui->editBundleName->text().replace(" ", "_"); } QString DlgCreateBundle::authorName() const { return m_ui->editAuthor->text(); } QString DlgCreateBundle::email() const { return m_ui->editEmail->text(); } QString DlgCreateBundle::website() const { return m_ui->editWebsite->text(); } QString DlgCreateBundle::license() const { return m_ui->editLicense->text(); } QString DlgCreateBundle::description() const { return m_ui->editDescription->document()->toPlainText(); } QString DlgCreateBundle::saveLocation() const { return m_ui->lblSaveLocation->text(); } QString DlgCreateBundle::previewImage() const { return m_previewImage; } +void DlgCreateBundle::putResourcesInTheBundle() const +{ + KisResourceModel* emptyModel = KisResourceModelProvider::resourceModel(""); + Q_FOREACH(int id, m_selectedResourcesIds) { + KoResourceSP res = emptyModel->resourceForId(id); + KisResourceModel* resModel = KisResourceModelProvider::resourceModel(res->resourceType().first); + QVector tags = resModel->tagsForResource(id); + m_bundle->addResource(res->resourceType().first, res->filename(), tags, res->md5()); + } + +} + void DlgCreateBundle::accept() { - QString name = m_ui->editBundleName->text().remove(" "); + ENTER_FUNCTION(); + QString name = bundleName(); + QString filename = m_ui->lblSaveLocation->text() + "/" + name + ".bundle"; if (name.isEmpty()) { m_ui->editBundleName->setStyleSheet(QString(" border: 1px solid red")); QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("The resource bundle name cannot be empty.")); return; } else { - QFileInfo fileInfo(m_ui->lblSaveLocation->text() + "/" + name + ".bundle"); + ENTER_FUNCTION() << "(1)"; + QFileInfo fileInfo(filename); if (fileInfo.exists() && !m_bundle) { + ENTER_FUNCTION() << "(2)"; m_ui->editBundleName->setStyleSheet("border: 1px solid red"); QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("A bundle with this name already exists.")); return; } else { + ENTER_FUNCTION() << "(3)"; if (!m_bundle) { KisConfig cfg(false); - cfg.writeEntry("BunleExportLocation", m_ui->lblSaveLocation->text()); - cfg.writeEntry("BundleAuthorName", m_ui->editAuthor->text()); - cfg.writeEntry("BundleAuthorEmail", m_ui->editEmail->text()); - cfg.writeEntry("BundleWebsite", m_ui->editWebsite->text()); - cfg.writeEntry("BundleLicense", m_ui->editLicense->text()); + cfg.writeEntry("BunleExportLocation", saveLocation()); + cfg.writeEntry("BundleAuthorName", authorName()); + cfg.writeEntry("BundleAuthorEmail", email()); + cfg.writeEntry("BundleWebsite", website()); + cfg.writeEntry("BundleLicense", license()); + + m_bundle.reset(new KoResourceBundle(filename)); + putResourcesInTheBundle(); + m_bundle->save(); + } KoDialog::accept(); } } } void DlgCreateBundle::selectSaveLocation() { KoFileDialog dialog(this, KoFileDialog::OpenDirectory, "resourcebundlesavelocation"); dialog.setDefaultDir(m_ui->lblSaveLocation->text()); dialog.setCaption(i18n("Select a directory to save the bundle")); QString location = dialog.filename(); m_ui->lblSaveLocation->setText(location); } void DlgCreateBundle::addSelected() { int row = m_ui->tableAvailable->currentRow(); Q_FOREACH (QListWidgetItem *item, m_ui->tableAvailable->selectedItems()) { m_ui->tableSelected->addItem(m_ui->tableAvailable->takeItem(m_ui->tableAvailable->row(item))); + m_selectedResourcesIds.append(item->data(Qt::UserRole).toInt()); + + /* QString resourceType = m_ui->cmbResourceTypes->itemData(m_ui->cmbResourceTypes->currentIndex()).toString(); if (resourceType == ResourceType::Brushes) { m_selectedBrushes.append(item->data(Qt::UserRole).toString()); } else if (resourceType == "presets") { m_selectedPresets.append(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::Gradients) { m_selectedGradients.append(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::Patterns) { m_selectedPatterns.append(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::Palettes) { m_selectedPalettes.append(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::Workspaces) { m_selectedWorkspaces.append(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::GamutMasks) { m_selectedGamutMasks.append(item->data(Qt::UserRole).toString()); } + */ } m_ui->tableAvailable->setCurrentRow(row); } void DlgCreateBundle::removeSelected() { int row = m_ui->tableSelected->currentRow(); Q_FOREACH (QListWidgetItem *item, m_ui->tableSelected->selectedItems()) { m_ui->tableAvailable->addItem(m_ui->tableSelected->takeItem(m_ui->tableSelected->row(item))); + m_selectedResourcesIds.removeAll(item->data(Qt::UserRole).toInt()); + + /* QString resourceType = m_ui->cmbResourceTypes->itemData(m_ui->cmbResourceTypes->currentIndex()).toString(); if (resourceType == ResourceType::Brushes) { m_selectedBrushes.removeAll(item->data(Qt::UserRole).toString()); } else if (resourceType == "presets") { m_selectedPresets.removeAll(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::Gradients) { m_selectedGradients.removeAll(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::Patterns) { m_selectedPatterns.removeAll(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::Palettes) { m_selectedPalettes.removeAll(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::Workspaces) { m_selectedWorkspaces.removeAll(item->data(Qt::UserRole).toString()); } else if (resourceType == ResourceType::GamutMasks) { m_selectedGamutMasks.removeAll(item->data(Qt::UserRole).toString()); } + */ } m_ui->tableSelected->setCurrentRow(row); } QPixmap imageToIcon(const QImage &img) { QPixmap pixmap(ICON_SIZE, ICON_SIZE); pixmap.fill(); QImage scaled = img.scaled(ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation); int x = (ICON_SIZE - scaled.width()) / 2; int y = (ICON_SIZE - scaled.height()) / 2; QPainter gc(&pixmap); gc.drawImage(x, y, scaled); gc.end(); return pixmap; } void DlgCreateBundle::resourceTypeSelected(int idx) { QString resourceType = m_ui->cmbResourceTypes->itemData(idx).toString(); m_ui->tableAvailable->clear(); m_ui->tableSelected->clear(); QString standarizedResourceType = (resourceType == "presets" ? ResourceType::PaintOpPresets : resourceType); QStringList& list = m_selectedBrushes; if (standarizedResourceType == ResourceType::Brushes) { list = m_selectedBrushes; } else if (standarizedResourceType == ResourceType::Gradients) { list = m_selectedGradients; } else if (standarizedResourceType == ResourceType::GamutMasks) { list = m_selectedGamutMasks; } else if (standarizedResourceType == ResourceType::Palettes) { list = m_selectedPalettes; } else if (standarizedResourceType == ResourceType::Patterns) { list = m_selectedPatterns; } else if (standarizedResourceType == ResourceType::PaintOpPresets) { list = m_selectedPresets; } else if (standarizedResourceType == ResourceType::Workspaces) { list = m_selectedWorkspaces; } KisResourceModel* model = KisResourceModelProvider::resourceModel(standarizedResourceType); for (int i = 0; i < model->rowCount(); i++) { QModelIndex idx = model->index(i, 0); QString filename = model->data(idx, Qt::UserRole + KisResourceModel::Filename).toString(); + int id = model->data(idx, Qt::UserRole + KisResourceModel::Id).toInt(); if (resourceType == ResourceType::Gradients) { if (filename == "Foreground to Transparent" || filename == "Foreground to Background") { continue; } } QImage image = (model->data(idx, Qt::UserRole + KisResourceModel::Thumbnail)).value(); QString name = model->data(idx, Qt::UserRole + KisResourceModel::Name).toString(); // Function imageToIcon(QImage()) returns a square white pixmap and a warning "QImage::scaled: Image is a null image" // while QPixmap() returns an empty pixmap. // The difference between them is relevant in case of Workspaces which has no images. // Using QPixmap() makes them appear in a dense list without icons, while imageToIcon(QImage()) // would give a list with big white rectangles and names of the workspaces. QListWidgetItem *item = new QListWidgetItem(image.isNull() ? QPixmap() : imageToIcon(image), name); - item->setData(Qt::UserRole, filename); + item->setData(Qt::UserRole, id); - if (list.contains(filename)) { + if (m_selectedResourcesIds.contains(id)) { m_ui->tableSelected->addItem(item); } else { m_ui->tableAvailable->addItem(item); } } } void DlgCreateBundle::getPreviewImage() { KoFileDialog dialog(this, KoFileDialog::OpenFile, "BundlePreviewImage"); dialog.setCaption(i18n("Select file to use as bundle icon")); dialog.setDefaultDir(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)); dialog.setMimeTypeFilters(KisImportExportManager::supportedMimeTypes(KisImportExportManager::Import)); m_previewImage = dialog.filename(); QImage img(m_previewImage); img = img.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation); m_ui->lblPreview->setPixmap(QPixmap::fromImage(img)); } diff --git a/plugins/extensions/resourcemanager/dlg_create_bundle.h b/plugins/extensions/resourcemanager/dlg_create_bundle.h index 579c84ed1b..64e5c40c51 100644 --- a/plugins/extensions/resourcemanager/dlg_create_bundle.h +++ b/plugins/extensions/resourcemanager/dlg_create_bundle.h @@ -1,83 +1,88 @@ /* * Copyright (c) 2014 Victor Lafon metabolic.ewilan@hotmail.fr * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KOBUNDLECREATIONWIDGET_H #define KOBUNDLECREATIONWIDGET_H #include #include namespace Ui { class WdgDlgCreateBundle; } class DlgCreateBundle : public KoDialog { Q_OBJECT public: explicit DlgCreateBundle(KoResourceBundleSP bundle = nullptr, QWidget *parent = 0); ~DlgCreateBundle() override; QString bundleName() const; QString authorName() const; QString email() const; QString website() const; QString license() const; QString description() const; QString saveLocation() const; QString previewImage() const; QStringList selectedBrushes() const { return m_selectedBrushes; } QStringList selectedPresets() const { return m_selectedPresets; } QStringList selectedGradients() const { return m_selectedGradients; } QStringList selectedPatterns() const { return m_selectedPatterns; } QStringList selectedPalettes() const { return m_selectedPalettes; } QStringList selectedWorkspaces() const { return m_selectedWorkspaces; } QStringList selectedGamutMasks() const { return m_selectedGamutMasks; } private Q_SLOTS: void accept() override; void selectSaveLocation(); void addSelected(); void removeSelected(); void resourceTypeSelected(int idx); void getPreviewImage(); private: + + void putResourcesInTheBundle() const; + QWidget *m_page; Ui::WdgDlgCreateBundle *m_ui; + QList m_selectedResourcesIds; + QStringList m_selectedBrushes; QStringList m_selectedPresets; QStringList m_selectedGradients; QStringList m_selectedPatterns; QStringList m_selectedPalettes; QStringList m_selectedWorkspaces; QStringList m_selectedGamutMasks; QString m_previewImage; KoResourceBundleSP m_bundle; }; #endif // KOBUNDLECREATIONWIDGET_H