1 #ifndef Header_Latex_Document
2 #define Header_Latex_Document
3 //#undef QT_NO_DEBUG
4 #include "mostQtHeaders.h"
5 #include "latexstructure.h"
6 #include "qdocument.h"
7 #include "codesnippet.h"
8 #include "bibtexparser.h"
9 #include "latexparser.h"
10 #include "usermacro.h"
11 #include "syntaxcheck.h"
12 #include "grammarcheck.h"
13 #include "latexpackage.h"
14 //#include "latexeditorview.h"
15 
16 //class QDocumentLineHandle;
17 class LatexEditorView;
18 class QDocumentCursor;
19 class Macro;
20 
21 
22 struct FileNamePair {
23 	QString relative, absolute;
24 	FileNamePair(const QString &rel, const QString &abs);
25 };
26 
27 
28 struct ReferencePair {
29 	QString name;
30 	int start;
31 };
32 
33 struct ReferencePairEx {
34     QDocumentLineHandle *dlh;
35     QVector<int> starts,lengths,formats;
36     QList<int> formatList;
37 };
38 
39 
40 struct UserCommandPair {
41 	// name of command ("\command") or environment ("environment"),
42 	// null string for other user definitions (e.g. newcolumntype, definecolor)
43 	QString name;
44 	// information for code completion
45 	CodeSnippet snippet;
46 	UserCommandPair(const QString &name, const CodeSnippet &snippet);
47 };
48 
49 
50 /*! \brief extended QDocument
51  *
52  * Extended document for handling latex documents
53  * Extension encompass filename handling, label,bibliography as well as syntax interpreting (Token system)
54  * Also structureview is maintained here
55  * The live-update of syntactical information is performed in \method patchStructure
56  */
57 class LatexDocument: public QDocument
58 {
59 	Q_OBJECT
60 
61 public:
62     LatexDocument(QObject *parent = nullptr);
63 	~LatexDocument();
64 
65 	enum CookieType {
66 		CK_COLS = 0
67 	};
68 	static const QSet<QString> LATEX_LIKE_LANGUAGES;
69 
70 	void setFileName(const QString &fileName);
71 	void setEditorView(LatexEditorView *edView);///< set reference to actual GUI element of editor
72     Q_INVOKABLE LatexEditorView *getEditorView() const;
73 	QString getFileName() const;
74 	QFileInfo getFileInfo() const;
75 	//QSet<QString> texFiles; //absolute file names, also contains fileName
76 
77     Q_PROPERTY(QString fileName READ getFileName)
78     Q_PROPERTY(QFileInfo fileInfo READ getFileInfo)
79 #if (QT_VERSION<QT_VERSION_CHECK(6,0,0))
80     Q_PROPERTY(LatexEditorView *editorView READ getEditorView)
81 #endif
82 
83 	bool isHidden(); ///< true if editor is not displayed
84 
85 	//	References containedLabels,containedReferences;
86 	QMultiHash<QDocumentLineHandle *, FileNamePair> &mentionedBibTeXFiles();
87 	const QMultiHash<QDocumentLineHandle *, FileNamePair> &mentionedBibTeXFiles() const;
88 	QStringList listOfMentionedBibTeXFiles() const;
89 	QSet<QString> lastCompiledBibTeXFiles;
90 
91 	QList<Macro> localMacros;
92 
93 	friend class SyntaxCheckTest;
94     friend class LatexEditorViewTest;
95 	friend class LatexStructureMerger;
96 	friend class LatexStructureMergerMerge;
97 	friend class ScriptEngineTest;
98 
99 private:
100 	static QStringList someItems(const QMultiHash<QDocumentLineHandle *, ReferencePair> &list);
101 	void setFileNameInternal(const QString& fileName);
102 	void setFileNameInternal(const QString& fileName, const QFileInfo &pairedFileInfo);
103 
104 public:
105 	Q_INVOKABLE QStringList labelItems() const; ///< all labels in this document
106 	Q_INVOKABLE QStringList refItems() const; ///< all references in this document
107 	Q_INVOKABLE QStringList bibItems() const; ///< all bibitem defined in this document
108 	Q_INVOKABLE QList<CodeSnippet> userCommandList() const; ///< all user commands defined in this document, sorted
109 	Q_INVOKABLE CodeSnippetList additionalCommandsList();
110 	void updateRefsLabels(const QString &ref);
111     void recheckRefsLabels(QList<LatexDocument *> listOfDocs=QList<LatexDocument*>(), QStringList items=QStringList());
112     static void updateRefHighlight(ReferencePairEx p);
113 	Q_INVOKABLE int countLabels(const QString &name);
114 	Q_INVOKABLE int countRefs(const QString &name);
115 	Q_INVOKABLE bool bibIdValid(const QString &name);
116 	Q_INVOKABLE bool isBibItem(const QString &name);
117 	Q_INVOKABLE QString findFileFromBibId(const QString &name); ///< find bib-file from bibid
118 	Q_INVOKABLE QMultiHash<QDocumentLineHandle *, int> getLabels(const QString &name); ///< get line/column from label name
119 	Q_INVOKABLE QMultiHash<QDocumentLineHandle *, int> getRefs(const QString &name); ///< get line/column from reference name
120 	Q_INVOKABLE QMultiHash<QDocumentLineHandle *, int> getBibItems(const QString &name);
121 	Q_INVOKABLE QDocumentLineHandle *findCommandDefinition(const QString &name); ///< get line of definition from command name (may return nullptr)
122 	Q_INVOKABLE QDocumentLineHandle *findUsePackage(const QString &name); ///< get line of \usepackage from package name (may return nullptr)
123 	Q_INVOKABLE void replaceItems(QMultiHash<QDocumentLineHandle *, ReferencePair> items, const QString &newName, QDocumentCursor *cursor = nullptr);
124     Q_INVOKABLE void replaceLabel(const QString &name, const QString &newName, QDocumentCursor *cursor = nullptr);
125     Q_INVOKABLE void replaceRefs(const QString &name, const QString &newName, QDocumentCursor *cursor = nullptr);
126 	Q_INVOKABLE void replaceLabelsAndRefs(const QString &name, const QString &newName);
127 
128 	void patchLinesContaining(const QStringList cmds);
129 
130 	StructureEntry *baseStructure;
131 
132 	QDocumentSelection sectionSelection(StructureEntry *section);
clearAppendix()133 	void clearAppendix()
134 	{
135         mAppendixLine = nullptr;
136 	}
137 	StructureEntry *findSectionForLine(int currentLine);
138 
139 	LatexDocuments *parent;
140 
141 	void setTemporaryFileName(const QString &fileName);
142 	Q_INVOKABLE QString getTemporaryFileName() const;
143 	Q_INVOKABLE QString getFileNameOrTemporaryFileName() const;
144 	Q_INVOKABLE QFileInfo getTemporaryFileInfo() const;
145 	Q_INVOKABLE QString getAbsoluteFilePath(const QString &relName, const QString &extension, const QStringList &additionalSearchPaths = QStringList()) const;
146 
147 	void setMasterDocument(LatexDocument *doc, bool recheck = true);
148 	void addChild(LatexDocument *doc);
149 	void removeChild(LatexDocument *doc);
150 	bool containsChild(LatexDocument *doc) const;
getMasterDocument()151 	Q_INVOKABLE LatexDocument *getMasterDocument() const
152 	{
153 		return masterDocument;
154 	}
155     const LatexDocument *getRootDocument(QSet<const LatexDocument *> *visitedDocs = nullptr) const;
156 	Q_INVOKABLE LatexDocument *getRootDocument();
getTopMasterDocument()157 	Q_INVOKABLE LatexDocument *getTopMasterDocument()
158 	{
159 		return getRootDocument();    // DEPRECATED: only the for backward compatibility of user scripts
160 	}
161 
162 	Q_INVOKABLE QStringList includedFiles();
163 	Q_INVOKABLE QStringList includedFilesAndParent();
164     Q_INVOKABLE QList<LatexDocument *> getListOfDocs(QSet<LatexDocument *> *visitedDocs = nullptr);
165 
166 	LatexParser ltxCommands, lp;
167 
168 	Q_INVOKABLE bool containsPackage(const QString &name);
169 	Q_INVOKABLE QStringList containedPackages();
170 	Q_INVOKABLE QSet<QString> usedPackages();
171     bool updateCompletionFiles(const bool forceUpdate,const bool forceLabelUpdate = false,const bool delayUpdate = false, const bool dontPatch = false );
172 	const QSet<QString> &getCWLFiles() const;
173 
spellingDictName()174 	Q_INVOKABLE QString spellingDictName() const
175 	{
176 		return mSpellingDictName;
177 	}
178 	Q_INVOKABLE QString getMagicComment(const QString &name) const;
179 	Q_INVOKABLE StructureEntry *getMagicCommentEntry(const QString &name) const;
180     Q_INVOKABLE void updateMagicComment(const QString &name, const QString &val, bool createIfNonExisting = false, QString prefix="!TeX");
181 
182 	void updateMagicCommentScripts();
183 	static bool splitMagicComment(const QString &comment, QString &name, QString &val);
184 
185 	QString findFileName(QString fname);
186 	bool fileExits(QString fname);
187 
188 	void saveLineSnapshot();
189 	QDocumentLine lineFromLineSnapshot(int lineNumber);
190 	int lineToLineSnapshotLineNumber(const QDocumentLine &line);
191 
192 	bool remeberAutoReload; //remember whether doc is auto reloaded while hidden (and auto reload is always activated).
193 
194 	bool mayHaveDiffMarkers;
195 
196 	void emitUpdateCompleter();
197 
198     static int syntaxErrorFormat,spellErrorFormat;
199 
200 	bool languageIsLatexLike() const;
201 	void reCheckSyntax(int lineStart = 0, int lineNum = -1);
202 	QString getErrorAt(QDocumentLineHandle *dlh, int pos, StackEnvironment previous, TokenStack stack);
203 
204 	void getEnv(int lineNumber, StackEnvironment &env); // get Environment for syntax checking, number of cols is now part of env
205 	Q_INVOKABLE QString getLastEnvName(int lineNumber); // special function to use with javascript (insert "\item" from menu)
206 
enableSyntaxCheck(bool enable)207 	void enableSyntaxCheck(bool enable)
208 	{
209 		syntaxChecking = enable;
210         SynChecker.enableSyntaxCheck(enable);
211 	}
212 
213 private:
214 	QString fileName; //absolute
215 	QString temporaryFileName; //absolute, temporary
216 	QFileInfo fileInfo;
217 
218 	LatexEditorView *edView;
219 
220 	LatexDocument *masterDocument;
221 	QSet<LatexDocument *> childDocs;
222 
223 	StructureEntry *magicCommentList;
224 	StructureEntry *labelList;
225 	StructureEntry *todoList;
226 	StructureEntry *bibTeXList;
227 	StructureEntry *blockList;
228 
229 	QMultiHash<QDocumentLineHandle *, ReferencePair> mLabelItem;
230 	QMultiHash<QDocumentLineHandle *, ReferencePair> mBibItem;
231 	QMultiHash<QDocumentLineHandle *, ReferencePair> mRefItem;
232 	QMultiHash<QDocumentLineHandle *, FileNamePair> mMentionedBibTeXFiles;
233 	QMultiHash<QDocumentLineHandle *, UserCommandPair> mUserCommandList;
234 	QMultiHash<QDocumentLineHandle *, QString> mUsepackageList;
235 	QMultiHash<QDocumentLineHandle *, QString> mIncludedFilesList;
236 
237 	QList<QDocumentLineHandle *> mLineSnapshot;
238 
239 	QSet<QString> mCompleterWords; // local list of completer words
240 	QSet<QString> mCWLFiles;
241 
242 	QString mSpellingDictName;
243 
244 	QString mClassOptions; // store class options, if they are defined in this doc
245 
246 	QDocumentLineHandle *mAppendixLine, *mBeyondEnd;
247 
248 	void updateContext(QDocumentLineHandle *oldLine, QDocumentLineHandle *newLine, StructureEntry::Context context);
249 	void setContextForLines(StructureEntry *se, int startLine, int endLine, StructureEntry::Context context, bool state);
250 
251 	int findStructureParentPos(const QList<StructureEntry *> &children, QList<StructureEntry *> &removedElements, int linenr, int count);
252 
253 	bool IsInTree (StructureEntry *se);
updateElementWithSignal(StructureEntry * se)254 	void updateElementWithSignal(StructureEntry *se){ emit updateElement(se); }
255 	void removeElementWithSignal(StructureEntry *se);
256 	void addElementWithSignal(StructureEntry *parent, StructureEntry *se);
257 	void insertElementWithSignal(StructureEntry *parent, int pos, StructureEntry *se);
258 	void moveElementWithSignal(StructureEntry *se, StructureEntry *parent, int pos);
259 
260 	void addMagicComment(const QString &text, int lineNr, int posMagicComment);
261 	void parseMagicComment(const QString &name, const QString &val, StructureEntry *se);
262 
263 	void gatherCompletionFiles(QStringList &files, QStringList &loadedFiles, LatexPackage &pck, bool gatherForCompleter = false);
264 
265 	SyntaxCheck SynChecker;
266 	Environment unclosedEnv;
267 
268 	bool syntaxChecking;
269 
270 #ifndef QT_NO_DEBUG
271 public:
272 	QSet<StructureEntry *> StructureContent;
273 	void checkForLeak();
274 #endif
275 
276 public slots:
277 	void updateStructure();
278 	bool patchStructure(int linenr, int count, bool recheck = false);
279     void patchStructureRemoval(QDocumentLineHandle *dlh,int hint=-1);
280 	void initClearStructure();
281 	void updateLtxCommands(bool updateAll = false);
282 	void setLtxCommands(const LatexParser &cmds);
283     void setSpeller(SpellerUtility *speller);
284     void setReplacementList(QMap<QString,QString> replacementList);
285 	void updateSettings();
286     void checkNextLine(QDocumentLineHandle *dlh, bool clearOverlay, int ticket, int hint=-1);
287 
288 signals:
289 	void hasBeenIncluded(const LatexDocument &newMasterDocument);
290     void structureUpdated(LatexDocument *document, StructureEntry *highlight = nullptr);
291     void setHighlightedEntry(StructureEntry *highlight);
292 	void structureLost(LatexDocument *document);
293 	void removeElement(StructureEntry *se, int row);
294 	void removeElementFinished();
295 	void addElement(StructureEntry *se, int row);
296 	void addElementFinished();
297 	void updateElement(StructureEntry *se);
298 	void updateCompleter();
299 	void updateBibTeXFiles();
300 	void toBeChanged();
301 	void importPackage(QString name);
302 	void spellingDictChanged(const QString &name);
303 	void encodingChanged();
304 	void bookmarkLineUpdated(int lineNr);
305 };
306 //Q_DECLARE_METATYPE(LatexDocument *)
307 
308 
309 
310 /*! \brief administrate all open documents
311  * organizes all open documents
312  * handles master/slave or root/child relation between documents
313  * documents can be hidden, i.e. they don't have a visible editor
314  * hidden documents are used to keep syntax information present in the editor without the necessesity to make an extra storage architecture for closed elements
315  * documents which are closed/deleted are hidden if they are child documents of still used documents
316  * Furthermore autimatically loaded documents are generally hidden
317  */
318 class LatexDocuments: public QObject
319 {
320 	Q_OBJECT
321 
322 public:
323     //LatexDocumentsModel *model; ///< reference to latexmodel which generates the structure information for treeview
324 	LatexDocument *masterDocument; ///< master/root document if it is set (in automatic mode ==NULL)
325 	LatexDocument *currentDocument; ///< current edited document
326 	QList<LatexDocument *> documents; ///< list of open documents
327 	QList<LatexDocument *> hiddenDocuments; ///< list of open documents with no visible editor
328 
329 	LatexDocuments();
330 
331 	void addDocument(LatexDocument *document, bool hidden = false);
332 	void deleteDocument(LatexDocument *document, bool hidden = false, bool purge = false);
333 	void move(int from, int to);
334 	Q_INVOKABLE void setMasterDocument(LatexDocument *document); ///< explicitely set master document
335 	Q_INVOKABLE LatexDocument *getCurrentDocument() const;
336 	Q_INVOKABLE LatexDocument *getMasterDocument() const; ///< get explicit master if set
337 	Q_INVOKABLE QList<LatexDocument *> getDocuments() const; ///< get all documents (visible&hidden)
338 
339     Q_PROPERTY(LatexDocument *currentDocument READ getCurrentDocument)
340     Q_PROPERTY(LatexDocument *masterDocument READ getMasterDocument)
341     Q_PROPERTY(QList<LatexDocument *> documents READ getDocuments); //<- semicolon necessary due to qt bug 22992
342 
343     Q_INVOKABLE LatexDocument *getRootDocumentForDoc(LatexDocument *doc = nullptr) const ; ///< no argument means current doc ...
344 
345 	Q_INVOKABLE QString getCurrentFileName() const; ///< returns the absolute file name of the current file or "" if none is opened
346 	Q_INVOKABLE QString getCompileFileName() const; ///< returns the absolute file name of the file to be compiled (master or current)
347 	Q_INVOKABLE QString getTemporaryCompileFileName() const; ///< returns the absolute file name of the file to be compiled (master or current)
348 	Q_INVOKABLE QString getLogFileName() const;
349 	Q_INVOKABLE QString getAbsoluteFilePath(const QString &relName, const QString &extension = "", const QStringList &additionalSearchPaths = QStringList()) const;
350 
351 	Q_INVOKABLE LatexDocument *findDocument(const QString &fileName, bool checkTemporaryNames = false) const;
352 	Q_INVOKABLE LatexDocument *findDocument(const QDocument *qDoc) const;
353 	Q_INVOKABLE LatexDocument *findDocumentFromName(const QString &fileName) const;
354 
355 	void reorder(const QList<LatexDocument *> &order);
356 
357 	void settingsRead();
358 
359 	Q_INVOKABLE bool singleMode() const;
360 
361 	//support for included BibTeX-files
362 	QMap<QString, BibTeXFileInfo> bibTeXFiles; ///< bibtex files loaded by txs
363 	bool bibTeXFilesModified; ///< true if the BibTeX files were changed after the last compilation
364 	QStringList mentionedBibTeXFiles; ///< bibtex files imported in the tex file (absolute after updateBibFiles)
365 	//QSet<QString> bibItems; // direct defined bibitems
366 	//QSet<QString> allBibTeXIds;
367 	void updateBibFiles(bool updateFiles = true);
368 
369 	void updateMasterSlaveRelations(LatexDocument *doc, bool recheckRefs = true, bool updateCompleterNow = false);
370 
371 	bool showLineNumbersInStructure;
372 	int indentationInStructure;
373 	bool showCommentedElementsInStructure;
374 	bool markStructureElementsBeyondEnd;
375 	bool markStructureElementsInAppendix;
376 	bool indentIncludesInStructure; //pointer! those above should be changed as well
377 
378 
379 	QHash<QString, LatexPackage> cachedPackages;
380 	void addDocToLoad(QString filename);
381 	void removeDocs(QStringList removeIncludes);
382 	void hideDocInEditor(LatexEditorView *edView);
383 	QString findPackageByCommand(const QString command);
384 	void enablePatch(const bool enable);
385 	bool patchEnabled();
386 	void requestQNFAupdate();
387 
388 signals:
389 	void masterDocumentChanged(LatexDocument *masterDocument);
390 	void aboutToDeleteDocument(LatexDocument *document);
391 	void docToLoad(QString filename);
392 	void docToHide(LatexEditorView *edView);
393 	void updateQNFA();
394 
395 private slots:
396 	void bibTeXFilesNeedUpdate();
397 
398 public slots:
399     void lineGrammarChecked(LatexDocument *doc, QDocumentLineHandle *line, int lineNr, const QList<GrammarError> &errors);
400 	void requestedClose();
401 
402 private:
403 	bool m_patchEnabled;
404 };
405 
406 #endif // LATEXDOCUMENT_H
407