4
#include <initializer_list>
7
#include <celutil/gettext.h>
11
UserCategoryManager::UserCategoryManager() = default;
12
UserCategoryManager::~UserCategoryManager() = default;
15
UserCategoryManager::create(const std::string& name,
16
UserCategoryId parent,
17
const std::string& domain)
19
if (parent != UserCategoryId::Invalid)
21
auto parentIndex = static_cast<std::size_t>(parent);
22
if (parentIndex >= m_categories.size() || m_categories[parentIndex] == nullptr)
23
return UserCategoryId::Invalid;
27
bool reusedExisting = false;
28
if (m_available.empty())
29
id = static_cast<UserCategoryId>(m_categories.size());
32
id = m_available.back();
33
m_available.pop_back();
34
reusedExisting = true;
37
if (!m_categoryMap.try_emplace(name, id).second)
40
m_available.push_back(id);
41
return UserCategoryId::Invalid;
44
return createNew(id, name, parent, domain);
48
UserCategoryManager::destroy(UserCategoryId category)
50
auto categoryIndex = static_cast<std::size_t>(category);
51
if (categoryIndex >= m_categories.size() || m_categories[categoryIndex] == nullptr)
54
auto& entry = m_categories[categoryIndex];
55
if (!entry->m_children.empty())
59
for (const Selection& sel : entry->m_members)
61
auto it = m_objectMap.find(sel);
62
if (it == m_objectMap.end())
65
auto& categories = it->second;
66
if (auto item = std::find(categories.begin(), categories.end(), category); item != categories.end())
68
categories.erase(item);
69
if (categories.empty())
70
m_objectMap.erase(it);
74
m_active.erase(category);
75
if (entry->m_parent == UserCategoryId::Invalid)
76
m_roots.erase(category);
79
auto& parentChildren = m_categories[static_cast<std::size_t>(entry->m_parent)]->m_children;
80
auto it = std::find(parentChildren.begin(), parentChildren.end(), category);
81
parentChildren.erase(it);
84
m_categoryMap.erase(entry->m_name);
85
m_categories[categoryIndex] = nullptr;
86
m_available.push_back(category);
93
UserCategoryManager::get(UserCategoryId category) const
95
auto categoryIndex = static_cast<std::size_t>(category);
96
if (categoryIndex >= m_categories.size())
98
return m_categories[categoryIndex].get();
102
UserCategoryManager::find(std::string_view name) const
104
auto it = m_categoryMap.find(name);
105
return it == m_categoryMap.end()
106
? UserCategoryId::Invalid
111
UserCategoryManager::findOrAdd(const std::string& name, const std::string& domain)
113
auto id = static_cast<UserCategoryId>(m_categories.size());
114
if (auto [it, emplaced] = m_categoryMap.try_emplace(name, id); !emplaced)
117
return createNew(id, name, UserCategoryId::Invalid, domain);
121
UserCategoryManager::createNew(UserCategoryId id,
122
const std::string& name,
123
UserCategoryId parent,
124
const std::string& domain)
127
std::string i18nName = dgettext(name.c_str(), domain.c_str());
129
std::string i18nName = name;
132
auto category = std::make_unique<UserCategory>(ConstructorToken{}, name, parent, std::move(i18nName));
134
if (auto idIndex = static_cast<std::size_t>(id); idIndex < m_categories.size())
135
m_categories[idIndex] = std::move(category);
137
m_categories.push_back(std::move(category));
139
m_active.emplace(id);
140
if (parent == UserCategoryId::Invalid)
143
m_categories[static_cast<std::size_t>(parent)]->m_children.push_back(id);
149
UserCategoryManager::addObject(Selection selection, UserCategoryId category)
151
auto categoryIndex = static_cast<std::size_t>(category);
152
if (categoryIndex >= m_categories.size())
155
if (!m_categories[categoryIndex]->m_members.emplace(selection).second)
158
if (auto it = m_objectMap.find(selection); it == m_objectMap.end())
159
m_objectMap.try_emplace(selection, std::initializer_list<UserCategoryId> { category });
161
it->second.push_back(category);
166
UserCategoryManager::removeObject(Selection selection, UserCategoryId category)
168
auto categoryIndex = static_cast<std::size_t>(category);
169
if (categoryIndex >= m_categories.size())
172
if (m_categories[categoryIndex]->m_members.erase(selection) == 0)
175
auto it = m_objectMap.find(selection);
176
if (it == m_objectMap.end())
182
auto& categories = it->second;
183
if (auto item = std::find(categories.begin(), categories.end(), category); item != categories.end())
185
categories.erase(item);
186
if (categories.empty())
187
m_objectMap.erase(it);
194
UserCategoryManager::clearCategories(Selection selection)
196
auto iter = m_objectMap.find(selection);
197
if (iter == m_objectMap.end())
200
for (UserCategoryId category : iter->second)
202
m_categories[static_cast<std::size_t>(category)]->m_members.erase(selection);
205
m_objectMap.erase(selection);
209
UserCategoryManager::isInCategory(Selection selection, UserCategoryId category) const
211
auto categoryIndex = static_cast<std::size_t>(category);
212
if (categoryIndex >= m_categories.size())
215
const auto& members = m_categories[categoryIndex]->m_members;
216
return members.find(selection) != members.end();
219
const std::vector<UserCategoryId>*
220
UserCategoryManager::getCategories(Selection selection) const
222
auto it = m_objectMap.find(selection);
223
return it == m_objectMap.end()
228
UserCategory::UserCategory(UserCategoryManager::ConstructorToken,
229
const std::string& name,
230
UserCategoryId parent,
231
std::string&& i18nName) :
234
m_i18nName(std::move(i18nName))
238
UserCategory::getName(bool i18n) const
240
return i18n ? m_i18nName : m_name;
244
UserCategory::hasChild(UserCategoryId child) const
246
auto it = std::find(m_children.begin(), m_children.end(), child);
247
return it != m_children.end();
251
UserCategory::get(UserCategoryId category)
253
return manager.get(category);
257
UserCategory::loadCategories(Selection selection,
258
const AssociativeArray& hash,
259
DataDisposition disposition,
260
const std::string& domain)
262
if (disposition == DataDisposition::Replace)
263
manager.clearCategories(selection);
265
auto categoryValue = hash.getValue("Category");
266
if (categoryValue == nullptr)
269
if (const std::string* cn = categoryValue->getString(); cn != nullptr)
273
auto categoryId = manager.findOrAdd(*cn, domain);
274
manager.addObject(selection, categoryId);
277
const ValueArray *categoryArray = categoryValue->getArray();
278
if (categoryArray == nullptr)
281
for (const auto& it : *categoryArray)
283
const std::string* cn = it.getString();
284
if (cn == nullptr || cn->empty())
287
auto categoryId = manager.findOrAdd(*cn, domain);
288
manager.addObject(selection, categoryId);