File indexing completed on 2024-05-12 05:13:14
0001 /* 0002 SPDX-FileCopyrightText: 2005 Rafal Rzepecki <divide@users.sourceforge.net> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "categoryhierarchyreader.h" 0008 0009 #include <QComboBox> 0010 0011 using namespace CalendarSupport; 0012 0013 namespace CategoryConfig 0014 { 0015 static const QLatin1StringView categorySeparator(":"); 0016 } 0017 0018 inline QString "e(QString &string) 0019 { 0020 Q_ASSERT(CategoryConfig::categorySeparator != QLatin1StringView("@")); 0021 return string.replace(QLatin1Char('@'), QStringLiteral("@0")).replace(QLatin1Char('\\') + CategoryConfig::categorySeparator, QStringLiteral("@1")); 0022 } 0023 0024 inline QStringList &unquote(QStringList &strings) 0025 { 0026 return strings.replaceInStrings(QStringLiteral("@1"), CategoryConfig::categorySeparator).replaceInStrings(QStringLiteral("@0"), QStringLiteral("@")); 0027 } 0028 0029 QStringList CategoryHierarchyReader::path(QString string) 0030 { 0031 QStringList _path = quote(string).split(CategoryConfig::categorySeparator, Qt::SkipEmptyParts); 0032 return unquote(_path); 0033 } 0034 0035 void CategoryHierarchyReader::read(const QStringList &categories) 0036 { 0037 clear(); 0038 0039 // case insensitive sort 0040 QMap<QString, QString> sortedCategories; 0041 for (const QString &str : categories) { 0042 sortedCategories.insert(str.toLower(), str); 0043 } 0044 0045 QStringList last_path; 0046 for (const QString &category : std::as_const(sortedCategories)) { 0047 QStringList _path = path(category); 0048 0049 // we need to figure out where last item and the new one differ 0050 QStringList::Iterator jt; 0051 QStringList::Iterator kt; 0052 int split_level = 0; 0053 QStringList new_path = _path; // save it for later 0054 for (jt = _path.begin(), kt = last_path.begin(); jt != _path.end() && kt != last_path.end(); ++jt, ++kt) { 0055 if (*jt == *kt) { 0056 split_level++; 0057 } else { 0058 break; // now we have first non_equal component in the iterators 0059 } 0060 } 0061 0062 // make a path relative to the shared ancestor 0063 if (jt != _path.begin()) { 0064 _path.erase(_path.begin(), jt); 0065 } 0066 last_path = new_path; 0067 0068 if (_path.isEmpty()) { 0069 // something is wrong, we already have this node 0070 continue; 0071 } 0072 0073 // find that ancestor 0074 while (split_level < depth()) { 0075 goUp(); 0076 } 0077 Q_ASSERT(split_level == depth()); 0078 0079 // make the node and any non-existent ancestors 0080 while (!_path.isEmpty()) { 0081 addChild(_path.first(), QVariant(category)); 0082 _path.pop_front(); 0083 } 0084 } 0085 } 0086 0087 void CategoryHierarchyReaderQComboBox::clear() 0088 { 0089 mBox->clear(); 0090 } 0091 0092 void CategoryHierarchyReaderQComboBox::goUp() 0093 { 0094 mCurrentDepth--; 0095 } 0096 0097 void CategoryHierarchyReaderQComboBox::addChild(const QString &label, const QVariant &userData) 0098 { 0099 QString spaces; 0100 spaces.fill(QLatin1Char(' '), 2 * mCurrentDepth); 0101 mBox->addItem(spaces + label, userData); 0102 mCurrentDepth++; 0103 } 0104 0105 int CategoryHierarchyReaderQComboBox::depth() const 0106 { 0107 return mCurrentDepth; 0108 }