Blob Blame History Raw
From: eli mackenzie <argonel@gmail.com>
Date: Fri, 30 Sep 2011 10:41:58 +0000
Subject: reformulation of cbe876c for v1.3.1
X-Git-Url: http://quickgit.kde.org/?p=konversation.git&amp;a=commitdiff&amp;h=4a9627ef625342b450b1101ac1575bab44b5641a
---
reformulation of cbe876c for v1.3.1

CCBUG:210106
---


--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+Changes from 1.3.1 to 1.3.1 #4056.1
+This patch was created as a stop-gap measure to allow
+Konversation 1.3.1 to work with Qt 4.7.4 and newer. Nokia allowed a
+source-incompatible change to fix a bug in QtCreator, which
+causes Konversation to crash when keeping track of the marker and
+remember lines.
+
+As this is not a released version, do not report bugs against it.
+
+For more information about the Qt change, see QTBUG-20916.
+
+
 Changes from 1.3 to 1.3.1:
 Konversation 1.3.1 is a maintenance release that improves program behavior
 and fixes defects, the most serious of which is a regression that unfortu-

--- a/src/commit.h
+++ b/src/commit.h
@@ -1,4 +1,4 @@
 // This COMMIT number is added to version string to be used as "patch level"
 #ifndef COMMIT
-#define COMMIT 4056
+#define COMMIT 4056.1
 #endif

--- a/src/version.h
+++ b/src/version.h
@@ -1,3 +1,3 @@
 #ifndef KONVI_VERSION
-#define KONVI_VERSION "1.3.1"
+#define KONVI_VERSION "1.3.1 #4056.1"
 #endif

--- a/src/viewer/ircview.cpp
+++ b/src/viewer/ircview.cpp
@@ -11,7 +11,7 @@
   Copyright (C) 2002 Dario Abatianni <eisfuchs@tigress.com>
   Copyright (C) 2005-2007 Peter Simonsson <psn@linux.se>
   Copyright (C) 2006-2008 Eike Hein <hein@kde.org>
-  Copyright (C) 2004-2009 Eli Mackenzie <argonel@gmail.com>
+  Copyright (C) 2004-2011 Eli Mackenzie <argonel@gmail.com>
 */
 
 #include "ircview.h"
@@ -111,7 +111,10 @@ class SelectionPin
             if (d->textCursor().hasSelection())
             {
                 int end = d->document()->rootFrame()->lastPosition();
-                QTextBlock b = d->document()->lastBlock();
+
+                //WARNING if selection pins don't work in some build environments, we need to keep the result
+                d->document()->lastBlock();
+
                 pos = d->textCursor().position();
                 anc = d->textCursor().anchor();
                 if (pos != end && anc != end)
@@ -132,7 +135,7 @@ class SelectionPin
 };
 
 
-IRCView::IRCView(QWidget* parent, Server* newServer) : KTextBrowser(parent), m_nextCullIsMarker(false), m_rememberLinePosition(-1), m_rememberLineDirtyBit(false), markerFormatObject(this)
+IRCView::IRCView(QWidget* parent, Server* newServer) : KTextBrowser(parent), m_rememberLine(0), m_lastMarkerLine(0), m_rememberLineDirtyBit(false), markerFormatObject(this)
 {
     m_copyUrlMenu = false;
     m_resetScrollbar = true;
@@ -325,34 +328,6 @@ bool IRCView::searchNext(bool reversed)
     return find(m_pattern, m_searchFlags);
 }
 
-//// Marker lines
-
-#define _S(x) #x << (x)
-void dump_doc(QTextDocument* document)
-{
-    QTextBlock b(document->firstBlock());
-    while (b.isValid())
-    {
-        kDebug()    << _S(b.position())
-                    << _S(b.length())
-                    << _S(b.userState())
-                    ;
-                    b=b.next();
-    };
-}
-
-QDebug operator<<(QDebug dbg, QList<QTextBlock> &l)
-{
-    dbg.space() << _S(l.count()) << endl;
-        for (int i=0; i< l.count(); ++i)
-        {
-            QTextBlock b=l[i];
-            dbg.space() << _S(i) << _S(b.blockNumber()) << _S(b.length()) << _S(b.userState()) << endl;
-        }
-
-    return dbg.space();
-}
-
 class IrcViewMimeData : public QMimeData
 {
 public:
@@ -417,13 +392,52 @@ void IRCView::dropEvent(QDropEvent* e)
         emit urlsDropped(KUrl::List::fromMimeData(e->mimeData(), KUrl::List::PreferLocalUrls));
 }
 
+// Marker lines
+
+// This object gets stuffed into the userData field of a text block.
+// Qt does not give us a way to track blocks, so we have to
+// rely on the destructor of this object to notify us that a
+// block we care about was removed from the document. This does not
+// prevent the first block bug from deleting the wrong block's data,
+// however that should not result in a crash.
+struct Burr: public QTextBlockUserData
+{
+    Burr(IRCView* o, Burr* prev, QTextBlock b, int objFormat)
+        : m_block(b), m_format(objFormat), m_prev(prev), m_next(0),
+        m_owner(o)
+    {
+        if (m_prev)
+            m_prev->m_next = this;
+    }
+
+    ~Burr()
+    {
+        m_owner->blockDeleted(this);
+        unlink();
+    }
+
+    void unlink()
+    {
+        if (m_prev)
+            m_prev->m_next = m_next;
+        if (m_next)
+            m_next->m_prev = m_prev;
+    }
+
+    QTextBlock m_block;
+    int m_format;
+    Burr* m_prev, *m_next;
+    IRCView* m_owner;
+};
+
 void IrcViewMarkerLine::drawObject(QPainter *painter, const QRectF &r, QTextDocument *doc, int posInDocument, const QTextFormat &format)
 {
     Q_UNUSED(format);
 
     QTextBlock block=doc->findBlock(posInDocument);
     QPen pen;
-    switch (block.userState())
+    Burr* b = dynamic_cast<Burr*>(block.userData());
+    switch (b->m_format)
     {
         case IRCView::BlockIsMarker:
             pen.setColor(Preferences::self()->color(Preferences::ActionMessage));
@@ -456,33 +470,36 @@ QSizeF IrcViewMarkerLine::intrinsicSize(
     return QSizeF(width, 6); // FIXME this is a hardcoded value...
 }
 
+QTextCharFormat IRCView::getFormat(ObjectFormats x)
+{
+    QTextCharFormat f;
+    f.setObjectType(x);
+    return f;
+}
+
+void IRCView::blockDeleted(Burr* b) //slot
+{
+    //tracking only the tail
+    if (b == m_lastMarkerLine)
+        m_lastMarkerLine = b->m_prev;
+
+    if (b == m_rememberLine)
+        m_rememberLine = 0;
+}
+
 void IRCView::cullMarkedLine(int where, int rem, int add) //slot
 {
-    if (where == 0 && add == 0 && rem !=0)
-    {
-        if (document()->blockCount() == 1 && document()->firstBlock().length() == 1)
-        {
+    int blockCount = document()->blockCount();
+    QTextBlock prime = document()->firstBlock();
+
+    if (prime.length() == 1 && document()->blockCount() == 1)
             wipeLineParagraphs();
-        }
-        else
-        {
-            if (m_nextCullIsMarker)
-            {
-                //move the remember line up.. if the cull removed it, this will forget its position
-                if (m_rememberLinePosition >= 0)
-                    --m_rememberLinePosition;
-                m_markers.takeFirst();
-            }
-            int s = document()->firstBlock().userState();
-            m_nextCullIsMarker = (s == BlockIsMarker || s == BlockIsRemember);
-        }
-    }
 }
 
 void IRCView::insertMarkerLine() //slot
 {
     //if the last line is already a marker of any kind, skip out
-    if (lastBlockIsLine())
+    if (lastBlockIsLine(BlockIsMarker))
         return;
 
     //the code used to preserve the dirty bit status, but that was never affected by appendLine...
@@ -505,7 +522,12 @@ void IRCView::cancelRememberLine() //slo
 
 bool IRCView::lastBlockIsLine(int select)
 {
-    int state = document()->lastBlock().userState();
+    Burr *b = dynamic_cast<Burr*>(document()->lastBlock().userData());
+
+    int state = -1;
+
+    if (b)
+        state = b->m_format;
 
     if (select == -1)
         return (state == BlockIsRemember || state == BlockIsMarker);
@@ -522,81 +544,51 @@ void IRCView::appendRememberLine()
     if (lastBlockIsLine(BlockIsRemember))
         return;
 
-    // if we already have a rememberline, remove the previous one
-    if (m_rememberLinePosition > -1)
+    if (m_rememberLine)
     {
-        //get the block that is the remember line
-        QTextBlock rem = m_markers[m_rememberLinePosition];
-        m_markers.removeAt(m_rememberLinePosition); //probably will be in there only once
-        m_rememberLinePosition=-1;
+        QTextBlock rem = m_rememberLine->m_block;
         voidLineBlock(rem);
+        if (m_rememberLine != 0)
+        {
+            kDebug() << "%%%%%%%%%%%%%%%%% m_rememberLine still set!";
+            // this probably means we had a block containing only 0x2029, so Scribe merged the userData/userState into the next
+            m_rememberLine = 0;
+        }
     }
 
-    //tell the control we did stuff
-    //FIXME do we still do something like this?
-    //repaintChanged();
+    m_rememberLine = appendLine(IRCView::RememberLine);
 
-    //actually insert a line
-    appendLine(IRCView::RememberLine);
-
-    //store the index of the remember line
-    m_rememberLinePosition = m_markers.count() - 1;
 }
 
 void IRCView::voidLineBlock(QTextBlock rem)
 {
-    if (rem.blockNumber() == 0)
-    {
-        Q_ASSERT(m_nextCullIsMarker);
-        m_nextCullIsMarker = false;
-    }
     QTextCursor c(rem);
-    //FIXME make sure this doesn't flicker
+
     c.select(QTextCursor::BlockUnderCursor);
     c.removeSelectedText();
 }
 
 void IRCView::clearLines()
 {
-    //if we have a remember line, put it in the list
-        //its already in the list
 
-    kDebug() << _S(m_nextCullIsMarker) << _S(m_rememberLinePosition) << _S(textCursor().position()) << m_markers;
-    dump_doc(document());
-
-    //are there any markers?
-    if (hasLines())
+    while (hasLines())
     {
-        for (int i=0; i < m_markers.count(); ++i)
-            voidLineBlock(m_markers[i]);
-
-        wipeLineParagraphs();
-
-        //FIXME do we have this? //repaintChanged();
-    }
-
+        //IRCView::blockDeleted takes care of the pointers
+        voidLineBlock(m_lastMarkerLine->m_block);
+    };
 }
 
 void IRCView::wipeLineParagraphs()
 {
-    m_nextCullIsMarker = false;
-    m_rememberLinePosition = -1;
-    m_markers.clear();
+    m_rememberLine = m_lastMarkerLine = 0;
 }
 
 bool IRCView::hasLines()
 {
-    return m_markers.count() > 0;
+    return m_lastMarkerLine != 0;
 }
 
-QTextCharFormat IRCView::getFormat(ObjectFormats x)
-{
-    QTextCharFormat f;
-    f.setObjectType(x);
-    return f;
-}
-
-void IRCView::appendLine(IRCView::ObjectFormats type)
+Burr* IRCView::appendLine(IRCView::ObjectFormats type)
 {
     ScrollBarPin barpin(verticalScrollBar());
     SelectionPin selpin(this);
@@ -604,13 +596,21 @@ void IRCView::appendLine(IRCView::Object
     QTextCursor cursor(document());
     cursor.movePosition(QTextCursor::End);
 
-    cursor.insertBlock();
+    if (cursor.block().length() > 1) // this will be a 0x2029
+        cursor.insertBlock();
     cursor.insertText(QString(QChar::ObjectReplacementCharacter), getFormat(type));
-    cursor.block().setUserState(type == MarkerLine? BlockIsMarker : BlockIsRemember);
 
-    m_markers.append(cursor.block());
-}
+    QTextBlock block = cursor.block();
+    Burr *b = new Burr(this, m_lastMarkerLine, block, type == MarkerLine? BlockIsMarker : BlockIsRemember);
+    block.setUserData(b);
+
+    m_lastMarkerLine = b;
 
+    //TODO figure out what this is for
+    cursor.setPosition(block.position());
+
+    return b;
+}
 
 //// Other stuff
 

--- a/src/viewer/ircview.h
+++ b/src/viewer/ircview.h
@@ -24,7 +24,7 @@
 
 class Server;
 class ChatWindow;
-
+class Burr;
 
 class KToggleAction;
 class KMenu;
@@ -139,9 +139,10 @@ class IRCView : public KTextBrowser
         void appendRememberLine();
 
         /// Create a remember line and insert it.
-        void appendLine(ObjectFormats=MarkerLine);
+        /// @return - Pointer to the Burr that was inserted into the block
+        Burr* appendLine(ObjectFormats=MarkerLine);
 
-        /// Forget the position of the remember line and markers.
+        /// Convenience method - forget the position of the remember line and markers.
         void wipeLineParagraphs();
 
         /// Convenience method - is the last block any sort of line, or a specific line?
@@ -154,16 +155,22 @@ class IRCView : public KTextBrowser
         /// Shortcut to get an object format of the desired type
         QTextCharFormat getFormat(ObjectFormats);
 
+    public slots:
+        // Doesn't have to be a slot, but what the hay.
+        /// Called *only* from ~Burr(), by QTextBlockData::free
+        void blockDeleted(Burr* b);
+
     private slots:
-        /** Called to see if a marker is queued up for deletion. Only triggers if
-            "where" is the beginning and there was nothing added.
-        */
+        /** Called every time a change occurs to the document.
+         *
+         * Used to infer the clearing of the entire document,
+         * because Trolltech removed virtual from the method
+         * that would indicate authoritatively.
+         */
         void cullMarkedLine(int, int, int);
 
     private: //marker/remember line data
-        bool m_nextCullIsMarker; ///< the next time a cull occurs, it'll be a marker
-        QList<QTextBlock> m_markers; ///< what blocks are markers?
-        int m_rememberLinePosition; ///< position of remember line in m_markers
+        Burr *m_rememberLine, *m_lastMarkerLine;
         bool m_rememberLineDirtyBit; ///< the next append needs a remember line
         IrcViewMarkerLine markerFormatObject; ///< a QTextObjectInterface