diff --git a/libs/resources/CMakeLists.txt b/libs/resources/CMakeLists.txt index dcac8ca70d..9243c86b35 100644 --- a/libs/resources/CMakeLists.txt +++ b/libs/resources/CMakeLists.txt @@ -1,65 +1,66 @@ include_directories(${QUAZIP_INCLUDE_DIRS}) add_subdirectory(tests) set(kritaresources_LIB_SRCS KisResourceCacheDb.cpp KisResourceLoader.cpp KisResourceLoaderRegistry.cpp KisResourceLocator.cpp KisResourceStorage.cpp KisResourceModel.cpp KisTagFilterResourceProxyModel.cpp KisResourceModelProvider.cpp KisResourceTypeModel.cpp KisStorageModel.cpp KisResourceIterator.cpp KisStoragePlugin.cpp KisBundleStorage.cpp KisFolderStorage.cpp KisMemoryStorage.cpp KisTag.cpp KisTagModel.cpp KisTagModelProvider.cpp + KisActiveFilterTagProxyModel.cpp KoResource.cpp KoResourceBundle.cpp KoResourceBundleManifest.cpp KoMD5Generator.cpp KoHashGeneratorProvider.cpp KoResourcePaths.cpp kconfigini.cpp kconfigdata.cpp kconfigbackend.cpp ) qt5_add_resources(kritaresources_LIB_SRCS sql.qrc) add_library(kritaresources SHARED ${kritaresources_LIB_SRCS}) generate_export_header(kritaresources BASE_NAME kritaresources) target_link_libraries(kritaresources PUBLIC Qt5::Core Qt5::Widgets PRIVATE Qt5::Sql kritaversion kritaglobal kritaplugin kritastore KF5::ConfigCore KF5::CoreAddons KF5::I18n ${QUAZIP_LIBRARIES} ) set_target_properties(kritaresources PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaresources ${INSTALL_TARGETS_DEFAULT_ARGS} ) diff --git a/libs/resources/KisActiveFilterTagProxyModel.cpp b/libs/resources/KisActiveFilterTagProxyModel.cpp new file mode 100644 index 0000000000..b185024fa5 --- /dev/null +++ b/libs/resources/KisActiveFilterTagProxyModel.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 Agata Cacko + * + * 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 "KisActiveFilterTagProxyModel.h" + +#include +#include +#include + + + +struct KisActiveFilterTagProxyModel::Private +{ + QList tags; +}; + + + + +KisActiveFilterTagProxyModel::KisActiveFilterTagProxyModel(QObject *parent) + : QSortFilterProxyModel(parent) + , d(new Private) +{ + +} + +KisActiveFilterTagProxyModel::~KisActiveFilterTagProxyModel() +{ + delete d; +} + +bool KisActiveFilterTagProxyModel::filterAcceptsColumn(int /*source_column*/, const QModelIndex &/*source_parent*/) const +{ + return true; +} + +bool KisActiveFilterTagProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + return true; +} + +bool KisActiveFilterTagProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const +{ + KisTagModel* model = qobject_cast(sourceModel()); + if (model != 0) { + KisTagSP left = model->tagForIndex(source_left); + KisTagSP right = model->tagForIndex(source_right); + return KisTag::compareNamesAndUrls(left, right); + } + return source_left.row() < source_right.row(); +} diff --git a/libs/resources/KisTagFilterResourceProxyModel.h b/libs/resources/KisActiveFilterTagProxyModel.h similarity index 51% copy from libs/resources/KisTagFilterResourceProxyModel.h copy to libs/resources/KisActiveFilterTagProxyModel.h index 3de781db7e..2fdff26605 100644 --- a/libs/resources/KisTagFilterResourceProxyModel.h +++ b/libs/resources/KisActiveFilterTagProxyModel.h @@ -1,66 +1,50 @@ /* - * Copyright (C) 2018 Boudewijn Rempt + * Copyright (C) 2019 Agata Cacko * * 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 KISTAGFILTERRESOURCEPROXYMODEL_H -#define KISTAGFILTERRESOURCEPROXYMODEL_H +#ifndef KIS_ACTIVE_FILTER_TAG_PROXY_MODEL_H +#define KIS_ACTIVE_FILTER_TAG_PROXY_MODEL_H + #include #include #include -#include +#include #include "kritaresources_export.h" -class KRITARESOURCES_EXPORT KisTagFilterResourceProxyModel : public QSortFilterProxyModel, public KisAbstractResourceModel +class KRITARESOURCES_EXPORT KisActiveFilterTagProxyModel : public QSortFilterProxyModel { Q_OBJECT public: - KisTagFilterResourceProxyModel(QObject *parent = 0); - ~KisTagFilterResourceProxyModel() override; - - // KisAbstractResourceModel interface -public: - KoResourceSP resourceForIndex(QModelIndex index = QModelIndex()) const override; - QModelIndex indexFromResource(KoResourceSP resource) const override; - bool removeResource(const QModelIndex &index) override; - bool importResourceFile(const QString &filename) override; - bool addResource(KoResourceSP resource, bool save = true) override; - bool updateResource(KoResourceSP resource) override; - bool removeResource(KoResourceSP resource) override; - bool setResourceMetaData(KoResourceSP resource, QMap metadata) override; + KisActiveFilterTagProxyModel(QObject *parent); + ~KisActiveFilterTagProxyModel() override; protected: - /** - * @brief setTag - * @param tag - */ - void setTag(const QString& tag); - bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override; bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; private: struct Private; Private *const d; - Q_DISABLE_COPY(KisTagFilterResourceProxyModel) + Q_DISABLE_COPY(KisActiveFilterTagProxyModel) }; -#endif // KISTAGFILTERRESOURCEPROXYMODEL_H +#endif // KIS_ACTIVE_FILTER_TAG_PROXY_MODEL_H diff --git a/libs/resources/KisTag.cpp b/libs/resources/KisTag.cpp index 0fc31e4d6f..d5bbc09c32 100644 --- a/libs/resources/KisTag.cpp +++ b/libs/resources/KisTag.cpp @@ -1,202 +1,217 @@ /* * Copyright (C) 2018 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 "KisTag.h" #include #include #include #include #include #include #include "kconfigini_p.h" #include "kconfigbackend_p.h" #include "kconfigdata.h" #include const QByteArray KisTag::s_group {"Desktop Entry"}; const QByteArray KisTag::s_type {"Type"}; const QByteArray KisTag::s_tag {"Tag"}; const QByteArray KisTag::s_name {"Name"}; const QByteArray KisTag::s_url {"URL"}; const QByteArray KisTag::s_comment {"Comment"}; const QByteArray KisTag::s_defaultResources {"Default Resources"}; class KisTag::Private { public: bool valid {false}; QString url; // This is the actual tag QString name; // The translated tag name QString comment; // The translated tag comment QStringList defaultResources; // The list of resources as defined in the tag file KEntryMap map; int id {-1}; bool active{true}; }; KisTag::KisTag() : d(new Private) { } KisTag::~KisTag() { } KisTag::KisTag(const KisTag &rhs) : d(new Private) { *this = rhs; } KisTag &KisTag::operator=(const KisTag &rhs) { if (this != &rhs) { d->valid = rhs.d->valid; d->url = rhs.d->url; d->name = rhs.d->name; d->comment = rhs.d->comment; d->defaultResources = rhs.d->defaultResources; d->map = rhs.d->map; } return *this; } KisTagSP KisTag::clone() const { return KisTagSP(new KisTag(*this)); } bool KisTag::valid() const { return d->valid; } int KisTag::id() const { return d->id; } bool KisTag::active() const { return d->active; } QString KisTag::name() const { return d->name; } void KisTag::setName(const QString &name) { d->map.setEntry(s_group, s_name, name, KEntryMap::EntryDirty); d->name = name; } QString KisTag::url() const { return d->url; } void KisTag::setUrl(const QString &url) { d->map.setEntry(s_group, s_url, url, KEntryMap::EntryDirty); d->url = url; } QString KisTag::comment() const { return d->comment; } void KisTag::setComment(const QString &comment) { d->map.setEntry(s_group, s_comment, comment, KEntryMap::EntryDirty); d->comment = comment; } QStringList KisTag::defaultResources() const { return d->defaultResources; } void KisTag::setDefaultResources(const QStringList &defaultResources) { d->defaultResources = defaultResources; } +bool KisTag::compareNamesAndUrls(KisTagSP left, KisTagSP right) +{ + if (left.isNull() && !right.isNull()) { + return true; + } + if (right.isNull()) { + return false; + } + if (left->name() != right->name()) { + return left->name().compare(right->name()) > 0; + } + + return left->url().compare(right->url()) > 0; +} + bool KisTag::load(QIODevice &io) { if (!io.isOpen()) { io.open(QIODevice::ReadOnly); } KIS_ASSERT(io.isOpen()); KConfigIniBackend ini; KConfigBackend::ParseInfo r = ini.parseConfigIO(io, QLocale().name().toUtf8(), d->map, KConfigBackend::ParseOption::ParseGlobal, false); if (r != KConfigBackend::ParseInfo::ParseOk) { qWarning() << "Could not load this tag file" << r; return false; } QString t = d->map.getEntry(s_group, s_type); if (t != s_tag) { qWarning() << "Not a tag desktop file" << t; return false; } d->url = d->map.getEntry(s_group, s_url); d->name = d->map.getEntry(s_group, s_name, QString(), KEntryMap::SearchLocalized); d->comment = d->map.getEntry(s_group, s_comment, QString(), KEntryMap::SearchLocalized); d->defaultResources = d->map.getEntry(s_group, s_defaultResources, QString()).split(',', QString::SkipEmptyParts); d->valid = true; return true; } bool KisTag::save(QIODevice &io) { KConfigIniBackend ini; d->map.setEntry(s_group, s_url, d->url, KEntryMap::EntryDirty); d->map.setEntry(s_group, s_name, d->name, KEntryMap::EntryDirty); d->map.setEntry(s_group, s_comment, d->comment, KEntryMap::EntryDirty); d->map.setEntry(s_group, s_defaultResources, d->defaultResources.join(','), KEntryMap::EntryDirty); ini.writeEntries(QLocale().name().toUtf8(), io, d->map); return true; } void KisTag::setId(int id) { d->id = id; } void KisTag::setActive(bool active) { d->active = active; } void KisTag::setValid(bool valid) { d->valid = valid; } diff --git a/libs/resources/KisTag.h b/libs/resources/KisTag.h index 11a333c6a0..4252efc54f 100644 --- a/libs/resources/KisTag.h +++ b/libs/resources/KisTag.h @@ -1,103 +1,106 @@ /* * Copyright (C) 2018 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. */ #ifndef KISTAGLOADER_H #define KISTAGLOADER_H #include #include #include #include class QIODevice; #include "kritaresources_export.h" class KisTag; typedef QSharedPointer KisTagSP; /** * @brief The KisTag loads a tag from a .tag file. * A .tag file is a .desktop file. The following fields * are important: * * name: the name of the tag, which can be translated * comment: a tooltip for the tag, which can be translagted * url: the untranslated name of the tag * */ class KRITARESOURCES_EXPORT KisTag { public: KisTag(); virtual ~KisTag(); KisTag(const KisTag &rhs); KisTag &operator=(const KisTag &rhs); KisTagSP clone() const; bool valid() const; int id() const; bool active() const; QString name() const; void setName(const QString &name); QString url() const; void setUrl(const QString &url); QString comment() const; void setComment(const QString &comment); QStringList defaultResources() const; void setDefaultResources(const QStringList &defaultResources); bool load(QIODevice &io); bool save(QIODevice &io); + static bool compareNamesAndUrls(KisTagSP left, KisTagSP right); + private: friend class KisTagModel; friend class KisResourceModel; + friend class KisTagChooserWidget; void setId(int id); void setActive(bool active); void setValid(bool valid); static const QByteArray s_group; static const QByteArray s_type; static const QByteArray s_tag; static const QByteArray s_name; static const QByteArray s_url; static const QByteArray s_comment; static const QByteArray s_defaultResources; class Private; QScopedPointer d; }; inline QDebug operator<<(QDebug dbg, const KisTagSP tag) { dbg.space() << "[TAG] Name" << tag->name() << "Url" << tag->url() << "Comment" << tag->comment() << "Default resources" << tag->defaultResources().join(", "); return dbg.space(); } #endif // KISTAGLOADER_H diff --git a/libs/resources/KisTagFilterResourceProxyModel.cpp b/libs/resources/KisTagFilterResourceProxyModel.cpp index 55e2203d2a..565b96c27a 100644 --- a/libs/resources/KisTagFilterResourceProxyModel.cpp +++ b/libs/resources/KisTagFilterResourceProxyModel.cpp @@ -1,149 +1,173 @@ /* * Copyright (C) 2018 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 "KisTagFilterResourceProxyModel.h" #include #include +#include struct KisTagFilterResourceProxyModel::Private { - QStringList tags; + QList tags; }; KisTagFilterResourceProxyModel::KisTagFilterResourceProxyModel(QObject *parent) : QSortFilterProxyModel(parent) , d(new Private) { } KisTagFilterResourceProxyModel::~KisTagFilterResourceProxyModel() { delete d; } KoResourceSP KisTagFilterResourceProxyModel::resourceForIndex(QModelIndex index) const { KisAbstractResourceModel *source = dynamic_cast(sourceModel()); if (source) { return source->resourceForIndex(mapToSource(index)); } return 0; } QModelIndex KisTagFilterResourceProxyModel::indexFromResource(KoResourceSP resource) const { KisAbstractResourceModel *source = dynamic_cast(sourceModel()); if (source) { return mapFromSource(source->indexFromResource(resource)); } return QModelIndex(); } bool KisTagFilterResourceProxyModel::removeResource(const QModelIndex &index) { KisAbstractResourceModel *source = dynamic_cast(sourceModel()); if (source) { return source->removeResource(mapToSource(index)); } return false; } bool KisTagFilterResourceProxyModel::importResourceFile(const QString &filename) { KisAbstractResourceModel *source = dynamic_cast(sourceModel()); if (source) { return source->importResourceFile(filename); } return false; } bool KisTagFilterResourceProxyModel::addResource(KoResourceSP resource, bool save) { KisAbstractResourceModel *source = dynamic_cast(sourceModel()); if (source) { return source->addResource(resource, save); } return false; } bool KisTagFilterResourceProxyModel::updateResource(KoResourceSP resource) { KisAbstractResourceModel *source = dynamic_cast(sourceModel()); if (source) { return source->updateResource(resource); } return false; } bool KisTagFilterResourceProxyModel::removeResource(KoResourceSP resource) { KisAbstractResourceModel *source = dynamic_cast(sourceModel()); if (source) { return source->removeResource(resource); } return false; } bool KisTagFilterResourceProxyModel::setResourceMetaData(KoResourceSP resource, QMap metadata) { KisAbstractResourceModel *source = dynamic_cast(sourceModel()); if (source) { return source->setResourceMetaData(resource, metadata); } return false; } -void KisTagFilterResourceProxyModel::setTag(const QString& tag) +void KisTagFilterResourceProxyModel::setTag(const KisTagSP tag) { - d->tags = tag.split(QRegExp("[,]\\s*"), QString::SkipEmptyParts); + fprintf(stderr, "we're setting a tag!: %s\n", tag->name().toUtf8().toStdString().c_str()); + ENTER_FUNCTION(); + //d->tags = tag.split(QRegExp("[,]\\s*"), QString::SkipEmptyParts); + d->tags.clear(); + d->tags << tag; + invalidateFilter(); } bool KisTagFilterResourceProxyModel::filterAcceptsColumn(int /*source_column*/, const QModelIndex &/*source_parent*/) const { return true; } bool KisTagFilterResourceProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { - if (d->tags.isEmpty()) return true; + if (d->tags.isEmpty()) { + return true; + } QModelIndex idx = sourceModel()->index(source_row, KisResourceModel::Name, source_parent); QStringList tags = sourceModel()->data(idx, Qt::UserRole + KisResourceModel::Tags).toStringList(); + + + //QString name = sourceModel()->data(idx, Qt::UserRole + KisResourceModel::Tags).toString(); + + + // TODO: RESOURCES: proper filtering by tag + if (!d->tags.first().isNull() && tags.contains(d->tags.first()->name())) { + return true; + } + + return false; + + //sourceModel()->data(idx, ) + + /* QSet tagResult = tags.toSet().subtract(tags.toSet()); if (!tagResult.isEmpty()) { return true; } QString name = sourceModel()->data(idx, Qt::UserRole + KisResourceModel::Name).toString(); - Q_FOREACH(const QString &tag, d->tags) { + Q_FOREACH(const KisTagSP &tag, d->tags) { if (name.startsWith(tag)) { return true; } } + */ return false; } bool KisTagFilterResourceProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { QString nameLeft = sourceModel()->data(source_left, Qt::UserRole + KisResourceModel::Name).toString(); QString nameRight = sourceModel()->data(source_right, Qt::UserRole + KisResourceModel::Name).toString(); return nameLeft < nameRight; } diff --git a/libs/resources/KisTagFilterResourceProxyModel.h b/libs/resources/KisTagFilterResourceProxyModel.h index 3de781db7e..2a90d0214e 100644 --- a/libs/resources/KisTagFilterResourceProxyModel.h +++ b/libs/resources/KisTagFilterResourceProxyModel.h @@ -1,66 +1,69 @@ /* * Copyright (C) 2018 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. */ #ifndef KISTAGFILTERRESOURCEPROXYMODEL_H #define KISTAGFILTERRESOURCEPROXYMODEL_H #include #include #include #include +#include #include "kritaresources_export.h" class KRITARESOURCES_EXPORT KisTagFilterResourceProxyModel : public QSortFilterProxyModel, public KisAbstractResourceModel { Q_OBJECT public: KisTagFilterResourceProxyModel(QObject *parent = 0); ~KisTagFilterResourceProxyModel() override; // KisAbstractResourceModel interface public: KoResourceSP resourceForIndex(QModelIndex index = QModelIndex()) const override; QModelIndex indexFromResource(KoResourceSP resource) const override; bool removeResource(const QModelIndex &index) override; bool importResourceFile(const QString &filename) override; bool addResource(KoResourceSP resource, bool save = true) override; bool updateResource(KoResourceSP resource) override; bool removeResource(KoResourceSP resource) override; bool setResourceMetaData(KoResourceSP resource, QMap metadata) override; -protected: - /** * @brief setTag * @param tag */ - void setTag(const QString& tag); + void setTag(const KisTagSP tag); + +protected: + + bool filterAcceptsColumn(int source_column, const QModelIndex &source_parent) const override; bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; private: struct Private; Private *const d; Q_DISABLE_COPY(KisTagFilterResourceProxyModel) }; #endif // KISTAGFILTERRESOURCEPROXYMODEL_H diff --git a/libs/resources/KisTagList.cpp b/libs/resources/KisTagList.cpp new file mode 100644 index 0000000000..aa7270447d --- /dev/null +++ b/libs/resources/KisTagList.cpp @@ -0,0 +1,10 @@ + + + +#include + +KisTagList::KisTagList() +{ + + +} diff --git a/libs/resources/KisTagList.h b/libs/resources/KisTagList.h new file mode 100644 index 0000000000..cc19d9b712 --- /dev/null +++ b/libs/resources/KisTagList.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Agata Cacko + * + * 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 + +#include + +class KisTagList : public QList +{ + KisTagList(); + + + +} + diff --git a/libs/resources/KisTagModel.cpp b/libs/resources/KisTagModel.cpp index 21620cd25d..574481c153 100644 --- a/libs/resources/KisTagModel.cpp +++ b/libs/resources/KisTagModel.cpp @@ -1,366 +1,369 @@ /* * Copyright (c) 2018 boud * * 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 "KisTagModel.h" #include #include #include #include #include #include struct KisTagModel::Private { QSqlQuery query; QString resourceType; int columnCount {5}; int cachedRowCount {-1}; int fakeRowsCount {1}; }; KisTagModel::KisTagModel(const QString &resourceType, QObject *parent) : QAbstractTableModel(parent) , d(new Private()) { d->resourceType = resourceType; if (!d->resourceType.isEmpty()) { prepareQuery(); } } KisTagModel::~KisTagModel() { delete d; } int KisTagModel::rowCount(const QModelIndex &/*parent*/) const { if (d->cachedRowCount < 0) { QSqlQuery q; q.prepare("SELECT count(*)\n" "FROM tags\n" ", resource_types\n" "WHERE active = 1\n" "AND tags.resource_type_id = resource_types.id\n" "AND resource_types.name = :resource_type"); q.bindValue(":resource_type", d->resourceType); q.exec(); q.first(); const_cast(this)->d->cachedRowCount = q.value(0).toInt() + d->fakeRowsCount; } return d->cachedRowCount; } int KisTagModel::columnCount(const QModelIndex &/*parent*/) const { return d->columnCount; } QVariant KisTagModel::data(const QModelIndex &index, int role) const { QVariant v; if (!index.isValid()) return v; if (index.row() > rowCount()) return v; if (index.column() > d->columnCount) return v; // The first row is All // XXX: Should we also add an "All Untagged"? if (index.row() < d->fakeRowsCount) { switch(role) { case Qt::DisplayRole: // fallthrough case Qt::ToolTipRole: // fallthrough case Qt::StatusTipRole: // fallthrough case Qt::WhatsThisRole: return i18n("All"); case Qt::UserRole + Id: return "-1"; case Qt::UserRole + Url: { return "All"; } case Qt::UserRole + ResourceType: return d->resourceType; default: ; } } else { bool pos = const_cast(this)->d->query.seek(index.row() - d->fakeRowsCount); if (pos) { switch(role) { case Qt::DisplayRole: return d->query.value("name"); case Qt::ToolTipRole: // fallthrough case Qt::StatusTipRole: // fallthrough case Qt::WhatsThisRole: return d->query.value("comment"); case Qt::UserRole + Id: return d->query.value("id"); case Qt::UserRole + Url: return d->query.value("url"); case Qt::UserRole + ResourceType: return d->query.value("resource_type"); default: ; } } } return v; } void KisTagModel::setResourceType(const QString &resourceType) { d->resourceType = resourceType; prepareQuery(); } KisTagSP KisTagModel::tagForIndex(QModelIndex index) const { KisTagSP tag = 0; if (!index.isValid()) return tag; if (index.row() > rowCount()) return tag; if (index.column() > columnCount()) return tag; bool pos = const_cast(this)->d->query.seek(index.row()); if (pos) { tag.reset(new KisTag()); tag->setUrl(d->query.value("url").toString()); tag->setName(d->query.value("name").toString()); tag->setComment(d->query.value("comment").toString()); tag->setId(d->query.value("id").toInt()); tag->setActive(d->query.value("active").toBool()); tag->setValid(true); } return tag; } bool KisTagModel::addTag(const KisTagSP tag, QVector taggedResouces) { + if (tag.isNull()) return false; if (!tag) return false; if (!tag->valid()) return false; // A new tag doesn't have an ID yet, that comes from the database if (tag->id() >= 0) return false; + /* if (!KisResourceCacheDb::hasTag(tag->url(), d->resourceType)) { if (!KisResourceCacheDb::addTag(d->resourceType, tag->url(), tag->name(), tag->comment())) { qWarning() << "Could not add tag" << tag; return false; } } else { QSqlQuery q; if (!q.prepare("UPDATE tags\n" "SET active = 1\n" "WHERE url = :url\n" "AND resource_type_id = (SELECT id\n" " FROM resource_types\n" " WHERE name = :resource_type\n)")) { qWarning() << "Couild not prepare make existing tag active query" << tag << q.lastError(); return false; } q.bindValue(":url", tag->url()); q.bindValue(":resource_type", d->resourceType); if (!q.exec()) { qWarning() << "Couild not execute make existing tag active query" << q.boundValues(), q.lastError(); return false; } } Q_FOREACH(const KoResourceSP resource, taggedResouces) { if (!resource) continue; if (!resource->valid()) continue; if (resource->resourceId() < 0) continue; tagResource(tag, resource); } + */ return prepareQuery(); } bool KisTagModel::removeTag(const KisTagSP tag) { if (!tag) return false; if (!tag->valid()) return false; if (tag->id() < 0) return false; QSqlQuery q; if (!q.prepare("UPDATE tags\n" "WHERE id = :id\n" "SET active = 0")) { qWarning() << "Could not prepare remove tag query" << q.lastError(); return false; } q.bindValue(":id", tag->id()); if (!q.exec()) { qWarning() << "Could not execute remove tag query" << q.lastError(); return false; } return prepareQuery(); } bool KisTagModel::tagResource(const KisTagSP tag, const KoResourceSP resource) { if (!tag) return false; if (!tag->valid()) return false; if (tag->id() < 0) return false; if (!resource) return false; if (!resource->valid()) return false; if (resource->resourceId() < 0) return false; QSqlQuery q; bool r = q.prepare("INSERT INTO resource_tags\n" "(resource_id, tag_id)\n" "VALUES\n" "( (SELECT id\n" " FROM resources\n" " WHERE id = :resource_id)\n" ", (SELECT id\n" " FROM tags\n" " WHERE url = :url\n" " AND name = :name\n" " AND comment = :comment\n" " AND resource_type_id = (SELECT id\n" " FROM resource_types\n" " WHERE name = :resource_type" " \n)" " )\n" ")\n"); if (!r) { qWarning() << "Could not prepare insert into resource tags statement" << q.lastError(); return false; } q.bindValue(":resource_id", resource->resourceId()); q.bindValue(":url", tag->url()); q.bindValue(":name", tag->name()); q.bindValue(":comment", tag->comment()); q.bindValue(":resource_type", d->resourceType); if (!q.exec()) { qWarning() << "Could not execute insert into resource tags statement" << q.boundValues() << q.lastError(); return false; } return prepareQuery(); } bool KisTagModel::untagResource(const KisTagSP tag, const KoResourceSP resource) { if (!tag) return false; if (!tag->valid()) return false; if (!tag->id()) return false; if (!resource) return false; if (!resource->valid()) return false; if (resource->resourceId() < 0) return false; bool r = d->query.prepare("DELETE FROM resource_tags.id\n" "WHERE resource_id = :resource_id\n" "AND tag_id in (SELECT id\n" " FROM tags where "); if (!r) { qWarning() << "Could not prepare KisTagModel query" << d->query.lastError(); } d->query.bindValue(":resource_type", d->resourceType); r = d->query.exec(); if (!r) { qWarning() << "Could not select tags" << d->query.lastError(); } return prepareQuery(); } bool KisTagModel::renameTag(const KisTagSP tag, const QString &name) { if (!tag) return false; if (!tag->valid()) return false; if (name.isEmpty()) return false; QSqlQuery q; if (!q.prepare("UPDATE tags\n" "SET name = :name\n" "WHERE url = :url\n" "AND resource_type_id = (SELECT id\n" " FROM resource_types\n" " WHERE name = :resource_type\n)")) { qWarning() << "Couild not prepare make existing tag active query" << tag << q.lastError(); return false; } q.bindValue(":name", name); q.bindValue(":url", tag->url()); q.bindValue(":resource_type", d->resourceType); if (!q.exec()) { qWarning() << "Couild not execute make existing tag active query" << q.boundValues(), q.lastError(); return false; } return prepareQuery(); } bool KisTagModel::prepareQuery() { beginResetModel(); bool r = d->query.prepare("SELECT tags.id\n" ", tags.url\n" ", tags.name\n" ", tags.comment\n" ", resource_types.name as resource_type\n" "FROM tags\n" ", resource_types\n" "WHERE tags.resource_type_id = resource_types.id\n" "AND resource_types.name = :resource_type\n" "AND tags.active = 1"); if (!r) { qWarning() << "Could not prepare KisTagModel query" << d->query.lastError(); } d->query.bindValue(":resource_type", d->resourceType); r = d->query.exec(); if (!r) { qWarning() << "Could not select tags" << d->query.lastError(); } d->cachedRowCount = -1; endResetModel(); return r; } diff --git a/libs/resources/KisTagModel.h b/libs/resources/KisTagModel.h index b93e85e146..1d1ef6a487 100644 --- a/libs/resources/KisTagModel.h +++ b/libs/resources/KisTagModel.h @@ -1,81 +1,84 @@ /* * Copyright (c) 2018 boud * * 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. */ #ifndef KISTAGMODEL_H #define KISTAGMODEL_H #include #include #include #include #include "kritaresources_export.h" class KRITARESOURCES_EXPORT KisTagModel : public QAbstractTableModel { Q_OBJECT private: KisTagModel(const QString &resourceType, QObject *parent = 0); public: enum Columns { Id = 0, Url, Name, Comment, ResourceType }; ~KisTagModel() override; int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role) const override; // KisTagModel API KisTagSP tagForIndex(QModelIndex index = QModelIndex()) const; + QList allTags() const; bool addTag(const KisTagSP tag, QVector taggedResouces = QVector()); bool removeTag(const KisTagSP tag); bool tagResource(const KisTagSP tag, const KoResourceSP resource); bool untagResource(const KisTagSP tag, const KoResourceSP resource); bool renameTag(const KisTagSP tag, const QString &name); private: friend class DlgDbExplorer; friend class KisTagModelProvider; friend class TestTagModel; void setResourceType(const QString &resourceType); bool prepareQuery(); struct Private; Private* const d; }; -#endif // KOTAGMODEL_H +typedef QSharedPointer KisTagModelSP; + +#endif // KISTAGMODEL_H diff --git a/libs/resourcewidgets/KisResourceItemChooser.cpp b/libs/resourcewidgets/KisResourceItemChooser.cpp index 52fd518e02..977f249155 100644 --- a/libs/resourcewidgets/KisResourceItemChooser.cpp +++ b/libs/resourcewidgets/KisResourceItemChooser.cpp @@ -1,542 +1,541 @@ /* This file is part of the KDE project Copyright (c) 2002 Patrick Julien Copyright (c) 2007 Jan Hambrecht Copyright (c) 2007 Sven Langkamp Copyright (C) 2011 Srikanth Tiyyagura Copyright (c) 2011 José Luis Vergara Copyright (c) 2013 Sascha Suelzer 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 "KisResourceItemChooser.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisResourceItemListView.h" #include "KisResourceItemDelegate.h" #include "KisTagFilterWidget.h" #include "KisTagChooserWidget.h" #include "KisResourceItemChooserSync.h" #include "KisResourceTaggingManager.h" #include "KisTagModelProvider.h" #include "kis_assert.h" class Q_DECL_HIDDEN KisResourceItemChooser::Private { public: Private(QString _resourceType) : resourceType(_resourceType) {} QString resourceType; KisResourceModel *resourceModel {0}; KisTagFilterResourceProxyModel *tagFilterProxyModel {0}; QSortFilterProxyModel *extraFilterModel {0}; KisResourceTaggingManager *tagManager {0}; KisResourceItemListView *view {0}; QButtonGroup *buttonGroup {0}; QToolButton *viewModeButton {0}; QScrollArea *previewScroller {0}; QLabel *previewLabel {0}; QSplitter *splitter {0}; QGridLayout *buttonLayout {0}; QPushButton *importButton {0}; QPushButton *deleteButton {0}; bool usePreview {false}; bool tiledPreview {false}; bool grayscalePreview {false}; bool synced {false}; bool updatesBlocked {false}; QModelIndex savedResourceWhileReset; // Indexes on the proxyModel, not the source resource model QList customButtons; }; KisResourceItemChooser::KisResourceItemChooser(const QString &resourceType, bool usePreview, QWidget *parent, QSortFilterProxyModel *extraFilterProxy) : QWidget(parent) , d(new Private(resourceType)) { d->splitter = new QSplitter(this); d->resourceModel = KisResourceModelProvider::resourceModel(resourceType); d->tagFilterProxyModel = new KisTagFilterResourceProxyModel(this); d->extraFilterModel = extraFilterProxy; if (d->extraFilterModel) { d->extraFilterModel->setParent(this); d->extraFilterModel->setSourceModel(d->resourceModel); d->tagFilterProxyModel->setSourceModel(d->extraFilterModel); } else { d->tagFilterProxyModel->setSourceModel(d->resourceModel); } connect(d->resourceModel, SIGNAL(beforeResourcesLayoutReset(QModelIndex)), SLOT(slotBeforeResourcesLayoutReset(QModelIndex))); connect(d->resourceModel, SIGNAL(afterResourcesLayoutReset()), SLOT(slotAfterResourcesLayoutReset())); d->view = new KisResourceItemListView(this); d->view->setObjectName("ResourceItemview"); d->view->setModel(d->tagFilterProxyModel); d->view->setItemDelegate(new KisResourceItemDelegate(this)); d->view->setSelectionMode(QAbstractItemView::SingleSelection); d->view->viewport()->installEventFilter(this); connect(d->view, SIGNAL(currentResourceChanged(QModelIndex)), this, SLOT(activated(QModelIndex))); connect(d->view, SIGNAL(currentResourceClicked(QModelIndex)), this, SLOT(clicked(QModelIndex))); connect(d->view, SIGNAL(contextMenuRequested(QPoint)), this, SLOT(contextMenuRequested(QPoint))); connect(d->view, SIGNAL(sigSizeChanged()), this, SLOT(updateView())); d->splitter->addWidget(d->view); d->splitter->setStretchFactor(0, 2); d->usePreview = usePreview; if (d->usePreview) { d->previewScroller = new QScrollArea(this); d->previewScroller->setWidgetResizable(true); d->previewScroller->setBackgroundRole(QPalette::Dark); d->previewScroller->setVisible(true); d->previewScroller->setAlignment(Qt::AlignCenter); d->previewLabel = new QLabel(this); d->previewScroller->setWidget(d->previewLabel); d->splitter->addWidget(d->previewScroller); if (d->splitter->count() == 2) { d->splitter->setSizes(QList() << 280 << 160); } QScroller* scroller = KisKineticScroller::createPreconfiguredScroller(d->previewScroller); if (scroller) { connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChanged(QScroller::State))); } } d->splitter->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); connect(d->splitter, SIGNAL(splitterMoved(int,int)), SIGNAL(splitterMoved())); d->buttonGroup = new QButtonGroup(this); d->buttonGroup->setExclusive(false); QGridLayout *layout = new QGridLayout(this); d->buttonLayout = new QGridLayout(); d->importButton = new QPushButton(this); d->importButton->setToolTip(i18nc("@info:tooltip", "Import resource")); d->importButton->setEnabled(true); d->buttonGroup->addButton(d->importButton, Button_Import); d->buttonLayout->addWidget(d->importButton, 0, 0); d->deleteButton = new QPushButton(this); d->deleteButton->setToolTip(i18nc("@info:tooltip", "Delete resource")); d->deleteButton->setEnabled(false); d->buttonGroup->addButton(d->deleteButton, Button_Remove); d->buttonLayout->addWidget(d->deleteButton, 0, 1); connect(d->buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(slotButtonClicked(int))); d->buttonLayout->setColumnStretch(0, 1); d->buttonLayout->setColumnStretch(1, 1); d->buttonLayout->setColumnStretch(2, 2); d->buttonLayout->setSpacing(0); d->buttonLayout->setMargin(0); d->viewModeButton = new QToolButton(this); d->viewModeButton->setPopupMode(QToolButton::InstantPopup); d->viewModeButton->setVisible(false); - d->tagManager = new KisResourceTaggingManager(KisTagModelProvider::tagModel(resourceType), d->tagFilterProxyModel, this); connect(d->tagManager, SIGNAL(updateView()), this, SLOT(updateView())); layout->addWidget(d->tagManager->tagChooserWidget(), 0, 0); layout->addWidget(d->viewModeButton, 0, 1); layout->addWidget(d->splitter, 1, 0, 1, 2); layout->addWidget(d->tagManager->tagFilterWidget(), 2, 0, 1, 2); layout->addLayout(d->buttonLayout, 3, 0, 1, 2); layout->setMargin(0); layout->setSpacing(0); updateView(); updateButtonState(); showTaggingBar(false); activated(d->view->model()->index(0, 0)); } KisResourceItemChooser::~KisResourceItemChooser() { disconnect(); delete d; } void KisResourceItemChooser::slotButtonClicked(int button) { if (button == Button_Import) { QStringList mimeTypes = KisResourceLoaderRegistry::instance()->mimeTypes(d->resourceType); KoFileDialog dialog(0, KoFileDialog::OpenFiles, "OpenDocument"); dialog.setMimeTypeFilters(mimeTypes); dialog.setCaption(i18nc("@title:window", "Choose File to Add")); Q_FOREACH(const QString &filename, dialog.filenames()) { if (QFileInfo(filename).exists() && QFileInfo(filename).isReadable()) { d->tagFilterProxyModel->importResourceFile(filename); } } } else if (button == Button_Remove) { QModelIndex index = d->view->currentIndex(); if (index.isValid()) { d->tagFilterProxyModel->removeResource(index); } int row = index.row(); int rowMin = --row; row = qBound(0, rowMin, row); setCurrentItem(row); activated(d->tagFilterProxyModel->index(row, index.column())); } updateButtonState(); } void KisResourceItemChooser::showButtons(bool show) { foreach (QAbstractButton * button, d->buttonGroup->buttons()) { show ? button->show() : button->hide(); } Q_FOREACH (QAbstractButton *button, d->customButtons) { show ? button->show() : button->hide(); } } void KisResourceItemChooser::addCustomButton(QAbstractButton *button, int cell) { d->buttonLayout->addWidget(button, 0, cell); d->buttonLayout->setColumnStretch(2, 1); d->buttonLayout->setColumnStretch(3, 1); } void KisResourceItemChooser::showTaggingBar(bool show) { d->tagManager->showTaggingBar(show); } int KisResourceItemChooser::rowCount() const { return d->view->model()->rowCount(); } void KisResourceItemChooser::setRowHeight(int rowHeight) { d->view->setItemSize(QSize(d->view->gridSize().width(), rowHeight)); } void KisResourceItemChooser::setColumnWidth(int columnWidth) { d->view->setItemSize(QSize(columnWidth, d->view->gridSize().height())); } void KisResourceItemChooser::setItemDelegate(QAbstractItemDelegate *delegate) { d->view->setItemDelegate(delegate); } KoResourceSP KisResourceItemChooser::currentResource() const { QModelIndex index = d->view->currentIndex(); if (index.isValid()) { return resourceFromModelIndex(index); } return 0; } void KisResourceItemChooser::setCurrentResource(KoResourceSP resource) { // don't update if the change came from the same chooser if (d->updatesBlocked) { return; } QModelIndex index = d->resourceModel->indexFromResource(resource); d->view->setCurrentIndex(index); updatePreview(index); } void KisResourceItemChooser::slotBeforeResourcesLayoutReset(QModelIndex activateAfterReset) { QModelIndex proxyIndex = d->tagFilterProxyModel->mapFromSource(d->tagFilterProxyModel->mapFromSource(activateAfterReset)); d->savedResourceWhileReset = proxyIndex.isValid() ? proxyIndex : d->view->currentIndex(); } void KisResourceItemChooser::slotAfterResourcesLayoutReset() { if (d->savedResourceWhileReset.isValid()) { this->blockSignals(true); setCurrentItem(d->savedResourceWhileReset.row()); this->blockSignals(false); } d->savedResourceWhileReset = QModelIndex(); } void KisResourceItemChooser::setPreviewOrientation(Qt::Orientation orientation) { d->splitter->setOrientation(orientation); } void KisResourceItemChooser::setPreviewTiled(bool tiled) { d->tiledPreview = tiled; } void KisResourceItemChooser::setGrayscalePreview(bool grayscale) { d->grayscalePreview = grayscale; } void KisResourceItemChooser::setCurrentItem(int row) { QModelIndex index = d->view->model()->index(row, 0); if (!index.isValid()) return; d->view->setCurrentIndex(index); if (index.isValid()) { updatePreview(index); } } void KisResourceItemChooser::activated(const QModelIndex &index) { if (!index.isValid()) return; KoResourceSP resource = 0; if (index.isValid()) { resource = resourceFromModelIndex(index); } if (resource && resource->valid()) { d->updatesBlocked = true; emit resourceSelected(resource); d->updatesBlocked = false; updatePreview(index); updateButtonState(); } } void KisResourceItemChooser::clicked(const QModelIndex &index) { Q_UNUSED(index); KoResourceSP resource = currentResource(); if (resource) { emit resourceClicked(resource); } } void KisResourceItemChooser::updateButtonState() { QAbstractButton *removeButton = d->buttonGroup->button(Button_Remove); if (! removeButton) return; KoResourceSP resource = currentResource(); if (resource) { removeButton->setEnabled(!resource->permanent()); return; } removeButton->setEnabled(false); } void KisResourceItemChooser::updatePreview(const QModelIndex &idx) { if (!d->usePreview) return; if (!idx.isValid()) { d->previewLabel->setPixmap(QPixmap()); return; } QImage image = idx.data(Qt::UserRole + KisResourceModel::Image).value(); if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_ARGB32 && image.format() != QImage::Format_ARGB32_Premultiplied) { image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); } if (d->tiledPreview) { int width = d->previewScroller->width() * 4; int height = d->previewScroller->height() * 4; QImage img(width, height, image.format()); QPainter gc(&img); gc.fillRect(img.rect(), Qt::white); gc.setPen(Qt::NoPen); gc.setBrush(QBrush(image)); gc.drawRect(img.rect()); image = img; } // Only convert to grayscale if it is rgb. Otherwise, it's gray already. if (d->grayscalePreview && !image.isGrayscale()) { QRgb *pixel = reinterpret_cast(image.bits()); for (int row = 0; row < image.height(); ++row) { for (int col = 0; col < image.width(); ++col) { const QRgb currentPixel = pixel[row * image.width() + col]; const int red = qRed(currentPixel); const int green = qGreen(currentPixel); const int blue = qBlue(currentPixel); const int grayValue = (red * 11 + green * 16 + blue * 5) / 32; pixel[row * image.width() + col] = qRgb(grayValue, grayValue, grayValue); } } } d->previewLabel->setPixmap(QPixmap::fromImage(image)); } KoResourceSP KisResourceItemChooser::resourceFromModelIndex(const QModelIndex &index) const { if (!index.isValid()) { return 0; } KoResourceSP r = d->tagFilterProxyModel->resourceForIndex(index); return r; } QSize KisResourceItemChooser::viewSize() const { return d->view->size(); } KisResourceItemListView *KisResourceItemChooser::itemView() const { return d->view; } void KisResourceItemChooser::contextMenuRequested(const QPoint &pos) { d->tagManager->contextMenuRequested(currentResource(), pos); } void KisResourceItemChooser::setViewModeButtonVisible(bool visible) { d->viewModeButton->setVisible(visible); } QToolButton *KisResourceItemChooser::viewModeButton() const { return d->viewModeButton; } void KisResourceItemChooser::setSynced(bool sync) { if (d->synced == sync) return; d->synced = sync; KisResourceItemChooserSync *chooserSync = KisResourceItemChooserSync::instance(); if (sync) { connect(chooserSync, SIGNAL(baseLengthChanged(int)), SLOT(baseLengthChanged(int))); baseLengthChanged(chooserSync->baseLength()); } else { chooserSync->disconnect(this); } } void KisResourceItemChooser::baseLengthChanged(int length) { if (d->synced) { d->view->setItemSize(QSize(length, length)); } } bool KisResourceItemChooser::eventFilter(QObject *object, QEvent *event) { if (d->synced && event->type() == QEvent::Wheel) { KisResourceItemChooserSync *chooserSync = KisResourceItemChooserSync::instance(); QWheelEvent *qwheel = static_cast(event); if (qwheel->modifiers() & Qt::ControlModifier) { int degrees = qwheel->delta() / 8; int newBaseLength = chooserSync->baseLength() + degrees / 15 * 10; chooserSync->setBaseLength(newBaseLength); return true; } } return QObject::eventFilter(object, event); } void KisResourceItemChooser::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); updateView(); } void KisResourceItemChooser::showEvent(QShowEvent *event) { QWidget::showEvent(event); updateView(); } void KisResourceItemChooser::updateView() { if (d->synced) { KisResourceItemChooserSync *chooserSync = KisResourceItemChooserSync::instance(); baseLengthChanged(chooserSync->baseLength()); } /// helps to set icons here in case the theme is changed d->viewModeButton->setIcon(koIcon("view-choose")); d->importButton->setIcon(koIcon("document-open")); d->deleteButton->setIcon(koIcon("trash-empty")); } diff --git a/libs/resourcewidgets/KisResourceItemChooserContextMenu.cpp b/libs/resourcewidgets/KisResourceItemChooserContextMenu.cpp index be86c6ac9b..b8522513ee 100644 --- a/libs/resourcewidgets/KisResourceItemChooserContextMenu.cpp +++ b/libs/resourcewidgets/KisResourceItemChooserContextMenu.cpp @@ -1,216 +1,245 @@ /* This file is part of the KDE project * Copyright (c) 2013 Sascha Suelzer * * 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 "KisResourceItemChooserContextMenu.h" #include #include #include #include #include - #include +#include + +#include "kis_debug.h" + KoLineEditAction::KoLineEditAction(QObject* parent) : QWidgetAction(parent) , m_closeParentOnTrigger(false) { QWidget* pWidget = new QWidget (0); QHBoxLayout* pLayout = new QHBoxLayout(); m_label = new QLabel(0); m_editBox = new QLineEdit(0); m_editBox->setClearButtonEnabled(true); m_AddButton = new QPushButton(); m_AddButton->setIcon(koIcon("list-add")); pLayout->addWidget(m_label); pLayout->addWidget(m_editBox); pLayout->addWidget(m_AddButton); pWidget->setLayout(pLayout); setDefaultWidget(pWidget); connect (m_editBox, &QLineEdit::returnPressed, this, &KoLineEditAction::onTriggered); connect (m_AddButton, &QPushButton::clicked, this, &KoLineEditAction::onTriggered); } KoLineEditAction::~KoLineEditAction() { } void KoLineEditAction::setIcon(const QIcon &icon) { QPixmap pixmap = QPixmap(icon.pixmap(16,16)); m_label->setPixmap(pixmap); } void KoLineEditAction::closeParentOnTrigger(bool closeParent) { m_closeParentOnTrigger = closeParent; } bool KoLineEditAction::closeParentOnTrigger() { return m_closeParentOnTrigger; } void KoLineEditAction::onTriggered() { + ENTER_FUNCTION(); if (! m_editBox->text().isEmpty()) { - emit triggered( m_editBox->text()); + // TODO: RESOURCES: what about "remove existing tag" action? + KisTagSP tag(new KisTag()); + tag->setName(m_editBox->text()); + tag->setUrl(m_editBox->text()); + emit triggered(tag); m_editBox->text().clear(); if (m_closeParentOnTrigger) { this->parentWidget()->close(); m_editBox->clearFocus(); } } } void KoLineEditAction::setPlaceholderText(const QString& clickMessage) { m_editBox->setPlaceholderText(clickMessage); } void KoLineEditAction::setText(const QString& text) { + ENTER_FUNCTION(); m_editBox->setText(text); } void KoLineEditAction::setVisible(bool showAction) { QLayout* currentLayout = defaultWidget()->layout(); this->QAction::setVisible(showAction); for(int i=0;icount();i++) { currentLayout->itemAt(i)->widget()->setVisible(showAction); } defaultWidget()->setVisible(showAction); } -ContextMenuExistingTagAction::ContextMenuExistingTagAction(KoResourceSP resource, QString tag, QObject* parent) +ContextMenuExistingTagAction::ContextMenuExistingTagAction(KoResourceSP resource, KisTagSP tag, QObject* parent) : QAction(parent) , m_resource(resource) , m_tag(tag) { - setText(tag); + setText(tag->name()); connect (this, SIGNAL(triggered()), this, SLOT(onTriggered())); } ContextMenuExistingTagAction::~ContextMenuExistingTagAction() { } void ContextMenuExistingTagAction::onTriggered() { + ENTER_FUNCTION(); emit triggered(m_resource, m_tag); } NewTagAction::~NewTagAction() { } NewTagAction::NewTagAction(KoResourceSP resource, QMenu* parent) :KoLineEditAction (parent) { m_resource = resource; setIcon(koIcon("document-new")); setPlaceholderText(i18n("New tag")); closeParentOnTrigger(true); - connect (this, SIGNAL(triggered(QString)), - this, SLOT(onTriggered(QString))); + connect (this, SIGNAL(triggered(KisTagSP)), + this, SLOT(onTriggered(KisTagSP))); } -void NewTagAction::onTriggered(const QString & tagName) +void NewTagAction::onTriggered(const KisTagSP tag) { - emit triggered(m_resource,tagName); + ENTER_FUNCTION(); + emit triggered(m_resource,tag); } KisResourceItemChooserContextMenu::KisResourceItemChooserContextMenu(KoResourceSP resource, - const QStringList& resourceTags, - const QString& currentlySelectedTag, - const QStringList& allTags) + const QList resourceTags, + const KisTagSP currentlySelectedTag, + const QList allTags) { + QImage image = resource->image(); QIcon icon(QPixmap::fromImage(image)); QAction * label = new QAction(resource->name(), this); label->setIcon(icon); addAction(label); QMenu * removableTagsMenu; QMenu * assignableTagsMenu; - QStringList removables = resourceTags; - QStringList assignables = allTags; + QList removables = resourceTags; + QList assignables = allTags; + + + std::sort(removables.begin(), removables.end(), KisTag::compareNamesAndUrls); + std::sort(assignables.begin(), assignables.end(), KisTag::compareNamesAndUrls); - removables.sort(); - assignables.sort(); assignableTagsMenu = addMenu(koIcon("list-add"),i18n("Assign to tag")); + if (!removables.isEmpty()) { addSeparator(); - QString currentTag = currentlySelectedTag; - if (removables.contains(currentTag)) { - assignables.removeAll(currentTag); - removables.removeAll(currentTag); + KisTagSP currentTag = currentlySelectedTag; + + if (!currentTag.isNull() && removables.contains(currentTag)) { + //assignables.remove(currentTag); + //removables.remove(currentTag); ContextMenuExistingTagAction * removeTagAction = new ContextMenuExistingTagAction(resource, currentTag, this); removeTagAction->setText(i18n("Remove from this tag")); removeTagAction->setIcon(koIcon("list-remove")); - connect(removeTagAction, SIGNAL(triggered(KoResourceSP,QString)), - this, SIGNAL(resourceTagRemovalRequested(KoResourceSP,QString))); + connect(removeTagAction, SIGNAL(triggered(KoResourceSP,KisTagSP)), + this, SIGNAL(resourceTagRemovalRequested(KoResourceSP,KisTagSP))); addAction(removeTagAction); } + if (!removables.isEmpty()) { removableTagsMenu = addMenu(koIcon("list-remove"),i18n("Remove from other tag")); - foreach (const QString &tag, removables) { - assignables.removeAll(tag); + foreach (const KisTagSP tag, removables) { + //assignables.remove(tag); + if (tag.isNull()) { + continue; + } + ContextMenuExistingTagAction * removeTagAction = new ContextMenuExistingTagAction(resource, tag, this); - connect(removeTagAction, SIGNAL(triggered(KoResourceSP,QString)), - this, SIGNAL(resourceTagRemovalRequested(KoResourceSP,QString))); + connect(removeTagAction, SIGNAL(triggered(KoResourceSP,KisTagSP)), + this, SIGNAL(resourceTagRemovalRequested(KoResourceSP,KisTagSP))); removableTagsMenu->addAction(removeTagAction); } } + } - foreach (const QString &tag, assignables) { + + foreach (const KisTagSP &tag, assignables) { + if (tag.isNull()) { + continue; + } + ContextMenuExistingTagAction * addTagAction = new ContextMenuExistingTagAction(resource, tag, this); - connect(addTagAction, SIGNAL(triggered(KoResourceSP,QString)), - this, SIGNAL(resourceTagAdditionRequested(KoResourceSP,QString))); + connect(addTagAction, SIGNAL(triggered(KoResourceSP, KisTagSP)), + this, SIGNAL(resourceTagAdditionRequested(KoResourceSP, KisTagSP))); assignableTagsMenu->addAction(addTagAction); } + /* assignableTagsMenu->addSeparator(); NewTagAction * addTagAction = new NewTagAction(resource, this); - connect(addTagAction, SIGNAL(triggered(KoResourceSP,QString)), - this, SIGNAL(resourceAssignmentToNewTagRequested(KoResourceSP,QString))); + connect(addTagAction, SIGNAL(triggered(KoResourceSP, KisTagSP)), + this, SIGNAL(resourceAssignmentToNewTagRequested(KoResourceSP, KisTagSP))); assignableTagsMenu->addAction(addTagAction); + */ } KisResourceItemChooserContextMenu::~KisResourceItemChooserContextMenu() { } diff --git a/libs/resourcewidgets/KisResourceItemChooserContextMenu.h b/libs/resourcewidgets/KisResourceItemChooserContextMenu.h index 320e9d335a..c60400bafb 100644 --- a/libs/resourcewidgets/KisResourceItemChooserContextMenu.h +++ b/libs/resourcewidgets/KisResourceItemChooserContextMenu.h @@ -1,121 +1,123 @@ /* * This file is part of the KDE project * Copyright (c) 2013 Sascha Suelzer * 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. * */ #ifndef KISRESOURCEITEMCHOOSERCONTEXTMENU_H #define KISRESOURCEITEMCHOOSERCONTEXTMENU_H #include #include #include #include #include #include +#include + class ContextMenuExistingTagAction : public QAction { Q_OBJECT public: - explicit ContextMenuExistingTagAction( KoResourceSP resource, QString tag, QObject* parent = 0); + explicit ContextMenuExistingTagAction( KoResourceSP resource, KisTagSP tag, QObject* parent = 0); ~ContextMenuExistingTagAction() override; Q_SIGNALS: - void triggered(KoResourceSP resource, QString tag); + void triggered(KoResourceSP resource, KisTagSP tag); protected Q_SLOTS: void onTriggered(); private: KoResourceSP m_resource; - QString m_tag; + KisTagSP m_tag; }; /*! * A line edit QWidgetAction. * Default behavior: Closes its parent upon triggering. */ class KoLineEditAction : public QWidgetAction { Q_OBJECT public: explicit KoLineEditAction(QObject* parent); ~KoLineEditAction() override; void setIcon(const QIcon &icon); void closeParentOnTrigger(bool closeParent); bool closeParentOnTrigger(); void setPlaceholderText(const QString& clickMessage); void setText(const QString& text); void setVisible(bool showAction); Q_SIGNALS: - void triggered(const QString &tag); + void triggered(const KisTagSP tag); protected Q_SLOTS: void onTriggered(); private: bool m_closeParentOnTrigger; QLabel * m_label; QLineEdit * m_editBox; QPushButton * m_AddButton; }; class NewTagAction : public KoLineEditAction { Q_OBJECT public: explicit NewTagAction (KoResourceSP resource, QMenu* parent); ~NewTagAction() override; Q_SIGNALS: - void triggered(KoResourceSP resource, const QString &tag); + void triggered(KoResourceSP resource, const KisTagSP &tag); protected Q_SLOTS: - void onTriggered(const QString& tagName); + void onTriggered(const KisTagSP tagName); private: KoResourceSP m_resource; }; class KisResourceItemChooserContextMenu : public QMenu { Q_OBJECT public: explicit KisResourceItemChooserContextMenu ( KoResourceSP resource, - const QStringList& resourceTags, - const QString& currentlySelectedTag, - const QStringList& allTags + const QList resourceTags, + const KisTagSP currentlySelectedTag, + const QList allTags ); ~KisResourceItemChooserContextMenu() override; Q_SIGNALS: /// Emitted when a resource should be added to an existing tag. - void resourceTagAdditionRequested(KoResourceSP resource, const QString& tag); + void resourceTagAdditionRequested(KoResourceSP resource, const KisTagSP tag); /// Emitted when a resource should be removed from an existing tag. - void resourceTagRemovalRequested(KoResourceSP resource, const QString& tag); + void resourceTagRemovalRequested(KoResourceSP resource, const KisTagSP tag); /// Emitted when a resource should be added to a new tag, which will need to be created. - void resourceAssignmentToNewTagRequested(KoResourceSP resource, const QString& tag); + void resourceAssignmentToNewTagRequested(KoResourceSP resource, const KisTagSP tag); }; #endif // KORESOURCEITEMCHOOSERCONTEXTMENU_H diff --git a/libs/resourcewidgets/KisResourceTaggingManager.cpp b/libs/resourcewidgets/KisResourceTaggingManager.cpp index 58e5733a23..5c491ccb64 100644 --- a/libs/resourcewidgets/KisResourceTaggingManager.cpp +++ b/libs/resourcewidgets/KisResourceTaggingManager.cpp @@ -1,380 +1,430 @@ /* * This file is part of the KDE project * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Jan Hambrecht * Copyright (c) 2007 Sven Langkamp * Copyright (C) 2011 Srikanth Tiyyagura * Copyright (c) 2011 José Luis Vergara * Copyright (c) 2013 Sascha Suelzer * * 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 "KisResourceTaggingManager.h" #include #include #include #include #include #include #include #include #include #include +#include +#include #include "KisTagFilterWidget.h" #include "KisTagChooserWidget.h" #include "KisResourceItemChooserContextMenu.h" +#include "kis_debug.h" +#include "KisTag.h" class TaggedResourceSet { public: TaggedResourceSet() {} TaggedResourceSet(const QString& tagName, const QList& resources) : tagName(tagName) , resources(resources) {} QString tagName; QList resources; }; class KisResourceTaggingManager::Private { public: - QString currentTag; + KisTagSP currentTag; KisTagChooserWidget *tagChooser; KisTagFilterWidget *tagFilter; QCompleter *tagCompleter; QPointer model; + + KisTagModel* tagModel; }; KisResourceTaggingManager::KisResourceTaggingManager(KisTagModel* tagModel, KisTagFilterResourceProxyModel *model, QWidget *parent) + : QObject(parent) , d(new Private()) { d->model = model; - - d->tagChooser = new KisTagChooserWidget(tagModel, parent); - d->tagChooser->addReadOnlyItem("All"); // not translatable until other tags made translatable! - //d->tagChooser->addItems(d->model->tagNamesList()); - d->tagFilter = new KisTagFilterWidget(parent); - connect(d->tagChooser, SIGNAL(tagChosen(QString)), this, SLOT(tagChooserIndexChanged(QString))); - connect(d->tagChooser, SIGNAL(newTagRequested(QString)), this, SLOT(contextCreateNewTag(QString))); - connect(d->tagChooser, SIGNAL(tagDeletionRequested(QString)), this, SLOT(removeTagFromComboBox(QString))); - connect(d->tagChooser, SIGNAL(tagRenamingRequested(QString,QString)), this, SLOT(renameTag(QString,QString))); - connect(d->tagChooser, SIGNAL(tagUndeletionRequested(QString)), this, SLOT(undeleteTag(QString))); + d->tagModel = tagModel; + d->tagChooser = new KisTagChooserWidget(d->tagModel, parent); + + connect(d->tagChooser, SIGNAL(tagChosen(KisTagSP)), this, SLOT(tagChooserIndexChanged(KisTagSP))); + connect(d->tagChooser, SIGNAL(newTagRequested(KisTagSP)), this, SLOT(contextCreateNewTag(KisTagSP))); + connect(d->tagChooser, SIGNAL(tagDeletionRequested(KisTagSP)), this, SLOT(removeTagFromComboBox(KisTagSP))); + connect(d->tagChooser, SIGNAL(tagRenamingRequested(KisTagSP,KisTagSP)), this, SLOT(renameTag(KisTagSP,KisTagSP))); + connect(d->tagChooser, SIGNAL(tagUndeletionRequested(KisTagSP)), this, SLOT(undeleteTag(KisTagSP))); connect(d->tagChooser, SIGNAL(tagUndeletionListPurgeRequested()), this, SLOT(purgeTagUndeleteList())); connect(d->tagFilter, SIGNAL(saveButtonClicked()), this, SLOT(tagSaveButtonPressed())); connect(d->tagFilter, SIGNAL(filterTextChanged(QString)), this, SLOT(tagSearchLineEditTextChanged(QString))); // connect(d->model, SIGNAL(tagBoxEntryAdded(QString)), this, SLOT(syncTagBoxEntryAddition(QString))); // connect(d->model, SIGNAL(tagBoxEntryRemoved(QString)), this, SLOT(syncTagBoxEntryRemoval(QString))); // connect(d->model, SIGNAL(tagBoxEntryModified()), this, SLOT(syncTagBoxEntries())); // FIXME: fix tag completer // d->tagCompleter = new QCompleter(this); // d->tagSearchLineEdit->setCompleter(d->tagCompleter); syncTagBoxEntries(); } KisResourceTaggingManager::~KisResourceTaggingManager() { delete d; } void KisResourceTaggingManager::showTaggingBar(bool show) { + ENTER_FUNCTION(); show ? d->tagFilter->show() : d->tagFilter->hide(); show ? d->tagChooser->show() : d->tagChooser->hide(); // blockSignals(!show); // QString tag("All"); // if (show) { // KConfigGroup group = KSharedConfig::openConfig()->group("SelectedTags"); // tag = group.readEntry(d->model->serverType(), "All"); // } // int idx = d->tagChooser->findIndexOf(tag); // if (idx < 0) idx = 0; // d->tagChooser->setCurrentIndex(idx); } void KisResourceTaggingManager::purgeTagUndeleteList() { + ENTER_FUNCTION(); //d->lastDeletedTag = TaggedResourceSet(); - d->tagChooser->setUndeletionCandidate(QString()); + //d->tagChooser->setUndeletionCandidate(QString()); } -void KisResourceTaggingManager::undeleteTag(const QString & tagToUndelete) +void KisResourceTaggingManager::undeleteTag(const KisTagSP tagToUndelete) { + ENTER_FUNCTION(); + /* QString tagName = tagToUndelete; QStringList allTags = availableTags(); if (allTags.contains(tagName)) { bool ok; tagName = QInputDialog::getText( d->tagChooser, i18n("Unable to undelete tag"), i18n("The tag you are trying to undelete already exists in tag list.
Please enter a new, unique name for it.
"), QLineEdit::Normal, tagName, &ok); if (!ok || allTags.contains(tagName) || tagName.isEmpty()) { QMessageBox msgBox; msgBox.setIcon(QMessageBox::Warning); msgBox.setText(i18n("Tag was not undeleted.")); msgBox.exec(); return; } } // QList serverResources = d->model->serverResources(); // Q_FOREACH(KoResourceSP resource, d->lastDeletedTag.resources) { // if (serverResources.contains(resource)) { // addResourceTag(resource, tagName); // } // } // d->model->tagCategoryAdded(tagName); d->tagChooser->setCurrentIndex(d->tagChooser->findIndexOf(tagName)); d->tagChooser->setUndeletionCandidate(QString()); // d->lastDeletedTag = TaggedResourceSet(); + */ } QStringList KisResourceTaggingManager::availableTags() const { - return d->tagChooser->allTags(); + ENTER_FUNCTION(); + return QStringList(); + //return d->tagChooser->allTags(); } -void KisResourceTaggingManager::addResourceTag(KoResourceSP resource, const QString& tagName) +void KisResourceTaggingManager::addResourceTag(KoResourceSP resource, const KisTagSP tag) { + ENTER_FUNCTION(); + d->tagModel->tagResource(tag, resource); + //d->tagModels->tagModel(resource->resourceType())->tagResource(tag, resource); + // we need to find a tag from a tagName? + // or... + // QStringList tagsList = d->model->assignedTagsList(resource); // if (tagsList.isEmpty()) { // d->model->addTag(resource, tagName); // } else { // Q_FOREACH (const QString & tag, tagsList) { // if (tag.compare(tagName)) { // d->model->addTag(resource, tagName); // } // } // } } -void KisResourceTaggingManager::syncTagBoxEntryAddition(const QString& tag) +void KisResourceTaggingManager::syncTagBoxEntryAddition(const KisTagSP tag) { - d->tagChooser->insertItem(tag); + ENTER_FUNCTION(); + //d->tagChooser->insertItem(tag); } -void KisResourceTaggingManager::contextCreateNewTag(const QString& tag) +void KisResourceTaggingManager::contextCreateNewTag(const KisTagSP tag) { + ENTER_FUNCTION(); + /* if (!tag.isEmpty()) { // d->model->addTag(0, tag); // d->model->tagCategoryAdded(tag); d->tagChooser->setCurrentIndex(d->tagChooser->findIndexOf(tag)); updateTaggedResourceView(); } + */ } -void KisResourceTaggingManager::contextCreateNewTag(KoResourceSP resource , const QString& tag) +void KisResourceTaggingManager::contextCreateNewTag(KoResourceSP resource , const KisTagSP tag) { + ENTER_FUNCTION(); + /* if (!tag.isEmpty()) { // d->model->tagCategoryAdded(tag); if (resource) { addResourceTag(resource, tag); } } + */ } -void KisResourceTaggingManager::syncTagBoxEntryRemoval(const QString& tag) +void KisResourceTaggingManager::syncTagBoxEntryRemoval(const KisTagSP tag) { - d->tagChooser->removeItem(tag); + ENTER_FUNCTION(); + //d->tagChooser->removeItem(tag); } void KisResourceTaggingManager::syncTagBoxEntries() { - QStringList tags; // = d->model->tagNamesList(); + ENTER_FUNCTION(); + /* + QList tags = d->tagModel->allTags(); tags.sort(); - Q_FOREACH (const QString &tag, tags) { - d->tagChooser->insertItem(tag); + Q_FOREACH (const KisTagSP &tag, tags) { + //d->tagChooser->insertItem(tag); } + */ } -void KisResourceTaggingManager::contextAddTagToResource(KoResourceSP resource, const QString& tag) +void KisResourceTaggingManager::contextAddTagToResource(KoResourceSP resource, const KisTagSP tag) { + ENTER_FUNCTION(); addResourceTag(resource, tag); // d->model->tagCategoryMembersChanged(); updateTaggedResourceView(); } -void KisResourceTaggingManager::contextRemoveTagFromResource(KoResourceSP resource, const QString& tag) +void KisResourceTaggingManager::contextRemoveTagFromResource(KoResourceSP resource, const KisTagSP tag) { + ENTER_FUNCTION(); removeResourceTag(resource, tag); // d->model->tagCategoryMembersChanged(); updateTaggedResourceView(); } -void KisResourceTaggingManager::removeTagFromComboBox(const QString &tag) +void KisResourceTaggingManager::removeTagFromComboBox(const KisTagSP tag) { + ENTER_FUNCTION(); // QList resources = d->model->currentlyVisibleResources(); // Q_FOREACH (KoResourceSP resource, resources) { // removeResourceTag(resource, tag); // } // d->model->tagCategoryRemoved(tag); // d->lastDeletedTag = TaggedResourceSet(tag, resources); - d->tagChooser->setUndeletionCandidate(tag); + // d->tagChooser->setUndeletionCandidate(tag); } -void KisResourceTaggingManager::removeResourceTag(KoResourceSP resource, const QString& tagName) +void KisResourceTaggingManager::removeResourceTag(KoResourceSP resource, const KisTagSP tag) { + ENTER_FUNCTION(); + d->tagModel->untagResource(tag, resource); // QStringList tagsList = d->model->assignedTagsList(resource); // Q_FOREACH (const QString & oldName, tagsList) { // if (!oldName.compare(tagName)) { // d->model->deleteTag(resource, oldName); // } // } } -void KisResourceTaggingManager::renameTag(const QString &oldName, const QString& newName) +void KisResourceTaggingManager::renameTag(const KisTagSP oldTag, const KisTagSP newName) { + ENTER_FUNCTION(); + //d->tagModel // if (!d->model->tagNamesList().contains(newName)) { // QList resources = d->model->currentlyVisibleResources(); // Q_FOREACH (KoResourceSP resource, resources) { // removeResourceTag(resource, oldName); // addResourceTag(resource, newName); // } // contextCreateNewTag(newName); // d->model->tagCategoryRemoved(oldName); // d->model->tagCategoryAdded(newName); // } } void KisResourceTaggingManager::updateTaggedResourceView() { + ENTER_FUNCTION(); // d->model->setCurrentTag(d->currentTag); // d->model->updateServer(); // d->originalResources = d->model->currentlyVisibleResources(); emit updateView(); } -void KisResourceTaggingManager::tagChooserIndexChanged(const QString& lineEditText) +void KisResourceTaggingManager::tagChooserIndexChanged(const KisTagSP tag) { + ENTER_FUNCTION(); + d->model->setTag(tag); + d->currentTag = tag; + +/* if (!d->tagChooser->selectedTagIsReadOnly()) { - d->currentTag = lineEditText; + d->currentTag = d->tagChooser->currentlySelectedTag(); d->tagFilter->allowSave(true); // d->model->enableResourceFiltering(true); } else { // d->model->enableResourceFiltering(false); d->tagFilter->allowSave(false); d->currentTag.clear(); } - +*/ d->tagFilter->clear(); updateTaggedResourceView(); } void KisResourceTaggingManager::tagSearchLineEditTextChanged(const QString& lineEditText) { + ENTER_FUNCTION() << ppVar(lineEditText); // if (d->tagChooser->selectedTagIsReadOnly()) { // d->model->enableResourceFiltering(!lineEditText.isEmpty()); // } else { // d->model->enableResourceFiltering(true); // } // d->model->searchTextChanged(lineEditText); // d->model->updateServer(); //FIXME: fix completer // d->tagCompleter = new QCompleter(tagNamesList(lineEditText),this); // d->tagSearchLineEdit->setCompleter(d->tagCompleter); emit updateView(); } void KisResourceTaggingManager::tagSaveButtonPressed() { + ENTER_FUNCTION(); // if (!d->tagChooser->selectedTagIsReadOnly()) { // QList newResources = d->model->currentlyVisibleResources(); // Q_FOREACH (KoResourceSP oldRes, d->originalResources) { // if (!newResources.contains(oldRes)) // removeResourceTag(oldRes, d->currentTag); // } // Q_FOREACH (KoResourceSP newRes, newResources) { // if (!d->originalResources.contains(newRes)) // addResourceTag(newRes, d->currentTag); // } // d->model->tagCategoryMembersChanged(); // } updateTaggedResourceView(); } -void KisResourceTaggingManager::contextMenuRequested(KoResourceSP resource, const QStringList& resourceTags, const QPoint& pos) +void KisResourceTaggingManager::contextMenuRequested(KoResourceSP resource, const QList resourceTags, const QPoint& pos) { + ENTER_FUNCTION(); // No visible tag chooser usually means no intended tag interaction, // context menu makes no sense then either if (!resource || !d->tagChooser->isVisible()) return; KisResourceItemChooserContextMenu menu(resource, resourceTags, d->tagChooser->currentlySelectedTag(), d->tagChooser->allTags()); connect(&menu, SIGNAL(resourceTagAdditionRequested(KoResourceSP,QString)), this, SLOT(contextAddTagToResource(KoResourceSP,QString))); connect(&menu, SIGNAL(resourceTagRemovalRequested(KoResourceSP,QString)), this, SLOT(contextRemoveTagFromResource(KoResourceSP,QString))); connect(&menu, SIGNAL(resourceAssignmentToNewTagRequested(KoResourceSP,QString)), this, SLOT(contextCreateNewTag(KoResourceSP,QString))); menu.exec(pos); } void KisResourceTaggingManager::contextMenuRequested(KoResourceSP currentResource, QPoint pos) { -// if (currentResource) { -// contextMenuRequested(currentResource, d->model->assignedTagsList(currentResource), pos); -// } + ENTER_FUNCTION(); + // d->model->assignedTagsList(currentResource) + if (currentResource) { + contextMenuRequested(currentResource, QList(), pos); + } + } KisTagChooserWidget *KisResourceTaggingManager::tagChooserWidget() { + ENTER_FUNCTION(); return d->tagChooser; } KisTagFilterWidget *KisResourceTaggingManager::tagFilterWidget() { + ENTER_FUNCTION(); return d->tagFilter; } diff --git a/libs/resourcewidgets/KisResourceTaggingManager.h b/libs/resourcewidgets/KisResourceTaggingManager.h index 3905918a94..4aabc2fad3 100644 --- a/libs/resourcewidgets/KisResourceTaggingManager.h +++ b/libs/resourcewidgets/KisResourceTaggingManager.h @@ -1,100 +1,104 @@ /* * This file is part of the KDE project * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Jan Hambrecht * Copyright (c) 2007 Sven Langkamp * Copyright (C) 2011 Srikanth Tiyyagura * Copyright (c) 2011 José Luis Vergara * Copyright (c) 2013 Sascha Suelzer * 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. */ #ifndef KISRESOURCETAGGINGMANAGER_H #define KISRESOURCETAGGINGMANAGER_H #include #include #include #include +#include +#include + class QWidget; class QStringList; class QString; class QPoint; class KisTagFilterWidget; class KisTagChooserWidget; class KisTagFilterResourceProxyModel; + /** * @brief The KisResourceTaggingManager class is ... * * XXX: this needs to be documented! */ class KisResourceTaggingManager : public QObject { Q_OBJECT public: explicit KisResourceTaggingManager(KisTagModel* tagModel, KisTagFilterResourceProxyModel *model, QWidget *parent); ~KisResourceTaggingManager() override; void showTaggingBar(bool show); QStringList availableTags() const; void contextMenuRequested(KoResourceSP currentResource, QPoint pos); void allowTagModification( bool set ); bool allowTagModification(); KisTagFilterWidget *tagFilterWidget(); KisTagChooserWidget *tagChooserWidget(); Q_SIGNALS: void updateView(); private Q_SLOTS: - void undeleteTag(const QString& tagToUndelete); + void undeleteTag(const KisTagSP tagToUndelete); void purgeTagUndeleteList(); - void contextCreateNewTag(KoResourceSP resource, const QString& tag); - void contextCreateNewTag(const QString& tag); - void syncTagBoxEntryRemoval(const QString& tag); - void syncTagBoxEntryAddition(const QString& tag); + void contextCreateNewTag(KoResourceSP resource, const KisTagSP tag); + void contextCreateNewTag(const KisTagSP tag); + void syncTagBoxEntryRemoval(const KisTagSP tag); + void syncTagBoxEntryAddition(const KisTagSP tag); void syncTagBoxEntries(); void tagSaveButtonPressed(); - void contextRemoveTagFromResource(KoResourceSP resource, const QString& tag); - void contextAddTagToResource(KoResourceSP resource, const QString& tag); - void renameTag(const QString &oldName, const QString &newName); - void tagChooserIndexChanged(const QString& lineEditText); - void tagSearchLineEditTextChanged(const QString& lineEditText); - void removeTagFromComboBox(const QString& tag); + void contextRemoveTagFromResource(KoResourceSP resource, const KisTagSP tag); + void contextAddTagToResource(KoResourceSP resource, const KisTagSP tag); + void renameTag(const KisTagSP oldName, const KisTagSP newName); + void tagChooserIndexChanged(const KisTagSP lineEditText); + void tagSearchLineEditTextChanged(const QString &lineEditText); + void removeTagFromComboBox(const KisTagSP tag); private: - void contextMenuRequested(KoResourceSP resource, const QStringList& resourceTags, const QPoint& pos); + void contextMenuRequested(KoResourceSP resource, const QList resourceTags, const QPoint& pos); void enableContextMenu(bool enable); - void removeResourceTag(KoResourceSP resource, const QString& tagName); - void addResourceTag(KoResourceSP resource, const QString& tagName); + void removeResourceTag(KoResourceSP resource, const KisTagSP tagName); + void addResourceTag(KoResourceSP resource, const KisTagSP tagName); void updateTaggedResourceView(); class Private; Private* const d; }; #endif // KORESOURCETAGGINGINTERFACE_H diff --git a/libs/resourcewidgets/KisTagChooserWidget.cpp b/libs/resourcewidgets/KisTagChooserWidget.cpp index 50a88a4c38..78820a842d 100644 --- a/libs/resourcewidgets/KisTagChooserWidget.cpp +++ b/libs/resourcewidgets/KisTagChooserWidget.cpp @@ -1,217 +1,236 @@ /* * This file is part of the KDE project * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Jan Hambrecht * Copyright (c) 2007 Sven Langkamp * Copyright (C) 2011 Srikanth Tiyyagura * Copyright (c) 2011 José Luis Vergara * Copyright (c) 2013 Sascha Suelzer * * 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 "KisTagChooserWidget.h" #include #include #include +#include #include #include #include #include "KisResourceItemChooserContextMenu.h" #include "KisTagToolButton.h" -#include - +#include "kis_debug.h" +#include class Q_DECL_HIDDEN KisTagChooserWidget::Private { public: - KisSqueezedComboBox *comboBox; + QComboBox *comboBox; KisTagToolButton *tagToolButton; - QStringList readOnlyTags; - QStringList tags; + QList readOnlyTags; + QList tags; + KisTagModel* model; + QScopedPointer activeFilterModel; + + Private(KisTagModel* model) + : activeFilterModel(new KisActiveFilterTagProxyModel(model)) + { + + } }; KisTagChooserWidget::KisTagChooserWidget(KisTagModel* model, QWidget* parent) : QWidget(parent) - , d(new Private()) + , d(new Private(model)) { - d->comboBox = new KisSqueezedComboBox(this); + d->comboBox = new QComboBox(this); + d->comboBox->setToolTip(i18n("Tag")); d->comboBox->setSizePolicy(QSizePolicy::MinimumExpanding , QSizePolicy::Fixed ); - QStringList list; + //d->comboBox->setModel(d->activeFilterModel.get()); + d->comboBox->setModel(model); - for (int i = 0; i < model->rowCount(); i++) { - QModelIndex index = model->index(i, 0); - KisTagSP tag = model->tagForIndex(index); - if (!tag.isNull()) { - list << tag->name(); - } - } - - d->comboBox->insertItems(0, list); - d->tags = list; + d->model = model; QGridLayout* comboLayout = new QGridLayout(this); comboLayout->addWidget(d->comboBox, 0, 0); d->tagToolButton = new KisTagToolButton(this); comboLayout->addWidget(d->tagToolButton, 0, 1); comboLayout->setSpacing(0); comboLayout->setMargin(0); comboLayout->setColumnStretch(0, 3); this->setEnabled(true); - clear(); - connect(d->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(tagChanged(int))); + connect(d->comboBox, SIGNAL(currentIndexChanged(int)), + this, SLOT(tagChanged(int))); connect(d->tagToolButton, SIGNAL(popupMenuAboutToShow()), this, SLOT (tagOptionsContextMenuAboutToShow())); - connect(d->tagToolButton, SIGNAL(newTagRequested(QString)), - this, SIGNAL(newTagRequested(QString))); + + connect(d->tagToolButton, SIGNAL(newTagRequested(KisTagSP)), + this, SLOT(insertItem(KisTagSP))); connect(d->tagToolButton, SIGNAL(deletionOfCurrentTagRequested()), this, SLOT(contextDeleteCurrentTag())); - connect(d->tagToolButton, SIGNAL(renamingOfCurrentTagRequested(QString)), - this, SLOT(tagRenamingRequested(QString))); - connect(d->tagToolButton, SIGNAL(undeletionOfTagRequested(QString)), - this, SIGNAL(tagUndeletionRequested(QString))); + + connect(d->tagToolButton, SIGNAL(renamingOfCurrentTagRequested(KisTagSP)), + this, SLOT(tagRenamingRequested(KisTagSP))); + connect(d->tagToolButton, SIGNAL(undeletionOfTagRequested(KisTagSP)), + this, SIGNAL(tagUndeletionRequested(KisTagSP))); connect(d->tagToolButton, SIGNAL(purgingOfTagUndeleteListRequested()), this, SIGNAL(tagUndeletionListPurgeRequested())); } KisTagChooserWidget::~KisTagChooserWidget() { delete d; } void KisTagChooserWidget::contextDeleteCurrentTag() { - if (selectedTagIsReadOnly()) { - return; - } - emit tagDeletionRequested(currentlySelectedTag()); + ENTER_FUNCTION(); + KisTagSP currentTag = currentlySelectedTag(); + d->model->removeTag(currentTag); } void KisTagChooserWidget::tagChanged(int) { - emit tagChosen(d->comboBox->currentUnsqueezedText()); + ENTER_FUNCTION(); + emit tagChosen(currentlySelectedTag()); } -void KisTagChooserWidget::tagRenamingRequested(const QString& newName) +void KisTagChooserWidget::tagRenamingRequested(const KisTagSP newName) { - if (newName.isEmpty() || selectedTagIsReadOnly()) { - return; - } - emit tagRenamingRequested(currentlySelectedTag(), newName); + ENTER_FUNCTION(); + // TODO: RESOURCES: implement renaming (implement update in KisTagModel?) + warnKrita << "Renaming of tags not implemented"; } -void KisTagChooserWidget::setUndeletionCandidate(const QString& tag) +void KisTagChooserWidget::setUndeletionCandidate(const KisTagSP tag) { + ENTER_FUNCTION(); d->tagToolButton->setUndeletionCandidate(tag); } void KisTagChooserWidget::setCurrentIndex(int index) { + ENTER_FUNCTION(); d->comboBox->setCurrentIndex(index); } -int KisTagChooserWidget::findIndexOf(QString tagName) +int KisTagChooserWidget::findIndexOf(KisTagSP tagName) { - return d->comboBox->findOriginalText(tagName); + ENTER_FUNCTION(); + return -1; + //return d->comboBox->findOriginalText(tagName); } -void KisTagChooserWidget::addReadOnlyItem(QString tagName) +void KisTagChooserWidget::addReadOnlyItem(KisTagSP tag) { - d->readOnlyTags.append(tagName); + d->model->addTag(tag); + ENTER_FUNCTION(); } -void KisTagChooserWidget::insertItem(QString tagName) +void KisTagChooserWidget::insertItem(KisTagSP tag) { - QStringList tags = allTags(); - tags.append(tagName); - tags.sort(); - foreach (QString readOnlyTag, d->readOnlyTags) { - tags.prepend(readOnlyTag); - } - - int index = tags.indexOf(tagName); - if (d->comboBox->findOriginalText(tagName) == -1) { - d->comboBox->insertSqueezedItem(tagName, index); - d->tags.append(tagName); - } + fprintf(stderr, "inserting item!!! %s\n", tag->name().toUtf8().toStdString().c_str()); + tag->setUrl(tag->name()); + tag->setComment(tag->name()); + tag->setActive(true); + tag->setValid(true); + ENTER_FUNCTION(); + bool added = d->model->addTag(tag); + fprintf(stderr, "added = %d\n", added); } -QString KisTagChooserWidget::currentlySelectedTag() +KisTagSP KisTagChooserWidget::currentlySelectedTag() { - return d->comboBox->currentUnsqueezedText(); + int row = d->comboBox->currentIndex(); + // TODO: RESOURCES: there shouldn't be any +1 for "All", of course; + //d->comboBox->currentData(); + fprintf(stderr, "current data type = %s", d->comboBox->currentData().typeName()); + + QModelIndex index = d->model->index(row - 1, 0); + KisTagSP tag = d->model->tagForIndex(index); + ENTER_FUNCTION() << tag; + return tag; } -QStringList KisTagChooserWidget::allTags() +QList KisTagChooserWidget::allTags() { - return d->tags; + ENTER_FUNCTION(); + QList list; + for (int i = 0; i < d->model->rowCount(); i++) { + QModelIndex index = d->model->index(i, 0); + KisTagSP tag = d->model->tagForIndex(index); + if (!tag.isNull()) { + list << tag; + } + } + + return list; } bool KisTagChooserWidget::selectedTagIsReadOnly() { - return d->readOnlyTags.contains(d->comboBox->currentUnsqueezedText()) ; + ENTER_FUNCTION(); + return false; } -void KisTagChooserWidget::addItems(QStringList tagNames) +void KisTagChooserWidget::addItems(QList tags) { - d->tags.append(tagNames); - d->tags.removeDuplicates(); - d->tags.sort(); - d->readOnlyTags.sort(); - - QStringList items = d->readOnlyTags + d->tags; - - items.removeDuplicates(); + ENTER_FUNCTION(); + warnKrita << "not implemented"; - d->comboBox->resetOriginalTexts(items); + Q_FOREACH(KisTagSP tag, tags) { + insertItem(tag); + } } void KisTagChooserWidget::clear() { - d->comboBox->resetOriginalTexts(QStringList()); + ENTER_FUNCTION(); } -void KisTagChooserWidget::removeItem(QString item) +void KisTagChooserWidget::removeItem(KisTagSP item) { - int pos = findIndexOf(item); - if (pos >= 0) { - d->comboBox->removeSqueezedItem(pos); - d->tags.removeOne(item); - } + fprintf(stderr, "removing item: %s\n", item->name().toUtf8().toStdString().c_str()); + ENTER_FUNCTION(); + d->model->removeTag(item); } void KisTagChooserWidget::tagOptionsContextMenuAboutToShow() { + ENTER_FUNCTION(); /* only enable the save button if the selected tag set is editable */ d->tagToolButton->readOnlyMode(selectedTagIsReadOnly()); emit popupMenuAboutToShow(); } void KisTagChooserWidget::showTagToolButton(bool show) { + ENTER_FUNCTION(); d->tagToolButton->setVisible(show); } diff --git a/libs/resourcewidgets/KisTagChooserWidget.h b/libs/resourcewidgets/KisTagChooserWidget.h index a03fb08f26..6206d1f981 100644 --- a/libs/resourcewidgets/KisTagChooserWidget.h +++ b/libs/resourcewidgets/KisTagChooserWidget.h @@ -1,78 +1,84 @@ /* * This file is part of the KDE project * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Jan Hambrecht * Copyright (c) 2007 Sven Langkamp * Copyright (C) 2011 Srikanth Tiyyagura * Copyright (c) 2011 José Luis Vergara * Copyright (c) 2013 Sascha Suelzer * 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. */ #ifndef KISTAGCHOOSERWIDGET_H #define KISTAGCHOOSERWIDGET_H #include #include "kritaresourcewidgets_export.h" #include #include class KRITARESOURCEWIDGETS_EXPORT KisTagChooserWidget : public QWidget { Q_OBJECT public: explicit KisTagChooserWidget(KisTagModel* model, QWidget* parent); ~KisTagChooserWidget() override; void setCurrentIndex(int index); - int findIndexOf(QString tagName); - void insertItem(QString tagName); - QString currentlySelectedTag(); - QStringList allTags(); + int findIndexOf(KisTagSP tagName); + + KisTagSP currentlySelectedTag(); + QList allTags(); bool selectedTagIsReadOnly(); - void removeItem(QString item); - void addItems(QStringList tagNames); - void addReadOnlyItem(QString tagName); + void removeItem(KisTagSP item); + void addItems(QList tagNames); + void addReadOnlyItem(KisTagSP tagName); void clear(); - void setUndeletionCandidate(const QString &tag); + void setUndeletionCandidate(const KisTagSP tag); void showTagToolButton(bool show); Q_SIGNALS: - void newTagRequested(const QString &tagname); - void tagDeletionRequested(const QString &tagname); - void tagRenamingRequested(const QString &oldTagname, const QString &newTagname); - void tagUndeletionRequested(const QString &tagname); + void newTagRequested(const KisTagSP tag); + void tagDeletionRequested(const KisTagSP tag); + void tagRenamingRequested(const KisTagSP oldTag, const KisTagSP newTag); + void tagUndeletionRequested(const KisTagSP tag); void tagUndeletionListPurgeRequested(); void popupMenuAboutToShow(); - void tagChosen(const QString &tag); + void tagChosen(const KisTagSP tag); + +public Q_SLOTS: + void insertItem(KisTagSP tag); + void tagChanged(int index); + private Q_SLOTS: - void tagRenamingRequested(const QString &newName); + void tagRenamingRequested(const KisTagSP newName); void tagOptionsContextMenuAboutToShow(); void contextDeleteCurrentTag(); - void tagChanged(int index); + + private: class Private; Private* const d; }; ; #endif // KOTAGCHOOSERWIDGET_H diff --git a/libs/resourcewidgets/KisTagFilterWidget.cpp b/libs/resourcewidgets/KisTagFilterWidget.cpp index 461a2fb750..729384f8d0 100644 --- a/libs/resourcewidgets/KisTagFilterWidget.cpp +++ b/libs/resourcewidgets/KisTagFilterWidget.cpp @@ -1,135 +1,139 @@ /* * This file is part of the KDE project * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Jan Hambrecht * Copyright (c) 2007 Sven Langkamp * Copyright (C) 2011 Srikanth Tiyyagura * Copyright (c) 2011 José Luis Vergara * Copyright (c) 2013 Sascha Suelzer * * 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 "KisTagFilterWidget.h" #include #include #include #include #include #include +#include + class KisTagFilterWidget::Private { public: QString tagSearchBarTooltip_saving_disabled; QString tagSearchBarTooltip_saving_enabled; QLineEdit* tagSearchLineEdit; QPushButton* tagSearchSaveButton; QGridLayout* filterBarLayout; }; KisTagFilterWidget::KisTagFilterWidget(QWidget* parent) : QWidget(parent) , d(new Private()) { QString searchTooltipMaintext = i18nc( "@info:tooltip", "

Enter search terms here to add resources to, or remove them from, the current tag view.

" "

To filter based on the partial, case insensitive name of a resource:
" "partialname or !partialname

" "

To include or exclude other tag sets:
" "[Tagname] or ![Tagname]

" "

For case sensitive and full name matching in-/exclusion:
" "\"ExactMatch\" or !\"ExactMatch\"

"); d->tagSearchBarTooltip_saving_disabled = searchTooltipMaintext + i18nc( "@info:tooltip", "

Filter results cannot be saved for the All Presets view. " "In this view, pressing Enter or clearing the filter box will restore all items. " "Create and/or switch to a different tag if you want to save filtered resources into named sets.

"); d->tagSearchBarTooltip_saving_enabled = searchTooltipMaintext + i18nc( "@info:tooltip", "

Pressing Enter or clicking the Save button will save the changes.

"); QGridLayout* filterBarLayout = new QGridLayout; d->tagSearchLineEdit = new QLineEdit(this); d->tagSearchLineEdit->setClearButtonEnabled(true); d->tagSearchLineEdit->setPlaceholderText(i18n("Search")); d->tagSearchLineEdit->setToolTip(d->tagSearchBarTooltip_saving_disabled); d->tagSearchLineEdit->setEnabled(true); filterBarLayout->setSpacing(0); filterBarLayout->setMargin(0); filterBarLayout->setColumnStretch(0, 1); filterBarLayout->addWidget(d->tagSearchLineEdit, 0, 0); d->tagSearchSaveButton = new QPushButton(this); d->tagSearchSaveButton->setIcon(koIcon("media-floppy")); d->tagSearchSaveButton->setToolTip(i18nc("@info:tooltip", "Save the currently filtered set as the new members of the current tag.")); d->tagSearchSaveButton->setEnabled(false); filterBarLayout->addWidget(d->tagSearchSaveButton, 0, 1); connect(d->tagSearchSaveButton, SIGNAL(pressed()), this, SLOT(onSaveButtonClicked())); connect(d->tagSearchLineEdit, SIGNAL(returnPressed()), this, SLOT(onSaveButtonClicked())); connect(d->tagSearchLineEdit, SIGNAL(textChanged(QString)), this, SLOT(onTextChanged(QString))); allowSave(false); this->setLayout(filterBarLayout); } KisTagFilterWidget::~KisTagFilterWidget() { delete d; } void KisTagFilterWidget::allowSave(bool allow) { if (allow) { d->tagSearchSaveButton->show(); d->tagSearchLineEdit->setToolTip(d->tagSearchBarTooltip_saving_enabled); } else { d->tagSearchSaveButton->hide(); d->tagSearchLineEdit->setToolTip(d->tagSearchBarTooltip_saving_disabled); } } void KisTagFilterWidget::clear() { d->tagSearchLineEdit->clear(); d->tagSearchSaveButton->setEnabled(false); } void KisTagFilterWidget::onTextChanged(const QString& lineEditText) { + ENTER_FUNCTION() << ppVar(lineEditText); d->tagSearchSaveButton->setEnabled(!lineEditText.isEmpty()); emit filterTextChanged(lineEditText); } void KisTagFilterWidget::onSaveButtonClicked() { + ENTER_FUNCTION() << ppVar(d->tagSearchLineEdit->text()); emit saveButtonClicked(); clear(); } diff --git a/libs/resourcewidgets/KisTagToolButton.cpp b/libs/resourcewidgets/KisTagToolButton.cpp index c0a1b2c2cb..f71f0ecba8 100644 --- a/libs/resourcewidgets/KisTagToolButton.cpp +++ b/libs/resourcewidgets/KisTagToolButton.cpp @@ -1,143 +1,148 @@ /* * This file is part of the KDE project * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Jan Hambrecht * Copyright (c) 2007 Sven Langkamp * Copyright (C) 2011 Srikanth Tiyyagura * Copyright (c) 2011 José Luis Vergara * Copyright (c) 2013 Sascha Suelzer * * 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 "KisTagToolButton.h" #include #include #include #include #include "KisResourceItemChooserContextMenu.h" +#include "kis_debug.h" class KisTagToolButton::Private { public: QToolButton* tagToolButton; QAction* action_undeleteTag; QAction* action_deleteTag; KoLineEditAction* action_renameTag; QAction* action_purgeTagUndeleteList; - QString undeleteCandidate; + KisTagSP undeleteCandidate; }; KisTagToolButton::KisTagToolButton(QWidget* parent) :QWidget(parent), d(new Private()) { + QGridLayout* buttonLayout = new QGridLayout(this); buttonLayout->setMargin(0); buttonLayout->setSpacing(0); d->tagToolButton = new QToolButton(this); d->tagToolButton->setIcon(koIcon("bookmarks")); d->tagToolButton->setText(i18n("Tag")); d->tagToolButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); d->tagToolButton->setToolTip(i18nc("@info:tooltip", "Show the tag box options.")); d->tagToolButton->setPopupMode(QToolButton::InstantPopup); d->tagToolButton->setEnabled(true); QMenu* popup = new QMenu(this); KoLineEditAction* addTagAction = new KoLineEditAction(popup); addTagAction->setPlaceholderText(i18n("New tag")); addTagAction->setIcon(koIcon("document-new")); addTagAction->closeParentOnTrigger(true); popup->addAction(addTagAction); - connect(addTagAction, SIGNAL(triggered(QString)), - this, SIGNAL(newTagRequested(QString))); + connect(addTagAction, SIGNAL(triggered(KisTagSP)), + this, SIGNAL(newTagRequested(KisTagSP))); d->action_renameTag = new KoLineEditAction(popup); d->action_renameTag->setPlaceholderText(i18n("Rename tag")); d->action_renameTag->setIcon(koIcon("edit-rename")); d->action_renameTag->closeParentOnTrigger(true); popup->addAction(d->action_renameTag); - connect(d->action_renameTag, SIGNAL(triggered(QString)), - this, SIGNAL(renamingOfCurrentTagRequested(QString))); + connect(d->action_renameTag, SIGNAL(triggered(KisTagSP)), + this, SIGNAL(renamingOfCurrentTagRequested(KisTagSP))); popup->addSeparator(); d->action_deleteTag = new QAction(popup); d->action_deleteTag->setText(i18n("Delete this tag")); d->action_deleteTag->setIcon(koIcon("edit-delete")); popup->addAction(d->action_deleteTag); connect(d->action_deleteTag, SIGNAL(triggered()), this, SIGNAL(deletionOfCurrentTagRequested())); popup->addSeparator(); d->action_undeleteTag = new QAction(popup); d->action_undeleteTag->setIcon(koIcon("edit-redo")); d->action_undeleteTag->setVisible(false); popup->addAction(d->action_undeleteTag); connect(d->action_undeleteTag, SIGNAL(triggered()), this, SLOT(onTagUndeleteClicked())); d->action_purgeTagUndeleteList = new QAction(popup); d->action_purgeTagUndeleteList->setText(i18n("Clear undelete list")); d->action_purgeTagUndeleteList->setIcon(koIcon("edit-clear")); d->action_purgeTagUndeleteList->setVisible(false); popup->addAction(d->action_purgeTagUndeleteList); connect(d->action_purgeTagUndeleteList, SIGNAL(triggered()), this, SIGNAL(purgingOfTagUndeleteListRequested())); connect(popup, SIGNAL(aboutToShow()), this, SIGNAL(popupMenuAboutToShow())); d->tagToolButton->setMenu(popup); buttonLayout->addWidget(d->tagToolButton); } KisTagToolButton::~KisTagToolButton() { delete d; } void KisTagToolButton::readOnlyMode(bool activate) { + ENTER_FUNCTION(); activate = !activate; d->action_renameTag->setVisible(activate); d->action_deleteTag->setVisible(activate); } -void KisTagToolButton::setUndeletionCandidate(const QString& deletedTagName) +void KisTagToolButton::setUndeletionCandidate(const KisTagSP deletedTag) { - d->undeleteCandidate = deletedTagName; - d->action_undeleteTag->setText(i18n("Undelete") +" "+ deletedTagName); - d->action_undeleteTag->setVisible(!deletedTagName.isEmpty()); - d->action_purgeTagUndeleteList->setVisible(!deletedTagName.isEmpty()); + ENTER_FUNCTION(); + d->undeleteCandidate = deletedTag; + d->action_undeleteTag->setText(i18n("Undelete") +" "+ deletedTag->name()); + d->action_undeleteTag->setVisible(!deletedTag->name().isEmpty()); + d->action_purgeTagUndeleteList->setVisible(!deletedTag->name().isEmpty()); } void KisTagToolButton::onTagUndeleteClicked() { + ENTER_FUNCTION(); emit undeletionOfTagRequested(d->undeleteCandidate); } diff --git a/libs/resourcewidgets/KisTagToolButton.h b/libs/resourcewidgets/KisTagToolButton.h index 478c100932..883d00a98b 100644 --- a/libs/resourcewidgets/KisTagToolButton.h +++ b/libs/resourcewidgets/KisTagToolButton.h @@ -1,58 +1,59 @@ /* * This file is part of the KDE project * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Jan Hambrecht * Copyright (c) 2007 Sven Langkamp * Copyright (C) 2011 Srikanth Tiyyagura * Copyright (c) 2011 José Luis Vergara * Copyright (c) 2013 Sascha Suelzer * * 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 KISTAGTOOLBUTTON_H #define KISTAGTOOLBUTTON_H #include +#include class KisTagToolButton : public QWidget { Q_OBJECT private: explicit KisTagToolButton(QWidget* parent = 0); ~KisTagToolButton() override; void readOnlyMode(bool activate); - void setUndeletionCandidate(const QString &deletedTagName); + void setUndeletionCandidate(const KisTagSP deletedTag); Q_SIGNALS: - void newTagRequested(const QString &tagname); - void renamingOfCurrentTagRequested(const QString &tagname); + void newTagRequested(const KisTagSP tag); + void renamingOfCurrentTagRequested(const KisTagSP tag); void deletionOfCurrentTagRequested(); - void undeletionOfTagRequested(const QString &tagname); + void undeletionOfTagRequested(const KisTagSP tag); void purgingOfTagUndeleteListRequested(); void popupMenuAboutToShow(); private Q_SLOTS: void onTagUndeleteClicked(); private: class Private; Private* const d; friend class KisTagChooserWidget; }; #endif // KOTAGTOOLBUTTON_H