vnote/src/widgets/outlineprovider.h
Le Tan 6109737b9d Fixes
1. OutlineViewer: support section number;
2. Allow to close the file before opening with external program;
3. Skip end marker within a block marker;
2021-08-17 20:58:55 +08:00

113 lines
2.8 KiB
C++

#ifndef OUTLINEPROVIDER_H
#define OUTLINEPROVIDER_H
#include <QObject>
#include <QSharedPointer>
#include <QVector>
namespace vnotex
{
typedef QVector<int> 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<Heading> 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<Outline> &getOutline() const;
void setOutline(const QSharedPointer<Outline> &p_outline);
// Get current heading index in outline.
int getCurrentHeadingIndex() const;
void setCurrentHeadingIndex(int p_idx);
template <class T>
static void makePerfectHeadings(const QVector<T> &p_headings, QVector<T> &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<Outline> m_outline;
int m_currentHeadingIndex = -1;
};
template <class T>
void OutlineProvider::makePerfectHeadings(const QVector<T> &p_headings, QVector<T> &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