MauiKit TextEditor

documenthandler.h
1/****************************************************************************
2 * *
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** BSD License Usage
18 ** Alternatively, you may use this file under the terms of the BSD license
19 ** as follows:
20 **
21 ** "Redistribution and use in source and binary forms, with or without
22 ** modification, are permitted provided that the following conditions are
23 ** met:
24 ** * Redistributions of source code must retain the above copyright
25 ** notice, this list of conditions and the following disclaimer.
26 ** * Redistributions in binary form must reproduce the above copyright
27 ** notice, this list of conditions and the following disclaimer in
28 ** the documentation and/or other materials provided with the
29 ** distribution.
30 ** * Neither the name of The Qt Company Ltd nor the names of its
31 ** contributors may be used to endorse or promote products derived
32 ** from this software without specific prior written permission.
33 **
34 **
35 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 **
47 ** $QT_END_LICENSE$
48 **
49 ****************************************************************************/
50
51#pragma once
52
53#include <QAbstractListModel>
54#include <QDebug>
55#include <QFont>
56#include <QObject>
57#include <QTextCursor>
58#include <QThread>
59#include <QTimer>
60#include <QUrl>
61#include <QQuickTextDocument>
62#include <QQmlEngine>
63
65class QTextDocument;
66
67namespace KSyntaxHighlighting
68{
69class Repository;
70class SyntaxHighlighter;
71}
72
73/**
74 * @brief The AlertAction struct
75 */
77{
78 QString label;
79 std::function<void()> action;
80};
81
82/**
83 * @brief The DocumentAlert class
84 */
85class DocumentAlert : public QObject
86{
88 Q_PROPERTY(QString title MEMBER m_title CONSTANT FINAL)
89 Q_PROPERTY(QString body MEMBER m_body CONSTANT FINAL)
90 Q_PROPERTY(uint level MEMBER m_level CONSTANT FINAL)
91 Q_PROPERTY(QStringList actionLabels READ actionLabels CONSTANT FINAL)
92
93public:
94 enum LEVEL : uint { INFO_LEVEL = 0, WARNING_LEVEL = 1, DANGER_LEVEL = 2 };
95
96 DocumentAlert(const QString &title, const QString &body, const uint &level, const int &id, QObject *parent = nullptr)
98 {
99 this->m_title = title;
100 this->m_body = body;
101 this->m_level = level;
102 this->m_id = id;
103 }
104
105 /**
106 * @brief setIndex
107 * @param index
108 */
109 void setIndex(const int &index)
110 {
111 this->m_index = index;
112 }
113
114 /**
115 * @brief setActions
116 * @param actions
117 */
119 {
120 this->m_actions = actions;
121 }
122
123 /**
124 * @brief getId
125 * @return
126 */
127 int getId() const
128 {
129 return this->m_id;
130 }
131
132 /**
133 * @brief operator ==
134 * @param other
135 * @param other2
136 * @return
137 */
138 friend bool operator==(const DocumentAlert &other, const DocumentAlert &other2)
139 {
140 return other.getId() == other2.getId();
141 }
142
143 /**
144 * @brief actionLabels
145 * @return
146 */
148 {
149 return std::accumulate(this->m_actions.constBegin(), this->m_actions.constEnd(), QStringList(), [](QStringList &labels, const AlertAction &action) -> QStringList {
150 labels << action.label;
151 return labels;
152 });
153 }
154
155private:
156 QString m_title;
157 QString m_body;
158 uint m_level;
159 int m_index = -1;
160 int m_id = -1;
161
162 QVector<AlertAction> m_actions;
163
164public Q_SLOTS:
165 /**
166 * @brief triggerAction
167 * @param actionIndex
168 * @param alertIndex
169 */
170 void triggerAction(const int &actionIndex, const int &alertIndex)
171 {
172 qDebug() << "TRIGGERING DOCUMENT ACTION AT INDEX << " << actionIndex << alertIndex;
173 this->m_actions.at(actionIndex).action();
174 Q_EMIT this->done(alertIndex);
175 }
176
178 /**
179 * @brief done
180 * @param index
181 */
182 void done(int index);
183};
184
185/**
186 * @brief The Alerts class
187 */
189{
191
192public:
193 enum ROLES : uint { ALERT = Qt::DisplayRole + 1 };
194
195 enum ALERT_TYPES : uint { MISSING, UNSAVED, MODIFIED, SAVE_ERROR };
196
197 explicit Alerts(QObject *parent = nullptr);
198 ~Alerts();
199 QVariant data(const QModelIndex &index, int role) const override final;
200 int rowCount(const QModelIndex &parent = QModelIndex()) const override final;
201 QHash<int, QByteArray> roleNames() const override;
202
203 void append(DocumentAlert *alert);
204
205private:
207 bool contains(DocumentAlert *const alert);
208};
209
210/**
211 * @brief The FileLoader class
212 */
213class FileLoader : public QObject
214{
216
217public Q_SLOTS:
218 /**
219 * @brief loadFile
220 * @param url
221 */
222 void loadFile(const QUrl &url);
223
225 /**
226 * @brief fileReady
227 * @param array
228 * @param url
229 */
230 void fileReady(QString array, QUrl url);
231};
232
233/**
234 * @brief The DocumentHandler class.
235 * @note This is not part of any public API, and can it is only exposed as part of the TextEditor control.
236 *
237 */
239{
241 QML_ELEMENT
242 /**
243 *
244 */
245 Q_PROPERTY(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged)
246
247 /**
248 *
249 */
250 Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged)
251
252 /**
253 *
254 */
255 Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged)
256
257 /**
258 *
259 */
260 Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged)
261
262 /**
263 *
264 */
265 Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor NOTIFY textColorChanged)
266
267 /**
268 *
269 */
270 Q_PROPERTY(QString fontFamily READ fontFamily WRITE setFontFamily NOTIFY fontFamilyChanged)
271
272 /**
273 *
274 */
275 Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged)
276
277 /**
278 *
279 */
280 Q_PROPERTY(bool bold READ bold WRITE setBold NOTIFY boldChanged)
281
282 /**
283 *
284 */
285 Q_PROPERTY(bool uppercase READ uppercase WRITE setUppercase NOTIFY uppercaseChanged)
286
287 /**
288 *
289 */
290 Q_PROPERTY(bool italic READ italic WRITE setItalic NOTIFY italicChanged)
291
292 /**
293 *
294 */
295 Q_PROPERTY(bool underline READ underline WRITE setUnderline NOTIFY underlineChanged)
296
297 /**
298 *
299 */
300 Q_PROPERTY(bool isRich READ getIsRich NOTIFY isRichChanged)
301
302 /**
303 *
304 */
305 Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged)
306
307 /**
308 *
309 */
310 Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
311
312 /**
313 *
314 */
315 Q_PROPERTY(qreal tabSpace READ tabSpace WRITE setTabSpace NOTIFY tabSpaceChanged)
316
317 /**
318 *
319 */
320 Q_PROPERTY(QString fileName READ fileName NOTIFY fileUrlChanged)
321
322 /**
323 *
324 */
325 Q_PROPERTY(QString fileType READ fileType NOTIFY fileUrlChanged)
326
327 /**
328 *
329 */
330 Q_PROPERTY(QVariantMap fileInfo READ fileInfo NOTIFY fileInfoChanged)
331
332 /**
333 *
334 */
335 Q_PROPERTY(QUrl fileUrl READ fileUrl WRITE setFileUrl NOTIFY fileUrlChanged)
336
337 /**
338 *
339 */
340 Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
341
342 /**
343 *
344 */
345 Q_PROPERTY(bool externallyModified READ getExternallyModified NOTIFY externallyModifiedChanged)
346
347 /**
348 *
349 */
350 Q_PROPERTY(bool modified READ getModified NOTIFY modifiedChanged)
351
352 /**
353 *
354 */
355 Q_PROPERTY(bool autoReload READ getAutoReload WRITE setAutoReload NOTIFY autoReloadChanged)
356
357 /**
358 *
359 */
360 Q_PROPERTY(bool autoSave READ autoSave WRITE setAutoSave NOTIFY autoSaveChanged)
361
362 /**
363 *
364 */
365 Q_PROPERTY(QString formatName READ formatName WRITE setFormatName NOTIFY formatNameChanged)
366
367 /**
368 *
369 */
370 Q_PROPERTY(int currentLineIndex READ getCurrentLineIndex NOTIFY currentLineIndexChanged)
371
372 /**
373 *
374 */
375 Q_PROPERTY(Alerts *alerts READ getAlerts CONSTANT FINAL)
376
377 /**
378 *
379 */
380 Q_PROPERTY(QColor backgroundColor READ getBackgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged)
381
382 /**
383 *
384 */
385 Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged)
386
387 /**
388 *
389 */
390 Q_PROPERTY(bool enableSyntaxHighlighting READ enableSyntaxHighlighting WRITE setEnableSyntaxHighlighting NOTIFY enableSyntaxHighlightingChanged)
391
392 /**
393 *
394 */
395 Q_PROPERTY(bool findWholeWords MEMBER m_findWholeWords NOTIFY findWholeWordsChanged)
396
397 /**
398 *
399 */
400 Q_PROPERTY(bool findCaseSensitively MEMBER m_findCaseSensitively NOTIFY findCaseSensitivelyChanged)
401
402public:
403 /**
404 * @private
405 */
406 explicit DocumentHandler(QObject *parent = nullptr);
407
408 /**
409 * @private
410 */
412
413 /**
414 * @brief document
415 * @return
416 */
417 QQuickTextDocument *document() const;
418
419 /**
420 * @brief setDocument
421 * @param document
422 */
423 void setDocument(QQuickTextDocument *document);
424
425 /**
426 * @brief cursorPosition
427 * @return
428 */
429 int cursorPosition() const;
430
431 /**
432 * @brief setCursorPosition
433 * @param position
434 */
435 void setCursorPosition(int position);
436
437 /**
438 * @brief selectionStart
439 * @return
440 */
441 int selectionStart() const;
442
443 /**
444 * @brief setSelectionStart
445 * @param position
446 */
447 void setSelectionStart(int position);
448
449 /**
450 * @brief selectionEnd
451 * @return
452 */
453 int selectionEnd() const;
454
455 /**
456 * @brief setSelectionEnd
457 * @param position
458 */
459 void setSelectionEnd(int position);
460
461 /**
462 * @brief fontFamily
463 * @return
464 */
465 QString fontFamily() const;
466
467 /**
468 * @brief setFontFamily
469 * @param family
470 */
471 void setFontFamily(const QString &family);
472
473 /**
474 * @brief textColor
475 * @return
476 */
477 QColor textColor() const;
478
479 /**
480 * @brief setTextColor
481 * @param color
482 */
483 void setTextColor(const QColor &color);
484
485 /**
486 * @brief alignment
487 * @return
488 */
489 Qt::Alignment alignment() const;
490
491 /**
492 * @brief setAlignment
493 * @param alignment
494 */
495 void setAlignment(Qt::Alignment alignment);
496
497 /**
498 * @brief bold
499 * @return
500 */
501 bool bold() const;
502
503 /**
504 * @brief setBold
505 * @param bold
506 */
507 void setBold(bool bold);
508
509 /**
510 * @brief uppercase
511 * @return
512 */
513 bool uppercase() const;
514
515 /**
516 * @brief setUppercase
517 * @param uppercase
518 */
519 void setUppercase(bool uppercase);
520
521 /**
522 * @brief italic
523 * @return
524 */
525 bool italic() const;
526
527 /**
528 * @brief setItalic
529 * @param italic
530 */
531 void setItalic(bool italic);
532
533 /**
534 * @brief underline
535 * @return
536 */
537 bool underline() const;
538
539 /**
540 * @brief setUnderline
541 * @param underline
542 */
543 void setUnderline(bool underline);
544
545 /**
546 * @brief getIsRich
547 * @return
548 */
549 bool getIsRich() const;
550
551 /**
552 * @brief fontSize
553 * @return
554 */
555 int fontSize() const;
556
557 /**
558 * @brief setFontSize
559 * @param size
560 */
561 void setFontSize(int size);
562
563 qreal tabSpace() const;
564 void setTabSpace(qreal value);
565
566 /**
567 * @brief fileName
568 * @return
569 */
570 QString fileName() const;
571
572 /**
573 * @brief fileType
574 * @return
575 */
576 QString fileType() const;
577
578 /**
579 * @brief fileUrl
580 * @return
581 */
582 QUrl fileUrl() const;
583
584 /**
585 * @brief setFileUrl
586 * @param url
587 */
588 void setFileUrl(const QUrl &url);
589
590 /**
591 * @brief fileInfo
592 * @return
593 */
594 QVariantMap fileInfo() const;
595
596 /**
597 * @brief text
598 * @return
599 */
600 inline QString text() const
601 {
602 return m_text;
603 }
604
605 /**
606 * @brief setText
607 * @param text
608 */
609 void setText(const QString &text);
610
611 /**
612 * @brief getAutoReload
613 * @return
614 */
615 bool getAutoReload() const;
616
617 /**
618 * @brief setAutoReload
619 * @param value
620 */
621 void setAutoReload(const bool &value);
622
623 /**
624 * @brief autoSave
625 * @return
626 */
627 bool autoSave() const;
628
629 /**
630 * @brief setAutoSave
631 * @param value
632 */
633 void setAutoSave(const bool &value);
634
635 /**
636 * @brief getModified
637 * @return
638 */
639 bool getModified() const;
640
641 /**
642 * @brief getExternallyModified
643 * @return
644 */
645 bool getExternallyModified() const;
646
647 /**
648 * @brief setExternallyModified
649 * @param value
650 */
651 void setExternallyModified(const bool &value);
652
653 /**
654 * @brief formatName
655 * @return
656 */
657 QString formatName() const;
658
659 /**
660 * @brief setFormatName
661 * @param formatName
662 */
663 void setFormatName(const QString &formatName);
664
665 /**
666 * @brief getBackgroundColor
667 * @return
668 */
670
671 /**
672 * @brief setBackgroundColor
673 * @param color
674 */
675 void setBackgroundColor(const QColor &color);
676
677 /**
678 * @brief getAlerts
679 * @return
680 */
681 Alerts *getAlerts() const;
682
683 /**
684 * @brief theme
685 * @return
686 */
687 QString theme() const;
688
689 /**
690 * @brief setTheme
691 * @param theme
692 */
693 void setTheme(const QString &theme);
694
695 /**
696 * @brief enableSyntaxHighlighting
697 * @return
698 */
699 bool enableSyntaxHighlighting() const;
700
701 /**
702 * @brief setEnableSyntaxHighlighting
703 * @param value
704 */
705 void setEnableSyntaxHighlighting(const bool &value);
706
707 /**
708 * @brief isDark
709 * @param color
710 * @return
711 */
712 static bool isDark(const QColor &color)
713 {
714 const double darkness = 1 - (0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255;
715 return (darkness > 0.5);
716 }
717
718private Q_SLOTS:
719 /**
720 * @brief load
721 * @param url
722 */
723 void load(const QUrl &url);
724
725public Q_SLOTS:
726
727 /**
728 * @brief saveAs
729 * @param url
730 */
731 void saveAs(const QUrl &url);
732
733 /**
734 * @brief find
735 * @param query
736 */
737 void find(const QString &query, const bool &forward = true);
738
739 void replace(const QString &query, const QString &value);
740
741 void replaceAll(const QString &query, const QString &value);
742
743 bool isFoldable(const int &line) const;
744 bool isFolded(const int &line) const;
745 void toggleFold(const int &line);
746
747 /**
748 * @brief lineHeight
749 * @param line
750 * @return
751 */
752 int lineHeight(const int &line);
753
754 int lineCount();
755
756 /**
757 * @brief getCurrentLineIndex
758 * @return
759 */
761
762 int goToLine(const int &line);
763
764 /**
765 * @brief getLanguageNameList
766 * @return
767 */
768 static const QStringList getLanguageNameList();
769
770 /**
771 * @brief getLanguageNameFromFileName
772 * @param fileName
773 * @return
774 */
775 static const QString getLanguageNameFromFileName(const QUrl &fileName);
776
778 void documentChanged();
779 void fileSaved();
780
781 void cursorPositionChanged();
782 void selectionStartChanged();
783 void selectionEndChanged();
784
785 void fontFamilyChanged();
786 void textColorChanged();
787 void alignmentChanged();
788
789 void boldChanged();
790 void uppercaseChanged();
791 void italicChanged();
792 void underlineChanged();
793 void isRichChanged();
794
795 void lineCountChanged();
796 void fontSizeChanged();
797 void tabSpaceChanged();
798
799 void textChanged();
800 void fileUrlChanged();
801 void fileInfoChanged();
802
803 void loaded(const QUrl &url);
804 void error(const QString &message);
805 void loadFile(QUrl url);
806
807 void autoReloadChanged();
808 void autoSaveChanged();
809
810 void externallyModifiedChanged();
811
812 void backgroundColorChanged();
813
814 void formatNameChanged();
815
816 void modifiedChanged();
817
818 void currentLineIndexChanged();
819
820 void enableSyntaxHighlightingChanged();
821 void themeChanged();
822
823 void searchFound(int start, int end);
824 void findCaseSensitivelyChanged();
825 void findWholeWordsChanged();
826// void cursorYPosChanged();
827
828private:
829 void reset();
830 void setStyle();
831
832 QTextCursor textCursor() const;
833 QTextDocument *textDocument() const;
834 void mergeFormatOnWordOrSelection(const QTextCharFormat &format);
835
836 QQuickTextDocument *m_document;
837 QFileSystemWatcher *m_watcher;
838
839 int m_cursorPosition;
840 int m_selectionStart;
841 int m_selectionEnd;
842
843 bool isRich = false;
844
845 QFont m_font;
846 int m_fontSize = 12;
847 qreal m_tabSpace = 8;
848
849 QUrl m_fileUrl;
850
851 QThread m_worker;
852 QString m_text;
853
854 bool m_autoReload = false;
855 bool m_autoSave = false;
856
857 bool m_externallyModified = false;
858 bool m_internallyModified = false;
859
860 bool m_findCaseSensitively = false;
861 bool m_findWholeWords = false;
862
863 QColor m_backgroundColor;
864
865 static int m_instanceCount;
866 QString m_formatName = "None";
867 static KSyntaxHighlighting::Repository *m_repository;
869
870 bool m_enableSyntaxHighlighting = false;
871 QString m_theme;
872
873 QString m_searchQuery;
874 QString m_replaceText;
875
876 Alerts *m_alerts;
877 DocumentAlert *missingAlert();
878 DocumentAlert *externallyModifiedAlert();
879 DocumentAlert *canNotSaveAlert(const QString &details);
880
881 QTimer m_autoSaveTimer;
882
883 void refreshAllBlocks();
884};
The Alerts class.
The DocumentAlert class.
void done(int index)
done
QStringList actionLabels() const
actionLabels
void setActions(QVector< AlertAction > actions)
setActions
friend bool operator==(const DocumentAlert &other, const DocumentAlert &other2)
operator ==
int getId() const
getId
void setIndex(const int &index)
setIndex
void triggerAction(const int &actionIndex, const int &alertIndex)
triggerAction
The DocumentHandler class.
bool getAutoReload() const
getAutoReload
void setAutoSave(const bool &value)
setAutoSave
void setDocument(QQuickTextDocument *document)
setDocument
void setBackgroundColor(const QColor &color)
setBackgroundColor
void setCursorPosition(int position)
setCursorPosition
void setFileUrl(const QUrl &url)
setFileUrl
int lineHeight(const int &line)
lineHeight
int getCurrentLineIndex()
getCurrentLineIndex
QColor getBackgroundColor() const
getBackgroundColor
void setItalic(bool italic)
setItalic
bool getIsRich() const
getIsRich
void setBold(bool bold)
setBold
void setUnderline(bool underline)
setUnderline
static const QStringList getLanguageNameList()
getLanguageNameList
void setText(const QString &text)
setText
void find(const QString &query, const bool &forward=true)
find
void setUppercase(bool uppercase)
setUppercase
void setEnableSyntaxHighlighting(const bool &value)
setEnableSyntaxHighlighting
void setSelectionEnd(int position)
setSelectionEnd
void setExternallyModified(const bool &value)
setExternallyModified
void setFontSize(int size)
setFontSize
bool getExternallyModified() const
getExternallyModified
Alerts * getAlerts() const
getAlerts
void setAutoReload(const bool &value)
setAutoReload
void setSelectionStart(int position)
setSelectionStart
void setFontFamily(const QString &family)
setFontFamily
QString text() const
text
void setAlignment(Qt::Alignment alignment)
setAlignment
bool getModified() const
getModified
static const QString getLanguageNameFromFileName(const QUrl &fileName)
getLanguageNameFromFileName
void setTextColor(const QColor &color)
setTextColor
static bool isDark(const QColor &color)
isDark
void setTheme(const QString &theme)
setTheme
void setFormatName(const QString &formatName)
setFormatName
void saveAs(const QUrl &url)
saveAs
The FileLoader class.
void loadFile(const QUrl &url)
loadFile
void fileReady(QString array, QUrl url)
fileReady
Q_SCRIPTABLE Q_NOREPLY void start()
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
int blue() const const
int green() const const
int red() const const
const_reference at(qsizetype i) const const
QObject(QObject *parent)
Q_EMITQ_EMIT
Q_OBJECTQ_OBJECT
Q_PROPERTY(...)
Q_SIGNALSQ_SIGNALS
Q_SLOTSQ_SLOTS
QObject * parent() const const
typedef Alignment
DisplayRole
The AlertAction struct.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:58:09 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.