#ifndef OUTLINEPROVIDER_H #define OUTLINEPROVIDER_H #include #include #include namespace vnotex { typedef QVector SectionNumber; // Toc content. struct Outline { struct Heading { Heading() = default; Heading(const QString &p_name, int p_level); bool operator==(const Heading &p_a) const; QString m_name; // Heading level, 1-based. int m_level = -1; }; void clear(); bool operator==(const Outline &p_a) const; bool isEmpty() const; QVector m_headings; // 1-based. // -1 to disable section number by force. int m_sectionNumberBaseLevel = 1; bool m_sectionNumberEndingDot = true; }; // Used to hold toc-related data of one ViewWindow. class OutlineProvider : public QObject { Q_OBJECT public: explicit OutlineProvider(QObject *p_parent = nullptr); virtual ~OutlineProvider(); // Get the outline. const QSharedPointer &getOutline() const; void setOutline(const QSharedPointer &p_outline); // Get current heading index in outline. int getCurrentHeadingIndex() const; void setCurrentHeadingIndex(int p_idx); template static void makePerfectHeadings(const QVector &p_headings, QVector &p_perfectHeadings); static void increaseSectionNumber(SectionNumber &p_sectionNumber, int p_level, int p_baseLevel); static QString joinSectionNumber(const SectionNumber &p_sectionNumber, bool p_endingDot); signals: void outlineChanged(); void currentHeadingChanged(); void headingClicked(int p_idx); private: QSharedPointer m_outline; int m_currentHeadingIndex = -1; }; template void OutlineProvider::makePerfectHeadings(const QVector &p_headings, QVector &p_perfectHeadings) { p_perfectHeadings.clear(); if (p_headings.isEmpty()) { return; } int baseLevel = INT_MAX; for (const auto &heading : p_headings) { if (heading.m_level < baseLevel) { baseLevel = heading.m_level; } } p_perfectHeadings.reserve(p_headings.size()); int curLevel = baseLevel - 1; for (const auto &heading : p_headings) { while (heading.m_level > curLevel + 1) { curLevel += 1; // Insert empty level which is an invalid header. p_perfectHeadings.append(T(tr("[EMPTY]"), curLevel)); } p_perfectHeadings.append(heading); curLevel = heading.m_level; } } } #endif // OUTLINEPROVIDER_H