From: eli mackenzie 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&a=commitdiff&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 Copyright (C) 2005-2007 Peter Simonsson Copyright (C) 2006-2008 Eike Hein - Copyright (C) 2004-2009 Eli Mackenzie + Copyright (C) 2004-2011 Eli Mackenzie */ #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 &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(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(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 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