1 /** -*- mode: c++ ; c-basic-offset: 2 -*-
2 *
3 * @file FilterTagMap.h
4 *
5 * Copyright 2017 Sebastien Fourey
6 *
7 * This file is part of G'MIC-Qt, a generic plug-in for raster graphics
8 * editors, offering hundreds of filters thanks to the underlying G'MIC
9 * image processing framework.
10 *
11 * gmic_qt is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * gmic_qt is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with gmic_qt. If not, see <http://www.gnu.org/licenses/>.
23 *
24 */
25 #include "FilterTagMap.h"
26 #include <QBuffer>
27 #include <QByteArray>
28 #include <QDataStream>
29 #include <QDebug>
30 #include <QFile>
31 #include <QJsonArray>
32 #include <QJsonDocument>
33 #include <QJsonObject>
34 #include <QJsonValue>
35 #include <QList>
36 #include "Common.h"
37 #include "Globals.h"
38 #include "GmicQt.h"
39 #include "Logger.h"
40 #include "Utils.h"
41
42 namespace GmicQt
43 {
44
45 QMap<QString, TagColorSet> FiltersTagMap::_hashesToColors;
46
filterTags(const QString & hash)47 TagColorSet FiltersTagMap::filterTags(const QString & hash)
48 {
49 auto it = _hashesToColors.find(hash);
50 if (it == _hashesToColors.end()) {
51 return TagColorSet::Empty;
52 }
53 return it.value();
54 }
55
setFilterTags(const QString & hash,const TagColorSet & colors)56 void FiltersTagMap::setFilterTags(const QString & hash, const TagColorSet & colors)
57 {
58 if (colors.isEmpty()) {
59 _hashesToColors.remove(hash);
60 return;
61 }
62 _hashesToColors[hash] = colors;
63 }
64
load()65 void FiltersTagMap::load()
66 {
67 _hashesToColors.clear();
68 QString jsonFilename = QString("%1%2").arg(gmicConfigPath(true), FILTERS_TAGS_FILENAME);
69 QFile jsonFile(jsonFilename);
70 if (!jsonFile.exists()) {
71 return;
72 }
73 if (jsonFile.open(QFile::ReadOnly)) {
74 #ifdef _GMIC_QT_DEBUG_
75 QJsonDocument jsonDoc;
76 QByteArray allFile = jsonFile.readAll();
77 if (allFile.startsWith("{")) {
78 jsonDoc = QJsonDocument::fromJson(allFile);
79 } else {
80 jsonDoc = QJsonDocument::fromJson(qUncompress(allFile));
81 }
82 #else
83 QJsonDocument jsonDoc = QJsonDocument::fromJson(qUncompress(jsonFile.readAll()));
84 #endif
85 if (jsonDoc.isNull()) {
86 Logger::warning(QString("Cannot parse ") + jsonFilename);
87 Logger::warning("Fiter tags are lost!");
88 } else {
89 if (!jsonDoc.isObject()) {
90 Logger::error(QString("JSON file format is not correct (") + jsonFilename + ")");
91 } else {
92 QJsonObject documentObject = jsonDoc.object();
93 for (QJsonObject::const_iterator it = documentObject.constBegin(); //
94 it != documentObject.constEnd(); //
95 ++it) {
96 _hashesToColors[it.key()] = TagColorSet(it.value().toInt());
97 }
98 }
99 }
100 } else {
101 Logger::error("Cannot open " + jsonFilename);
102 Logger::error("Tags cannot be restored");
103 }
104 }
105
save()106 void FiltersTagMap::save()
107 {
108 QJsonObject documentObject;
109 auto it = _hashesToColors.begin();
110 while (it != _hashesToColors.end()) {
111 documentObject.insert(it.key(), QJsonValue(int(it.value().mask())));
112 ++it;
113 }
114 QJsonDocument jsonDoc(documentObject);
115 QString jsonFilename = QString("%1%2").arg(gmicConfigPath(true), FILTERS_TAGS_FILENAME);
116 if (QFile::exists(jsonFilename)) {
117 QString bakFilename = QString("%1%2").arg(gmicConfigPath(false), FILTERS_TAGS_FILENAME ".bak");
118 QFile::remove(bakFilename);
119 QFile::copy(jsonFilename, bakFilename);
120 }
121
122 #ifdef _GMIC_QT_DEBUG_
123 const bool ok = safelyWrite(jsonDoc.toJson(), jsonFilename);
124 #else
125 const bool ok = safelyWrite(qCompress(jsonDoc.toJson(QJsonDocument::Compact)), jsonFilename);
126 #endif
127 if (!ok) {
128 Logger::error("Cannot write " + jsonFilename);
129 Logger::error("Parameters cannot be saved");
130 }
131 }
132
usedColors(int * count)133 TagColorSet FiltersTagMap::usedColors(int * count)
134 {
135 TagColorSet all;
136 auto it = _hashesToColors.cbegin();
137 if (count) {
138 memset(count, 0, sizeof(int) * int(TagColor::Count));
139 while (it != _hashesToColors.cend()) {
140 TagColorSet colors = it.value();
141 for (TagColor color : colors) {
142 ++count[int(color)];
143 }
144 all |= colors;
145 ++it;
146 }
147 } else {
148 while (it != _hashesToColors.cend()) {
149 all |= it.value();
150 ++it;
151 }
152 }
153 return all;
154 }
155
removeAllTags(TagColor color)156 void FiltersTagMap::removeAllTags(TagColor color)
157 {
158 QList<QString> toBeRemoved;
159 auto it = _hashesToColors.begin();
160 while (it != _hashesToColors.end()) {
161 it.value() -= color;
162 if (it.value().isEmpty()) {
163 toBeRemoved.push_back(it.key());
164 }
165 ++it;
166 }
167 for (const QString & hash : toBeRemoved) {
168 _hashesToColors.remove(hash);
169 }
170 }
171
clearFilterTag(const QString & hash,TagColor color)172 void FiltersTagMap::clearFilterTag(const QString & hash, TagColor color)
173 {
174 auto it = _hashesToColors.find(hash);
175 if (it == _hashesToColors.end()) {
176 return;
177 }
178 it.value() -= color;
179 if (it.value().isEmpty()) {
180 _hashesToColors.erase(it);
181 }
182 }
183
setFilterTag(const QString & hash,TagColor color)184 void FiltersTagMap::setFilterTag(const QString & hash, TagColor color)
185 {
186 _hashesToColors[hash] += color;
187 }
188
toggleFilterTag(const QString & hash,TagColor color)189 void FiltersTagMap::toggleFilterTag(const QString & hash, TagColor color)
190 {
191 _hashesToColors[hash].toggle(color);
192 }
193
remove(const QString & hash)194 void FiltersTagMap::remove(const QString & hash)
195 {
196 _hashesToColors.remove(hash);
197 }
198 } // namespace GmicQt
199