1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr> 4 ** 5 ** This file is part of the Edyuk project <http://edyuk.org> 6 ** 7 ** This file may be used under the terms of the GNU General Public License 8 ** version 3 as published by the Free Software Foundation and appearing in the 9 ** file GPL.txt included in the packaging of this file. 10 ** 11 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 12 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 13 ** 14 ****************************************************************************/ 15 16 #ifndef Header_QDocument 17 #define Header_QDocument 18 19 #include "modifiedQObject.h" 20 21 #include "qce-config.h" 22 23 /*! 24 \file qdocument.h 25 \brief Definition of the QDocument class 26 27 \defgroup document Document related classes 28 */ 29 30 #include <QList> 31 #include <QMap> 32 #include <QVector> 33 //#include <QLinkedList> 34 #include <QFileInfo> 35 #include <QObject> 36 #include <QPalette> 37 #include <QMetaType> 38 #include <QFont> 39 #include <QTextCodec> 40 41 #include "qdocumentcursor.h" 42 43 class QRect; 44 class QPrinter; 45 class QDateTime; 46 class QFormatScheme; 47 class QLanguageDefinition; 48 49 struct QCE_EXPORT QDocumentSelection 50 { 51 int start, end; 52 int startLine, endLine; 53 }; 54 55 class QDocumentLine; 56 //class QDocumentCursor; 57 class QDocumentPrivate; 58 class QDocumentCommand; 59 class QDocumentLineHandle; 60 class QDocumentCursorHandle; 61 62 typedef QVector<QDocumentLineHandle*>::iterator QDocumentIterator; 63 typedef QVector<QDocumentLineHandle*>::const_iterator QDocumentConstIterator; 64 65 template<typename T> class FastCache{ 66 public: 67 FastCache(); 68 T* insert(const int c, const T& width); 69 bool contains(const int c) const; 70 T value(const int c) const; 71 bool valueIfThere(const int c, const T*& value) const; 72 inline T* insert(const QChar& c, const T& width); 73 inline bool contains(const QChar& c) const; 74 inline T value(const QChar& c) const; 75 inline bool valueIfThere(const QChar& c, const T*& value) const; 76 private: 77 T fastMap[512]; 78 QMap<int, T> slowMap; 79 }; 80 81 template<typename T> class CacheCache { 82 public: 83 FastCache<T> * getCache(int format); 84 void clear(); 85 private: 86 QMap<int, FastCache<T>* > caches; 87 }; 88 89 Q_DECLARE_METATYPE(QDocumentIterator) 90 Q_DECLARE_METATYPE(QDocumentConstIterator) 91 92 typedef void (*GuessEncodingCallback) (const QByteArray& data, QTextCodec *&guess, int &sure); 93 class QKeyEvent; 94 struct PlaceHolder 95 { 96 class Affector 97 { 98 public: ~AffectorPlaceHolder99 virtual ~Affector() {} 100 virtual QString affect(const QKeyEvent *e, const QString& base, int ph, int mirror) const = 0; 101 }; 102 PlaceHolderPlaceHolder103 PlaceHolder() : 104 length(0), autoRemove(true), autoOverride(false), autoRemoveIfLeft(false), affector(nullptr) {} PlaceHolderPlaceHolder105 PlaceHolder(const PlaceHolder& ph) : 106 length(ph.length), autoRemove(ph.autoRemove), autoOverride(ph.autoOverride), autoRemoveIfLeft(ph.autoRemoveIfLeft), affector(ph.affector), cursor(ph.cursor), mirrors(ph.mirrors){} PlaceHolderPlaceHolder107 PlaceHolder(int len, const QDocumentCursor &cur): 108 length(len), autoRemove(true), autoOverride(false), autoRemoveIfLeft(false), affector(nullptr), cursor(cur) {} 109 PlaceHolder& operator= (const PlaceHolder& ph) = default; // Silence -Wdeprecated-copy 110 111 int length; 112 bool autoRemove, autoOverride, autoRemoveIfLeft; 113 Affector *affector; 114 QDocumentCursor cursor; 115 QList<QDocumentCursor> mirrors; 116 }; 117 118 class QCE_EXPORT QDocument : public QObject 119 { 120 friend class QMatcher; 121 friend class QDocumentPrivate; 122 friend class QDocumentCommand; 123 friend class QDocumentCommandChangeCodec; 124 125 Q_OBJECT 126 127 public: 128 struct PaintContext 129 { 130 qreal width; 131 qreal height; 132 qreal xoffset; // draw content from position x+xoffset at position x (used for horizontal scrolling). 133 qreal yoffset; 134 QPalette palette; 135 bool blinkingCursor; 136 bool fillCursorRect; 137 QList<QDocumentCursorHandle*> extra; 138 QList<QDocumentCursorHandle*> cursors; 139 QList<QDocumentSelection> selections; 140 int curPlaceHolder, lastPlaceHolder; 141 QList<PlaceHolder> placeHolders; 142 }; 143 144 enum LineEnding 145 { 146 Conservative, 147 Local, 148 Unix, 149 Windows, 150 Mac 151 }; 152 153 enum TextProcessing 154 { 155 RemoveTrailingWS = 1, 156 PreserveIndent = 2, 157 RestoreTrailingIndent = 4 158 }; 159 160 enum WhiteSpaceFlag 161 { 162 ShowNone = 0x00, 163 ShowTrailing = 0x01, 164 ShowLeading = 0x02, 165 ShowTabs = 0x04 166 }; 167 168 Q_DECLARE_FLAGS(WhiteSpaceMode, WhiteSpaceFlag) 169 170 enum WorkAroundFlag 171 { 172 DisableFixedPitchMode = 0x01, 173 DisableWidthCache = 0x02, 174 DisableLineCache = 0x04, 175 ForceQTextLayout = 0x08, 176 ForceSingleCharacterDrawing = 0x10, 177 QImageCache = 0x20 178 }; 179 180 Q_DECLARE_FLAGS(WorkAroundMode, WorkAroundFlag) 181 182 explicit QDocument(QObject *p = nullptr); 183 virtual ~QDocument(); 184 185 Q_INVOKABLE QString text(int mode) const; 186 Q_INVOKABLE QString text(bool removeTrailing = false, bool preserveIndent = true) const; 187 Q_INVOKABLE QStringList textLines() const; 188 Q_INVOKABLE void setText(const QString& s, bool allowUndo); 189 190 void load(const QString& file, QTextCodec* codec); 191 void startChunkLoading(); 192 void stopChunkLoading(); 193 void addChunk(const QString& txt); 194 195 QString getFileName() const; 196 QFileInfo getFileInfo() const; 197 QString getName() const; 198 void setFileName_DONOTCALLTHIS(const QString& fileName); 199 200 LineEnding lineEnding() const; 201 LineEnding originalLineEnding() const; 202 Q_INVOKABLE QString lineEndingString() const; 203 void setLineEnding(LineEnding le); 204 void setLineEndingDirect(LineEnding le,bool dontSendEmit=false); 205 206 QTextCodec* codec() const; 207 void setCodec(QTextCodec* codec); 208 void setCodecDirect(QTextCodec* codec); 209 210 bool isReadOnly() const; 211 void setReadOnly(bool b); 212 213 QDateTime lastModified() const; 214 void setLastModified(const QDateTime& d); 215 216 Q_INVOKABLE bool canUndo() const; 217 Q_INVOKABLE bool canRedo() const; 218 219 qreal width() const; 220 qreal height() const; 221 qreal widthConstraint() const; 222 223 int lines() const; 224 Q_INVOKABLE int lineCount() const; 225 int visualLines() const; 226 Q_INVOKABLE int visualLineCount() const; 227 228 int visualLineNumber(int textLineNumber) const; 229 int textLineNumber(int visualLineNumber) const; 230 231 qreal y(int line) const; 232 int lineNumber(qreal ypos, int *wrap = nullptr) const; 233 234 QRectF lineRect(int line) const; 235 236 QDocumentCursor* editCursor() const; 237 void setEditCursor(QDocumentCursor *c); 238 239 QLanguageDefinition* languageDefinition() const; 240 void setLanguageDefinition(QLanguageDefinition *l); 241 242 int maxMarksPerLine() const; 243 int findNextMark(int id, int from = 0, int until = -1) const; 244 int findPreviousMark(int id, int from = -1, int until = 0) const; 245 void removeMarks(int id); 246 QList<int> marks(QDocumentLineHandle *dlh) const; 247 void removeMark(QDocumentLineHandle *dlh, int mid); 248 249 QDocumentLine lineAt(const QPointF& p) const; 250 void cursorForDocumentPosition(const QPointF& p, int& line, int& column, bool disallowPositionBeyondLine = false) const; 251 QDocumentCursor cursorAt(const QPointF& p, bool disallowPositionBeyondLine = false) const; 252 253 QDocumentLine line(int line) const; 254 QDocumentLine line(QDocumentConstIterator iterator) const; 255 256 Q_INVOKABLE QDocumentCursor cursor(int line, int column = 0, int lineTo=-1, int columnTo=-1) const; 257 258 QDocumentLine findLine(int& position) const; 259 int findLineContaining(const QString &searchText, const int& startLine=0, const Qt::CaseSensitivity cs = Qt::CaseSensitive, const bool backward=false) const; 260 int findLineRegExp(const QString &searchText, const int& startLine, const Qt::CaseSensitivity cs, const bool wholeWord, const bool useRegExp) const; 261 int findNearLine(const QString &lineText, int startLine) const; 262 263 bool isLineModified(const QDocumentLine& l) const; 264 bool hasLineEverBeenModified(const QDocumentLine& l) const; 265 266 virtual void draw(QPainter *p, PaintContext& cxt); 267 268 virtual QString exportAsHtml(const QDocumentCursor &range, bool includeHeader=true, bool simplifyCSS = false, int maxLineWidth = -1, int maxWrap = 0) const; 269 270 void execute(QDocumentCommand *cmd); 271 impl()272 inline QDocumentPrivate* impl() { return m_impl; } 273 274 QDocumentConstIterator begin() const; 275 QDocumentConstIterator end() const; 276 277 QDocumentConstIterator iterator(int ln) const; 278 QDocumentConstIterator iterator(const QDocumentLine& l) const; 279 280 Q_INVOKABLE void beginMacro(); 281 Q_INVOKABLE void endMacro(); 282 Q_INVOKABLE bool hasMacros(); 283 284 //Defer contentChange-signals until the last call of endDelayedUpdateBlock() and then emit all of them. 285 //ATTENTION: This only works if the commands don't change the document line count or all changes occur top-to-bottom. 286 Q_INVOKABLE void beginDelayedUpdateBlock(); 287 Q_INVOKABLE void endDelayedUpdateBlock(); 288 289 QFormatScheme* formatScheme() const; 290 void setFormatScheme(QFormatScheme *f); 291 QColor getBackground() const; 292 QColor getForeground() const; 293 294 int getNextGroupId(); 295 void releaseGroupId(int groupId); 296 void clearMatches(int groupId); 297 //void clearMatchesFromToWhenFlushing(int groupId, int firstMatch, int lastMatch); 298 void flushMatches(int groupId); 299 void addMatch(int groupId, int line, int pos, int len, int format); 300 301 void clearLanguageMatches(); 302 303 static QFont font(); 304 static QFont baseFont(); 305 static int fontSizeModifier(); 306 static void setBaseFont(const QFont& f, bool forceUpdate = false); 307 static void setFontSizeModifier(int m, bool forceUpdate = false); 308 //static const QFontMetrics fontMetrics() const; 309 static qreal getLineSpacing(); 310 static void setLineSpacingFactor(double scale); 311 void setCenterDocumentInEditor(bool center); 312 313 static LineEnding defaultLineEnding(); 314 static void setDefaultLineEnding(LineEnding le); 315 316 static QTextCodec* defaultCodec(); 317 static void setDefaultCodec(QTextCodec* codec); 318 static void addGuessEncodingCallback(const GuessEncodingCallback& callback); 319 static void removeGuessEncodingCallback(const GuessEncodingCallback& callback); 320 321 static int tabStop(); 322 static void setTabStop(int n); 323 324 static WhiteSpaceMode showSpaces(); 325 static void setShowSpaces(WhiteSpaceMode y); 326 327 static QFormatScheme* defaultFormatScheme(); 328 static void setDefaultFormatScheme(QFormatScheme *f); 329 static void formatScheme(QFormatScheme *f); 330 static void formatSchemeDeleted(QFormatScheme *f); 331 332 int getFormatId(const QString& id); 333 334 static int screenColumn(const QChar *d, int l, int tabStop, int column = 0); 335 static QString screenable(const QChar *d, int l, int tabStop, int column = 0); 336 markViewDirty()337 inline void markViewDirty() { emit formatsChanged(); } 338 339 bool isClean() const; 340 341 Q_INVOKABLE void expand(int line); 342 Q_INVOKABLE void collapse(int line); 343 Q_INVOKABLE void expandParents(int l); 344 Q_INVOKABLE void foldBlockAt(bool unFold, int line); 345 bool linesPartiallyFolded(int fromInc, int toInc); 346 void correctFolding(int fromInc, int toInc, bool forceCorrection = false); 347 QList<int> foldedLines(); 348 void foldLines(QList<int> &lines); 349 350 void adjustWidth(int line); 351 352 static void setWorkAround(WorkAroundFlag workAround, bool newValue); 353 static bool hasWorkAround(WorkAroundFlag workAround); 354 355 bool getFixedPitch() const; 356 357 bool forceLineWrapCalculation() const; 358 void setForceLineWrapCalculation(bool v); 359 void setOverwriteMode(bool overwrite); 360 361 void applyHardLineWrap(const QList<QDocumentLineHandle*>& handles); 362 bool linesMerged(QDocumentLineHandle* dlh,int bo,QDocumentLineHandle* fromLineHandle); 363 void linesUnMerged(QDocumentLineHandle *dlh,QDocumentLineHandle *fromLineHandle); 364 int bookMarkId(int bookmarkNumber); 365 getProposedPosition()366 QDocumentCursor getProposedPosition(){ 367 return m_proposedPostion; 368 } setProposedPosition(QDocumentCursor c)369 void setProposedPosition(QDocumentCursor c){ 370 m_proposedPostion=c; 371 } 372 373 QString debugUndoStack(int limit = 10000) const; 374 375 public slots: 376 void clear(); 377 378 void undo(); 379 void redo(); 380 381 void clearUndo(); 382 void setClean(); 383 384 void highlight(); 385 386 void print(QPrinter *p); 387 388 void clearWidthConstraint(); 389 void setWidthConstraint(int width); 390 void markFormatCacheDirty(); 391 392 signals: 393 void cleanChanged(bool m); 394 395 void undoAvailable(bool y); 396 void redoAvailable(bool y); 397 398 void formatsChanged(); 399 void contentsChanged(); 400 void fontChanged(QFont); 401 402 void formatsChange (int line, int lines); 403 void contentsChange(int line, int lines); 404 405 void widthChanged(int width); 406 void heightChanged(int height); 407 void sizeChanged(const QSize& s); 408 409 void lineCountChanged(int n); 410 void visualLineCountChanged(int n); 411 412 void lineDeleted(QDocumentLineHandle *h,int hint=-1); 413 void lineRemoved(QDocumentLineHandle *h); 414 void markChanged(QDocumentLineHandle *l, int m, bool on); 415 416 void lineEndingChanged(int lineEnding); 417 418 void slowOperationStarted(); 419 void slowOperationEnded(); 420 421 void bookmarkRemoved(QDocumentLineHandle *dlh); 422 void bookmarkAdded(QDocumentLineHandle *dlh,int nr); 423 public: 424 int indexOf(const QDocumentLineHandle* h, int hint = -1) const; 425 int indexOf(const QDocumentLine& l, int hint = -1) const; 426 private: 427 QString m_leftOver; 428 QDocumentPrivate *m_impl; 429 QDocumentCursor m_proposedPostion; 430 431 }; 432 433 Q_DECLARE_OPERATORS_FOR_FLAGS(QDocument::WhiteSpaceMode) 434 435 #endif 436 437