1 #include "latexstructure.h"
2 #include "latexdocument.h"
3 
4 
StructureEntry(LatexDocument * doc,Type newType)5 StructureEntry::StructureEntry(LatexDocument *doc, Type newType): type(newType), level(0), valid(false), expanded(false), parent(nullptr), document(doc), columnNumber(0), parentRow(-1), lineHandle(nullptr), lineNumber(-1), m_contexts(Unknown)
6 {
7 #ifndef QT_NO_DEBUG
8 	Q_ASSERT(document);
9 	document->StructureContent.insert(this);
10 #endif
11 }
12 
~StructureEntry()13 StructureEntry::~StructureEntry()
14 {
15 	level = -1; //invalidate entry
16 	foreach (StructureEntry *se, children)
17 		delete se;
18 #ifndef QT_NO_DEBUG
19 	Q_ASSERT(document);
20 	bool removed = document->StructureContent.remove(this);
21 	Q_ASSERT(removed); //prevent double deletion
22 #endif
23 }
24 
add(StructureEntry * child)25 void StructureEntry::add(StructureEntry *child)
26 {
27     Q_ASSERT(child != nullptr);
28 	children.append(child);
29 	child->parent = this;
30 }
31 
insert(int pos,StructureEntry * child)32 void StructureEntry::insert(int pos, StructureEntry *child)
33 {
34     Q_ASSERT(child != nullptr);
35 	children.insert(pos, child);
36 	child->parent = this;
37 }
38 
setLine(QDocumentLineHandle * handle,int lineNr)39 void StructureEntry::setLine(QDocumentLineHandle *handle, int lineNr)
40 {
41 	lineHandle = handle;
42 	lineNumber = lineNr;
43 }
44 
getLineHandle() const45 QDocumentLineHandle *StructureEntry::getLineHandle() const
46 {
47 	return lineHandle;
48 }
49 
getCachedLineNumber() const50 int StructureEntry::getCachedLineNumber() const
51 {
52 	return lineNumber;
53 }
54 
getRealLineNumber() const55 int StructureEntry::getRealLineNumber() const
56 {
57 	lineNumber = document->indexOf(lineHandle, lineNumber);
58 	Q_ASSERT(lineNumber == -1 || document->line(lineNumber).handle() == lineHandle);
59 	return lineNumber;
60 }
61 
hintedIndexOf(const QList<T * > & list,const T * elem,int hint)62 template <typename T> inline int hintedIndexOf (const QList<T *> &list, const T *elem, int hint)
63 {
64 	if (hint < 2) return list.indexOf(const_cast<T *>(elem));
65 	int backward = hint, forward = hint + 1;
66 	for (; backward >= 0 && forward < list.size();
67 	        backward--, forward++) {
68 		if (list[backward] == elem) return backward;
69 		if (list[forward] == elem) return forward;
70 	}
71 	if (backward >= list.size()) backward = list.size() - 1;
72 	for (; backward >= 0; backward--)
73 		if (list[backward] == elem) return backward;
74 	if (forward < 0) forward = 0;
75 	for (; forward < list.size(); forward++)
76 		if (list[forward] == elem) return forward;
77 	return -1;
78 }
79 
getRealParentRow() const80 int StructureEntry::getRealParentRow() const
81 {
82 	REQUIRE_RET(parent, -1);
83 	parentRow = hintedIndexOf<StructureEntry>(parent->children, this, parentRow);
84 	return parentRow;
85 }
86 
debugPrint(const char * message) const87 void StructureEntry::debugPrint(const char *message) const
88 {
89 	qDebug("%s %p", message, this);
90     qDebug()<<"   level: "<< level;
91     qDebug()<<"   type: "<< static_cast<int>(type);
92     qDebug()<<"   line nr: "<< lineNumber;
93     qDebug()<<"   title: " << title;
94 }
95 
StructureEntryIterator(StructureEntry * entry)96 StructureEntryIterator::StructureEntryIterator(StructureEntry *entry)
97 {
98 	if (!entry) return;
99 	while (entry->parent) {
100 		entryHierarchy.prepend(entry);
101 		indexHierarchy.prepend(entry->getRealParentRow());
102 		entry = entry->parent;
103 	}
104 	entryHierarchy.prepend(entry);
105 	indexHierarchy.prepend(0);
106 }
107 
hasNext()108 bool StructureEntryIterator::hasNext()
109 {
110 	return !entryHierarchy.isEmpty();
111 }
112 
next()113 StructureEntry *StructureEntryIterator::next()
114 {
115     if (!hasNext()) return nullptr;
116 	StructureEntry *result = entryHierarchy.last();
117 	if (!result->children.isEmpty()) { //first child is next element, go a level deeper
118 		entryHierarchy.append(result->children.at(0));
119 		indexHierarchy.append(0);
120 	} else { //no child, go to next on same level
121 		entryHierarchy.removeLast();
122 		indexHierarchy.last()++;
123 		while (!entryHierarchy.isEmpty() && indexHierarchy.last() >= entryHierarchy.last()->children.size()) {
124 			//doesn't exists, proceed to travel upwards
125 			entryHierarchy.removeLast();
126 			indexHierarchy.removeLast();
127 			indexHierarchy.last()++;
128 		}
129 		if (!entryHierarchy.isEmpty())
130 			entryHierarchy.append(entryHierarchy.last()->children.at(indexHierarchy.last()));
131 	}
132 	return result;
133 }
134 
135 
136 
137 
138