[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kwrite-devel
Subject:    [kate] part: implement line modification system
From:       Dominik Haumann <dhdev () gmx ! de>
Date:       2011-09-03 20:32:49
Message-ID: 20110903203249.8CB16A607A () git ! kde ! org
[Download RAW message or body]

Git commit c5946bf2c15bf166be3f83c93c0ac49396582c94 by Dominik Haumann.
Committed on 03/09/2011 at 22:20.
Pushed by dhaumann into branch 'master'.

implement line modification system

TODO:
- unit test
- improve visual appearance
- enable / disable in config page
- optionally show modified lines in scroll bar
- fine tuning

PS: Qt Creator's line modification system is totally buggy :^)
Example: http://wstaw.org/m/2011/09/03/plasma-desktopgz5185.jpg

CCBUG: 200753
CCMAIL: kwrite-devel@kde.org

M  +3    -2    part/undo/kateundomanager.h
M  +14   -1    part/view/kateviewhelpers.cpp
M  +326  -14   part/undo/kateundo.cpp
M  +31   -8    part/undo/kateundomanager.cpp
M  +34   -1    part/buffer/katetextline.h
M  +5    -0    part/buffer/katetextbuffer.h
M  +53   -36   part/undo/kateundo.h
M  +3    -6    part/document/katedocument.cpp
M  +43   -4    part/buffer/katetextblock.cpp
M  +9    -0    part/buffer/katetextbuffer.cpp
M  +5    -0    part/buffer/katetextblock.h

http://commits.kde.org/kate/c5946bf2c15bf166be3f83c93c0ac49396582c94

diff --git a/part/buffer/katetextblock.cpp b/part/buffer/katetextblock.cpp
index f52f8f3..a3df0dc 100644
--- a/part/buffer/katetextblock.cpp
+++ b/part/buffer/katetextblock.cpp
@@ -89,6 +89,16 @@ void TextBlock::wrapLine (const KTextEditor::Cursor &position)
   // create new line and insert it
   m_lines.insert (m_lines.begin() + line + 1, TextLine (new TextLineData()));
 
+  // cases for modification:
+  // 1. line is wrapped in the middle
+  // 2. if empty line is wrapped, mark new line as modified
+  // 3. line-to-be-wrapped is already modified
+  if (position.column() > 0 || text.size() == 0 || \
m_lines.at(line)->markedAsModified()) { +    m_lines.at(line + \
1)->markAsModified(true); +  } else if (m_lines.at(line)->markedAsSavedOnDisk()) {
+    m_lines.at(line + 1)->markAsSavedOnDisk(true);
+  }
+
   // perhaps remove some text from previous line and append it
   if (position.column() < text.size ()) {
     // text from old line moved first to new one
@@ -96,8 +106,12 @@ void TextBlock::wrapLine (const KTextEditor::Cursor &position)
 
     // now remove wrapped text from old line
     text.chop (text.size() - position.column());
+
+    // mark line as modified
+    m_lines.at(line)->markAsModified(true);
   }
 
+
   /**
    * notify the text history
    */
@@ -173,8 +187,13 @@ void TextBlock::unwrapLine (int line, TextBlock *previousBlock)
     previousBlock->m_lines.erase (previousBlock->m_lines.begin() + \
(previousBlock->lines () - 1));  
     // append text
-    int oldSizeOfPreviousLine = newFirst->text().size();
-    newFirst->textReadWrite().append (oldFirst->text());
+    const int oldSizeOfPreviousLine = newFirst->text().size();
+    if (oldFirst->length() > 0) {
+      newFirst->textReadWrite().append (oldFirst->text());
+
+      // mark line as modified, since text was appended
+      newFirst->markAsModified(true);
+    }
 
     // patch startLine of this block
     --m_startLine;
@@ -244,8 +263,16 @@ void TextBlock::unwrapLine (int line, TextBlock *previousBlock)
   }
 
   // easy: just move text to previous line and remove current one
-  int oldSizeOfPreviousLine = m_lines.at(line-1)->text().size();
-  m_lines.at(line-1)->textReadWrite().append (m_lines.at(line)->text());
+  const int oldSizeOfPreviousLine = m_lines.at(line-1)->length();
+  const int sizeOfCurrentLine = m_lines.at(line)->length();
+  if (sizeOfCurrentLine > 0) {
+    m_lines.at(line-1)->textReadWrite().append (m_lines.at(line)->text());
+  }
+
+  const bool lineChanged = (oldSizeOfPreviousLine > 0 && m_lines.at(line - \
1)->markedAsModified()) +    || (sizeOfCurrentLine > 0 && (oldSizeOfPreviousLine > 0 \
|| m_lines.at(line)->markedAsModified())); +  \
m_lines.at(line-1)->markAsModified(lineChanged); +
   m_lines.erase (m_lines.begin () + line);
 
   /**
@@ -296,6 +323,7 @@ void TextBlock::insertText (const KTextEditor::Cursor &position, \
const QString &  // get text
   QString &textOfLine = m_lines.at(line)->textReadWrite ();
   int oldLength = textOfLine.size ();
+  m_lines.at(line)->markAsModified(true);
 
   // check if valid column
   Q_ASSERT (position.column() >= 0);
@@ -369,6 +397,7 @@ void TextBlock::removeText (const KTextEditor::Range &range, \
QString &removedTex  
   // remove text
   textOfLine.remove (range.start().column(), range.end().column() - \
range.start().column()); +  m_lines.at(line)->markAsModified(true);
 
   /**
    * notify the text history
@@ -515,6 +544,16 @@ void TextBlock::clearBlockContent (TextBlock *targetBlock)
   m_lines.clear ();
 }
 
+void TextBlock::markModifiedLinesAsSaved ()
+{
+  // mark all modified lines as saved
+  for (int i = 0; i < m_lines.size(); ++i) {
+    TextLine textLine = m_lines[i];
+    if (textLine->markedAsModified())
+      textLine->markAsSavedOnDisk(true);
+  }
+}
+
 void TextBlock::updateRange (TextRange* range)
 {
   /**
diff --git a/part/buffer/katetextblock.h b/part/buffer/katetextblock.h
index 2b9d050..7b8a48a 100644
--- a/part/buffer/katetextblock.h
+++ b/part/buffer/katetextblock.h
@@ -173,6 +173,11 @@ class KATEPART_TESTS_EXPORT TextBlock {
       return m_cachedLineForRanges.contains(range) || \
m_uncachedRanges.contains(range);  }
 
+    /**
+     * Flag all modified text lines as saved on disk.
+     */
+    void markModifiedLinesAsSaved ();
+
   private:
     /**
      * Update a range from this block.
diff --git a/part/buffer/katetextbuffer.cpp b/part/buffer/katetextbuffer.cpp
index 9ea7768..dd1b044 100644
--- a/part/buffer/katetextbuffer.cpp
+++ b/part/buffer/katetextbuffer.cpp
@@ -753,6 +753,9 @@ bool TextBuffer::save (const QString &filename)
   kDebug (13020) << "Saved file " << filename << "with codec" << m_textCodec->name()
     << (ok ? "without" : "with") << "errors";
 
+  if (ok)
+    markModifiedLinesAsSaved();
+
   // emit signal on success
   if (ok)
     emit saved (filename);
@@ -784,6 +787,12 @@ void TextBuffer::notifyAboutRangeChange (KTextEditor::View \
*view, int startLine,  }
 }
 
+void TextBuffer::markModifiedLinesAsSaved()
+{
+  foreach(TextBlock* block, m_blocks)
+    block->markModifiedLinesAsSaved ();
+}
+
 QList<TextRange *> TextBuffer::rangesForLine (int line, KTextEditor::View *view, \
bool rangesWithAttributeOnly) const  {
   // get block, this will assert on invalid line
diff --git a/part/buffer/katetextbuffer.h b/part/buffer/katetextbuffer.h
index 2c0ef50..dd716b4 100644
--- a/part/buffer/katetextbuffer.h
+++ b/part/buffer/katetextbuffer.h
@@ -399,6 +399,11 @@ class KATEPART_TESTS_EXPORT TextBuffer : public QObject {
      */
     void notifyAboutRangeChange (KTextEditor::View *view, int startLine, int \
endLine, bool rangeWithAttribute);  
+    /**
+     * Mark all modified lines as lines saved on disk (modified line system).
+     */
+    void markModifiedLinesAsSaved();
+
   public:
     /**
      * Gets the document to which this buffer is bound.
diff --git a/part/buffer/katetextline.h b/part/buffer/katetextline.h
index a1d5d9f..cd1b540 100644
--- a/part/buffer/katetextline.h
+++ b/part/buffer/katetextline.h
@@ -51,7 +51,9 @@ class KATEPART_TESTS_EXPORT TextLineData {
       flagAutoWrapped = 2,
       flagFoldingColumnsOutdated = 4,
       flagNoIndentationBasedFolding = 8,
-      flagNoIndentationBasedFoldingAtStart = 16
+      flagNoIndentationBasedFoldingAtStart = 16,
+      flagLineModified = 32,
+      flagLineSavedOnDisk = 64
     };
 
     /**
@@ -131,6 +133,37 @@ class KATEPART_TESTS_EXPORT TextLineData {
       return QChar();
     }
 
+    inline void markAsModified(bool modified)
+    {
+      if (modified) {
+        m_flags |= flagLineModified;
+        m_flags &= (~flagLineSavedOnDisk);
+      } else {
+        m_flags &= (~flagLineModified);
+      }
+    }
+
+    inline bool markedAsModified() const
+    {
+      return m_flags & flagLineModified;
+    }
+
+    inline void markAsSavedOnDisk(bool savedOnDisk)
+    {
+      if (savedOnDisk) {
+        m_flags |= flagLineSavedOnDisk;
+        m_flags &= (~flagLineModified);
+      } else {
+        m_flags &= (~flagLineSavedOnDisk);
+      }
+    }
+
+    inline bool markedAsSavedOnDisk() const
+    {
+      return m_flags & flagLineSavedOnDisk;
+    }
+
+
     /**
      * Set the flag that only positions have changed, not folding region begins/ends \
                themselve
      * @param set folding columns our of date?
diff --git a/part/document/katedocument.cpp b/part/document/katedocument.cpp
index 76a5ff2..2af3e19 100644
--- a/part/document/katedocument.cpp
+++ b/part/document/katedocument.cpp
@@ -1135,12 +1135,8 @@ bool KateDocument::editWrapLine ( int line, int col, bool \
newLine, bool *newLine  
   Kate::TextLine nextLine = kateTextLine(line+1);
 
-  int pos = l->length() - col;
-
-  if (pos < 0)
-    pos = 0;
-
-  m_undoManager->slotLineWrapped(line, col, pos, (!nextLine || newLine));
+  const int length = l->length();
+  m_undoManager->slotLineWrapped(line, col, length, (!nextLine || newLine));
 
   if (!nextLine || newLine)
   {
@@ -2315,6 +2311,7 @@ bool KateDocument::saveFile()
   // (dominik) mark last undo group as not mergeable, otherwise the next
   // edit action might be merged and undo will never stop at the saved state
   m_undoManager->undoSafePoint();
+  m_undoManager->updateLineModifications();
 
   //
   // return success
diff --git a/part/undo/kateundo.cpp b/part/undo/kateundo.cpp
index 2cfa2b1..4ed1aa6 100644
--- a/part/undo/kateundo.cpp
+++ b/part/undo/kateundo.cpp
@@ -29,6 +29,7 @@
 
 KateUndo::KateUndo (KateDocument *document)
 : m_document (document)
+, m_lineModFlags(0x00)
 {
 }
 
@@ -36,6 +37,130 @@ KateUndo::~KateUndo ()
 {
 }
 
+void KateUndo::setFlag(ModificationFlag flag)
+{
+  m_lineModFlags |= flag;
+}
+
+void KateUndo::unsetFlag(ModificationFlag flag)
+{
+  m_lineModFlags &= (~flag);
+}
+
+bool KateUndo::isFlagSet(ModificationFlag flag) const
+{
+  return m_lineModFlags & flag;
+}
+
+KateEditInsertTextUndo::KateEditInsertTextUndo (KateDocument *document, int line, \
int col, const QString &text) +  : KateUndo (document)
+  , m_line (line)
+  , m_col (col)
+  , m_text (text)
+{
+  setFlag(RedoLine1Modified);
+  Kate::TextLine tl = document->plainKateTextLine(line);
+  if (tl->markedAsModified()) {
+    setFlag(UndoLine1Modified);
+  }
+  if (tl->markedAsSavedOnDisk()) {
+    setFlag(UndoLine1Saved);
+  }
+}
+
+KateEditRemoveTextUndo::KateEditRemoveTextUndo (KateDocument *document, int line, \
int col, const QString &text) +  : KateUndo (document)
+  , m_line (line)
+  , m_col (col)
+  , m_text (text)
+{
+  setFlag(RedoLine1Modified);
+  Kate::TextLine tl = document->plainKateTextLine(line);
+  if (tl->markedAsModified()) {
+    setFlag(UndoLine1Modified);
+  }
+  if (tl->markedAsSavedOnDisk()) {
+    setFlag(UndoLine1Saved);
+  }
+}
+
+KateEditWrapLineUndo::KateEditWrapLineUndo (KateDocument *document, int line, int \
col, int len, bool newLine) +  : KateUndo (document)
+  , m_line (line)
+  , m_col (col)
+  , m_len (len)
+  , m_newLine (newLine)
+{
+  Kate::TextLine tl = document->plainKateTextLine(line);
+  if (col < len || tl->markedAsModified()) {
+    setFlag(RedoLine1Modified);
+  } else if (tl->markedAsSavedOnDisk()) {
+    setFlag(RedoLine1Saved);
+  }
+
+  if (col > 0 || len == 0 || tl->markedAsModified()) {
+    setFlag(RedoLine2Modified);
+  } else if (tl->markedAsSavedOnDisk()) {
+    setFlag(RedoLine2Saved);
+  }
+
+  if (tl->markedAsModified()) {
+    setFlag(UndoLine1Modified);
+  }
+  if (tl->markedAsSavedOnDisk()) {
+    setFlag(UndoLine1Saved);
+  }
+}
+
+KateEditUnWrapLineUndo::KateEditUnWrapLineUndo (KateDocument *document, int line, \
int col, int len, bool removeLine) +  : KateUndo (document)
+  , m_line (line)
+  , m_col (col)
+  , m_len (len)
+  , m_removeLine (removeLine)
+{
+  setFlag(RedoLine1Modified);
+
+  Kate::TextLine tl = document->plainKateTextLine(line);
+  if (tl->markedAsModified()) {
+    setFlag(UndoLine1Modified);
+  }
+  if (tl->markedAsSavedOnDisk()) {
+    setFlag(UndoLine1Saved);
+  }
+
+  Kate::TextLine nextLine = document->plainKateTextLine(line + 1);
+  if (nextLine->markedAsModified()) {
+    setFlag(UndoLine2Modified);
+  }
+  if (nextLine->markedAsSavedOnDisk()) {
+    setFlag(UndoLine2Saved);
+  }
+}
+
+KateEditInsertLineUndo::KateEditInsertLineUndo (KateDocument *document, int line, \
const QString &text) +  : KateUndo (document)
+  , m_line (line)
+  , m_text (text)
+{
+  setFlag(RedoLine1Modified);
+}
+
+KateEditRemoveLineUndo::KateEditRemoveLineUndo (KateDocument *document, int line, \
const QString &text) +  : KateUndo (document)
+  , m_line (line)
+  , m_text (text)
+{
+  Kate::TextLine tl = document->plainKateTextLine(line);
+  if (tl->markedAsModified()) {
+    setFlag(UndoLine1Modified);
+  }
+  if (tl->markedAsSavedOnDisk()) {
+    setFlag(UndoLine1Saved);
+  }
+}
+
+
 bool KateUndo::isEmpty() const
 {
   return false;
@@ -90,98 +215,244 @@ void KateEditInsertTextUndo::undo ()
 {
   KateDocument *doc = document();
 
-      doc->editRemoveText (m_line, m_col, len());
+  doc->editRemoveText (m_line, m_col, len());
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(UndoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(UndoLine1Saved));
 }
 
 void KateEditRemoveTextUndo::undo ()
 {
   KateDocument *doc = document();
 
-      doc->editInsertText (m_line, m_col, m_text);
+  doc->editInsertText (m_line, m_col, m_text);
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(UndoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(UndoLine1Saved));
 }
 
 void KateEditWrapLineUndo::undo ()
 {
   KateDocument *doc = document();
 
-      doc->editUnWrapLine (m_line, m_newLine, m_len);
+  doc->editUnWrapLine (m_line, m_newLine, m_len);
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(UndoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(UndoLine1Saved));
 }
 
 void KateEditUnWrapLineUndo::undo ()
 {
   KateDocument *doc = document();
 
-      doc->editWrapLine (m_line, m_col, m_removeLine);
+  doc->editWrapLine (m_line, m_col, m_removeLine);
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(UndoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(UndoLine1Saved));
+
+  Kate::TextLine nextLine = doc->plainKateTextLine(m_line + 1);
+  nextLine->markAsModified(isFlagSet(UndoLine2Modified));
+  nextLine->markAsSavedOnDisk(isFlagSet(UndoLine2Saved));
 }
 
 void KateEditInsertLineUndo::undo ()
 {
   KateDocument *doc = document();
 
-      doc->editRemoveLine (m_line);
+  doc->editRemoveLine (m_line);
+
+  // no line modification needed, since the line is removed
 }
 
 void KateEditRemoveLineUndo::undo ()
 {
   KateDocument *doc = document();
 
-      doc->editInsertLine (m_line, m_text);
+  doc->editInsertLine (m_line, m_text);
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(UndoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(UndoLine1Saved));
 }
 
 void KateEditMarkLineAutoWrappedUndo::undo ()
 {
   KateDocument *doc = document();
 
-      doc->editMarkLineAutoWrapped (m_line, m_autowrapped);
+  doc->editMarkLineAutoWrapped (m_line, m_autowrapped);
 }
 
 void KateEditRemoveTextUndo::redo ()
 {
   KateDocument *doc = document();
 
-      doc->editRemoveText (m_line, m_col, len());
+  doc->editRemoveText (m_line, m_col, len());
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(RedoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(RedoLine1Saved));
 }
 
 void KateEditInsertTextUndo::redo ()
 {
   KateDocument *doc = document();
 
-      doc->editInsertText (m_line, m_col, m_text);
+  doc->editInsertText (m_line, m_col, m_text);
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(RedoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(RedoLine1Saved));
 }
 
 void KateEditUnWrapLineUndo::redo ()
 {
   KateDocument *doc = document();
 
-      doc->editUnWrapLine (m_line, m_removeLine, m_len);
+  doc->editUnWrapLine (m_line, m_removeLine, m_len);
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(RedoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(RedoLine1Saved));
 }
 
 void KateEditWrapLineUndo::redo ()
 {
   KateDocument *doc = document();
 
-      doc->editWrapLine (m_line, m_col, m_newLine);
+  doc->editWrapLine (m_line, m_col, m_newLine);
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(RedoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(RedoLine1Saved));
+
+  Kate::TextLine nextLine = doc->plainKateTextLine(m_line + 1);
+  nextLine->markAsModified(isFlagSet(RedoLine2Modified));
+  nextLine->markAsSavedOnDisk(isFlagSet(RedoLine2Saved));
 }
 
 void KateEditRemoveLineUndo::redo ()
 {
   KateDocument *doc = document();
 
-      doc->editRemoveLine (m_line);
+  doc->editRemoveLine (m_line);
+
+  // no line modification needed, since the line is removed
 }
 
 void KateEditInsertLineUndo::redo ()
 {
   KateDocument *doc = document();
 
-      doc->editInsertLine (m_line, m_text);
+  doc->editInsertLine (m_line, m_text);
+
+  Kate::TextLine tl = doc->plainKateTextLine(m_line);
+  tl->markAsModified(isFlagSet(RedoLine1Modified));
+  tl->markAsSavedOnDisk(isFlagSet(RedoLine1Saved));
 }
 
 void KateEditMarkLineAutoWrappedUndo::redo ()
 {
   KateDocument *doc = document();
 
-      doc->editMarkLineAutoWrapped (m_line, m_autowrapped);
+  doc->editMarkLineAutoWrapped (m_line, m_autowrapped);
+}
+
+void KateEditInsertTextUndo::updateRedoSavedOnDiskFlag(QBitArray & lines)
+{
+  if (!lines.testBit(m_line)) {
+    lines.setBit(m_line);
+
+    unsetFlag(RedoLine1Modified);
+    setFlag(RedoLine1Saved);
+  }
+}
+
+void KateEditInsertTextUndo::updateUndoSavedOnDiskFlag(QBitArray & lines)
+{
+  if (!lines.testBit(m_line)) {
+    lines.setBit(m_line);
+
+    unsetFlag(UndoLine1Modified);
+    setFlag(UndoLine1Saved);
+  }
+}
+
+void KateEditRemoveTextUndo::updateRedoSavedOnDiskFlag(QBitArray & lines)
+{
+  if (!lines.testBit(m_line)) {
+    lines.setBit(m_line);
+
+    unsetFlag(RedoLine1Modified);
+    setFlag(RedoLine1Saved);
+  }
+}
+
+void KateEditRemoveTextUndo::updateUndoSavedOnDiskFlag(QBitArray & lines)
+{
+  if (!lines.testBit(m_line)) {
+    lines.setBit(m_line);
+
+    unsetFlag(UndoLine1Modified);
+    setFlag(UndoLine1Saved);
+  }
+}
+
+void KateEditWrapLineUndo::updateRedoSavedOnDiskFlag(QBitArray & lines)
+{
+  if (isFlagSet(RedoLine1Modified) && !lines.testBit(m_line)) {
+    lines.setBit(m_line);
+
+    unsetFlag(RedoLine1Modified);
+    setFlag(RedoLine1Saved);
+  }
+
+  if (isFlagSet(RedoLine2Modified) && !lines.testBit(m_line + 1)) {
+    lines.setBit(m_line + 1);
+
+    unsetFlag(RedoLine2Modified);
+    setFlag(RedoLine2Saved);
+  }
+}
+
+void KateEditWrapLineUndo::updateUndoSavedOnDiskFlag(QBitArray & lines)
+{
+  if (isFlagSet(UndoLine1Modified) && !lines.testBit(m_line)) {
+    lines.setBit(m_line);
+
+    unsetFlag(UndoLine1Modified);
+    setFlag(UndoLine1Saved);
+  }
+}
+
+void KateEditUnWrapLineUndo::updateRedoSavedOnDiskFlag(QBitArray & lines)
+{
+  if (isFlagSet(RedoLine1Modified) && !lines.testBit(m_line)) {
+    lines.setBit(m_line);
+
+    unsetFlag(RedoLine1Modified);
+    setFlag(RedoLine1Saved);
+  }
+}
+
+void KateEditUnWrapLineUndo::updateUndoSavedOnDiskFlag(QBitArray & lines)
+{
+  if (isFlagSet(UndoLine1Modified) && !lines.testBit(m_line)) {
+    lines.setBit(m_line);
+
+    unsetFlag(UndoLine1Modified);
+    setFlag(UndoLine1Saved);
+  }
+
+  if (isFlagSet(UndoLine2Modified) && !lines.testBit(m_line + 1)) {
+    lines.setBit(m_line + 1);
+
+    unsetFlag(UndoLine2Modified);
+    setFlag(UndoLine2Saved);
+  }
 }
 
 KateUndoGroup::KateUndoGroup (KateUndoManager *manager, const KTextEditor::Cursor \
&cursorPosition, const KTextEditor::Range &selectionRange) @@ -291,6 +562,47 @@ void \
KateUndoGroup::safePoint (bool safePoint)  m_safePoint=safePoint;
 }
 
+void KateUndoGroup::flagSavedAsModified()
+{
+  foreach (KateUndo *item, m_items) {
+    if (item->isFlagSet(KateUndo::UndoLine1Saved)) {
+      item->unsetFlag(KateUndo::UndoLine1Saved);
+      item->setFlag(KateUndo::UndoLine1Modified);
+    }
+
+    if (item->isFlagSet(KateUndo::UndoLine2Saved)) {
+      item->unsetFlag(KateUndo::UndoLine2Saved);
+      item->setFlag(KateUndo::UndoLine2Modified);
+    }
+
+    if (item->isFlagSet(KateUndo::RedoLine1Saved)) {
+      item->unsetFlag(KateUndo::RedoLine1Saved);
+      item->setFlag(KateUndo::RedoLine1Modified);
+    }
+
+    if (item->isFlagSet(KateUndo::RedoLine2Saved)) {
+      item->unsetFlag(KateUndo::RedoLine2Saved);
+      item->setFlag(KateUndo::RedoLine2Modified);
+    }
+  }
+}
+
+void KateUndoGroup::markUndoAsSaved(QBitArray & lines)
+{
+  for (int i = m_items.size() - 1; i >= 0; --i) {
+    KateUndo* item = m_items[i];
+    item->updateUndoSavedOnDiskFlag(lines);
+  }
+}
+
+void KateUndoGroup::markRedoAsSaved(QBitArray & lines)
+{
+  for (int i = m_items.size() - 1; i >= 0; --i) {
+    KateUndo* item = m_items[i];
+    item->updateRedoSavedOnDiskFlag(lines);
+  }
+}
+
 KTextEditor::Document *KateUndoGroup::document()
 {
   return m_manager->document();
diff --git a/part/undo/kateundo.h b/part/undo/kateundo.h
index 6ee28a2..66db181 100644
--- a/part/undo/kateundo.h
+++ b/part/undo/kateundo.h
@@ -25,6 +25,7 @@
 #include <QtCore/QList>
 
 #include <ktexteditor/range.h>
+#include <QtCore/QBitArray>
 
 class KateUndoManager;
 class KateDocument;
@@ -110,17 +111,37 @@ class KateUndo
      * the document the undo item belongs to
      */
     KateDocument *m_document;
+
+  //
+  // Line modification system
+  //
+  public:
+    enum ModificationFlag {
+      UndoLine1Modified = 1,
+      UndoLine2Modified = 2,
+      UndoLine1Saved = 4,
+      UndoLine2Saved = 8,
+      RedoLine1Modified = 16,
+      RedoLine2Modified = 32,
+      RedoLine1Saved = 64,
+      RedoLine2Saved = 128
+    };
+
+    void setFlag(ModificationFlag flag);
+    void unsetFlag(ModificationFlag flag);
+    bool isFlagSet(ModificationFlag flag) const;
+
+    virtual void updateUndoSavedOnDiskFlag(QBitArray & lines) { Q_UNUSED(lines) }
+    virtual void updateRedoSavedOnDiskFlag(QBitArray & lines) { Q_UNUSED(lines) }
+
+  private:
+    uchar m_lineModFlags;
 };
 
 class KateEditInsertTextUndo : public KateUndo
 {
   public:
-    KateEditInsertTextUndo (KateDocument *document, int line, int col, const QString \
                &text)
-      : KateUndo (document)
-      , m_line (line)
-      , m_col (col)
-      , m_text (text)
-    {}
+    KateEditInsertTextUndo (KateDocument *document, int line, int col, const QString \
&text);  
     /**
      * @copydoc KateUndo::isEmpty()
@@ -147,6 +168,9 @@ class KateEditInsertTextUndo : public KateUndo
      */
     KateUndo::UndoType type() const { return KateUndo::editInsertText; }
 
+    void updateUndoSavedOnDiskFlag(QBitArray & lines);
+    void updateRedoSavedOnDiskFlag(QBitArray & lines);
+
   private:
     int len() const { return m_text.length(); }
 
@@ -159,12 +183,7 @@ class KateEditInsertTextUndo : public KateUndo
 class KateEditRemoveTextUndo : public KateUndo
 {
   public:
-    KateEditRemoveTextUndo (KateDocument *document, int line, int col, const QString \
                &text)
-      : KateUndo (document)
-      , m_line (line)
-      , m_col (col)
-      , m_text (text)
-    {}
+    KateEditRemoveTextUndo (KateDocument *document, int line, int col, const QString \
&text);  
     /**
      * @copydoc KateUndo::isEmpty()
@@ -191,6 +210,10 @@ class KateEditRemoveTextUndo : public KateUndo
      */
     KateUndo::UndoType type() const { return KateUndo::editRemoveText; }
 
+    void updateUndoSavedOnDiskFlag(QBitArray & lines);
+    void updateRedoSavedOnDiskFlag(QBitArray & lines);
+
+
   private:
     int len() const { return m_text.length(); }
 
@@ -232,13 +255,7 @@ class KateEditMarkLineAutoWrappedUndo : public KateUndo
 class KateEditWrapLineUndo : public KateUndo
 {
   public:
-    KateEditWrapLineUndo (KateDocument *document, int line, int col, int len, bool \
                newLine)
-      : KateUndo (document)
-      , m_line (line)
-      , m_col (col)
-      , m_len (len)
-      , m_newLine (newLine)
-    {}
+    KateEditWrapLineUndo (KateDocument *document, int line, int col, int len, bool \
newLine);  
     /**
      * @copydoc KateUndo::undo()
@@ -255,6 +272,9 @@ class KateEditWrapLineUndo : public KateUndo
      */
     KateUndo::UndoType type() const { return KateUndo::editWrapLine; }
 
+    void updateUndoSavedOnDiskFlag(QBitArray & lines);
+    void updateRedoSavedOnDiskFlag(QBitArray & lines);
+
   private:
     const int m_line;
     const int m_col;
@@ -265,13 +285,7 @@ class KateEditWrapLineUndo : public KateUndo
 class KateEditUnWrapLineUndo : public KateUndo
 {
   public:
-    KateEditUnWrapLineUndo (KateDocument *document, int line, int col, int len, bool \
                removeLine)
-      : KateUndo (document)
-      , m_line (line)
-      , m_col (col)
-      , m_len (len)
-      , m_removeLine (removeLine)
-    {}
+    KateEditUnWrapLineUndo (KateDocument *document, int line, int col, int len, bool \
removeLine);  
     /**
      * @copydoc KateUndo::undo()
@@ -288,6 +302,9 @@ class KateEditUnWrapLineUndo : public KateUndo
      */
     KateUndo::UndoType type() const { return KateUndo::editUnWrapLine; }
 
+    void updateUndoSavedOnDiskFlag(QBitArray & lines);
+    void updateRedoSavedOnDiskFlag(QBitArray & lines);
+
   private:
     const int m_line;
     const int m_col;
@@ -298,11 +315,7 @@ class KateEditUnWrapLineUndo : public KateUndo
 class KateEditInsertLineUndo : public KateUndo
 {
   public:
-    KateEditInsertLineUndo (KateDocument *document, int line, const QString &text)
-      : KateUndo (document)
-      , m_line (line)
-      , m_text (text)
-    {}
+    KateEditInsertLineUndo (KateDocument *document, int line, const QString &text);
 
     /**
      * @copydoc KateUndo::undo()
@@ -327,11 +340,7 @@ class KateEditInsertLineUndo : public KateUndo
 class KateEditRemoveLineUndo : public KateUndo
 {
   public:
-    KateEditRemoveLineUndo (KateDocument *document, int line, const QString &text)
-      : KateUndo (document)
-      , m_line (line)
-      , m_text (text)
-    {}
+    KateEditRemoveLineUndo (KateDocument *document, int line, const QString &text);
 
     /**
      * @copydoc KateUndo::undo()
@@ -401,6 +410,14 @@ class KateUndoGroup
      */
     bool isEmpty() const { return m_items.isEmpty(); }
 
+    /**
+     * Change all LineSaved flags to LineModified of the line modification system.
+     */
+    void flagSavedAsModified();
+
+    void markUndoAsSaved(QBitArray & lines);
+    void markRedoAsSaved(QBitArray & lines);
+
   private:
     KTextEditor::Document *document();
 
diff --git a/part/undo/kateundomanager.cpp b/part/undo/kateundomanager.cpp
index a39dd79..df3048c 100644
--- a/part/undo/kateundomanager.cpp
+++ b/part/undo/kateundomanager.cpp
@@ -22,6 +22,8 @@
 #include "katedocument.h"
 #include "kateundo.h"
 
+#include <QBitArray>
+
 KateUndoManager::KateUndoManager (KateDocument *doc)
   : QObject (doc)
   , m_document (doc)
@@ -152,10 +154,10 @@ void KateUndoManager::slotMarkLineAutoWrapped(int line, bool \
                autowrapped)
     addUndoItem(new KateEditMarkLineAutoWrappedUndo(m_document, line, autowrapped));
 }
 
-void KateUndoManager::slotLineWrapped(int line, int col, int pos, bool newLine)
+void KateUndoManager::slotLineWrapped(int line, int col, int length, bool newLine)
 {
   if (m_editCurrentUndo != 0) // do we care about notifications?
-    addUndoItem(new KateEditWrapLineUndo(m_document, line, col, pos, newLine));
+    addUndoItem(new KateEditWrapLineUndo(m_document, line, col, length, newLine));
 }
 
 void KateUndoManager::slotLineUnWrapped(int line, int col, int length, bool \
lineRemoved) @@ -327,6 +329,7 @@ void KateUndoManager::updateModified()
   {
     if ( currentPattern == patterns[patternIndex] )
     {
+      // Note: m_document->setModified() calls KateUndoManager::setModified!
       m_document->setModified( false );
       // (dominik) whenever the doc is not modified, succeeding edits
       // should not be merged
@@ -359,16 +362,15 @@ void KateUndoManager::clearRedo()
   emit undoChanged ();
 }
 
-void KateUndoManager::setModified(bool m) {
-  if ( m == false )
+void KateUndoManager::setModified(bool modified)
+{
+  if ( !modified )
   {
-    if ( ! undoItems.isEmpty() )
-    {
+    if ( ! undoItems.isEmpty() ) {
       lastUndoGroupWhenSaved = undoItems.last();
     }
 
-    if ( ! redoItems.isEmpty() )
-    {
+    if ( ! redoItems.isEmpty() ) {
       lastRedoGroupWhenSaved = redoItems.last();
     }
 
@@ -377,6 +379,27 @@ void KateUndoManager::setModified(bool m) {
   }
 }
 
+void KateUndoManager::updateLineModifications()
+{
+  // change LineSaved flag of all undo & redo items to LineModified
+  foreach (KateUndoGroup* undoGroup, undoItems)
+    undoGroup->flagSavedAsModified();
+
+  foreach (KateUndoGroup* undoGroup, redoItems)
+    undoGroup->flagSavedAsModified();
+
+  // iterate all undo/redo items to find out, which item sets the flag LineSaved
+  QBitArray lines(document()->lines(), false);
+  for (int i = undoItems.size() - 1; i >= 0; --i) {
+    undoItems[i]->markRedoAsSaved(lines);
+  }
+
+  lines.fill(false);
+  for (int i = redoItems.size() - 1; i >= 0; --i) {
+    redoItems[i]->markUndoAsSaved(lines);
+  }
+}
+
 void KateUndoManager::updateConfig ()
 {
   emit undoChanged ();
diff --git a/part/undo/kateundomanager.h b/part/undo/kateundomanager.h
index 9e60640..5c3541d 100644
--- a/part/undo/kateundomanager.h
+++ b/part/undo/kateundomanager.h
@@ -88,8 +88,9 @@ class KATEPART_TESTS_EXPORT KateUndoManager : public QObject
 
     bool isActive() const { return m_isActive; }
 
-    void setModified( bool m );
+    void setModified( bool modified );
     void updateConfig ();
+    void updateLineModifications();
 
   public Q_SLOTS:
     /**
@@ -143,7 +144,7 @@ class KATEPART_TESTS_EXPORT KateUndoManager : public QObject
     /**
      * Notify KateUndoManager that a line was wrapped.
      */
-    void slotLineWrapped(int line, int col, int pos, bool newLine);
+    void slotLineWrapped(int line, int col, int length, bool newLine);
 
     /**
      * Notify KateUndoManager that a line was un-wrapped.
diff --git a/part/view/kateviewhelpers.cpp b/part/view/kateviewhelpers.cpp
index 3164108..fd15f98 100644
--- a/part/view/kateviewhelpers.cpp
+++ b/part/view/kateviewhelpers.cpp
@@ -1271,7 +1271,20 @@ void KateIconBorder::paintBorder (int /*x*/, int y, int \
/*width*/, int height)  oldInfo = info;
       }
 
-      lnX += iconPaneWidth + 2;
+      lnX += iconPaneWidth;
+    }
+
+    // modified line system
+    if (realLine > -1) {
+      Kate::TextLine tl = m_doc->plainKateTextLine(realLine);
+      if (tl->markedAsModified()) {
+        p.setPen(Qt::red);
+        p.fillRect(lnX, y, 2, h, QColor(242, 155, 104));
+      }
+      if (tl->markedAsSavedOnDisk()) {
+        p.setPen(Qt::darkGreen);
+        p.fillRect(lnX, y, 2, h, QColor(119, 183, 83));
+      }
     }
   }
 }
_______________________________________________
KWrite-Devel mailing list
KWrite-Devel@kde.org
https://mail.kde.org/mailman/listinfo/kwrite-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic