File indexing completed on 2024-12-22 04:48:18

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2024 Louis Schul <schul9louis@gmail.com>
0004 */
0005 
0006 #include "noteMapperParserUtils.h"
0007 
0008 #include "kleverconfig.h"
0009 #include "logic/parser/parser.h"
0010 
0011 NoteMapperParserUtils::NoteMapperParserUtils(Parser *parser)
0012     : m_parser(parser)
0013 {
0014 }
0015 
0016 void NoteMapperParserUtils::setPathsInfo(const QString &notePath)
0017 {
0018     // notePath == storagePath/Category/Group/Note/ => /Category/Group/Note
0019     m_mapperNotePath = notePath.chopped(1).remove(KleverConfig::storagePath());
0020 
0021     // /Category/Group/Note => /Category/Group (no '/' at the end to make it easier for m_categPath)
0022     const QString groupPath = m_mapperNotePath.chopped(m_mapperNotePath.size() - m_mapperNotePath.lastIndexOf(QStringLiteral("/")));
0023     if (m_groupPath != groupPath) {
0024         m_groupPath = groupPath + QStringLiteral("/"); // /Category/Group => /Category/Group/
0025         m_categPath = groupPath.chopped(groupPath.size() - groupPath.lastIndexOf(QStringLiteral("/")) - 1); // /Category/Group => /Category/
0026     }
0027 }
0028 
0029 QPair<QString, bool> NoteMapperParserUtils::sanitizePath(const QString &_path) const
0030 {
0031     static const QString slashStr = QStringLiteral("/");
0032     QStringList parts = _path.split(slashStr);
0033 
0034     bool leadingSlashRemnant = false;
0035     for (int i = 0; i < parts.count(); i++) {
0036         QString part = parts[i].trimmed();
0037         if (part.isEmpty()) {
0038             if (i == 0) {
0039                 leadingSlashRemnant = true;
0040             } else { // The path is not correctly formed
0041                 return qMakePair(_path, false);
0042             }
0043         }
0044         parts[i] = part;
0045     }
0046 
0047     if (leadingSlashRemnant)
0048         parts.removeAt(0);
0049 
0050     if (parts[0] == KleverConfig::defaultCategoryDisplayNameValue())
0051         parts[0] = QStringLiteral(".BaseCategory");
0052 
0053     QString path = _path;
0054     switch (parts.count()) {
0055     case 1: // Note name only
0056         path = m_groupPath + parts[0];
0057         break;
0058     case 2:
0059         if (parts[0] == QStringLiteral(".")) { // Note name only
0060             path = m_groupPath + parts[1];
0061         } else { // Note inside category
0062             path = slashStr + parts[0] + QStringLiteral("/.BaseGroup/") + parts[1];
0063         }
0064         break;
0065     case 3: // 'Full' path
0066         path = slashStr + parts.join(slashStr);
0067         break;
0068     default: // Not a note path
0069         return qMakePair(_path, false);
0070     }
0071 
0072     return qMakePair(path, true);
0073 }
0074 
0075 void NoteMapperParserUtils::setHeaderInfo(const QStringList &headerInfo)
0076 {
0077     m_header = headerInfo[0];
0078     m_headerLevel = m_header.isEmpty() ? QStringLiteral("0") : headerInfo[1];
0079 }
0080 
0081 QString NoteMapperParserUtils::headerLevel() const
0082 {
0083     return m_headerLevel;
0084 };
0085 
0086 void NoteMapperParserUtils::checkHeaderFound(const QString &header, const QString &level)
0087 {
0088     if (header == m_header && level == QString(m_headerLevel)) {
0089         m_headerFound = true;
0090     }
0091 }
0092 
0093 bool NoteMapperParserUtils::headerFound() const
0094 {
0095     return m_headerFound;
0096 }
0097 
0098 void NoteMapperParserUtils::addToLinkedNoteInfos(const QStringList &infos)
0099 {
0100     if ((!m_previousLinkedNotesInfos.remove(infos) && !m_linkedNotesInfos.contains(infos)) || infos.isEmpty()) {
0101         m_linkedNotesChanged = true;
0102     }
0103     m_linkedNotesInfos.insert(infos);
0104 }
0105 
0106 void NoteMapperParserUtils::addToNoteHeaders(const QString &header)
0107 {
0108     if (!m_previousNoteHeaders.remove(header) && !m_noteHeaders.contains(header)) {
0109         m_noteHeadersChanged = true;
0110     }
0111     m_noteHeaders.insert(header);
0112 }
0113 
0114 void NoteMapperParserUtils::postTok()
0115 {
0116     m_notePathChanged = false;
0117 
0118     // We try to not spam with signals
0119     if (m_linkedNotesChanged || !m_previousLinkedNotesInfos.isEmpty()) { // The previous is not empty, some links notes are no longer there
0120         Q_EMIT m_parser->newLinkedNotesInfos(m_linkedNotesInfos);
0121     }
0122     m_previousLinkedNotesInfos = m_linkedNotesInfos;
0123 
0124     if (m_noteHeadersChanged || !m_previousNoteHeaders.isEmpty()) { // The previous is not empty, some headers are no longer there
0125         m_emptyHeadersSent = false;
0126         Q_EMIT m_parser->noteHeadersSent(m_mapperNotePath, m_noteHeaders.values());
0127     } else if (m_noteHeaders.isEmpty() && !m_emptyHeadersSent) {
0128         // This way the mapper can receive info about the note (the note has no header), and we still prevent spamming
0129         m_emptyHeadersSent = true;
0130         Q_EMIT m_parser->noteHeadersSent(m_mapperNotePath, {});
0131     }
0132     m_previousNoteHeaders = m_noteHeaders;
0133 
0134     if (!m_headerFound) { // Prevent the TextDisplay.qml scrollToHeader to search an unexisting header
0135         m_headerLevel = QStringLiteral("0");
0136         m_header = QLatin1String();
0137     }
0138 }
0139 
0140 void NoteMapperParserUtils::clearInfo()
0141 {
0142     m_linkedNotesInfos.clear();
0143     m_noteHeaders.clear();
0144     m_linkedNotesInfos.clear();
0145 
0146     m_headerFound = false;
0147     if (!m_notePathChanged) {
0148         m_linkedNotesChanged = false;
0149     }
0150 }
0151 
0152 void NoteMapperParserUtils::clearPreviousInfo()
0153 {
0154     m_previousLinkedNotesInfos.clear();
0155     m_previousNoteHeaders.clear();
0156     m_linkedNotesChanged = true;
0157     m_notePathChanged = true;
0158 }