1 /*
2  *  Copyright (C) 2012 Felix Geyer <debfx@fobos.de>
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 2 or (at your option)
7  *  version 3 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "EntryAttributes.h"
19 
20 const QString EntryAttributes::TitleKey = "Title";
21 const QString EntryAttributes::UserNameKey = "UserName";
22 const QString EntryAttributes::PasswordKey = "Password";
23 const QString EntryAttributes::URLKey = "URL";
24 const QString EntryAttributes::NotesKey = "Notes";
25 const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey
26                                                      << PasswordKey << URLKey << NotesKey);
27 
EntryAttributes(QObject * parent)28 EntryAttributes::EntryAttributes(QObject* parent)
29     : QObject(parent)
30 {
31     clear();
32 }
33 
keys() const34 QList<QString> EntryAttributes::keys() const
35 {
36     return m_attributes.keys();
37 }
38 
hasKey(const QString & key) const39 bool EntryAttributes::hasKey(const QString& key) const
40 {
41     return m_attributes.keys().contains(key);
42 }
43 
customKeys()44 QList<QString> EntryAttributes::customKeys()
45 {
46     QList<QString> customKeys;
47     const QList<QString> keyList = keys();
48     for (const QString& key : keyList) {
49         if (!isDefaultAttribute(key)) {
50             customKeys.append(key);
51         }
52     }
53     return customKeys;
54 }
55 
value(const QString & key) const56 QString EntryAttributes::value(const QString& key) const
57 {
58     return m_attributes.value(key);
59 }
60 
isProtected(const QString & key) const61 bool EntryAttributes::isProtected(const QString& key) const
62 {
63     return m_protectedAttributes.contains(key);
64 }
65 
set(const QString & key,const QString & value,bool protect)66 void EntryAttributes::set(const QString& key, const QString& value, bool protect)
67 {
68     bool emitModified = false;
69 
70     bool addAttribute = !m_attributes.contains(key);
71     bool changeValue = !addAttribute && (m_attributes.value(key) != value);
72     bool defaultAttribute = isDefaultAttribute(key);
73 
74     if (addAttribute && !defaultAttribute) {
75         Q_EMIT aboutToBeAdded(key);
76     }
77 
78     if (addAttribute || changeValue) {
79         m_attributes.insert(key, value);
80         emitModified = true;
81     }
82 
83     if (protect) {
84         if (!m_protectedAttributes.contains(key)) {
85             emitModified = true;
86         }
87         m_protectedAttributes.insert(key);
88     }
89     else if (m_protectedAttributes.remove(key)) {
90         emitModified = true;
91     }
92 
93     if (emitModified) {
94         Q_EMIT modified();
95     }
96 
97     if (defaultAttribute && changeValue) {
98         Q_EMIT defaultKeyModified();
99     }
100     else if (addAttribute) {
101         Q_EMIT added(key);
102     }
103     else if (emitModified) {
104         Q_EMIT customKeyModified(key);
105     }
106 }
107 
remove(const QString & key)108 void EntryAttributes::remove(const QString& key)
109 {
110     Q_ASSERT(!isDefaultAttribute(key));
111 
112     if (!m_attributes.contains(key)) {
113         Q_ASSERT(false);
114         return;
115     }
116 
117     Q_EMIT aboutToBeRemoved(key);
118 
119     m_attributes.remove(key);
120     m_protectedAttributes.remove(key);
121 
122     Q_EMIT removed(key);
123     Q_EMIT modified();
124 }
125 
rename(const QString & oldKey,const QString & newKey)126 void EntryAttributes::rename(const QString& oldKey, const QString& newKey)
127 {
128     Q_ASSERT(!isDefaultAttribute(oldKey));
129     Q_ASSERT(!isDefaultAttribute(newKey));
130 
131     if (!m_attributes.contains(oldKey)) {
132         Q_ASSERT(false);
133         return;
134     }
135 
136     if (m_attributes.contains(newKey)) {
137         Q_ASSERT(false);
138         return;
139     }
140 
141     QString data = value(oldKey);
142     bool protect = isProtected(oldKey);
143 
144     Q_EMIT aboutToRename(oldKey, newKey);
145 
146     m_attributes.remove(oldKey);
147     m_attributes.insert(newKey, data);
148     if (protect) {
149         m_protectedAttributes.remove(oldKey);
150         m_protectedAttributes.insert(newKey);
151     }
152 
153     Q_EMIT modified();
154     Q_EMIT renamed(oldKey, newKey);
155 }
156 
copyCustomKeysFrom(const EntryAttributes * other)157 void EntryAttributes::copyCustomKeysFrom(const EntryAttributes* other)
158 {
159     if (!areCustomKeysDifferent(other)) {
160         return;
161     }
162 
163     Q_EMIT aboutToBeReset();
164 
165     // remove all non-default keys
166     const QList<QString> keyList = keys();
167     for (const QString& key : keyList) {
168         if (!isDefaultAttribute(key)) {
169             m_attributes.remove(key);
170             m_protectedAttributes.remove(key);
171         }
172     }
173 
174     const QList<QString> otherKeyList = other->keys();
175     for (const QString& key : otherKeyList) {
176         if (!isDefaultAttribute(key)) {
177             m_attributes.insert(key, other->value(key));
178             if (other->isProtected(key)) {
179                 m_protectedAttributes.insert(key);
180             }
181         }
182     }
183 
184     Q_EMIT reset();
185     Q_EMIT modified();
186 }
187 
areCustomKeysDifferent(const EntryAttributes * other)188 bool EntryAttributes::areCustomKeysDifferent(const EntryAttributes* other)
189 {
190     // check if they are equal ignoring the order of the keys
191     if (keys().toSet() != other->keys().toSet()) {
192         return true;
193     }
194 
195     const QList<QString> keyList = keys();
196     for (const QString& key : keyList) {
197         if (isDefaultAttribute(key)) {
198             continue;
199         }
200 
201         if (isProtected(key) != other->isProtected(key) || value(key) != other->value(key)) {
202             return true;
203         }
204     }
205 
206     return false;
207 }
208 
copyDataFrom(const EntryAttributes * other)209 void EntryAttributes::copyDataFrom(const EntryAttributes* other)
210 {
211     if (*this != *other) {
212         Q_EMIT aboutToBeReset();
213 
214         m_attributes = other->m_attributes;
215         m_protectedAttributes = other->m_protectedAttributes;
216 
217         Q_EMIT reset();
218         Q_EMIT modified();
219     }
220 }
221 
operator ==(const EntryAttributes & other) const222 bool EntryAttributes::operator==(const EntryAttributes& other) const
223 {
224     return (m_attributes == other.m_attributes
225             && m_protectedAttributes == other.m_protectedAttributes);
226 }
227 
operator !=(const EntryAttributes & other) const228 bool EntryAttributes::operator!=(const EntryAttributes& other) const
229 {
230     return (m_attributes != other.m_attributes
231             || m_protectedAttributes != other.m_protectedAttributes);
232 }
233 
clear()234 void EntryAttributes::clear()
235 {
236     Q_EMIT aboutToBeReset();
237 
238     m_attributes.clear();
239     m_protectedAttributes.clear();
240 
241     for (const QString& key : DefaultAttributes) {
242         m_attributes.insert(key, "");
243     }
244 
245     Q_EMIT reset();
246     Q_EMIT modified();
247 }
248 
attributesSize()249 int EntryAttributes::attributesSize()
250 {
251     int size = 0;
252 
253     QMapIterator<QString, QString> i(m_attributes);
254     while (i.hasNext()) {
255         i.next();
256         size += i.value().toUtf8().size();
257     }
258     return size;
259 }
260 
isDefaultAttribute(const QString & key)261 bool EntryAttributes::isDefaultAttribute(const QString& key)
262 {
263     return DefaultAttributes.contains(key);
264 }
265