CalendarSupport

categoryhierarchyreader.cpp
1/*
2 SPDX-FileCopyrightText: 2005 Rafal Rzepecki <divide@users.sourceforge.net>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "categoryhierarchyreader.h"
8using namespace Qt::Literals::StringLiterals;
9
10#include <QComboBox>
11
12using namespace CalendarSupport;
13
14namespace CategoryConfig
15{
16static const QLatin1StringView categorySeparator(":");
17}
18
19inline QString &quote(QString &string)
20{
21 Q_ASSERT(CategoryConfig::categorySeparator != "@"_L1);
22 return string.replace(QLatin1Char('@'), QStringLiteral("@0")).replace(QLatin1Char('\\') + CategoryConfig::categorySeparator, QStringLiteral("@1"));
23}
24
25inline QStringList &unquote(QStringList &strings)
26{
27 return strings.replaceInStrings(QStringLiteral("@1"), CategoryConfig::categorySeparator).replaceInStrings(QStringLiteral("@0"), QStringLiteral("@"));
28}
29
30QStringList CategoryHierarchyReader::path(QString string)
31{
32 QStringList _path = quote(string).split(CategoryConfig::categorySeparator, Qt::SkipEmptyParts);
33 return unquote(_path);
34}
35
36void CategoryHierarchyReader::read(const QStringList &categories)
37{
38 clear();
39
40 // case insensitive sort
41 QMap<QString, QString> sortedCategories;
42 for (const QString &str : categories) {
43 sortedCategories.insert(str.toLower(), str);
44 }
45
46 QStringList last_path;
47 for (const QString &category : std::as_const(sortedCategories)) {
48 QStringList _path = path(category);
49
50 // we need to figure out where last item and the new one differ
53 int split_level = 0;
54 QStringList new_path = _path; // save it for later
55 for (jt = _path.begin(), kt = last_path.begin(); jt != _path.end() && kt != last_path.end(); ++jt, ++kt) {
56 if (*jt == *kt) {
57 split_level++;
58 } else {
59 break; // now we have first non_equal component in the iterators
60 }
61 }
62
63 // make a path relative to the shared ancestor
64 if (jt != _path.begin()) {
65 _path.erase(_path.begin(), jt);
66 }
67 last_path = new_path;
68
69 if (_path.isEmpty()) {
70 // something is wrong, we already have this node
71 continue;
72 }
73
74 // find that ancestor
75 while (split_level < depth()) {
76 goUp();
77 }
78 Q_ASSERT(split_level == depth());
79
80 // make the node and any non-existent ancestors
81 while (!_path.isEmpty()) {
82 addChild(_path.first(), QVariant(category));
83 _path.pop_front();
84 }
85 }
86}
87
88void CategoryHierarchyReaderQComboBox::clear()
89{
90 mBox->clear();
91}
92
93void CategoryHierarchyReaderQComboBox::goUp()
94{
95 mCurrentDepth--;
96}
97
98void CategoryHierarchyReaderQComboBox::addChild(const QString &label, const QVariant &userData)
99{
100 QString spaces;
101 spaces.fill(QLatin1Char(' '), 2 * mCurrentDepth);
102 mBox->addItem(spaces + label, userData);
103 mCurrentDepth++;
104}
105
106int CategoryHierarchyReaderQComboBox::depth() const
107{
108 return mCurrentDepth;
109}
void addItem(const QIcon &icon, const QString &text, const QVariant &userData)
void clear()
iterator begin()
iterator end()
iterator erase(const_iterator begin, const_iterator end)
T & first()
bool isEmpty() const const
void pop_front()
iterator insert(const Key &key, const T &value)
QString & fill(QChar ch, qsizetype size)
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QStringList & replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs)
SkipEmptyParts
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:19:27 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.