| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | /**************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** Contact: Nokia Corporation (qt-info@nokia.com) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Commercial Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Licensees holding valid Qt Commercial licenses may use this file in | 
					
						
							|  |  |  | ** accordance with the Qt Commercial License Agreement provided with the | 
					
						
							|  |  |  | ** Software or, alternatively, in accordance with the terms contained in | 
					
						
							|  |  |  | ** a written agreement between you and Nokia. | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** GNU Lesser General Public License Usage | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
					
						
							|  |  |  | ** General Public License version 2.1 as published by the Free Software | 
					
						
							|  |  |  | ** Foundation and appearing in the file LICENSE.LGPL included in the | 
					
						
							|  |  |  | ** packaging of this file.  Please review the following information to | 
					
						
							|  |  |  | ** ensure the GNU Lesser General Public License version 2.1 requirements | 
					
						
							|  |  |  | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** If you are unsure which license is appropriate for your use, please | 
					
						
							| 
									
										
										
										
											2009-06-17 00:01:27 +10:00
										 |  |  | ** contact the sales department at http://www.qtsoftware.com/contact.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | **************************************************************************/ | 
					
						
							| 
									
										
										
										
											2008-12-02 16:19:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "texteditor_global.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 16:19:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "texteditorconstants.h"
 | 
					
						
							|  |  |  | #ifndef TEXTEDITOR_STANDALONE
 | 
					
						
							|  |  |  | #include "texteditorplugin.h"
 | 
					
						
							|  |  |  | #include "completionsupport.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #include "basetextdocument.h"
 | 
					
						
							|  |  |  | #include "basetexteditor_p.h"
 | 
					
						
							|  |  |  | #include "codecselector.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef TEXTEDITOR_STANDALONE
 | 
					
						
							| 
									
										
										
										
											2009-07-15 12:38:45 +02:00
										 |  |  | #include <aggregation/aggregate.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <coreplugin/coreconstants.h>
 | 
					
						
							|  |  |  | #include <coreplugin/editormanager/editormanager.h>
 | 
					
						
							| 
									
										
										
										
											2009-05-12 12:57:26 +02:00
										 |  |  | #include <coreplugin/manhattanstyle.h>
 | 
					
						
							| 
									
										
										
										
											2009-01-19 12:39:20 +01:00
										 |  |  | #include <extensionsystem/pluginmanager.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <find/basetextfind.h>
 | 
					
						
							| 
									
										
										
										
											2009-07-15 12:38:45 +02:00
										 |  |  | #include <utils/stylehelper.h>
 | 
					
						
							| 
									
										
										
										
											2009-06-17 19:12:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #include <utils/linecolumnlabel.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  | #include <utils/qtcassert.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <QtCore/QCoreApplication>
 | 
					
						
							|  |  |  | #include <QtCore/QTextCodec>
 | 
					
						
							|  |  |  | #include <QtCore/QFile>
 | 
					
						
							|  |  |  | #include <QtCore/QDebug>
 | 
					
						
							|  |  |  | #include <QtCore/QTimer>
 | 
					
						
							|  |  |  | #include <QtGui/QAbstractTextDocumentLayout>
 | 
					
						
							|  |  |  | #include <QtGui/QApplication>
 | 
					
						
							|  |  |  | #include <QtGui/QKeyEvent>
 | 
					
						
							|  |  |  | #include <QtGui/QLabel>
 | 
					
						
							|  |  |  | #include <QtGui/QLayout>
 | 
					
						
							|  |  |  | #include <QtGui/QPainter>
 | 
					
						
							|  |  |  | #include <QtGui/QPrinter>
 | 
					
						
							|  |  |  | #include <QtGui/QPrintDialog>
 | 
					
						
							|  |  |  | #include <QtGui/QPainter>
 | 
					
						
							|  |  |  | #include <QtGui/QScrollBar>
 | 
					
						
							|  |  |  | #include <QtGui/QShortcut>
 | 
					
						
							|  |  |  | #include <QtGui/QScrollBar>
 | 
					
						
							|  |  |  | #include <QtGui/QStyle>
 | 
					
						
							|  |  |  | #include <QtGui/QSyntaxHighlighter>
 | 
					
						
							|  |  |  | #include <QtGui/QTextCursor>
 | 
					
						
							|  |  |  | #include <QtGui/QTextBlock>
 | 
					
						
							|  |  |  | #include <QtGui/QTextLayout>
 | 
					
						
							|  |  |  | #include <QtGui/QToolBar>
 | 
					
						
							|  |  |  | #include <QtGui/QToolTip>
 | 
					
						
							|  |  |  | #include <QtGui/QInputDialog>
 | 
					
						
							| 
									
										
										
										
											2008-12-04 19:33:23 +01:00
										 |  |  | #include <QtGui/QMenu>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace TextEditor; | 
					
						
							|  |  |  | using namespace TextEditor::Internal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace TextEditor { | 
					
						
							| 
									
										
										
										
											2009-01-20 11:52:04 +01:00
										 |  |  | namespace Internal { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TextEditExtraArea : public QWidget { | 
					
						
							|  |  |  |     BaseTextEditor *textEdit; | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     TextEditExtraArea(BaseTextEditor *edit):QWidget(edit) { | 
					
						
							|  |  |  |         textEdit = edit; | 
					
						
							|  |  |  |         setAutoFillBackground(true); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QSize sizeHint() const { | 
					
						
							|  |  |  |         return QSize(textEdit->extraAreaWidth(), 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     void paintEvent(QPaintEvent *event){ | 
					
						
							|  |  |  |         textEdit->extraAreaPaintEvent(event); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void mousePressEvent(QMouseEvent *event){ | 
					
						
							|  |  |  |         textEdit->extraAreaMouseEvent(event); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void mouseMoveEvent(QMouseEvent *event){ | 
					
						
							|  |  |  |         textEdit->extraAreaMouseEvent(event); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void mouseReleaseEvent(QMouseEvent *event){ | 
					
						
							|  |  |  |         textEdit->extraAreaMouseEvent(event); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void leaveEvent(QEvent *event){ | 
					
						
							|  |  |  |         textEdit->extraAreaLeaveEvent(event); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void wheelEvent(QWheelEvent *event) { | 
					
						
							|  |  |  |         QCoreApplication::sendEvent(textEdit->viewport(), event); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-20 11:52:04 +01:00
										 |  |  | } // namespace Internal
 | 
					
						
							|  |  |  | } // namespace TextEditor
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | ITextEditor *BaseTextEditor::openEditorAt(const QString &fileName, | 
					
						
							| 
									
										
										
										
											2009-03-05 16:40:42 +01:00
										 |  |  |                                           int line, | 
					
						
							|  |  |  |                                           int column, | 
					
						
							|  |  |  |                                           const QString &editorKind) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-21 15:52:34 +01:00
										 |  |  |     Core::EditorManager *editorManager = Core::EditorManager::instance(); | 
					
						
							| 
									
										
										
										
											2009-03-18 17:17:53 +01:00
										 |  |  |     editorManager->addCurrentPositionToNavigationHistory(); | 
					
						
							| 
									
										
										
										
											2009-01-30 17:10:22 +01:00
										 |  |  |     Core::IEditor *editor = editorManager->openEditor(fileName, editorKind, Core::EditorManager::IgnoreNavigationHistory); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     TextEditor::ITextEditor *texteditor = qobject_cast<TextEditor::ITextEditor *>(editor); | 
					
						
							|  |  |  |     if (texteditor) { | 
					
						
							|  |  |  |         texteditor->gotoLine(line, column); | 
					
						
							|  |  |  |         return texteditor; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BaseTextEditor::BaseTextEditor(QWidget *parent) | 
					
						
							|  |  |  |     : QPlainTextEdit(parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d = new BaseTextEditorPrivate(); | 
					
						
							|  |  |  |     d->q = this; | 
					
						
							|  |  |  |     d->m_extraArea = new TextEditExtraArea(this); | 
					
						
							|  |  |  |     d->m_extraArea->setMouseTracking(true); | 
					
						
							|  |  |  |     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d->setupDocumentSignals(d->m_document); | 
					
						
							|  |  |  |     d->setupDocumentSignals(d->m_document); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d->m_lastScrollPos = -1; | 
					
						
							|  |  |  |     setCursorWidth(2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // from RESEARCH
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setLayoutDirection(Qt::LeftToRight); | 
					
						
							|  |  |  |     viewport()->setMouseTracking(true); | 
					
						
							|  |  |  |     d->extraAreaSelectionAnchorBlockNumber | 
					
						
							|  |  |  |         = d->extraAreaToggleMarkBlockNumber | 
					
						
							|  |  |  |         = d->extraAreaHighlightCollapseBlockNumber | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |         = d->extraAreaHighlightCollapseColumn | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d->visibleCollapsedBlockNumber = d->suggestedVisibleCollapsedBlockNumber = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(slotUpdateExtraAreaWidth())); | 
					
						
							|  |  |  |     connect(this, SIGNAL(modificationChanged(bool)), this, SLOT(slotModificationChanged(bool))); | 
					
						
							|  |  |  |     connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(slotCursorPositionChanged())); | 
					
						
							|  |  |  |     connect(this, SIGNAL(updateRequest(QRect, int)), this, SLOT(slotUpdateRequest(QRect, int))); | 
					
						
							|  |  |  |     connect(this, SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //     (void) new QShortcut(tr("CTRL+L"), this, SLOT(centerCursor()), 0, Qt::WidgetShortcut);
 | 
					
						
							|  |  |  | //     (void) new QShortcut(tr("F9"), this, SLOT(slotToggleMark()), 0, Qt::WidgetShortcut);
 | 
					
						
							|  |  |  | //     (void) new QShortcut(tr("F11"), this, SLOT(slotToggleBlockVisible()));
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // parentheses matcher
 | 
					
						
							|  |  |  |     d->m_parenthesesMatchingEnabled = false; | 
					
						
							|  |  |  |     d->m_formatRange = true; | 
					
						
							|  |  |  |     d->m_matchFormat.setForeground(Qt::red); | 
					
						
							|  |  |  |     d->m_rangeFormat.setBackground(QColor(0xb4, 0xee, 0xb4)); | 
					
						
							|  |  |  |     d->m_mismatchFormat.setBackground(Qt::magenta); | 
					
						
							|  |  |  |     d->m_parenthesesMatchingTimer = new QTimer(this); | 
					
						
							|  |  |  |     d->m_parenthesesMatchingTimer->setSingleShot(true); | 
					
						
							|  |  |  |     connect(d->m_parenthesesMatchingTimer, SIGNAL(timeout()), this, SLOT(_q_matchParentheses())); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |     d->m_highlightBlocksTimer = new QTimer(this); | 
					
						
							|  |  |  |     d->m_highlightBlocksTimer->setSingleShot(true); | 
					
						
							|  |  |  |     connect(d->m_highlightBlocksTimer, SIGNAL(timeout()), this, SLOT(_q_highlightBlocks())); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  |     d->m_animator = 0; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     d->m_searchResultFormat.setBackground(QColor(0xffef0b)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     slotUpdateExtraAreaWidth(); | 
					
						
							|  |  |  |     slotCursorPositionChanged(); | 
					
						
							|  |  |  |     setFrameStyle(QFrame::NoFrame); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), | 
					
						
							|  |  |  |             this, SLOT(currentEditorChanged(Core::IEditor*))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BaseTextEditor::~BaseTextEditor() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     delete d; | 
					
						
							|  |  |  |     d = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString BaseTextEditor::mimeType() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_document->mimeType(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setMimeType(const QString &mt) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_document->setMimeType(mt); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::print(QPrinter *printer) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const bool oldFullPage =  printer->fullPage(); | 
					
						
							|  |  |  |     printer->setFullPage(true); | 
					
						
							|  |  |  |     QPrintDialog *dlg = new QPrintDialog(printer, this); | 
					
						
							|  |  |  |     dlg->setWindowTitle(tr("Print Document")); | 
					
						
							|  |  |  |     if (dlg->exec() == QDialog::Accepted) { | 
					
						
							|  |  |  |         d->print(printer); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     printer->setFullPage(oldFullPage); | 
					
						
							|  |  |  |     delete dlg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  | static int collapseBoxWidth(const QFontMetrics &fm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const int lineSpacing = fm.lineSpacing(); | 
					
						
							|  |  |  |     return lineSpacing + lineSpacing%2 + 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | static void printPage(int index, QPainter *painter, const QTextDocument *doc, | 
					
						
							|  |  |  |                       const QRectF &body, const QRectF &titleBox, | 
					
						
							|  |  |  |                       const QString &title) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     painter->save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     painter->translate(body.left(), body.top() - (index - 1) * body.height()); | 
					
						
							|  |  |  |     QRectF view(0, (index - 1) * body.height(), body.width(), body.height()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QAbstractTextDocumentLayout *layout = doc->documentLayout(); | 
					
						
							|  |  |  |     QAbstractTextDocumentLayout::PaintContext ctx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     painter->setFont(QFont(doc->defaultFont())); | 
					
						
							|  |  |  |     QRectF box = titleBox.translated(0, view.top()); | 
					
						
							|  |  |  |     int dpix = painter->device()->logicalDpiX(); | 
					
						
							|  |  |  |     int dpiy = painter->device()->logicalDpiY(); | 
					
						
							|  |  |  |     int mx = 5 * dpix / 72.0; | 
					
						
							|  |  |  |     int my = 2 * dpiy / 72.0; | 
					
						
							|  |  |  |     painter->fillRect(box.adjusted(-mx, -my, mx, my), QColor(210, 210, 210)); | 
					
						
							|  |  |  |     if (!title.isEmpty()) | 
					
						
							|  |  |  |         painter->drawText(box, Qt::AlignCenter, title); | 
					
						
							|  |  |  |     const QString pageString = QString::number(index); | 
					
						
							|  |  |  |     painter->drawText(box, Qt::AlignRight, pageString); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     painter->setClipRect(view); | 
					
						
							|  |  |  |     ctx.clip = view; | 
					
						
							|  |  |  |     // don't use the system palette text as default text color, on HP/UX
 | 
					
						
							|  |  |  |     // for example that's white, and white text on white paper doesn't
 | 
					
						
							|  |  |  |     // look that nice
 | 
					
						
							|  |  |  |     ctx.palette.setColor(QPalette::Text, Qt::black); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     layout->draw(painter, ctx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     painter->restore(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorPrivate::print(QPrinter *printer) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextDocument *doc = q->document(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString title = q->displayName(); | 
					
						
							|  |  |  |     if (title.isEmpty()) | 
					
						
							|  |  |  |         printer->setDocName(title); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QPainter p(printer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Check that there is a valid device to print to.
 | 
					
						
							|  |  |  |     if (!p.isActive()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     doc = doc->clone(doc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextOption opt = doc->defaultTextOption(); | 
					
						
							|  |  |  |     opt.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere); | 
					
						
							|  |  |  |     doc->setDefaultTextOption(opt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     (void)doc->documentLayout(); // make sure that there is a layout
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QColor background = q->palette().color(QPalette::Base); | 
					
						
							|  |  |  |     bool backgroundIsDark = background.value() < 128; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (QTextBlock srcBlock = q->document()->firstBlock(), dstBlock = doc->firstBlock(); | 
					
						
							|  |  |  |          srcBlock.isValid() && dstBlock.isValid(); | 
					
						
							|  |  |  |          srcBlock = srcBlock.next(), dstBlock = dstBlock.next()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QList<QTextLayout::FormatRange> formatList = srcBlock.layout()->additionalFormats(); | 
					
						
							|  |  |  |         if (backgroundIsDark) { | 
					
						
							|  |  |  |             // adjust syntax highlighting colors for better contrast
 | 
					
						
							|  |  |  |             for (int i = formatList.count() - 1; i >=0; --i) { | 
					
						
							|  |  |  |                 QTextCharFormat &format = formatList[i].format; | 
					
						
							|  |  |  |                 if (format.background().color() == background) { | 
					
						
							|  |  |  |                     QBrush brush = format.foreground(); | 
					
						
							|  |  |  |                     QColor color = brush.color(); | 
					
						
							|  |  |  |                     int h,s,v,a; | 
					
						
							|  |  |  |                     color.getHsv(&h, &s, &v, &a); | 
					
						
							|  |  |  |                     color.setHsv(h, s, qMin(128, v), a); | 
					
						
							|  |  |  |                     brush.setColor(color); | 
					
						
							|  |  |  |                     format.setForeground(brush); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 format.setBackground(Qt::white); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dstBlock.layout()->setAdditionalFormats(formatList); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QAbstractTextDocumentLayout *layout = doc->documentLayout(); | 
					
						
							|  |  |  |     layout->setPaintDevice(p.device()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int dpiy = p.device()->logicalDpiY(); | 
					
						
							|  |  |  |     int margin = (int) ((2/2.54)*dpiy); // 2 cm margins
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextFrameFormat fmt = doc->rootFrame()->frameFormat(); | 
					
						
							|  |  |  |     fmt.setMargin(margin); | 
					
						
							|  |  |  |     doc->rootFrame()->setFrameFormat(fmt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QRectF pageRect(printer->pageRect()); | 
					
						
							|  |  |  |     QRectF body = QRectF(0, 0, pageRect.width(), pageRect.height()); | 
					
						
							|  |  |  |     QFontMetrics fontMetrics(doc->defaultFont(), p.device()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QRectF titleBox(margin, | 
					
						
							|  |  |  |                     body.top() + margin | 
					
						
							|  |  |  |                     - fontMetrics.height() | 
					
						
							|  |  |  |                     - 6 * dpiy / 72.0, | 
					
						
							|  |  |  |                     body.width() - 2*margin, | 
					
						
							|  |  |  |                     fontMetrics.height()); | 
					
						
							|  |  |  |     doc->setPageSize(body.size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int docCopies; | 
					
						
							|  |  |  |     int pageCopies; | 
					
						
							|  |  |  |     if (printer->collateCopies() == true){ | 
					
						
							|  |  |  |         docCopies = 1; | 
					
						
							|  |  |  |         pageCopies = printer->numCopies(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         docCopies = printer->numCopies(); | 
					
						
							|  |  |  |         pageCopies = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int fromPage = printer->fromPage(); | 
					
						
							|  |  |  |     int toPage = printer->toPage(); | 
					
						
							|  |  |  |     bool ascending = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fromPage == 0 && toPage == 0) { | 
					
						
							|  |  |  |         fromPage = 1; | 
					
						
							|  |  |  |         toPage = doc->pageCount(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // paranoia check
 | 
					
						
							|  |  |  |     fromPage = qMax(1, fromPage); | 
					
						
							|  |  |  |     toPage = qMin(doc->pageCount(), toPage); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (printer->pageOrder() == QPrinter::LastPageFirst) { | 
					
						
							|  |  |  |         int tmp = fromPage; | 
					
						
							|  |  |  |         fromPage = toPage; | 
					
						
							|  |  |  |         toPage = tmp; | 
					
						
							|  |  |  |         ascending = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i < docCopies; ++i) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         int page = fromPage; | 
					
						
							|  |  |  |         while (true) { | 
					
						
							|  |  |  |             for (int j = 0; j < pageCopies; ++j) { | 
					
						
							|  |  |  |                 if (printer->printerState() == QPrinter::Aborted | 
					
						
							|  |  |  |                     || printer->printerState() == QPrinter::Error) | 
					
						
							|  |  |  |                     goto UserCanceled; | 
					
						
							|  |  |  |                 printPage(page, &p, doc, body, titleBox, title); | 
					
						
							|  |  |  |                 if (j < pageCopies - 1) | 
					
						
							|  |  |  |                     printer->newPage(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (page == toPage) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (ascending) | 
					
						
							|  |  |  |                 ++page; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 --page; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             printer->newPage(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ( i < docCopies - 1) | 
					
						
							|  |  |  |             printer->newPage(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | UserCanceled: | 
					
						
							|  |  |  |     delete doc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool DocumentMarker::addMark(TextEditor::ITextMark *mark, int line) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(line >= 1, return false); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     int blockNumber = line - 1; | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(document->documentLayout()); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(documentLayout, return false); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QTextBlock block = document->findBlockByNumber(blockNumber); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (block.isValid()) { | 
					
						
							|  |  |  |         TextBlockUserData *userData = TextEditDocumentLayout::userData(block); | 
					
						
							|  |  |  |         userData->addMark(mark); | 
					
						
							|  |  |  |         mark->updateLineNumber(blockNumber + 1); | 
					
						
							|  |  |  |         mark->updateBlock(block); | 
					
						
							|  |  |  |         documentLayout->hasMarks = true; | 
					
						
							|  |  |  |         documentLayout->requestUpdate(); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  | int BaseTextEditorPrivate::visualIndent(const QTextBlock &block) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!block.isValid()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     const QTextDocument *document = block.document(); | 
					
						
							|  |  |  |     int i = 0; | 
					
						
							|  |  |  |     while (i < block.length()) { | 
					
						
							|  |  |  |         if (!document->characterAt(block.position() + i).isSpace()) { | 
					
						
							|  |  |  |             QTextCursor cursor(block); | 
					
						
							|  |  |  |             cursor.setPosition(block.position() + i); | 
					
						
							|  |  |  |             return q->cursorRect(cursor).x(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         ++i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | TextEditor::TextMarks DocumentMarker::marksAt(int line) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(line >= 1, return TextMarks()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     int blockNumber = line - 1; | 
					
						
							|  |  |  |     QTextBlock block = document->findBlockByNumber(blockNumber); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (block.isValid()) { | 
					
						
							|  |  |  |         if (TextBlockUserData *userData = TextEditDocumentLayout::testUserData(block)) | 
					
						
							|  |  |  |             return userData->marks(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return TextMarks(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DocumentMarker::removeMark(TextEditor::ITextMark *mark) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool needUpdate = false; | 
					
						
							|  |  |  |     QTextBlock block = document->begin(); | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         if (TextBlockUserData *data = static_cast<TextBlockUserData *>(block.userData())) { | 
					
						
							|  |  |  |             needUpdate |= data->removeMark(mark); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (needUpdate) | 
					
						
							|  |  |  |         updateMark(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool DocumentMarker::hasMark(TextEditor::ITextMark *mark) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextBlock block = document->begin(); | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         if (TextBlockUserData *data = static_cast<TextBlockUserData *>(block.userData())) { | 
					
						
							|  |  |  |             if (data->hasMark(mark)) | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ITextMarkable *BaseTextEditor::markableInterface() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return baseTextDocument()->documentMarker(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ITextEditable *BaseTextEditor::editableInterface() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!d->m_editable) { | 
					
						
							|  |  |  |         d->m_editable = const_cast<BaseTextEditor*>(this)->createEditableInterface(); | 
					
						
							|  |  |  |         connect(this, SIGNAL(textChanged()), | 
					
						
							|  |  |  |                 d->m_editable, SIGNAL(contentsChanged())); | 
					
						
							|  |  |  |         connect(this, SIGNAL(changed()), | 
					
						
							|  |  |  |                 d->m_editable, SIGNAL(changed())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return d->m_editable; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::currentEditorChanged(Core::IEditor *editor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (editor == d->m_editable) { | 
					
						
							|  |  |  |         if (d->m_document->hasDecodingError()) { | 
					
						
							|  |  |  |             Core::EditorManager::instance()->showEditorInfoBar(QLatin1String(Constants::SELECT_ENCODING), | 
					
						
							| 
									
										
										
										
											2008-11-28 15:36:54 +01:00
										 |  |  |                 tr("<b>Error:</b> Could not decode \"%1\" with \"%2\"-encoding. Editing not possible.") | 
					
						
							|  |  |  |                     .arg(displayName()).arg(QString::fromLatin1(d->m_document->codec()->name())), | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 tr("Select Encoding"), | 
					
						
							|  |  |  |                 this, SLOT(selectEncoding())); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::selectEncoding() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BaseTextDocument *doc = d->m_document; | 
					
						
							|  |  |  |     CodecSelector codecSelector(this, doc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (codecSelector.exec()) { | 
					
						
							|  |  |  |     case CodecSelector::Reload: | 
					
						
							|  |  |  |         doc->reload(codecSelector.selectedCodec()); | 
					
						
							|  |  |  |         setReadOnly(d->m_document->hasDecodingError()); | 
					
						
							|  |  |  |         if (doc->hasDecodingError()) | 
					
						
							|  |  |  |             currentEditorChanged(Core::EditorManager::instance()->currentEditor()); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             Core::EditorManager::instance()->hideEditorInfoBar(QLatin1String(Constants::SELECT_ENCODING)); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case CodecSelector::Save: | 
					
						
							|  |  |  |         doc->setCodec(codecSelector.selectedCodec()); | 
					
						
							|  |  |  |         Core::EditorManager::instance()->saveEditor(editableInterface()); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case CodecSelector::Cancel: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void DocumentMarker::updateMark(ITextMark *mark) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-13 17:35:17 +02:00
										 |  |  |     Q_UNUSED(mark) | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(document->documentLayout()); | 
					
						
							|  |  |  |     QTC_ASSERT(documentLayout, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     documentLayout->requestUpdate(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::triggerCompletions() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     emit requestAutoCompletion(editableInterface(), true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 14:32:42 +02:00
										 |  |  | void BaseTextEditor::triggerQuickFix() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     emit requestQuickFix(editableInterface()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | bool BaseTextEditor::createNew(const QString &contents) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     setPlainText(contents); | 
					
						
							|  |  |  |     document()->setModified(false); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::open(const QString &fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (d->m_document->open(fileName)) { | 
					
						
							|  |  |  |         moveCursor(QTextCursor::Start); | 
					
						
							|  |  |  |         setReadOnly(d->m_document->hasDecodingError()); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-20 11:52:04 +01:00
										 |  |  | Core::IFile *BaseTextEditor::file() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return d->m_document; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::editorContentsChange(int position, int charsRemoved, int charsAdded) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_contentsChanged = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Keep the line numbers and the block information for the text marks updated
 | 
					
						
							|  |  |  |     if (charsRemoved != 0) { | 
					
						
							|  |  |  |         d->updateMarksLineNumber(); | 
					
						
							|  |  |  |         d->updateMarksBlock(document()->findBlock(position)); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         const QTextBlock posBlock = document()->findBlock(position); | 
					
						
							|  |  |  |         const QTextBlock nextBlock = document()->findBlock(position + charsAdded); | 
					
						
							|  |  |  |         if (posBlock != nextBlock) { | 
					
						
							|  |  |  |             d->updateMarksLineNumber(); | 
					
						
							|  |  |  |             d->updateMarksBlock(posBlock); | 
					
						
							|  |  |  |             d->updateMarksBlock(nextBlock); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             d->updateMarksBlock(posBlock); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::slotSelectionChanged() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool changed = (d->m_inBlockSelectionMode != d->m_lastEventWasBlockSelectionEvent); | 
					
						
							|  |  |  |     d->m_inBlockSelectionMode = d->m_lastEventWasBlockSelectionEvent; | 
					
						
							|  |  |  |     if (changed || d->m_inBlockSelectionMode) | 
					
						
							|  |  |  |         viewport()->update(); | 
					
						
							|  |  |  |     if (!d->m_inBlockSelectionMode) | 
					
						
							|  |  |  |         d->m_blockSelectionExtraX = 0; | 
					
						
							| 
									
										
										
										
											2008-12-04 19:25:20 +01:00
										 |  |  |     if (!d->m_selectBlockAnchor.isNull() && !textCursor().hasSelection()) | 
					
						
							|  |  |  |         d->m_selectBlockAnchor = QTextCursor(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | void BaseTextEditor::gotoBlockStart() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |     if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, false)) { | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |         setTextCursor(cursor); | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |         _q_matchParentheses(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::gotoBlockEnd() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |     if (TextBlockUserData::findNextClosingParenthesis(&cursor, false)) { | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |         setTextCursor(cursor); | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |         _q_matchParentheses(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::gotoBlockStartWithSelection() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |     if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, true)) { | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |         setTextCursor(cursor); | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |         _q_matchParentheses(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::gotoBlockEndWithSelection() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |     if (TextBlockUserData::findNextClosingParenthesis(&cursor, true)) { | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |         setTextCursor(cursor); | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |         _q_matchParentheses(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static QTextCursor flippedCursor(const QTextCursor &cursor) { | 
					
						
							|  |  |  |     QTextCursor flipped = cursor; | 
					
						
							|  |  |  |     flipped.clearSelection(); | 
					
						
							|  |  |  |     flipped.setPosition(cursor.anchor(), QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     return flipped; | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-04 19:25:20 +01:00
										 |  |  | void BaseTextEditor::selectBlockUp() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |     if (!cursor.hasSelection()) | 
					
						
							|  |  |  |         d->m_selectBlockAnchor = cursor; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         cursor.setPosition(cursor.selectionStart()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!TextBlockUserData::findPreviousOpenParenthesis(&cursor, false)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     if (!TextBlockUserData::findNextClosingParenthesis(&cursor, true)) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |     setTextCursor(flippedCursor(cursor)); | 
					
						
							|  |  |  |     _q_matchParentheses(); | 
					
						
							| 
									
										
										
										
											2008-12-04 19:25:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::selectBlockDown() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor tc = textCursor(); | 
					
						
							|  |  |  |     QTextCursor cursor = d->m_selectBlockAnchor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!tc.hasSelection() || cursor.isNull()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     tc.setPosition(tc.selectionStart()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     forever { | 
					
						
							|  |  |  |         QTextCursor ahead = cursor; | 
					
						
							|  |  |  |         if (!TextBlockUserData::findPreviousOpenParenthesis(&ahead, false)) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         if (ahead.position() <= tc.position()) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         cursor = ahead; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ( cursor != d->m_selectBlockAnchor) | 
					
						
							|  |  |  |         TextBlockUserData::findNextClosingParenthesis(&cursor, true); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-05 17:06:17 +01:00
										 |  |  |     setTextCursor(flippedCursor(cursor)); | 
					
						
							|  |  |  |     _q_matchParentheses(); | 
					
						
							| 
									
										
										
										
											2008-12-04 19:25:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 23:17:11 +02:00
										 |  |  | void BaseTextEditor::copyLineUp() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     copyLineUpDown(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::copyLineDown() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     copyLineUpDown(false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::copyLineUpDown(bool up) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |     QTextCursor move = cursor; | 
					
						
							|  |  |  |     move.beginEditBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool hasSelection = cursor.hasSelection(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (hasSelection) { | 
					
						
							|  |  |  |         move.setPosition(cursor.selectionStart()); | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::StartOfBlock); | 
					
						
							|  |  |  |         move.setPosition(cursor.selectionEnd(), QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::StartOfBlock); | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString text = move.selectedText(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (up) { | 
					
						
							|  |  |  |         move.setPosition(cursor.selectionStart()); | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::StartOfBlock); | 
					
						
							|  |  |  |         move.insertBlock(); | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::Left); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::EndOfBlock); | 
					
						
							|  |  |  |         if (move.atBlockStart()) { | 
					
						
							|  |  |  |             move.movePosition(QTextCursor::NextBlock); | 
					
						
							|  |  |  |             move.insertBlock(); | 
					
						
							|  |  |  |             move.movePosition(QTextCursor::Left); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             move.insertBlock(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int start = move.position(); | 
					
						
							|  |  |  |     move.clearSelection(); | 
					
						
							|  |  |  |     move.insertText(text); | 
					
						
							|  |  |  |     int end = move.position(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     move.setPosition(start); | 
					
						
							|  |  |  |     move.setPosition(end, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     indent(document(), move, QChar::Null); | 
					
						
							|  |  |  |     move.endEditBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setTextCursor(move); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  | void BaseTextEditor::moveLineUp() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     moveLineUpDown(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::moveLineDown() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     moveLineUpDown(false); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::moveLineUpDown(bool up) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |     QTextCursor move = cursor; | 
					
						
							| 
									
										
										
										
											2009-04-23 19:24:57 +02:00
										 |  |  |     if (d->m_moveLineUndoHack) | 
					
						
							|  |  |  |         move.joinPreviousEditBlock(); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         move.beginEditBlock(); | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool hasSelection = cursor.hasSelection(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (cursor.hasSelection()) { | 
					
						
							|  |  |  |         move.setPosition(cursor.selectionStart()); | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::StartOfBlock); | 
					
						
							|  |  |  |         move.setPosition(cursor.selectionEnd(), QTextCursor::KeepAnchor); | 
					
						
							| 
									
										
										
										
											2009-04-23 19:24:57 +02:00
										 |  |  |         move.movePosition(move.atBlockStart() ? QTextCursor::Left: QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::StartOfBlock); | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QString text = move.selectedText(); | 
					
						
							|  |  |  |     move.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     move.removeSelectedText(); | 
					
						
							| 
									
										
										
										
											2008-12-11 10:28:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  |     if (up) { | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::PreviousBlock); | 
					
						
							|  |  |  |         move.insertBlock(); | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::Left); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         move.movePosition(QTextCursor::EndOfBlock); | 
					
						
							|  |  |  |         if (move.atBlockStart()) { // empty block
 | 
					
						
							|  |  |  |             move.movePosition(QTextCursor::NextBlock); | 
					
						
							|  |  |  |             move.insertBlock(); | 
					
						
							|  |  |  |             move.movePosition(QTextCursor::Left); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             move.insertBlock(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-11 10:28:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  |     int start = move.position(); | 
					
						
							|  |  |  |     move.clearSelection(); | 
					
						
							|  |  |  |     move.insertText(text); | 
					
						
							|  |  |  |     int end = move.position(); | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  |     if (hasSelection) { | 
					
						
							|  |  |  |         move.setPosition(start); | 
					
						
							|  |  |  |         move.setPosition(end, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |     indent(document(), move, QChar::Null); | 
					
						
							|  |  |  |     move.endEditBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  |     setTextCursor(move); | 
					
						
							| 
									
										
										
										
											2009-04-23 19:24:57 +02:00
										 |  |  |     d->m_moveLineUndoHack = true; | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-09 17:43:31 +01:00
										 |  |  | void BaseTextEditor::cleanWhitespace() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-15 16:09:42 +01:00
										 |  |  |     d->m_document->cleanWhitespace(); | 
					
						
							| 
									
										
										
										
											2008-12-09 17:43:31 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void BaseTextEditor::keyPressEvent(QKeyEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-06-12 12:38:27 +02:00
										 |  |  |     viewport()->setCursor(Qt::BlankCursor); | 
					
						
							|  |  |  |     QToolTip::hideText(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-23 19:24:57 +02:00
										 |  |  |     d->m_moveLineUndoHack = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     d->clearVisibleCollapsedBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QKeyEvent *original_e = e; | 
					
						
							|  |  |  |     d->m_lastEventWasBlockSelectionEvent = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (e->key() == Qt::Key_Escape) { | 
					
						
							|  |  |  |         e->accept(); | 
					
						
							|  |  |  |         QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |         cursor.clearSelection(); | 
					
						
							|  |  |  |         setTextCursor(cursor); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool ro = isReadOnly(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (d->m_inBlockSelectionMode) { | 
					
						
							|  |  |  |         if (e == QKeySequence::Cut) { | 
					
						
							|  |  |  |             if (!ro) { | 
					
						
							|  |  |  |                 cut(); | 
					
						
							|  |  |  |                 e->accept(); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-05-29 18:48:18 +02:00
										 |  |  |         } else if (e == QKeySequence::Delete || e->key() == Qt::Key_Backspace) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             if (!ro) { | 
					
						
							|  |  |  |                 d->removeBlockSelection(); | 
					
						
							|  |  |  |                 e->accept(); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |         } else if (e == QKeySequence::Paste) { | 
					
						
							|  |  |  |             if (!ro) { | 
					
						
							|  |  |  |                 d->removeBlockSelection(); | 
					
						
							|  |  |  |                 // continue
 | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!ro | 
					
						
							|  |  |  |         && (e == QKeySequence::InsertParagraphSeparator | 
					
						
							|  |  |  |             || (!d->m_lineSeparatorsAllowed && e == QKeySequence::InsertLineSeparator)) | 
					
						
							|  |  |  |         ) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |         if (d->m_inBlockSelectionMode) | 
					
						
							|  |  |  |             cursor.clearSelection(); | 
					
						
							|  |  |  |         if (d->m_document->tabSettings().m_autoIndent) { | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  |             cursor.beginEditBlock(); | 
					
						
							|  |  |  |             cursor.insertBlock(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             indent(document(), cursor, QChar::Null); | 
					
						
							| 
									
										
										
										
											2008-12-10 18:01:33 +01:00
										 |  |  |             cursor.endEditBlock(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             cursor.insertBlock(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         e->accept(); | 
					
						
							|  |  |  |         setTextCursor(cursor); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } else switch (e->key()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  |     case Qt::Key_sterling: { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         static bool toggle = false; | 
					
						
							|  |  |  |         if ((toggle = !toggle)) { | 
					
						
							|  |  |  |             QList<BaseTextEditor::BlockRange> rangeList; | 
					
						
							|  |  |  |             rangeList += BaseTextEditor::BlockRange(4, 12); | 
					
						
							|  |  |  |             rangeList += BaseTextEditor::BlockRange(15, 19); | 
					
						
							|  |  |  |             setIfdefedOutBlocks(rangeList); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             setIfdefedOutBlocks(QList<BaseTextEditor::BlockRange>()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         e->accept(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     case Qt::Key_Tab: | 
					
						
							| 
									
										
										
										
											2009-05-18 12:21:30 -05:00
										 |  |  |     case Qt::Key_Backtab: { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         if (ro) break; | 
					
						
							| 
									
										
										
										
											2009-05-18 12:21:30 -05:00
										 |  |  |         QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |         int newPosition; | 
					
						
							|  |  |  |         if (d->m_document->tabSettings().tabShouldIndent(document(), cursor, &newPosition)) { | 
					
						
							|  |  |  |             if (newPosition != cursor.position() && !cursor.hasSelection()) { | 
					
						
							|  |  |  |                 cursor.setPosition(newPosition); | 
					
						
							|  |  |  |                 setTextCursor(cursor); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             indent(document(), cursor, QChar::Null); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             indentOrUnindent(e->key() == Qt::Key_Tab); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         e->accept(); | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-05-18 12:21:30 -05:00
										 |  |  |     } break; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     case Qt::Key_Backspace: | 
					
						
							|  |  |  |         if (ro) break; | 
					
						
							|  |  |  |         if (d->m_document->tabSettings().m_smartBackspace | 
					
						
							|  |  |  |             && (e->modifiers() & (Qt::ControlModifier | 
					
						
							|  |  |  |                                | Qt::ShiftModifier | 
					
						
							|  |  |  |                                | Qt::AltModifier | 
					
						
							|  |  |  |                                | Qt::MetaModifier)) == Qt::NoModifier | 
					
						
							|  |  |  |             && !textCursor().hasSelection()) { | 
					
						
							|  |  |  |             handleBackspaceKey(); | 
					
						
							|  |  |  |             e->accept(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Qt::Key_Home: | 
					
						
							|  |  |  |         if (!(e == QKeySequence::MoveToStartOfDocument) && !(e == QKeySequence::SelectStartOfDocument)) { | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |             if ((e->modifiers() & (Qt::AltModifier | Qt::ShiftModifier)) == (Qt::AltModifier | Qt::ShiftModifier)) | 
					
						
							|  |  |  |                 d->m_lastEventWasBlockSelectionEvent = true; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             handleHomeKey(e->modifiers() & Qt::ShiftModifier); | 
					
						
							|  |  |  |             e->accept(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Qt::Key_Up: | 
					
						
							|  |  |  |     case Qt::Key_Down: | 
					
						
							|  |  |  |         if (e->modifiers() & Qt::ControlModifier) { | 
					
						
							|  |  |  |             verticalScrollBar()->triggerAction( | 
					
						
							|  |  |  |                     e->key() == Qt::Key_Up ? QAbstractSlider::SliderSingleStepSub : | 
					
						
							|  |  |  |                                              QAbstractSlider::SliderSingleStepAdd); | 
					
						
							|  |  |  |             e->accept(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // fall through
 | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |     case Qt::Key_End: | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     case Qt::Key_Right: | 
					
						
							|  |  |  |     case Qt::Key_Left: | 
					
						
							| 
									
										
										
										
											2009-06-03 20:45:49 +02:00
										 |  |  | #ifndef Q_WS_MAC
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         if ((e->modifiers() & (Qt::AltModifier | Qt::ShiftModifier)) == (Qt::AltModifier | Qt::ShiftModifier)) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             d->m_lastEventWasBlockSelectionEvent = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (d->m_inBlockSelectionMode) { | 
					
						
							|  |  |  |                 if (e->key() == Qt::Key_Right && textCursor().atBlockEnd()) { | 
					
						
							|  |  |  |                     d->m_blockSelectionExtraX++; | 
					
						
							|  |  |  |                     viewport()->update(); | 
					
						
							|  |  |  |                     e->accept(); | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } else if (e->key() == Qt::Key_Left && d->m_blockSelectionExtraX > 0) { | 
					
						
							|  |  |  |                     d->m_blockSelectionExtraX--; | 
					
						
							|  |  |  |                     e->accept(); | 
					
						
							|  |  |  |                     viewport()->update(); | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             e = new QKeyEvent( | 
					
						
							|  |  |  |                 e->type(), | 
					
						
							|  |  |  |                 e->key(), | 
					
						
							|  |  |  |                 e->modifiers() & ~Qt::AltModifier, | 
					
						
							|  |  |  |                 e->text(), | 
					
						
							|  |  |  |                 e->isAutoRepeat(), | 
					
						
							|  |  |  |                 e->count() | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case Qt::Key_PageUp: | 
					
						
							|  |  |  |     case Qt::Key_PageDown: | 
					
						
							|  |  |  |         if (e->modifiers() == Qt::ControlModifier) { | 
					
						
							|  |  |  |             verticalScrollBar()->triggerAction( | 
					
						
							|  |  |  |                     e->key() == Qt::Key_PageUp ? QAbstractSlider::SliderPageStepSub : | 
					
						
							|  |  |  |                                                  QAbstractSlider::SliderPageStepAdd); | 
					
						
							|  |  |  |             e->accept(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         if (! ro && d->m_document->tabSettings().m_autoIndent | 
					
						
							|  |  |  |             && ! e->text().isEmpty() && isElectricCharacter(e->text().at(0))) { | 
					
						
							|  |  |  |             QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |             const QString text = e->text(); | 
					
						
							|  |  |  |             cursor.insertText(text); | 
					
						
							| 
									
										
										
										
											2009-05-26 12:01:57 +02:00
										 |  |  |             indent(document(), cursor, text.at(0)); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  |             TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(document()->documentLayout()); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |             QTC_ASSERT(documentLayout, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             documentLayout->requestUpdate(); // a bit drastic
 | 
					
						
							|  |  |  |             e->accept(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |             setTextCursor(cursor); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (d->m_inBlockSelectionMode) { | 
					
						
							|  |  |  |         QString text = e->text(); | 
					
						
							|  |  |  |         if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t'))) { | 
					
						
							|  |  |  |             d->removeBlockSelection(text); | 
					
						
							|  |  |  |             goto skip_event; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QPlainTextEdit::keyPressEvent(e); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | skip_event: | 
					
						
							|  |  |  |     if (!ro && e->key() == Qt::Key_Delete && d->m_parenthesesMatchingEnabled) | 
					
						
							| 
									
										
										
										
											2009-05-06 11:18:56 +02:00
										 |  |  |         d->m_parenthesesMatchingTimer->start(50); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!ro && d->m_contentsChanged && !e->text().isEmpty() && e->text().at(0).isPrint()) | 
					
						
							|  |  |  |         emit requestAutoCompletion(editableInterface(), false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (e != original_e) | 
					
						
							|  |  |  |         delete e; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | void BaseTextEditor::setTextCursor(const QTextCursor &cursor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // workaround for QTextControl bug
 | 
					
						
							|  |  |  |     bool selectionChange = cursor.hasSelection() || textCursor().hasSelection(); | 
					
						
							|  |  |  |     QPlainTextEdit::setTextCursor(cursor); | 
					
						
							|  |  |  |     if (selectionChange) | 
					
						
							|  |  |  |         slotSelectionChanged(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-19 15:01:12 +01:00
										 |  |  | void BaseTextEditor::gotoLine(int line, int column) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-19 15:17:05 +01:00
										 |  |  |     d->m_lastCursorChangeWasInteresting = false; // avoid adding the previous position to history
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     const int blockNumber = line - 1; | 
					
						
							|  |  |  |     const QTextBlock &block = document()->findBlockByNumber(blockNumber); | 
					
						
							|  |  |  |     if (block.isValid()) { | 
					
						
							|  |  |  |         QTextCursor cursor(block); | 
					
						
							|  |  |  |         if (column > 0) { | 
					
						
							|  |  |  |             cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, column); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             int pos = cursor.position(); | 
					
						
							|  |  |  |             while (characterAt(pos).category() == QChar::Separator_Space) { | 
					
						
							|  |  |  |                 ++pos; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             cursor.setPosition(pos); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         setTextCursor(cursor); | 
					
						
							|  |  |  |         centerCursor(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-03-19 15:01:12 +01:00
										 |  |  |     saveCurrentCursorPositionForNavigation(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BaseTextEditor::position(ITextEditor::PositionOperation posOp, int at) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor tc = textCursor(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (at != -1) | 
					
						
							|  |  |  |         tc.setPosition(at); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (posOp == ITextEditor::Current) | 
					
						
							|  |  |  |         return tc.position(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (posOp) { | 
					
						
							|  |  |  |     case ITextEditor::EndOfLine: | 
					
						
							|  |  |  |         tc.movePosition(QTextCursor::EndOfLine); | 
					
						
							|  |  |  |         return tc.position(); | 
					
						
							|  |  |  |     case ITextEditor::StartOfLine: | 
					
						
							|  |  |  |         tc.movePosition(QTextCursor::StartOfLine); | 
					
						
							|  |  |  |         return tc.position(); | 
					
						
							|  |  |  |     case ITextEditor::Anchor: | 
					
						
							|  |  |  |         if (tc.hasSelection()) | 
					
						
							|  |  |  |             return tc.anchor(); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case ITextEditor::EndOfDoc: | 
					
						
							|  |  |  |         tc.movePosition(QTextCursor::End); | 
					
						
							|  |  |  |         return tc.position(); | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::convertPosition(int pos, int *line, int *column) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextBlock block = document()->findBlock(pos); | 
					
						
							|  |  |  |     if (!block.isValid()) { | 
					
						
							|  |  |  |         (*line) = -1; | 
					
						
							|  |  |  |         (*column) = -1; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         (*line) = block.blockNumber() + 1; | 
					
						
							|  |  |  |         (*column) = pos - block.position(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QChar BaseTextEditor::characterAt(int pos) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return document()->characterAt(pos); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::event(QEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-19 14:18:26 +01:00
										 |  |  |     d->m_contentsChanged = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     switch (e->type()) { | 
					
						
							|  |  |  |     case QEvent::ShortcutOverride: | 
					
						
							| 
									
										
										
										
											2009-04-23 14:41:55 +02:00
										 |  |  |         e->ignore(); // we are a really nice citizen
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return QPlainTextEdit::event(e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::duplicateFrom(BaseTextEditor *editor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (this == editor) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     setDisplayName(editor->displayName()); | 
					
						
							|  |  |  |     d->m_revisionsVisible = editor->d->m_revisionsVisible; | 
					
						
							|  |  |  |     if (d->m_document == editor->d->m_document) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     d->setupDocumentSignals(editor->d->m_document); | 
					
						
							|  |  |  |     d->m_document = editor->d->m_document; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString BaseTextEditor::displayName() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_displayName; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setDisplayName(const QString &title) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_displayName = title; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BaseTextDocument *BaseTextEditor::baseTextDocument() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_document; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setBaseTextDocument(BaseTextDocument *doc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (doc) { | 
					
						
							|  |  |  |         d->setupDocumentSignals(doc); | 
					
						
							|  |  |  |         d->m_document = doc; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::memorizeCursorPosition() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_tempState = saveState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::restoreCursorPosition() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     restoreState(d->m_tempState); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QByteArray BaseTextEditor::saveState() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QByteArray state; | 
					
						
							|  |  |  |     QDataStream stream(&state, QIODevice::WriteOnly); | 
					
						
							|  |  |  |     stream << 0; // version number
 | 
					
						
							|  |  |  |     stream << verticalScrollBar()->value(); | 
					
						
							|  |  |  |     stream << horizontalScrollBar()->value(); | 
					
						
							|  |  |  |     int line, column; | 
					
						
							|  |  |  |     convertPosition(textCursor().position(), &line, &column); | 
					
						
							|  |  |  |     stream << line; | 
					
						
							|  |  |  |     stream << column; | 
					
						
							|  |  |  |     return state; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::restoreState(const QByteArray &state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int version; | 
					
						
							|  |  |  |     int vval; | 
					
						
							|  |  |  |     int hval; | 
					
						
							|  |  |  |     int lval; | 
					
						
							|  |  |  |     int cval; | 
					
						
							|  |  |  |     QDataStream stream(state); | 
					
						
							|  |  |  |     stream >> version; | 
					
						
							|  |  |  |     stream >> vval; | 
					
						
							|  |  |  |     stream >> hval; | 
					
						
							|  |  |  |     stream >> lval; | 
					
						
							|  |  |  |     stream >> cval; | 
					
						
							| 
									
										
										
										
											2009-03-19 15:01:12 +01:00
										 |  |  |     d->m_lastCursorChangeWasInteresting = false; // avoid adding last position to history
 | 
					
						
							|  |  |  |     gotoLine(lval, cval); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     verticalScrollBar()->setValue(vval); | 
					
						
							|  |  |  |     horizontalScrollBar()->setValue(hval); | 
					
						
							| 
									
										
										
										
											2009-03-19 15:01:12 +01:00
										 |  |  |     saveCurrentCursorPositionForNavigation(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setDefaultPath(const QString &defaultPath) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     baseTextDocument()->setDefaultPath(defaultPath); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setSuggestedFileName(const QString &suggestedFileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     baseTextDocument()->setSuggestedFileName(suggestedFileName); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setParenthesesMatchingEnabled(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_parenthesesMatchingEnabled = b; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::isParenthesesMatchingEnabled() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_parenthesesMatchingEnabled; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setHighlightCurrentLine(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_highlightCurrentLine = b; | 
					
						
							| 
									
										
										
										
											2009-07-15 16:10:15 +02:00
										 |  |  |     updateCurrentLineHighlight(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::highlightCurrentLine() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_highlightCurrentLine; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setLineNumbersVisible(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_lineNumbersVisible = b; | 
					
						
							|  |  |  |     slotUpdateExtraAreaWidth(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::lineNumbersVisible() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_lineNumbersVisible; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setMarksVisible(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_marksVisible = b; | 
					
						
							|  |  |  |     slotUpdateExtraAreaWidth(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::marksVisible() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_marksVisible; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setRequestMarkEnabled(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_requestMarkEnabled = b; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::requestMarkEnabled() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_requestMarkEnabled; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setLineSeparatorsAllowed(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_lineSeparatorsAllowed = b; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::lineSeparatorsAllowed() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_lineSeparatorsAllowed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setCodeFoldingVisible(bool b) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-16 17:23:50 +01:00
										 |  |  |     d->m_codeFoldingVisible = b && d->m_codeFoldingSupported; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     slotUpdateExtraAreaWidth(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::codeFoldingVisible() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_codeFoldingVisible; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-16 17:23:50 +01:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Sets whether code folding is supported by the syntax highlighter. When not | 
					
						
							|  |  |  |  * supported (the default), this makes sure the code folding is not shown. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Needs to be called before calling setCodeFoldingVisible. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void BaseTextEditor::setCodeFoldingSupported(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_codeFoldingSupported = b; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::codeFoldingSupported() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_codeFoldingSupported; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void BaseTextEditor::setRevisionsVisible(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_revisionsVisible = b; | 
					
						
							|  |  |  |     slotUpdateExtraAreaWidth(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::revisionsVisible() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_revisionsVisible; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setVisibleWrapColumn(int column) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_visibleWrapColumn = column; | 
					
						
							|  |  |  |     viewport()->update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BaseTextEditor::visibleWrapColumn() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_visibleWrapColumn; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //--------- BaseTextEditorPrivate -----------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BaseTextEditorPrivate::BaseTextEditorPrivate() | 
					
						
							|  |  |  |     : | 
					
						
							|  |  |  |     m_contentsChanged(false), | 
					
						
							| 
									
										
										
										
											2009-03-19 14:18:26 +01:00
										 |  |  |     m_lastCursorChangeWasInteresting(false), | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     m_document(new BaseTextDocument()), | 
					
						
							|  |  |  |     m_parenthesesMatchingEnabled(false), | 
					
						
							|  |  |  |     m_extraArea(0), | 
					
						
							| 
									
										
										
										
											2009-03-25 11:38:54 +01:00
										 |  |  |     m_mouseOnCollapsedMarker(false), | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     m_marksVisible(false), | 
					
						
							|  |  |  |     m_codeFoldingVisible(false), | 
					
						
							| 
									
										
										
										
											2009-03-16 17:23:50 +01:00
										 |  |  |     m_codeFoldingSupported(false), | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     m_revisionsVisible(false), | 
					
						
							|  |  |  |     m_lineNumbersVisible(true), | 
					
						
							|  |  |  |     m_highlightCurrentLine(true), | 
					
						
							|  |  |  |     m_requestMarkEnabled(true), | 
					
						
							|  |  |  |     m_lineSeparatorsAllowed(false), | 
					
						
							|  |  |  |     m_visibleWrapColumn(0), | 
					
						
							|  |  |  |     m_editable(0), | 
					
						
							|  |  |  |     m_actionHack(0), | 
					
						
							|  |  |  |     m_inBlockSelectionMode(false), | 
					
						
							|  |  |  |     m_lastEventWasBlockSelectionEvent(false), | 
					
						
							| 
									
										
										
										
											2009-04-23 19:24:57 +02:00
										 |  |  |     m_blockSelectionExtraX(0), | 
					
						
							|  |  |  |     m_moveLineUndoHack(false) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BaseTextEditorPrivate::~BaseTextEditorPrivate() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorPrivate::setupDocumentSignals(BaseTextDocument *document) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BaseTextDocument *oldDocument = q->baseTextDocument(); | 
					
						
							|  |  |  |     if (oldDocument) { | 
					
						
							|  |  |  |         q->disconnect(oldDocument->document(), 0, q, 0); | 
					
						
							|  |  |  |         q->disconnect(oldDocument, 0, q, 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextDocument *doc = document->document(); | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout()); | 
					
						
							|  |  |  |     if (!documentLayout) { | 
					
						
							|  |  |  |         QTextOption opt = doc->defaultTextOption(); | 
					
						
							|  |  |  |         opt.setTextDirection(Qt::LeftToRight); | 
					
						
							|  |  |  |         opt.setFlags(opt.flags() | QTextOption::IncludeTrailingSpaces | 
					
						
							|  |  |  |                 | QTextOption::AddSpaceForLineAndParagraphSeparators | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |         doc->setDefaultTextOption(opt); | 
					
						
							|  |  |  |         documentLayout = new TextEditDocumentLayout(doc); | 
					
						
							|  |  |  |         doc->setDocumentLayout(documentLayout); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     q->setDocument(doc); | 
					
						
							|  |  |  |     QObject::connect(documentLayout, SIGNAL(updateBlock(QTextBlock)), q, SLOT(slotUpdateBlockNotify(QTextBlock))); | 
					
						
							|  |  |  |     QObject::connect(q, SIGNAL(requestBlockUpdate(QTextBlock)), documentLayout, SIGNAL(updateBlock(QTextBlock))); | 
					
						
							|  |  |  |     QObject::connect(doc, SIGNAL(modificationChanged(bool)), q, SIGNAL(changed())); | 
					
						
							|  |  |  |     QObject::connect(doc, SIGNAL(contentsChange(int,int,int)), q, | 
					
						
							|  |  |  |         SLOT(editorContentsChange(int,int,int)), Qt::DirectConnection); | 
					
						
							|  |  |  |     QObject::connect(document, SIGNAL(changed()), q, SIGNAL(changed())); | 
					
						
							|  |  |  |     QObject::connect(document, SIGNAL(titleChanged(QString)), q, SLOT(setDisplayName(const QString &))); | 
					
						
							|  |  |  |     QObject::connect(document, SIGNAL(aboutToReload()), q, SLOT(memorizeCursorPosition())); | 
					
						
							|  |  |  |     QObject::connect(document, SIGNAL(reloaded()), q, SLOT(restoreCursorPosition())); | 
					
						
							|  |  |  |     q->slotUpdateExtraAreaWidth(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Parenthesis::hasClosingCollapse(const Parentheses &parentheses) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return closeCollapseAtPos(parentheses) >= 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Parenthesis::closeCollapseAtPos(const Parentheses &parentheses) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int depth = 0; | 
					
						
							|  |  |  |     for (int i = 0; i < parentheses.size(); ++i) { | 
					
						
							|  |  |  |         const Parenthesis &p = parentheses.at(i); | 
					
						
							|  |  |  |         if (p.chr == QLatin1Char('{') || p.chr == QLatin1Char('+')) { | 
					
						
							|  |  |  |             ++depth; | 
					
						
							|  |  |  |         } else if (p.chr == QLatin1Char('}') || p.chr == QLatin1Char('-')) { | 
					
						
							|  |  |  |             if (--depth < 0) | 
					
						
							|  |  |  |                 return p.pos; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Parenthesis::collapseAtPos(const Parentheses &parentheses, QChar *character) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int result = -1; | 
					
						
							|  |  |  |     QChar c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int depth = 0; | 
					
						
							|  |  |  |     for (int i = 0; i < parentheses.size(); ++i) { | 
					
						
							|  |  |  |         const Parenthesis &p = parentheses.at(i); | 
					
						
							|  |  |  |         if (p.chr == QLatin1Char('{') || p.chr == QLatin1Char('+')) { | 
					
						
							|  |  |  |             if (depth == 0) { | 
					
						
							|  |  |  |                 result = p.pos; | 
					
						
							|  |  |  |                 c = p.chr; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             ++depth; | 
					
						
							|  |  |  |         } else if (p.chr == QLatin1Char('}') || p.chr == QLatin1Char('-')) { | 
					
						
							|  |  |  |             if (--depth < 0) | 
					
						
							|  |  |  |                 depth = 0; | 
					
						
							|  |  |  |             result = -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (result >= 0 && character) | 
					
						
							|  |  |  |         *character = c; | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int TextBlockUserData::collapseAtPos() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return Parenthesis::collapseAtPos(m_parentheses); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TextEditDocumentLayout::setParentheses(const QTextBlock &block, const Parentheses &parentheses) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (parentheses.isEmpty()) { | 
					
						
							|  |  |  |         if (TextBlockUserData *userData = testUserData(block)) | 
					
						
							|  |  |  |             userData->clearParentheses(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         userData(block)->setParentheses(parentheses); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parentheses TextEditDocumentLayout::parentheses(const QTextBlock &block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (TextBlockUserData *userData = testUserData(block)) | 
					
						
							|  |  |  |         return userData->parentheses(); | 
					
						
							|  |  |  |     return Parentheses(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TextEditDocumentLayout::hasParentheses(const QTextBlock &block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (TextBlockUserData *userData = testUserData(block)) | 
					
						
							|  |  |  |         return userData->hasParentheses(); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TextEditDocumentLayout::setIfdefedOut(const QTextBlock &block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return userData(block)->setIfdefedOut(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TextEditDocumentLayout::clearIfdefedOut(const QTextBlock &block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (TextBlockUserData *userData = testUserData(block)) | 
					
						
							|  |  |  |         return userData->clearIfdefedOut(); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TextEditDocumentLayout::ifdefedOut(const QTextBlock &block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (TextBlockUserData *userData = testUserData(block)) | 
					
						
							|  |  |  |         return userData->ifdefedOut(); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TextEditDocumentLayout::TextEditDocumentLayout(QTextDocument *doc) | 
					
						
							|  |  |  |     :QPlainTextDocumentLayout(doc) { | 
					
						
							|  |  |  |     lastSaveRevision = 0; | 
					
						
							|  |  |  |     hasMarks = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TextEditDocumentLayout::~TextEditDocumentLayout() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QRectF TextEditDocumentLayout::blockBoundingRect(const QTextBlock &block) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QRectF r = QPlainTextDocumentLayout::blockBoundingRect(block); | 
					
						
							|  |  |  |     return r; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::viewportEvent(QEvent *event) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-19 14:18:26 +01:00
										 |  |  |     d->m_contentsChanged = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     if (event->type() == QEvent::ContextMenu) { | 
					
						
							|  |  |  |         const QContextMenuEvent *ce = static_cast<QContextMenuEvent*>(event); | 
					
						
							|  |  |  |         if (ce->reason() == QContextMenuEvent::Mouse && !textCursor().hasSelection()) | 
					
						
							|  |  |  |             setTextCursor(cursorForPosition(ce->pos())); | 
					
						
							|  |  |  |     } else if (event->type() == QEvent::ToolTip) { | 
					
						
							|  |  |  |         const QHelpEvent *he = static_cast<QHelpEvent*>(event); | 
					
						
							| 
									
										
										
										
											2009-04-24 18:16:30 +02:00
										 |  |  |         if (QApplication::keyboardModifiers() & Qt::ControlModifier) | 
					
						
							|  |  |  |             return true; // eat tooltip event when control is pressed
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         const QPoint &pos = he->pos(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Allow plugins to show tooltips
 | 
					
						
							|  |  |  |         const QTextCursor &c = cursorForPosition(pos); | 
					
						
							|  |  |  |         QPoint cursorPos = mapToGlobal(cursorRect(c).bottomRight() + QPoint(1,1)); | 
					
						
							|  |  |  |         cursorPos.setX(cursorPos.x() + d->m_extraArea->width()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         editableInterface(); // create if necessary
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         emit d->m_editable->tooltipRequested(editableInterface(), cursorPos, c.position()); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return QPlainTextEdit::viewportEvent(event); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::resizeEvent(QResizeEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QPlainTextEdit::resizeEvent(e); | 
					
						
							|  |  |  |     QRect cr = viewport()->rect(); | 
					
						
							|  |  |  |     d->m_extraArea->setGeometry( | 
					
						
							|  |  |  |         QStyle::visualRect(layoutDirection(), cr, | 
					
						
							|  |  |  |                            QRect(cr.left(), cr.top(), extraAreaWidth(), cr.height()))); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  | QRect BaseTextEditor::collapseBox() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |     if (d->m_highlightBlocksInfo.isEmpty() || d->extraAreaHighlightCollapseBlockNumber < 0) | 
					
						
							|  |  |  |         return QRect(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |     QTextBlock begin = document()->findBlockByNumber(d->m_highlightBlocksInfo.open.last()); | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 12:04:40 +02:00
										 |  |  |     if (TextBlockUserData::hasCollapseAfter(begin.previous())) | 
					
						
							|  |  |  |         begin = begin.previous(); | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-27 14:10:54 +02:00
										 |  |  |     QTextBlock end = document()->findBlockByNumber(d->m_highlightBlocksInfo.close.first()); | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |     if (!begin.isValid() || !end.isValid()) | 
					
						
							|  |  |  |         return QRect(); | 
					
						
							|  |  |  |     QRectF br = blockBoundingGeometry(begin).translated(contentOffset()); | 
					
						
							|  |  |  |     QRectF er = blockBoundingGeometry(end).translated(contentOffset()); | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return QRect(d->m_extraArea->width() - collapseBoxWidth(fontMetrics()), | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                  int(br.top()), | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  |                  collapseBoxWidth(fontMetrics()), | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                  er.bottom() - br.top()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QTextBlock BaseTextEditor::collapsedBlockAt(const QPoint &pos, QRect *box) const { | 
					
						
							|  |  |  |     QPointF offset(contentOffset()); | 
					
						
							|  |  |  |     QTextBlock block = firstVisibleBlock(); | 
					
						
							|  |  |  |     int top = (int)blockBoundingGeometry(block).translated(offset).top(); | 
					
						
							|  |  |  |     int bottom = top + (int)blockBoundingRect(block).height(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int viewportHeight = viewport()->height(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (block.isValid() && top <= viewportHeight) { | 
					
						
							|  |  |  |         QTextBlock nextBlock = block.next(); | 
					
						
							|  |  |  |         if (block.isVisible() && bottom >= 0) { | 
					
						
							|  |  |  |             if (nextBlock.isValid() && !nextBlock.isVisible()) { | 
					
						
							|  |  |  |                 QTextLayout *layout = block.layout(); | 
					
						
							|  |  |  |                 QTextLine line = layout->lineAt(layout->lineCount()-1); | 
					
						
							|  |  |  |                 QRectF lineRect = line.naturalTextRect().translated(offset.x(), top); | 
					
						
							|  |  |  |                 lineRect.adjust(0, 0, -1, -1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 QRectF collapseRect(lineRect.right() + 12, | 
					
						
							|  |  |  |                                     lineRect.top(), | 
					
						
							|  |  |  |                                     fontMetrics().width(QLatin1String(" {...}; ")), | 
					
						
							|  |  |  |                                     lineRect.height()); | 
					
						
							|  |  |  |                 if (collapseRect.contains(pos)) { | 
					
						
							|  |  |  |                     QTextBlock result = block; | 
					
						
							|  |  |  |                     if (box) | 
					
						
							|  |  |  |                         *box = collapseRect.toAlignedRect(); | 
					
						
							|  |  |  |                     return result; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     block = nextBlock; | 
					
						
							|  |  |  |                     while (nextBlock.isValid() && !nextBlock.isVisible()) { | 
					
						
							|  |  |  |                         block = nextBlock; | 
					
						
							|  |  |  |                         nextBlock = block.next(); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         block = nextBlock; | 
					
						
							|  |  |  |         top = bottom; | 
					
						
							|  |  |  |         bottom = top + (int)blockBoundingRect(block).height(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return QTextBlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorPrivate::highlightSearchResults(const QTextBlock &block, | 
					
						
							|  |  |  |                                                    QVector<QTextLayout::FormatRange> *selections) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_searchExpr.isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString text = block.text(); | 
					
						
							|  |  |  |     text.replace(QChar::Nbsp, QLatin1Char(' ')); | 
					
						
							|  |  |  |     int idx = -1; | 
					
						
							|  |  |  |     while (idx < text.length()) { | 
					
						
							|  |  |  |         idx = m_searchExpr.indexIn(text, idx + 1); | 
					
						
							|  |  |  |         if (idx < 0) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         int l = m_searchExpr.matchedLength(); | 
					
						
							| 
									
										
										
										
											2009-05-29 16:12:19 +02:00
										 |  |  |         if ((m_findFlags & Find::IFindSupport::FindWholeWords) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             && ((idx && text.at(idx-1).isLetterOrNumber()) | 
					
						
							|  |  |  |                 || (idx + l < text.length() && text.at(idx + l).isLetterOrNumber()))) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (m_findScope.isNull() | 
					
						
							|  |  |  |             || (block.position() + idx >= m_findScope.selectionStart() | 
					
						
							|  |  |  |                 && block.position() + idx + l <= m_findScope.selectionEnd())) { | 
					
						
							|  |  |  |             QTextLayout::FormatRange selection; | 
					
						
							|  |  |  |             selection.start = idx; | 
					
						
							|  |  |  |             selection.length = l; | 
					
						
							|  |  |  |             selection.format = m_searchResultFormat; | 
					
						
							|  |  |  |             selections->append(selection); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace TextEditor { | 
					
						
							|  |  |  |     namespace Internal { | 
					
						
							|  |  |  |         struct BlockSelectionData { | 
					
						
							|  |  |  |             int selectionIndex; | 
					
						
							|  |  |  |             int selectionStart; | 
					
						
							|  |  |  |             int selectionEnd; | 
					
						
							|  |  |  |             int firstColumn; | 
					
						
							|  |  |  |             int lastColumn; | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorPrivate::clearBlockSelection() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_inBlockSelectionMode) { | 
					
						
							|  |  |  |         m_inBlockSelectionMode = false; | 
					
						
							|  |  |  |         QTextCursor cursor = q->textCursor(); | 
					
						
							|  |  |  |         cursor.clearSelection(); | 
					
						
							|  |  |  |         q->setTextCursor(cursor); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString BaseTextEditorPrivate::copyBlockSelection() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString text; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextCursor cursor = q->textCursor(); | 
					
						
							|  |  |  |     if (!cursor.hasSelection()) | 
					
						
							|  |  |  |         return text; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextDocument *doc = q->document(); | 
					
						
							|  |  |  |     int start = cursor.selectionStart(); | 
					
						
							|  |  |  |     int end = cursor.selectionEnd(); | 
					
						
							|  |  |  |     QTextBlock startBlock = doc->findBlock(start); | 
					
						
							|  |  |  |     int columnA = start - startBlock.position(); | 
					
						
							|  |  |  |     QTextBlock endBlock = doc->findBlock(end); | 
					
						
							|  |  |  |     int columnB = end - endBlock.position(); | 
					
						
							|  |  |  |     int firstColumn = qMin(columnA, columnB); | 
					
						
							|  |  |  |     int lastColumn = qMax(columnA, columnB) + m_blockSelectionExtraX; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextBlock block = startBlock; | 
					
						
							|  |  |  |     for (;;) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cursor.setPosition(block.position() + qMin(block.length()-1, firstColumn)); | 
					
						
							|  |  |  |         cursor.setPosition(block.position() + qMin(block.length()-1, lastColumn), QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |         text += cursor.selectedText(); | 
					
						
							|  |  |  |         if (block == endBlock) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         text += QLatin1Char('\n'); | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return text; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorPrivate::removeBlockSelection(const QString &text) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = q->textCursor(); | 
					
						
							|  |  |  |     if (!cursor.hasSelection()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextDocument *doc = q->document(); | 
					
						
							|  |  |  |     int start = cursor.selectionStart(); | 
					
						
							|  |  |  |     int end = cursor.selectionEnd(); | 
					
						
							|  |  |  |     QTextBlock startBlock = doc->findBlock(start); | 
					
						
							|  |  |  |     int columnA = start - startBlock.position(); | 
					
						
							|  |  |  |     QTextBlock endBlock = doc->findBlock(end); | 
					
						
							|  |  |  |     int columnB = end - endBlock.position(); | 
					
						
							|  |  |  |     int firstColumn = qMin(columnA, columnB); | 
					
						
							|  |  |  |     int lastColumn = qMax(columnA, columnB) + m_blockSelectionExtraX; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cursor.clearSelection(); | 
					
						
							|  |  |  |     cursor.beginEditBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextBlock block = startBlock; | 
					
						
							|  |  |  |     for (;;) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cursor.setPosition(block.position() + qMin(block.length()-1, firstColumn)); | 
					
						
							|  |  |  |         cursor.setPosition(block.position() + qMin(block.length()-1, lastColumn), QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |         cursor.removeSelectedText(); | 
					
						
							|  |  |  |         if (block == endBlock) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cursor.setPosition(start); | 
					
						
							|  |  |  |     if (!text.isEmpty()) | 
					
						
							|  |  |  |         cursor.insertText(text); | 
					
						
							|  |  |  |     cursor.endEditBlock(); | 
					
						
							|  |  |  |     q->setTextCursor(cursor); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | void BaseTextEditorPrivate::moveCursorVisible(bool ensureVisible) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = q->textCursor(); | 
					
						
							|  |  |  |     if (!cursor.block().isVisible()) { | 
					
						
							|  |  |  |         cursor.setVisualNavigation(true); | 
					
						
							|  |  |  |         cursor.movePosition(QTextCursor::Up); | 
					
						
							|  |  |  |         q->setTextCursor(cursor); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ensureVisible) | 
					
						
							|  |  |  |         q->ensureCursorVisible(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-22 20:04:38 +02:00
										 |  |  | static QColor calcBlendColor(const QColor &baseColor, int factor = 1) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |     const int blendBase = (baseColor.value() > 128) ? 0 : 255; | 
					
						
							| 
									
										
										
										
											2009-04-22 20:04:38 +02:00
										 |  |  |     // Darker backgrounds may need a bit more contrast
 | 
					
						
							| 
									
										
										
										
											2009-04-28 12:55:31 +02:00
										 |  |  |     const int blendFactor = (baseColor.value() > 128) ? 16 : 32; | 
					
						
							| 
									
										
										
										
											2009-04-22 20:04:38 +02:00
										 |  |  |     QColor blendColor = baseColor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (factor--) { | 
					
						
							|  |  |  |         blendColor = QColor( | 
					
						
							| 
									
										
										
										
											2009-04-28 11:43:13 +02:00
										 |  |  |                 (blendBase * blendFactor + blendColor.red() * (256 - blendFactor)) / 256, | 
					
						
							| 
									
										
										
										
											2009-04-22 20:04:38 +02:00
										 |  |  |                 (blendBase * blendFactor + blendColor.green() * (256 - blendFactor)) / 256, | 
					
						
							|  |  |  |                 (blendBase * blendFactor + blendColor.blue() * (256 - blendFactor)) / 256); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return blendColor; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 11:43:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | static QColor calcBlendColor(const QColor &baseColor, int level, int count) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QColor color80; | 
					
						
							|  |  |  |     QColor color90; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (baseColor.value() > 128) { | 
					
						
							| 
									
										
										
										
											2009-07-20 18:22:55 +02:00
										 |  |  |         const int f90 = 15; | 
					
						
							|  |  |  |         const int f80 = 30; | 
					
						
							|  |  |  |         color80.setRgb(qMax(0, baseColor.red() - f80), | 
					
						
							|  |  |  |                        qMax(0, baseColor.green() - f80), | 
					
						
							|  |  |  |                        qMax(0, baseColor.blue() - f80)); | 
					
						
							|  |  |  |         color90.setRgb(qMax(0, baseColor.red() - f90), | 
					
						
							|  |  |  |                        qMax(0, baseColor.green() - f90), | 
					
						
							|  |  |  |                        qMax(0, baseColor.blue() - f90)); | 
					
						
							| 
									
										
										
										
											2009-04-28 11:43:13 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-07-20 18:22:55 +02:00
										 |  |  |         const int f90 = 20; | 
					
						
							|  |  |  |         const int f80 = 40; | 
					
						
							|  |  |  |         color80.setRgb(qMin(255, baseColor.red() + f80), | 
					
						
							|  |  |  |                        qMin(255, baseColor.green() + f80), | 
					
						
							|  |  |  |                        qMin(255, baseColor.blue() + f80)); | 
					
						
							|  |  |  |         color90.setRgb(qMin(255, baseColor.red() + f90), | 
					
						
							|  |  |  |                        qMin(255, baseColor.green() + f90), | 
					
						
							|  |  |  |                        qMin(255, baseColor.blue() + f90)); | 
					
						
							| 
									
										
										
										
											2009-04-28 11:43:13 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (level == count) | 
					
						
							|  |  |  |         return baseColor; | 
					
						
							|  |  |  |     if (level == 0) | 
					
						
							|  |  |  |         return color80; | 
					
						
							|  |  |  |     if (level == count - 1) | 
					
						
							|  |  |  |         return color90; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int blendFactor = level * (256 / (count - 2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return QColor( | 
					
						
							|  |  |  |                 (color90.red() * blendFactor + color80.red() * (256 - blendFactor)) / 256, | 
					
						
							|  |  |  |                 (color90.green() * blendFactor + color80.green() * (256 - blendFactor)) / 256, | 
					
						
							|  |  |  |                 (color90.blue() * blendFactor + color80.blue() * (256 - blendFactor)) / 256); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void BaseTextEditor::paintEvent(QPaintEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |       Here comes an almost verbatim copy of | 
					
						
							|  |  |  |       QPlainTextEdit::paintEvent() so we can adjust the extra | 
					
						
							|  |  |  |       selections dynamically to indicate all search results. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     //begin QPlainTextEdit::paintEvent()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QPainter painter(viewport()); | 
					
						
							|  |  |  |     QTextDocument *doc = document(); | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout()); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(documentLayout, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QPointF offset(contentOffset()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 13:46:50 +02:00
										 |  |  |     bool hasMainSelection = textCursor().hasSelection(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QRect er = e->rect(); | 
					
						
							|  |  |  |     QRect viewportRect = viewport()->rect(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-09 12:10:26 +01:00
										 |  |  |     const QColor baseColor = palette().base().color(); | 
					
						
							| 
									
										
										
										
											2009-04-22 20:04:38 +02:00
										 |  |  |     const QColor blendColor = calcBlendColor(baseColor); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 11:33:59 +02:00
										 |  |  |     qreal lineX = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-09 12:10:26 +01:00
										 |  |  |     if (d->m_visibleWrapColumn > 0) { | 
					
						
							| 
									
										
										
										
											2009-05-04 11:33:59 +02:00
										 |  |  |         lineX = fontMetrics().averageCharWidth() * d->m_visibleWrapColumn + offset.x() + 4; | 
					
						
							| 
									
										
										
										
											2008-12-09 12:10:26 +01:00
										 |  |  |         painter.fillRect(QRectF(lineX, 0, viewportRect.width() - lineX, viewportRect.height()), blendColor); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-04 11:33:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-23 20:11:00 +02:00
										 |  |  | //    // keep right margin clean from full-width selection
 | 
					
						
							|  |  |  | //    int maxX = offset.x() + qMax((qreal)viewportRect.width(), documentLayout->documentSize().width())
 | 
					
						
							|  |  |  | //               - doc->documentMargin();
 | 
					
						
							|  |  |  | //    er.setRight(qMin(er.right(), maxX));
 | 
					
						
							|  |  |  | //    painter.setClipRect(er);
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool editable = !isReadOnly(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextBlock block = firstVisibleBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QAbstractTextDocumentLayout::PaintContext context = getPaintContext(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!d->m_findScope.isNull()) { | 
					
						
							|  |  |  |         QAbstractTextDocumentLayout::Selection selection; | 
					
						
							|  |  |  |         selection.format.setBackground(d->m_searchScopeFormat.background()); | 
					
						
							|  |  |  |         selection.cursor = d->m_findScope; | 
					
						
							|  |  |  |         context.selections.prepend(selection); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BlockSelectionData *blockSelection = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (d->m_inBlockSelectionMode | 
					
						
							|  |  |  |         && context.selections.count() && context.selections.last().cursor == textCursor()) { | 
					
						
							|  |  |  |         blockSelection = new BlockSelectionData; | 
					
						
							|  |  |  |         blockSelection->selectionIndex = context.selections.size()-1; | 
					
						
							|  |  |  |         const QAbstractTextDocumentLayout::Selection &selection = context.selections[blockSelection->selectionIndex]; | 
					
						
							|  |  |  |         int start = blockSelection->selectionStart = selection.cursor.selectionStart(); | 
					
						
							|  |  |  |         int end = blockSelection->selectionEnd = selection.cursor.selectionEnd(); | 
					
						
							|  |  |  |         QTextBlock block = doc->findBlock(start); | 
					
						
							|  |  |  |         int columnA = start - block.position(); | 
					
						
							|  |  |  |         block = doc->findBlock(end); | 
					
						
							|  |  |  |         int columnB = end - block.position(); | 
					
						
							|  |  |  |         blockSelection->firstColumn = qMin(columnA, columnB); | 
					
						
							|  |  |  |         blockSelection->lastColumn = qMax(columnA, columnB) + d->m_blockSelectionExtraX; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextBlock visibleCollapsedBlock; | 
					
						
							|  |  |  |     QPointF visibleCollapsedBlockOffset; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QRectF r = blockBoundingRect(block).translated(offset); | 
					
						
							| 
									
										
										
										
											2009-05-28 11:11:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |         if (!d->m_highlightBlocksInfo.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             int n = block.blockNumber(); | 
					
						
							|  |  |  |             int depth = 0; | 
					
						
							|  |  |  |             foreach (int i, d->m_highlightBlocksInfo.open) | 
					
						
							|  |  |  |                 if (n >= i) | 
					
						
							|  |  |  |                     ++depth; | 
					
						
							|  |  |  |             foreach (int i, d->m_highlightBlocksInfo.close) | 
					
						
							|  |  |  |                 if (n > i) | 
					
						
							|  |  |  |                     --depth; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 11:43:13 +02:00
										 |  |  |             int count = d->m_highlightBlocksInfo.count(); | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |             if (count) { | 
					
						
							| 
									
										
										
										
											2009-04-23 20:11:00 +02:00
										 |  |  |                 QRectF rr = r; | 
					
						
							|  |  |  |                 rr.setWidth(viewport()->width()); | 
					
						
							| 
									
										
										
										
											2009-05-04 11:33:59 +02:00
										 |  |  |                 if (lineX > 0) | 
					
						
							|  |  |  |                     rr.setRight(qMin(lineX, rr.right())); | 
					
						
							|  |  |  |                 for (int i = 0; i <= depth; ++i) { | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |                     int vi = i > 0 ? d->m_highlightBlocksInfo.visualIndent.at(i-1) : 0; | 
					
						
							| 
									
										
										
										
											2009-04-28 11:43:13 +02:00
										 |  |  |                     painter.fillRect(rr.adjusted(vi, 0, -8*i, 0), calcBlendColor(baseColor, i, count)); | 
					
						
							| 
									
										
										
										
											2009-04-22 20:04:38 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-05-28 11:11:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         QTextLayout *layout = block.layout(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextOption option = layout->textOption(); | 
					
						
							|  |  |  |         if (TextEditDocumentLayout::ifdefedOut(block)) { | 
					
						
							|  |  |  |             option.setFlags(option.flags() | QTextOption::SuppressColors); | 
					
						
							|  |  |  |             painter.setPen(d->m_ifdefedOutFormat.foreground().color()); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             option.setFlags(option.flags() & ~QTextOption::SuppressColors); | 
					
						
							|  |  |  |             painter.setPen(context.palette.text().color()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         layout->setTextOption(option); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (r.bottom() >= er.top() && r.top() <= er.bottom()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             int blpos = block.position(); | 
					
						
							|  |  |  |             int bllen = block.length(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             QVector<QTextLayout::FormatRange> selections; | 
					
						
							| 
									
										
										
										
											2009-05-04 13:46:50 +02:00
										 |  |  |             QVector<QTextLayout::FormatRange> prioritySelections; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             for (int i = 0; i < context.selections.size(); ++i) { | 
					
						
							|  |  |  |                 const QAbstractTextDocumentLayout::Selection &range = context.selections.at(i); | 
					
						
							|  |  |  |                 const int selStart = range.cursor.selectionStart() - blpos; | 
					
						
							|  |  |  |                 const int selEnd = range.cursor.selectionEnd() - blpos; | 
					
						
							|  |  |  |                 if (selStart < bllen && selEnd > 0 | 
					
						
							|  |  |  |                     && selEnd > selStart) { | 
					
						
							|  |  |  |                     QTextLayout::FormatRange o; | 
					
						
							|  |  |  |                     o.start = selStart; | 
					
						
							|  |  |  |                     o.length = selEnd - selStart; | 
					
						
							|  |  |  |                     o.format = range.format; | 
					
						
							|  |  |  |                     if (blockSelection && blockSelection->selectionIndex == i) { | 
					
						
							|  |  |  |                         o.start = qMin(blockSelection->firstColumn, bllen-1); | 
					
						
							|  |  |  |                         o.length = qMin(blockSelection->lastColumn, bllen-1) - o.start; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2009-05-04 13:46:50 +02:00
										 |  |  |                     if ((hasMainSelection && i == context.selections.size()-1) | 
					
						
							|  |  |  |                         || (o.format.foreground().style() == Qt::NoBrush | 
					
						
							|  |  |  |                         && o.format.underlineStyle() != QTextCharFormat::NoUnderline | 
					
						
							|  |  |  |                         && o.format.background() == Qt::NoBrush)) | 
					
						
							|  |  |  |                         prioritySelections.append(o); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     else | 
					
						
							|  |  |  |                         selections.append(o); | 
					
						
							|  |  |  |                 } else if (!range.cursor.hasSelection() && range.format.hasProperty(QTextFormat::FullWidthSelection) | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |                     && block.contains(range.cursor.position())) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     // for full width selections we don't require an actual selection, just
 | 
					
						
							|  |  |  |                     // a position to specify the line. that's more convenience in usage.
 | 
					
						
							|  |  |  |                     QTextLayout::FormatRange o; | 
					
						
							|  |  |  |                     QTextLine l = layout->lineForTextPosition(range.cursor.position() - blpos); | 
					
						
							|  |  |  |                     o.start = l.textStart(); | 
					
						
							|  |  |  |                     o.length = l.textLength(); | 
					
						
							|  |  |  |                     if (o.start + o.length == bllen - 1) | 
					
						
							|  |  |  |                         ++o.length; // include newline
 | 
					
						
							|  |  |  |                     o.format = range.format; | 
					
						
							| 
									
										
										
										
											2009-05-04 13:46:50 +02:00
										 |  |  |                     selections.append(o); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             d->highlightSearchResults(block, &selections); | 
					
						
							| 
									
										
										
										
											2009-05-04 13:46:50 +02:00
										 |  |  |             selections += prioritySelections; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             bool drawCursor = ((editable || true) // we want the cursor in read-only mode
 | 
					
						
							|  |  |  |                                && context.cursorPosition >= blpos | 
					
						
							|  |  |  |                                && context.cursorPosition < blpos + bllen); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             bool drawCursorAsBlock = drawCursor && overwriteMode() ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (drawCursorAsBlock) { | 
					
						
							|  |  |  |                 if (context.cursorPosition == blpos + bllen - 1) { | 
					
						
							|  |  |  |                     drawCursorAsBlock = false; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     QTextLayout::FormatRange o; | 
					
						
							|  |  |  |                     o.start = context.cursorPosition - blpos; | 
					
						
							|  |  |  |                     o.length = 1; | 
					
						
							|  |  |  |                     o.format.setForeground(palette().base()); | 
					
						
							|  |  |  |                     o.format.setBackground(palette().text()); | 
					
						
							|  |  |  |                     selections.append(o); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             layout->draw(&painter, offset, selections, er); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ((drawCursor && !drawCursorAsBlock) | 
					
						
							|  |  |  |                 || (editable && context.cursorPosition < -1 | 
					
						
							|  |  |  |                     && !layout->preeditAreaText().isEmpty())) { | 
					
						
							|  |  |  |                 int cpos = context.cursorPosition; | 
					
						
							|  |  |  |                 if (cpos < -1) | 
					
						
							|  |  |  |                     cpos = layout->preeditAreaPosition() - (cpos + 2); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     cpos -= blpos; | 
					
						
							|  |  |  |                 layout->drawCursor(&painter, offset, cpos, cursorWidth()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         offset.ry() += r.height(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (offset.y() > viewportRect.height()) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |         if (!block.isVisible()) { | 
					
						
							|  |  |  |             if (block.blockNumber() == d->visibleCollapsedBlockNumber) { | 
					
						
							|  |  |  |                 visibleCollapsedBlock = block; | 
					
						
							| 
									
										
										
										
											2009-04-28 12:55:31 +02:00
										 |  |  |                 visibleCollapsedBlockOffset = offset + QPointF(0,1); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // invisible blocks do have zero line count
 | 
					
						
							|  |  |  |             block = doc->findBlockByLineNumber(block.firstLineNumber()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (backgroundVisible() && !block.isValid() && offset.y() <= er.bottom() | 
					
						
							|  |  |  |         && (centerOnScroll() || verticalScrollBar()->maximum() == verticalScrollBar()->minimum())) { | 
					
						
							|  |  |  |         painter.fillRect(QRect(QPoint((int)er.left(), (int)offset.y()), er.bottomRight()), palette().background()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //end QPlainTextEdit::paintEvent()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     delete blockSelection; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     offset = contentOffset(); | 
					
						
							|  |  |  |     block = firstVisibleBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int top = (int)blockBoundingGeometry(block).translated(offset).top(); | 
					
						
							|  |  |  |     int bottom = top + (int)blockBoundingRect(block).height(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |     bool hasSelection = cursor.hasSelection(); | 
					
						
							|  |  |  |     int selectionStart = cursor.selectionStart(); | 
					
						
							|  |  |  |     int selectionEnd = cursor.selectionEnd(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (block.isValid() && top <= e->rect().bottom()) { | 
					
						
							|  |  |  |         QTextBlock nextBlock = block.next(); | 
					
						
							|  |  |  |         QTextBlock nextVisibleBlock = nextBlock; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!nextVisibleBlock.isVisible()) | 
					
						
							|  |  |  |             // invisible blocks do have zero line count
 | 
					
						
							|  |  |  |             nextVisibleBlock = doc->findBlockByLineNumber(nextVisibleBlock.firstLineNumber()); | 
					
						
							|  |  |  |         if (block.isVisible() && bottom >= e->rect().top()) { | 
					
						
							|  |  |  |             if (d->m_displaySettings.m_visualizeWhitespace) { | 
					
						
							|  |  |  |                 QTextLayout *layout = block.layout(); | 
					
						
							|  |  |  |                 int lineCount = layout->lineCount(); | 
					
						
							|  |  |  |                 if (lineCount >= 2 || !nextBlock.isValid()) { | 
					
						
							|  |  |  |                     painter.save(); | 
					
						
							|  |  |  |                     painter.setPen(Qt::lightGray); | 
					
						
							|  |  |  |                     for (int i = 0; i < lineCount-1; ++i) { // paint line wrap indicator
 | 
					
						
							|  |  |  |                         QTextLine line = layout->lineAt(i); | 
					
						
							|  |  |  |                         QRectF lineRect = line.naturalTextRect().translated(offset.x(), top); | 
					
						
							|  |  |  |                         QChar visualArrow((ushort)0x21b5); | 
					
						
							|  |  |  |                         painter.drawText(static_cast<int>(lineRect.right()), | 
					
						
							|  |  |  |                                          static_cast<int>(lineRect.top() + line.ascent()), visualArrow); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (!nextBlock.isValid()) { // paint EOF symbol
 | 
					
						
							|  |  |  |                         QTextLine line = layout->lineAt(lineCount-1); | 
					
						
							|  |  |  |                         QRectF lineRect = line.naturalTextRect().translated(offset.x(), top); | 
					
						
							|  |  |  |                         int h = 4; | 
					
						
							|  |  |  |                         lineRect.adjust(0, 0, -1, -1); | 
					
						
							|  |  |  |                         QPainterPath path; | 
					
						
							|  |  |  |                         QPointF pos(lineRect.topRight() + QPointF(h+4, line.ascent())); | 
					
						
							|  |  |  |                         path.moveTo(pos); | 
					
						
							|  |  |  |                         path.lineTo(pos + QPointF(-h, -h)); | 
					
						
							|  |  |  |                         path.lineTo(pos + QPointF(0, -2*h)); | 
					
						
							|  |  |  |                         path.lineTo(pos + QPointF(h, -h)); | 
					
						
							|  |  |  |                         path.closeSubpath(); | 
					
						
							|  |  |  |                         painter.setBrush(painter.pen().color()); | 
					
						
							|  |  |  |                         painter.drawPath(path); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     painter.restore(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (nextBlock.isValid() && !nextBlock.isVisible()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 bool selectThis = (hasSelection | 
					
						
							|  |  |  |                                    && nextBlock.position() >= selectionStart | 
					
						
							|  |  |  |                                    && nextBlock.position() < selectionEnd); | 
					
						
							|  |  |  |                 if (selectThis) { | 
					
						
							|  |  |  |                     painter.save(); | 
					
						
							|  |  |  |                     painter.setBrush(palette().highlight()); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 QTextLayout *layout = block.layout(); | 
					
						
							|  |  |  |                 QTextLine line = layout->lineAt(layout->lineCount()-1); | 
					
						
							|  |  |  |                 QRectF lineRect = line.naturalTextRect().translated(offset.x(), top); | 
					
						
							|  |  |  |                 lineRect.adjust(0, 0, -1, -1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 QRectF collapseRect(lineRect.right() + 12, | 
					
						
							|  |  |  |                                     lineRect.top(), | 
					
						
							|  |  |  |                                     fontMetrics().width(QLatin1String(" {...}; ")), | 
					
						
							|  |  |  |                                     lineRect.height()); | 
					
						
							|  |  |  |                 painter.setRenderHint(QPainter::Antialiasing, true); | 
					
						
							|  |  |  |                 painter.translate(.5, .5); | 
					
						
							|  |  |  |                 painter.drawRoundedRect(collapseRect.adjusted(0, 0, 0, -1), 3, 3); | 
					
						
							|  |  |  |                 painter.setRenderHint(QPainter::Antialiasing, false); | 
					
						
							|  |  |  |                 painter.translate(-.5, -.5); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 QString replacement = QLatin1String("..."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 QTextBlock info = block; | 
					
						
							|  |  |  |                 if (block.userData() | 
					
						
							|  |  |  |                     && static_cast<TextBlockUserData*>(block.userData())->collapseMode() == TextBlockUserData::CollapseAfter) | 
					
						
							|  |  |  |                     ; | 
					
						
							|  |  |  |                 else if (block.next().userData() | 
					
						
							|  |  |  |                          && static_cast<TextBlockUserData*>(block.next().userData())->collapseMode() | 
					
						
							|  |  |  |                          == TextBlockUserData::CollapseThis) { | 
					
						
							|  |  |  |                     replacement.prepend(nextBlock.text().trimmed().left(1)); | 
					
						
							|  |  |  |                     info = nextBlock; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 block = nextVisibleBlock.previous(); | 
					
						
							|  |  |  |                 if (!block.isValid()) | 
					
						
							|  |  |  |                     block = doc->lastBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (info.userData() | 
					
						
							|  |  |  |                     && static_cast<TextBlockUserData*>(info.userData())->collapseIncludesClosure()) { | 
					
						
							|  |  |  |                     QString right = block.text().trimmed(); | 
					
						
							|  |  |  |                     if (right.endsWith(QLatin1Char(';'))) { | 
					
						
							|  |  |  |                         right.chop(1); | 
					
						
							|  |  |  |                         right = right.trimmed(); | 
					
						
							|  |  |  |                         replacement.append(right.right(right.endsWith(QLatin1Char('/')) ? 2 : 1)); | 
					
						
							|  |  |  |                         replacement.append(QLatin1Char(';')); | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         replacement.append(right.right(right.endsWith(QLatin1Char('/')) ? 2 : 1)); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if (selectThis) | 
					
						
							|  |  |  |                     painter.setPen(palette().highlightedText().color()); | 
					
						
							|  |  |  |                 painter.drawText(collapseRect, Qt::AlignCenter, replacement); | 
					
						
							|  |  |  |                 if (selectThis) | 
					
						
							|  |  |  |                     painter.restore(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         block = nextVisibleBlock; | 
					
						
							|  |  |  |         top = bottom; | 
					
						
							|  |  |  |         bottom = top + (int)blockBoundingRect(block).height(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (visibleCollapsedBlock.isValid() ) { | 
					
						
							|  |  |  |         int margin = doc->documentMargin(); | 
					
						
							|  |  |  |         qreal maxWidth = 0; | 
					
						
							|  |  |  |         qreal blockHeight = 0; | 
					
						
							|  |  |  |         QTextBlock b = visibleCollapsedBlock; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while (!b.isVisible() && visibleCollapsedBlockOffset.y() + blockHeight <= e->rect().bottom()) { | 
					
						
							|  |  |  |             b.setVisible(true); // make sure block bounding rect works
 | 
					
						
							|  |  |  |             QRectF r = blockBoundingRect(b).translated(visibleCollapsedBlockOffset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             QTextLayout *layout = b.layout(); | 
					
						
							|  |  |  |             for (int i = layout->lineCount()-1; i >= 0; --i) | 
					
						
							|  |  |  |                 maxWidth = qMax(maxWidth, layout->lineAt(i).naturalTextWidth() + margin); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             blockHeight += r.height(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             b.setVisible(false); // restore previous state
 | 
					
						
							|  |  |  |             b = b.next(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         painter.save(); | 
					
						
							|  |  |  |         painter.setRenderHint(QPainter::Antialiasing, true); | 
					
						
							|  |  |  |         painter.translate(.5, .5); | 
					
						
							|  |  |  |         QColor color = blendColor; | 
					
						
							|  |  |  | //        color.setAlpha(240); // someone thinks alpha blending looks messy
 | 
					
						
							|  |  |  |         painter.setBrush(color); | 
					
						
							|  |  |  |         painter.drawRoundedRect(QRectF(visibleCollapsedBlockOffset.x(), | 
					
						
							|  |  |  |                                        visibleCollapsedBlockOffset.y(), | 
					
						
							| 
									
										
										
										
											2009-04-28 12:55:31 +02:00
										 |  |  |                                        maxWidth, blockHeight).adjusted(0, 0, 0, 0), 3, 3); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         painter.restore(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextBlock end = b; | 
					
						
							|  |  |  |         b = visibleCollapsedBlock; | 
					
						
							|  |  |  |         while (b != end) { | 
					
						
							|  |  |  |             b.setVisible(true); // make sure block bounding rect works
 | 
					
						
							|  |  |  |             QRectF r = blockBoundingRect(b).translated(visibleCollapsedBlockOffset); | 
					
						
							|  |  |  |             QTextLayout *layout = b.layout(); | 
					
						
							|  |  |  |             QVector<QTextLayout::FormatRange> selections; | 
					
						
							|  |  |  |             d->highlightSearchResults(b, &selections); | 
					
						
							|  |  |  |             layout->draw(&painter, visibleCollapsedBlockOffset, selections, er); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             b.setVisible(false); // restore previous state
 | 
					
						
							|  |  |  |             visibleCollapsedBlockOffset.ry() += r.height(); | 
					
						
							|  |  |  |             b = b.next(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 19:02:58 +02:00
										 |  |  |     if (d->m_animator && d->m_animator->isRunning()) { | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  |         QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |         cursor.setPosition(d->m_animator->position()); | 
					
						
							|  |  |  |         d->m_animator->draw(&painter, cursorRect(cursor).topLeft()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 11:33:59 +02:00
										 |  |  |     if (lineX > 0) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         const QColor bg = palette().base().color(); | 
					
						
							|  |  |  |         QColor col = (bg.value() > 128) ? Qt::black : Qt::white; | 
					
						
							|  |  |  |         col.setAlpha(32); | 
					
						
							|  |  |  |         painter.setPen(QPen(col, 0)); | 
					
						
							|  |  |  |         painter.drawLine(QPointF(lineX, 0), QPointF(lineX, viewport()->height())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QWidget *BaseTextEditor::extraArea() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_extraArea; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BaseTextEditor::extraAreaWidth(int *markWidthPtr) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(document()->documentLayout()); | 
					
						
							|  |  |  |     if (!documentLayout) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!d->m_marksVisible && documentLayout->hasMarks) | 
					
						
							|  |  |  |         d->m_marksVisible = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int space = 0; | 
					
						
							|  |  |  |     const QFontMetrics fm(d->m_extraArea->fontMetrics()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (d->m_lineNumbersVisible) { | 
					
						
							|  |  |  |         int digits = 2; | 
					
						
							|  |  |  |         int max = qMax(1, blockCount()); | 
					
						
							|  |  |  |         while (max >= 100) { | 
					
						
							|  |  |  |             max /= 10; | 
					
						
							|  |  |  |             ++digits; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         space += fm.width(QLatin1Char('9')) * digits; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int markWidth = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (d->m_marksVisible) { | 
					
						
							|  |  |  |         markWidth += fm.lineSpacing(); | 
					
						
							|  |  |  | //     if (documentLayout->doubleMarkCount)
 | 
					
						
							|  |  |  | //         markWidth += fm.lineSpacing() / 3;
 | 
					
						
							|  |  |  |         space += markWidth; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         space += 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (markWidthPtr) | 
					
						
							|  |  |  |         *markWidthPtr = markWidth; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     space += 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (d->m_codeFoldingVisible) | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  |         space += collapseBoxWidth(fm); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return space; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | void BaseTextEditor::slotUpdateExtraAreaWidth() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  |     if (isLeftToRight()) | 
					
						
							|  |  |  |         setViewportMargins(extraAreaWidth(), 0, 0, 0); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         setViewportMargins(0, 0, extraAreaWidth(), 0); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  | static void drawRectBox(QPainter *painter, const QRect &rect, bool start, bool end, | 
					
						
							|  |  |  |                         const QPalette &pal) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-29 15:31:05 +02:00
										 |  |  |     painter->save(); | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  |     painter->setRenderHint(QPainter::Antialiasing, false); | 
					
						
							| 
									
										
										
										
											2009-06-03 20:19:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QRgb b = pal.base().color().rgb(); | 
					
						
							|  |  |  |     QRgb h = pal.highlight().color().rgb(); | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  |     QColor c = StyleHelper::mergedColors(b,h, 50); | 
					
						
							| 
									
										
										
										
											2009-06-03 20:19:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-29 15:31:05 +02:00
										 |  |  |     QLinearGradient grad(rect.topLeft(), rect.topRight()); | 
					
						
							| 
									
										
										
										
											2009-06-03 20:19:47 +02:00
										 |  |  |     grad.setColorAt(0, c.lighter(110)); | 
					
						
							| 
									
										
										
										
											2009-06-05 13:59:10 +02:00
										 |  |  |     grad.setColorAt(1, c.lighter(130)); | 
					
						
							| 
									
										
										
										
											2009-06-03 20:19:47 +02:00
										 |  |  |     QColor outline = c; | 
					
						
							| 
									
										
										
										
											2009-05-29 16:50:38 +02:00
										 |  |  |     QRect r = rect; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     painter->fillRect(rect, grad); | 
					
						
							| 
									
										
										
										
											2009-05-29 15:31:05 +02:00
										 |  |  |     painter->setPen(outline); | 
					
						
							| 
									
										
										
										
											2009-05-29 16:50:38 +02:00
										 |  |  |     if (start) | 
					
						
							|  |  |  |         painter->drawLine(rect.topLeft() + QPoint(1, 0), rect.topRight() -  QPoint(1, 0)); | 
					
						
							|  |  |  |     if (end) | 
					
						
							|  |  |  |         painter->drawLine(rect.bottomLeft() + QPoint(1, 0), rect.bottomRight() -  QPoint(1, 0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     painter->drawLine(rect.topRight() + QPoint(0, start ? 1 : 0), rect.bottomRight() - QPoint(0, end ? 1 : 0)); | 
					
						
							|  |  |  |     painter->drawLine(rect.topLeft() + QPoint(0, start ? 1 : 0), rect.bottomLeft() - QPoint(0, end ? 1 : 0)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-29 15:31:05 +02:00
										 |  |  |     painter->restore(); | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextDocument *doc = document(); | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout()); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(documentLayout, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 12:55:31 +02:00
										 |  |  |     int selStart = textCursor().selectionStart(); | 
					
						
							|  |  |  |     int selEnd = textCursor().selectionEnd(); | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const QColor baseColor = palette().base().color(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QPalette pal = d->m_extraArea->palette(); | 
					
						
							|  |  |  |     pal.setCurrentColorGroup(QPalette::Active); | 
					
						
							|  |  |  |     QPainter painter(d->m_extraArea); | 
					
						
							|  |  |  |     QFontMetrics fm(painter.fontMetrics()); | 
					
						
							|  |  |  |     int fmLineSpacing = fm.lineSpacing(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int markWidth = 0; | 
					
						
							|  |  |  |     if (d->m_marksVisible) | 
					
						
							|  |  |  |         markWidth += fm.lineSpacing(); | 
					
						
							|  |  |  | //     if (documentLayout->doubleMarkCount)
 | 
					
						
							|  |  |  | //         markWidth += fm.lineSpacing() / 3;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-09 18:17:38 +02:00
										 |  |  |     const int collapseColumnWidth = d->m_codeFoldingVisible ? collapseBoxWidth(fm): 0; | 
					
						
							|  |  |  |     const int extraAreaWidth = d->m_extraArea->width() - collapseColumnWidth; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     painter.fillRect(e->rect(), pal.color(QPalette::Base)); | 
					
						
							|  |  |  |     painter.fillRect(e->rect().intersected(QRect(0, 0, extraAreaWidth, INT_MAX)), | 
					
						
							|  |  |  |                      pal.color(QPalette::Background)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextBlock block = firstVisibleBlock(); | 
					
						
							|  |  |  |     int blockNumber = block.blockNumber(); | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  |     int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     int bottom = top; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (block.isValid() && top <= e->rect().bottom()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         top = bottom; | 
					
						
							|  |  |  |         bottom = top + (int)blockBoundingRect(block).height(); | 
					
						
							|  |  |  |         QTextBlock nextBlock = block.next(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextBlock nextVisibleBlock = nextBlock; | 
					
						
							|  |  |  |         int nextVisibleBlockNumber = blockNumber + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!nextVisibleBlock.isVisible()) { | 
					
						
							|  |  |  |             // invisible blocks do have zero line count
 | 
					
						
							|  |  |  |             nextVisibleBlock = doc->findBlockByLineNumber(nextVisibleBlock.firstLineNumber()); | 
					
						
							|  |  |  |             nextVisibleBlockNumber = nextVisibleBlock.blockNumber(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         painter.setPen(pal.color(QPalette::Dark)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (d->m_codeFoldingVisible || d->m_marksVisible) { | 
					
						
							|  |  |  |             painter.save(); | 
					
						
							|  |  |  |             painter.setRenderHint(QPainter::Antialiasing, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             int previousBraceDepth = block.previous().userState(); | 
					
						
							|  |  |  |             if (previousBraceDepth >= 0) | 
					
						
							|  |  |  |                 previousBraceDepth >>= 8; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 previousBraceDepth = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             int braceDepth = block.userState(); | 
					
						
							|  |  |  |             if (!nextBlock.isVisible()) { | 
					
						
							|  |  |  |                 QTextBlock lastInvisibleBlock = nextVisibleBlock.previous(); | 
					
						
							|  |  |  |                 if (!lastInvisibleBlock.isValid()) | 
					
						
							|  |  |  |                     lastInvisibleBlock = doc->lastBlock(); | 
					
						
							|  |  |  |                 braceDepth = lastInvisibleBlock.userState(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (braceDepth >= 0) | 
					
						
							|  |  |  |                 braceDepth >>= 8; | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 braceDepth = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (TextBlockUserData *userData = static_cast<TextBlockUserData*>(block.userData())) { | 
					
						
							|  |  |  |                 if (d->m_marksVisible) { | 
					
						
							|  |  |  |                     int xoffset = 0; | 
					
						
							|  |  |  |                     foreach (ITextMark *mrk, userData->marks()) { | 
					
						
							|  |  |  |                         int x = 0; | 
					
						
							|  |  |  |                         int radius = fmLineSpacing - 1; | 
					
						
							|  |  |  |                         QRect r(x + xoffset, top, radius, radius); | 
					
						
							|  |  |  |                         mrk->icon().paint(&painter, r, Qt::AlignCenter); | 
					
						
							|  |  |  |                         xoffset += 2; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 12:04:40 +02:00
										 |  |  |             if (d->m_codeFoldingVisible) { | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 bool collapseThis = false; | 
					
						
							|  |  |  |                 bool collapseAfter = false; | 
					
						
							|  |  |  |                 bool hasClosingCollapse = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (TextBlockUserData *userData = static_cast<TextBlockUserData*>(block.userData())) { | 
					
						
							|  |  |  |                     if (!userData->ifdefedOut()) { | 
					
						
							|  |  |  |                         collapseAfter = (userData->collapseMode() == TextBlockUserData::CollapseAfter); | 
					
						
							|  |  |  |                         collapseThis = (userData->collapseMode() == TextBlockUserData::CollapseThis); | 
					
						
							|  |  |  |                         hasClosingCollapse = userData->hasClosingCollapse() && (previousBraceDepth > 0); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 int extraAreaHighlightCollapseBlockNumber = -1; | 
					
						
							|  |  |  |                 int extraAreaHighlightCollapseEndBlockNumber = -1; | 
					
						
							|  |  |  |                 bool endIsVisible = false; | 
					
						
							|  |  |  |                 if (!d->m_highlightBlocksInfo.isEmpty()) { | 
					
						
							|  |  |  |                     extraAreaHighlightCollapseBlockNumber =  d->m_highlightBlocksInfo.open.last(); | 
					
						
							|  |  |  |                     extraAreaHighlightCollapseEndBlockNumber =  d->m_highlightBlocksInfo.close.first(); | 
					
						
							|  |  |  |                     endIsVisible = doc->findBlockByNumber(extraAreaHighlightCollapseEndBlockNumber).isVisible(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 16:46:54 +02:00
										 |  |  |                     QTextBlock before = doc->findBlockByNumber(extraAreaHighlightCollapseBlockNumber-1); | 
					
						
							|  |  |  |                     if (TextBlockUserData::hasCollapseAfter(before)) { | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  |                         extraAreaHighlightCollapseBlockNumber--; | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 TextBlockUserData *nextBlockUserData = TextEditDocumentLayout::testUserData(nextBlock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 bool collapseNext = nextBlockUserData | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  |                                     && nextBlockUserData->collapseMode() == TextBlockUserData::CollapseThis | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  |                                     && !nextBlockUserData->ifdefedOut(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 bool nextHasClosingCollapse = nextBlockUserData | 
					
						
							|  |  |  |                                               && nextBlockUserData->hasClosingCollapseInside() | 
					
						
							|  |  |  |                                               && nextBlockUserData->ifdefedOut(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 bool drawBox = ((collapseAfter || collapseNext) && !nextHasClosingCollapse); | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  |                 bool active = blockNumber == extraAreaHighlightCollapseBlockNumber; | 
					
						
							|  |  |  |                 bool drawStart = drawBox && active; | 
					
						
							|  |  |  |                 bool drawEnd = blockNumber == extraAreaHighlightCollapseEndBlockNumber || (drawStart && !endIsVisible); | 
					
						
							| 
									
										
										
										
											2009-05-05 10:20:43 +02:00
										 |  |  |                 bool hovered = blockNumber >= extraAreaHighlightCollapseBlockNumber | 
					
						
							|  |  |  |                                && blockNumber <= extraAreaHighlightCollapseEndBlockNumber; | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  |                 int boxWidth = collapseBoxWidth(fm); | 
					
						
							| 
									
										
										
										
											2009-05-05 10:20:43 +02:00
										 |  |  |                 if (hovered) { | 
					
						
							| 
									
										
										
										
											2009-08-03 18:13:37 +02:00
										 |  |  |                     QRect box = QRect(extraAreaWidth + 1, top, boxWidth - 2, bottom - top); | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  |                     drawRectBox(&painter, box, drawStart, drawEnd, pal); | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (drawBox) { | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  |                     bool expanded = nextBlock.isVisible(); | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  |                     int size = boxWidth/4; | 
					
						
							|  |  |  |                     QRect box(extraAreaWidth + size, top + size, | 
					
						
							|  |  |  |                               2 * (size) + 1, 2 * (size) + 1); | 
					
						
							| 
									
										
										
										
											2009-05-05 10:20:43 +02:00
										 |  |  |                     drawFoldingMarker(&painter, pal, box, expanded, active, hovered); | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             painter.restore(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (d->m_revisionsVisible && block.revision() != documentLayout->lastSaveRevision) { | 
					
						
							|  |  |  |             painter.save(); | 
					
						
							|  |  |  |             painter.setRenderHint(QPainter::Antialiasing, false); | 
					
						
							|  |  |  |             if (block.revision() < 0) | 
					
						
							|  |  |  |                 painter.setPen(QPen(Qt::darkGreen, 2)); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 painter.setPen(QPen(Qt::red, 2)); | 
					
						
							| 
									
										
										
										
											2009-07-16 11:27:02 +02:00
										 |  |  |             painter.drawLine(extraAreaWidth - 1, top, extraAreaWidth - 1, bottom - 1); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             painter.restore(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (d->m_lineNumbersVisible) { | 
					
						
							|  |  |  |             const QString &number = QString::number(blockNumber + 1); | 
					
						
							| 
									
										
										
										
											2009-04-28 12:55:31 +02:00
										 |  |  |             bool selected = ( | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  |                     (selStart < block.position() + block.length() | 
					
						
							|  |  |  |                     && selEnd > block.position()) | 
					
						
							|  |  |  |                     || (selStart == selEnd && selStart == block.position()) | 
					
						
							| 
									
										
										
										
											2009-04-28 12:55:31 +02:00
										 |  |  |                     ); | 
					
						
							|  |  |  |             if (selected) { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                 painter.save(); | 
					
						
							| 
									
										
										
										
											2009-04-27 14:10:54 +02:00
										 |  |  |                 QFont f = painter.font(); | 
					
						
							|  |  |  |                 f.setBold(d->m_currentLineNumberFormat.font().bold()); | 
					
						
							|  |  |  |                 f.setItalic(d->m_currentLineNumberFormat.font().italic()); | 
					
						
							|  |  |  |                 painter.setFont(f); | 
					
						
							|  |  |  |                 painter.setPen(d->m_currentLineNumberFormat.foreground().color()); | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             painter.drawText(markWidth, top, extraAreaWidth - markWidth - 4, fm.height(), Qt::AlignRight, number); | 
					
						
							| 
									
										
										
										
											2009-04-28 12:55:31 +02:00
										 |  |  |             if (selected) | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                 painter.restore(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         block = nextVisibleBlock; | 
					
						
							|  |  |  |         blockNumber = nextVisibleBlockNumber; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-05 10:20:43 +02:00
										 |  |  | void BaseTextEditor::drawFoldingMarker(QPainter *painter, const QPalette &pal, | 
					
						
							|  |  |  |                                        const QRect &rect, | 
					
						
							|  |  |  |                                        bool expanded, | 
					
						
							|  |  |  |                                        bool active, | 
					
						
							|  |  |  |                                        bool hovered) const | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-07-13 17:35:17 +02:00
										 |  |  |     Q_UNUSED(active) | 
					
						
							|  |  |  |     Q_UNUSED(hovered) | 
					
						
							| 
									
										
										
										
											2009-06-08 12:07:39 +02:00
										 |  |  |     QStyle *s = style(); | 
					
						
							|  |  |  |     if (ManhattanStyle *ms = qobject_cast<ManhattanStyle*>(s)) | 
					
						
							|  |  |  |         s = ms->systemStyle(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!qstrcmp(s->metaObject()->className(), "OxygenStyle")) { | 
					
						
							|  |  |  |         painter->save(); | 
					
						
							|  |  |  |         painter->setPen(Qt::NoPen); | 
					
						
							|  |  |  |         int size = rect.size().width(); | 
					
						
							|  |  |  |         int sqsize = 2*(size/2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QColor textColor = pal.buttonText().color(); | 
					
						
							|  |  |  |         QColor brushColor = textColor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         textColor.setAlpha(100); | 
					
						
							|  |  |  |         brushColor.setAlpha(100); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QPolygon a; | 
					
						
							|  |  |  |         if (expanded) { | 
					
						
							|  |  |  |             // down arrow
 | 
					
						
							|  |  |  |             a.setPoints(3, 0, sqsize/3,  sqsize/2, sqsize  - sqsize/3,  sqsize, sqsize/3); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             // right arrow
 | 
					
						
							|  |  |  |             a.setPoints(3, sqsize - sqsize/3, sqsize/2,  sqsize/2 - sqsize/3, 0,  sqsize/2 - sqsize/3, sqsize); | 
					
						
							|  |  |  |             painter->setBrush(brushColor); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         painter->translate(0.5, 0.5); | 
					
						
							|  |  |  |         painter->setRenderHint(QPainter::Antialiasing); | 
					
						
							|  |  |  |         painter->translate(rect.topLeft()); | 
					
						
							|  |  |  |         painter->setPen(textColor); | 
					
						
							|  |  |  |         painter->setBrush(textColor); | 
					
						
							|  |  |  |         painter->drawPolygon(a); | 
					
						
							|  |  |  |         painter->restore(); | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2009-06-08 12:07:39 +02:00
										 |  |  |         QStyleOptionViewItemV2 opt; | 
					
						
							|  |  |  |         opt.rect = rect; | 
					
						
							|  |  |  |         opt.state = QStyle::State_Active | QStyle::State_Item | QStyle::State_Children; | 
					
						
							|  |  |  |         if (expanded) | 
					
						
							|  |  |  |             opt.state |= QStyle::State_Open; | 
					
						
							|  |  |  |         if (active) | 
					
						
							|  |  |  |             opt.state |= QStyle::State_MouseOver | QStyle::State_Enabled | QStyle::State_Selected; | 
					
						
							|  |  |  |         if (hovered) | 
					
						
							|  |  |  |             opt.palette.setBrush(QPalette::Window, pal.highlight()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          // QGtkStyle needs a small correction to draw the marker in the right place
 | 
					
						
							|  |  |  |         if (!qstrcmp(s->metaObject()->className(), "QGtkStyle")) | 
					
						
							|  |  |  |            opt.rect.translate(-2, 0); | 
					
						
							|  |  |  |         else if (!qstrcmp(s->metaObject()->className(), "QMacStyle")) | 
					
						
							|  |  |  |             opt.rect.translate(-1, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         s->drawPrimitive(QStyle::PE_IndicatorBranch, &opt, painter, this); | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | void BaseTextEditor::slotModificationChanged(bool m) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextDocument *doc = document(); | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout()); | 
					
						
							|  |  |  |     QTC_ASSERT(documentLayout, return); | 
					
						
							|  |  |  |     int oldLastSaveRevision = documentLayout->lastSaveRevision; | 
					
						
							|  |  |  |     documentLayout->lastSaveRevision = doc->revision(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (oldLastSaveRevision != documentLayout->lastSaveRevision) { | 
					
						
							|  |  |  |         QTextBlock block = doc->begin(); | 
					
						
							|  |  |  |         while (block.isValid()) { | 
					
						
							|  |  |  |             if (block.revision() < 0 || block.revision() != oldLastSaveRevision) { | 
					
						
							|  |  |  |                 block.setRevision(-documentLayout->lastSaveRevision - 1); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 block.setRevision(documentLayout->lastSaveRevision); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             block = block.next(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     d->m_extraArea->update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::slotUpdateRequest(const QRect &r, int dy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (dy) | 
					
						
							|  |  |  |         d->m_extraArea->scroll(0, dy); | 
					
						
							|  |  |  |     else if (r.width() > 4) { // wider than cursor width, not just cursor blinking
 | 
					
						
							|  |  |  |         d->m_extraArea->update(0, r.y(), d->m_extraArea->width(), r.height()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (r.contains(viewport()->rect())) | 
					
						
							|  |  |  |         slotUpdateExtraAreaWidth(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-19 14:18:26 +01:00
										 |  |  | void BaseTextEditor::saveCurrentCursorPositionForNavigation() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_lastCursorChangeWasInteresting = true; | 
					
						
							| 
									
										
										
										
											2009-04-02 17:56:20 +02:00
										 |  |  |     d->m_tempNavigationState = saveState(); | 
					
						
							| 
									
										
										
										
											2009-03-19 14:18:26 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-15 16:10:15 +02:00
										 |  |  | void BaseTextEditor::updateCurrentLineHighlight() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QList<QTextEdit::ExtraSelection> extraSelections; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (d->m_highlightCurrentLine) { | 
					
						
							|  |  |  |         QTextEdit::ExtraSelection sel; | 
					
						
							|  |  |  |         sel.format.setBackground(d->m_currentLineFormat.background()); | 
					
						
							|  |  |  |         sel.format.setProperty(QTextFormat::FullWidthSelection, true); | 
					
						
							|  |  |  |         sel.cursor = textCursor(); | 
					
						
							|  |  |  |         sel.cursor.clearSelection(); | 
					
						
							|  |  |  |         extraSelections.append(sel); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setExtraSelections(CurrentLineSelection, extraSelections); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | void BaseTextEditor::slotCursorPositionChanged() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-19 14:18:26 +01:00
										 |  |  |     if (!d->m_contentsChanged && d->m_lastCursorChangeWasInteresting) { | 
					
						
							| 
									
										
										
										
											2009-07-17 18:08:59 +02:00
										 |  |  |         Core::EditorManager::instance()->addCurrentPositionToNavigationHistory(editableInterface(), d->m_tempNavigationState); | 
					
						
							| 
									
										
										
										
											2009-03-19 14:18:26 +01:00
										 |  |  |         d->m_lastCursorChangeWasInteresting = false; | 
					
						
							|  |  |  |     } else if (d->m_contentsChanged) { | 
					
						
							|  |  |  |         saveCurrentCursorPositionForNavigation(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-27 13:01:28 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (d->m_parenthesesMatchingEnabled) { | 
					
						
							|  |  |  |         // Delay update when no matching is displayed yet, to avoid flicker
 | 
					
						
							|  |  |  |         if (extraSelections(ParenthesesMatchingSelection).isEmpty()) { | 
					
						
							|  |  |  |             d->m_parenthesesMatchingTimer->start(50); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2009-05-27 20:49:57 +02:00
										 |  |  |              // use 0-timer, not direct call, to give the syntax highlighter a chance
 | 
					
						
							|  |  |  |             // to update the parantheses information
 | 
					
						
							|  |  |  |             d->m_parenthesesMatchingTimer->start(0); | 
					
						
							| 
									
										
										
										
											2009-04-27 13:01:28 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-15 16:10:15 +02:00
										 |  |  |     updateCurrentLineHighlight(); | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |     if (d->m_displaySettings.m_highlightBlocks) { | 
					
						
							| 
									
										
										
										
											2009-04-27 13:01:28 +02:00
										 |  |  |         QTextCursor cursor = textCursor(); | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |         d->extraAreaHighlightCollapseBlockNumber = cursor.blockNumber(); | 
					
						
							|  |  |  |         d->extraAreaHighlightCollapseColumn = cursor.position() - cursor.block().position(); | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |         d->m_highlightBlocksTimer->start(100); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::slotUpdateBlockNotify(const QTextBlock &block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static bool blockRecursion = false; | 
					
						
							|  |  |  |     if (blockRecursion) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     if (block.previous().isValid() && block.userState() != block.previous().userState()) { | 
					
						
							|  |  |  |         /* The syntax highlighting state changes. This opens up for
 | 
					
						
							|  |  |  |            the possibility that the paragraph has braces that support | 
					
						
							|  |  |  |            code folding. In this case, do the save thing and also | 
					
						
							|  |  |  |            update the previous block, which might contain a collapse | 
					
						
							|  |  |  |            box which now is invalid.*/ | 
					
						
							|  |  |  |         blockRecursion = true; | 
					
						
							|  |  |  |         emit requestBlockUpdate(block.previous()); | 
					
						
							|  |  |  |         blockRecursion = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void BaseTextEditor::timerEvent(QTimerEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (e->timerId() == d->autoScrollTimer.timerId()) { | 
					
						
							|  |  |  |         const QPoint globalPos = QCursor::pos(); | 
					
						
							|  |  |  |         const QPoint pos = d->m_extraArea->mapFromGlobal(globalPos); | 
					
						
							|  |  |  |         QRect visible = d->m_extraArea->rect(); | 
					
						
							|  |  |  |         verticalScrollBar()->triggerAction( pos.y() < visible.center().y() ? | 
					
						
							|  |  |  |                                             QAbstractSlider::SliderSingleStepSub | 
					
						
							|  |  |  |                                             : QAbstractSlider::SliderSingleStepAdd); | 
					
						
							|  |  |  |         QMouseEvent ev(QEvent::MouseMove, pos, globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); | 
					
						
							|  |  |  |         extraAreaMouseEvent(&ev); | 
					
						
							|  |  |  |         int delta = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height(); | 
					
						
							|  |  |  |         if (delta < 7) | 
					
						
							|  |  |  |             delta = 7; | 
					
						
							|  |  |  |         int timeout = 4900 / (delta * delta); | 
					
						
							|  |  |  |         d->autoScrollTimer.start(timeout, this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } else if (e->timerId() == d->collapsedBlockTimer.timerId()) { | 
					
						
							|  |  |  |         d->visibleCollapsedBlockNumber = d->suggestedVisibleCollapsedBlockNumber; | 
					
						
							|  |  |  |         d->suggestedVisibleCollapsedBlockNumber = -1; | 
					
						
							|  |  |  |         d->collapsedBlockTimer.stop(); | 
					
						
							|  |  |  |         viewport()->update(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QPlainTextEdit::timerEvent(e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorPrivate::clearVisibleCollapsedBlock() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (suggestedVisibleCollapsedBlockNumber) { | 
					
						
							|  |  |  |         suggestedVisibleCollapsedBlockNumber = -1; | 
					
						
							|  |  |  |         collapsedBlockTimer.stop(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (visibleCollapsedBlockNumber >= 0) { | 
					
						
							|  |  |  |         visibleCollapsedBlockNumber = -1; | 
					
						
							|  |  |  |         q->viewport()->update(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::mouseMoveEvent(QMouseEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_lastEventWasBlockSelectionEvent = (e->modifiers() & Qt::AltModifier); | 
					
						
							| 
									
										
										
										
											2009-03-25 11:38:54 +01:00
										 |  |  |     if (e->buttons() == Qt::NoButton) { | 
					
						
							|  |  |  |         const QTextBlock collapsedBlock = collapsedBlockAt(e->pos()); | 
					
						
							|  |  |  |         const int blockNumber = collapsedBlock.next().blockNumber(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         if (blockNumber < 0) { | 
					
						
							|  |  |  |             d->clearVisibleCollapsedBlock(); | 
					
						
							|  |  |  |         } else if (blockNumber != d->visibleCollapsedBlockNumber) { | 
					
						
							|  |  |  |             d->suggestedVisibleCollapsedBlockNumber = blockNumber; | 
					
						
							|  |  |  |             d->collapsedBlockTimer.start(40, this); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-25 11:38:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Update the mouse cursor
 | 
					
						
							|  |  |  |         if (collapsedBlock.isValid() && !d->m_mouseOnCollapsedMarker) { | 
					
						
							|  |  |  |             d->m_mouseOnCollapsedMarker = true; | 
					
						
							|  |  |  |             viewport()->setCursor(Qt::PointingHandCursor); | 
					
						
							|  |  |  |         } else if (!collapsedBlock.isValid() && d->m_mouseOnCollapsedMarker) { | 
					
						
							|  |  |  |             d->m_mouseOnCollapsedMarker = false; | 
					
						
							|  |  |  |             viewport()->setCursor(Qt::IBeamCursor); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         QPlainTextEdit::mouseMoveEvent(e); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (d->m_lastEventWasBlockSelectionEvent && d->m_inBlockSelectionMode) { | 
					
						
							|  |  |  |         if (textCursor().atBlockEnd()) { | 
					
						
							| 
									
										
										
										
											2009-03-25 11:38:54 +01:00
										 |  |  |             d->m_blockSelectionExtraX = qMax(0, e->pos().x() - cursorRect().center().x()) / fontMetrics().averageCharWidth(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             d->m_blockSelectionExtraX = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-06-12 12:38:27 +02:00
										 |  |  |     if (viewport()->cursor().shape() == Qt::BlankCursor) | 
					
						
							|  |  |  |         viewport()->setCursor(Qt::IBeamCursor); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::mousePressEvent(QMouseEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (e->button() == Qt::LeftButton) { | 
					
						
							|  |  |  |         d->clearBlockSelection(); // just in case, otherwise we might get strange drag and drop
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextBlock collapsedBlock = collapsedBlockAt(e->pos()); | 
					
						
							|  |  |  |         if (collapsedBlock.isValid()) { | 
					
						
							|  |  |  |             toggleBlockVisible(collapsedBlock); | 
					
						
							|  |  |  |             viewport()->setCursor(Qt::IBeamCursor); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QPlainTextEdit::mousePressEvent(e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::extraAreaLeaveEvent(QEvent *) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |     // fake missing mouse move event from Qt
 | 
					
						
							|  |  |  |     QMouseEvent me(QEvent::MouseMove, QPoint(-1, -1), Qt::NoButton, 0, 0); | 
					
						
							|  |  |  |     extraAreaMouseEvent(&me); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = cursorForPosition(QPoint(0, e->pos().y())); | 
					
						
							|  |  |  |     cursor.setPosition(cursor.block().position()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int markWidth; | 
					
						
							|  |  |  |     extraAreaWidth(&markWidth); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |     if (d->m_codeFoldingVisible | 
					
						
							|  |  |  |         && e->type() == QEvent::MouseMove && e->buttons() == 0) { // mouse tracking
 | 
					
						
							| 
									
										
										
										
											2008-12-15 16:09:42 +01:00
										 |  |  |         // Update which folder marker is highlighted
 | 
					
						
							|  |  |  |         const int highlightBlockNumber = d->extraAreaHighlightCollapseBlockNumber; | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |         const int highlightColumn = d->extraAreaHighlightCollapseColumn; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         d->extraAreaHighlightCollapseBlockNumber = -1; | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |         d->extraAreaHighlightCollapseColumn = -1; | 
					
						
							| 
									
										
										
										
											2008-12-15 16:09:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  |         if (e->pos().x() > extraArea()->width() - collapseBoxWidth(fontMetrics())) { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |             d->extraAreaHighlightCollapseBlockNumber = cursor.blockNumber(); | 
					
						
							| 
									
										
										
										
											2009-04-29 16:46:54 +02:00
										 |  |  |             if (TextBlockUserData::canCollapse(cursor.block()) | 
					
						
							|  |  |  |                 || !TextBlockUserData::hasClosingCollapse(cursor.block())) | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                 d->extraAreaHighlightCollapseColumn = cursor.block().length()-1; | 
					
						
							| 
									
										
										
										
											2009-05-04 12:04:40 +02:00
										 |  |  |             if (TextBlockUserData::hasCollapseAfter(cursor.block())) { | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  |                 d->extraAreaHighlightCollapseBlockNumber++; | 
					
						
							| 
									
										
										
										
											2009-04-29 16:46:54 +02:00
										 |  |  |                 d->extraAreaHighlightCollapseColumn = -1; | 
					
						
							|  |  |  |                 if (TextBlockUserData::canCollapse(cursor.block().next()) | 
					
						
							|  |  |  |                     || !TextBlockUserData::hasClosingCollapse(cursor.block().next())) | 
					
						
							| 
									
										
										
										
											2009-04-29 15:37:38 +02:00
										 |  |  |                     d->extraAreaHighlightCollapseColumn = cursor.block().next().length()-1; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-05-04 11:47:28 +02:00
										 |  |  |         } else if (d->m_displaySettings.m_highlightBlocks) { | 
					
						
							|  |  |  |             QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |             d->extraAreaHighlightCollapseBlockNumber = cursor.blockNumber(); | 
					
						
							|  |  |  |             d->extraAreaHighlightCollapseColumn = cursor.position() - cursor.block().position(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-05-04 11:47:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |         if (highlightBlockNumber != d->extraAreaHighlightCollapseBlockNumber | 
					
						
							| 
									
										
										
										
											2009-06-04 16:40:34 +02:00
										 |  |  |             || highlightColumn != d->extraAreaHighlightCollapseColumn) { | 
					
						
							|  |  |  |             d->m_highlightBlocksTimer->start(d->m_highlightBlocksInfo.isEmpty() ? 120 : 0); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-16 12:15:33 +02:00
										 |  |  |     // Set whether the mouse cursor is a hand or normal arrow
 | 
					
						
							|  |  |  |     if (e->type() == QEvent::MouseMove) { | 
					
						
							|  |  |  |         bool hand = (e->pos().x() <= markWidth); | 
					
						
							|  |  |  |         if (hand != (d->m_extraArea->cursor().shape() == Qt::PointingHandCursor)) | 
					
						
							|  |  |  |             d->m_extraArea->setCursor(hand ? Qt::PointingHandCursor : Qt::ArrowCursor); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonDblClick) { | 
					
						
							|  |  |  |         if (e->button() == Qt::LeftButton) { | 
					
						
							| 
									
										
										
										
											2009-06-05 16:16:03 +02:00
										 |  |  |             int boxWidth = collapseBoxWidth(fontMetrics()); | 
					
						
							|  |  |  |             if (d->m_codeFoldingVisible && e->pos().x() > extraArea()->width() - boxWidth) { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                 if (!cursor.block().next().isVisible()) { | 
					
						
							|  |  |  |                     toggleBlockVisible(cursor.block()); | 
					
						
							|  |  |  |                     d->moveCursorVisible(false); | 
					
						
							|  |  |  |                 } else if (collapseBox().contains(e->pos())) { | 
					
						
							|  |  |  |                     cursor.setPosition( | 
					
						
							|  |  |  |                             document()->findBlockByNumber(d->m_highlightBlocksInfo.open.last()).position() | 
					
						
							|  |  |  |                             ); | 
					
						
							|  |  |  |                     QTextBlock c = cursor.block(); | 
					
						
							|  |  |  |                     if (!TextBlockUserData::canCollapse(c)) | 
					
						
							|  |  |  |                         c = c.previous(); | 
					
						
							|  |  |  |                     toggleBlockVisible(c); | 
					
						
							|  |  |  |                     d->moveCursorVisible(false); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2008-12-15 16:09:42 +01:00
										 |  |  |             } else if (d->m_marksVisible && e->pos().x() > markWidth) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 QTextCursor selection = cursor; | 
					
						
							|  |  |  |                 selection.setVisualNavigation(true); | 
					
						
							|  |  |  |                 d->extraAreaSelectionAnchorBlockNumber = selection.blockNumber(); | 
					
						
							|  |  |  |                 selection.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |                 selection.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |                 setTextCursor(selection); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 d->extraAreaToggleMarkBlockNumber = cursor.blockNumber(); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-15 16:09:42 +01:00
										 |  |  |         } else if (d->m_marksVisible && e->button() == Qt::RightButton) { | 
					
						
							| 
									
										
										
										
											2008-12-04 19:33:23 +01:00
										 |  |  |             QMenu * contextMenu = new QMenu(this); | 
					
						
							| 
									
										
										
										
											2008-12-11 15:50:37 +01:00
										 |  |  |             emit d->m_editable->markContextMenuRequested(editableInterface(), cursor.blockNumber() + 1, contextMenu); | 
					
						
							| 
									
										
										
										
											2008-12-04 19:33:23 +01:00
										 |  |  |             if (!contextMenu->isEmpty()) | 
					
						
							|  |  |  |                 contextMenu->exec(e->globalPos()); | 
					
						
							| 
									
										
										
										
											2008-12-05 12:12:20 +01:00
										 |  |  |             delete contextMenu; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } else if (d->extraAreaSelectionAnchorBlockNumber >= 0) { | 
					
						
							|  |  |  |         QTextCursor selection = cursor; | 
					
						
							|  |  |  |         selection.setVisualNavigation(true); | 
					
						
							|  |  |  |         if (e->type() == QEvent::MouseMove) { | 
					
						
							|  |  |  |             QTextBlock anchorBlock = document()->findBlockByNumber(d->extraAreaSelectionAnchorBlockNumber); | 
					
						
							|  |  |  |             selection.setPosition(anchorBlock.position()); | 
					
						
							|  |  |  |             if (cursor.blockNumber() < d->extraAreaSelectionAnchorBlockNumber) { | 
					
						
							|  |  |  |                 selection.movePosition(QTextCursor::EndOfBlock); | 
					
						
							|  |  |  |                 selection.movePosition(QTextCursor::Right); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             selection.setPosition(cursor.block().position(), QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |             if (cursor.blockNumber() >= d->extraAreaSelectionAnchorBlockNumber) { | 
					
						
							|  |  |  |                 selection.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |                 selection.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (e->pos().y() >= 0 && e->pos().y() <= d->m_extraArea->height()) | 
					
						
							|  |  |  |                 d->autoScrollTimer.stop(); | 
					
						
							|  |  |  |             else if (!d->autoScrollTimer.isActive()) | 
					
						
							|  |  |  |                 d->autoScrollTimer.start(100, this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             d->autoScrollTimer.stop(); | 
					
						
							|  |  |  |             d->extraAreaSelectionAnchorBlockNumber = -1; | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         setTextCursor(selection); | 
					
						
							|  |  |  |     } else if (d->extraAreaToggleMarkBlockNumber >= 0 && d->m_marksVisible && d->m_requestMarkEnabled) { | 
					
						
							|  |  |  |         if (e->type() == QEvent::MouseButtonRelease && e->button() == Qt::LeftButton) { | 
					
						
							|  |  |  |             int n = d->extraAreaToggleMarkBlockNumber; | 
					
						
							|  |  |  |             d->extraAreaToggleMarkBlockNumber = -1; | 
					
						
							|  |  |  |             if (cursor.blockNumber() == n) { | 
					
						
							|  |  |  |                 int line = n + 1; | 
					
						
							| 
									
										
										
										
											2008-12-05 12:12:20 +01:00
										 |  |  |                 emit d->m_editable->markRequested(editableInterface(), line); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QTextBlock TextBlockUserData::testCollapse(const QTextBlock& block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextBlock info = block; | 
					
						
							|  |  |  |     if (block.userData() && static_cast<TextBlockUserData*>(block.userData())->collapseMode() == CollapseAfter) | 
					
						
							|  |  |  |         ; | 
					
						
							|  |  |  |     else if (block.next().userData() | 
					
						
							|  |  |  |              && static_cast<TextBlockUserData*>(block.next().userData())->collapseMode() | 
					
						
							|  |  |  |              == TextBlockUserData::CollapseThis) | 
					
						
							|  |  |  |         info = block.next(); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return QTextBlock(); | 
					
						
							|  |  |  |     int pos = static_cast<TextBlockUserData*>(info.userData())->collapseAtPos(); | 
					
						
							|  |  |  |     if (pos < 0) | 
					
						
							|  |  |  |         return QTextBlock(); | 
					
						
							|  |  |  |     QTextCursor cursor(info); | 
					
						
							|  |  |  |     cursor.setPosition(cursor.position() + pos); | 
					
						
							|  |  |  |     matchCursorForward(&cursor); | 
					
						
							|  |  |  |     return cursor.block(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void TextBlockUserData::doCollapse(const QTextBlock& block, bool visible) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextBlock info = block; | 
					
						
							|  |  |  |     if (block.userData() && static_cast<TextBlockUserData*>(block.userData())->collapseMode() == CollapseAfter) | 
					
						
							|  |  |  |         ; | 
					
						
							|  |  |  |     else if (block.next().userData() | 
					
						
							|  |  |  |              && static_cast<TextBlockUserData*>(block.next().userData())->collapseMode() | 
					
						
							|  |  |  |              == TextBlockUserData::CollapseThis) | 
					
						
							|  |  |  |         info = block.next(); | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (visible && !block.next().isVisible()) { | 
					
						
							|  |  |  |             // no match, at least unfold!
 | 
					
						
							|  |  |  |             QTextBlock b = block.next(); | 
					
						
							|  |  |  |             while (b.isValid() && !b.isVisible()) { | 
					
						
							|  |  |  |                 b.setVisible(true); | 
					
						
							|  |  |  |                 b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0); | 
					
						
							|  |  |  |                 b = b.next(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     int pos = static_cast<TextBlockUserData*>(info.userData())->collapseAtPos(); | 
					
						
							|  |  |  |     if (pos < 0) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     QTextCursor cursor(info); | 
					
						
							|  |  |  |     cursor.setPosition(cursor.position() + pos); | 
					
						
							|  |  |  |     if (matchCursorForward(&cursor) != Match) { | 
					
						
							|  |  |  |         if (visible) { | 
					
						
							|  |  |  |             // no match, at least unfold!
 | 
					
						
							|  |  |  |             QTextBlock b = block.next(); | 
					
						
							|  |  |  |             while (b.isValid() && !b.isVisible()) { | 
					
						
							|  |  |  |                 b.setVisible(true); | 
					
						
							|  |  |  |                 b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0); | 
					
						
							|  |  |  |                 b = b.next(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextBlock b = block.next(); | 
					
						
							|  |  |  |     while (b < cursor.block()) { | 
					
						
							|  |  |  |         b.setVisible(visible); | 
					
						
							|  |  |  |         b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0); | 
					
						
							|  |  |  |         if (visible) { | 
					
						
							|  |  |  |             TextBlockUserData *data = canCollapse(b); | 
					
						
							|  |  |  |             if (data && data->collapsed()) { | 
					
						
							|  |  |  |                 QTextBlock end =  testCollapse(b); | 
					
						
							|  |  |  |                 if (data->collapseIncludesClosure()) | 
					
						
							|  |  |  |                     end = end.next(); | 
					
						
							|  |  |  |                 if (end.isValid()) { | 
					
						
							|  |  |  |                     b = end; | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         b = b.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool collapseIncludesClosure = hasClosingCollapseAtEnd(b); | 
					
						
							|  |  |  |     if (collapseIncludesClosure) { | 
					
						
							|  |  |  |         b.setVisible(visible); | 
					
						
							|  |  |  |         b.setLineCount(visible ? qMax(1, b.layout()->lineCount()) : 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     static_cast<TextBlockUserData*>(info.userData())->setCollapseIncludesClosure(collapseIncludesClosure); | 
					
						
							|  |  |  |     static_cast<TextBlockUserData*>(info.userData())->setCollapsed(!block.next().isVisible()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::ensureCursorVisible() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextBlock block = textCursor().block(); | 
					
						
							|  |  |  |     if (!block.isVisible()) { | 
					
						
							|  |  |  |         while (!block.isVisible() && block.previous().isValid()) | 
					
						
							|  |  |  |             block = block.previous(); | 
					
						
							|  |  |  |         toggleBlockVisible(block); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QPlainTextEdit::ensureCursorVisible(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::toggleBlockVisible(const QTextBlock &block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(document()->documentLayout()); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(documentLayout, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool visible = block.next().isVisible(); | 
					
						
							|  |  |  |     TextBlockUserData::doCollapse(block, !visible); | 
					
						
							|  |  |  |     documentLayout->requestUpdate(); | 
					
						
							|  |  |  |     documentLayout->emitDocumentSizeChanged(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const TabSettings &BaseTextEditor::tabSettings() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_document->tabSettings(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const DisplaySettings &BaseTextEditor::displaySettings() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_displaySettings; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::indentOrUnindent(bool doIndent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |     cursor.beginEditBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int pos = cursor.position(); | 
					
						
							|  |  |  |     const TextEditor::TabSettings &tabSettings = d->m_document->tabSettings(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextDocument *doc = document(); | 
					
						
							|  |  |  |     if (!cursor.hasSelection() | 
					
						
							|  |  |  |         || (doc->findBlock(cursor.selectionStart()) == doc->findBlock(cursor.selectionEnd()) )) { | 
					
						
							|  |  |  |         cursor.removeSelectedText(); | 
					
						
							|  |  |  |         QTextBlock block = cursor.block(); | 
					
						
							|  |  |  |         QString text = block.text(); | 
					
						
							|  |  |  |         int indentPosition = (cursor.position() - block.position());; | 
					
						
							|  |  |  |         int spaces = tabSettings.spacesLeftFromPosition(text, indentPosition); | 
					
						
							|  |  |  |         int startColumn = tabSettings.columnAt(text, indentPosition - spaces); | 
					
						
							|  |  |  |         int targetColumn = tabSettings.indentedColumn(tabSettings.columnAt(text, indentPosition), doIndent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cursor.setPosition(block.position() + indentPosition); | 
					
						
							|  |  |  |         cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |         cursor.removeSelectedText(); | 
					
						
							|  |  |  |         cursor.insertText(tabSettings.indentationString(startColumn, targetColumn)); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         int anchor = cursor.anchor(); | 
					
						
							|  |  |  |         int start = qMin(anchor, pos); | 
					
						
							|  |  |  |         int end = qMax(anchor, pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextBlock startBlock = doc->findBlock(start); | 
					
						
							|  |  |  |         QTextBlock endBlock = doc->findBlock(end-1).next(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (QTextBlock block = startBlock; block != endBlock; block = block.next()) { | 
					
						
							|  |  |  |             QString text = block.text(); | 
					
						
							|  |  |  |             int indentPosition = tabSettings.lineIndentPosition(text); | 
					
						
							|  |  |  |             if (!doIndent && !indentPosition) | 
					
						
							|  |  |  |                 indentPosition = tabSettings.firstNonSpace(text); | 
					
						
							|  |  |  |             int targetColumn = tabSettings.indentedColumn(tabSettings.columnAt(text, indentPosition), doIndent); | 
					
						
							|  |  |  |             cursor.setPosition(block.position() + indentPosition); | 
					
						
							|  |  |  |             cursor.insertText(tabSettings.indentationString(0, targetColumn)); | 
					
						
							|  |  |  |             cursor.setPosition(block.position()); | 
					
						
							|  |  |  |             cursor.setPosition(block.position() + indentPosition, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |             cursor.removeSelectedText(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cursor.endEditBlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::handleHomeKey(bool anchor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |     QTextCursor::MoveMode mode = QTextCursor::MoveAnchor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (anchor) | 
					
						
							|  |  |  |         mode = QTextCursor::KeepAnchor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int initpos = cursor.position(); | 
					
						
							|  |  |  |     int pos = cursor.block().position(); | 
					
						
							|  |  |  |     QChar character = characterAt(pos); | 
					
						
							|  |  |  |     const QLatin1Char tab = QLatin1Char('\t'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (character == tab || character.category() == QChar::Separator_Space) { | 
					
						
							|  |  |  |         ++pos; | 
					
						
							| 
									
										
										
										
											2008-12-11 14:11:28 +01:00
										 |  |  |         if (pos == initpos) | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         character = characterAt(pos); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Go to the start of the block when we're already at the start of the text
 | 
					
						
							|  |  |  |     if (pos == initpos) | 
					
						
							|  |  |  |         pos = cursor.block().position(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cursor.setPosition(pos, mode); | 
					
						
							|  |  |  |     setTextCursor(cursor); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::handleBackspaceKey() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(!cursor.hasSelection(), return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const TextEditor::TabSettings &tabSettings = d->m_document->tabSettings(); | 
					
						
							|  |  |  |     QTextBlock currentBlock = cursor.block(); | 
					
						
							|  |  |  |     int positionInBlock = cursor.position() - currentBlock.position(); | 
					
						
							|  |  |  |     const QString blockText = currentBlock.text(); | 
					
						
							|  |  |  |     if (cursor.atBlockStart() || tabSettings.firstNonSpace(blockText) < positionInBlock) { | 
					
						
							|  |  |  |         cursor.deletePreviousChar(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int previousIndent = 0; | 
					
						
							|  |  |  |     const int indent = tabSettings.columnAt(blockText, positionInBlock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (QTextBlock previousNonEmptyBlock = currentBlock.previous(); | 
					
						
							|  |  |  |          previousNonEmptyBlock.isValid(); | 
					
						
							|  |  |  |          previousNonEmptyBlock = previousNonEmptyBlock.previous()) { | 
					
						
							|  |  |  |         QString previousNonEmptyBlockText = previousNonEmptyBlock.text(); | 
					
						
							|  |  |  |         if (previousNonEmptyBlockText.trimmed().isEmpty()) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         previousIndent = tabSettings.columnAt(previousNonEmptyBlockText, | 
					
						
							|  |  |  |                                               tabSettings.firstNonSpace(previousNonEmptyBlockText)); | 
					
						
							|  |  |  |         if (previousIndent < indent) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (previousIndent >= indent) | 
					
						
							|  |  |  |         previousIndent = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cursor.beginEditBlock(); | 
					
						
							|  |  |  |     cursor.setPosition(currentBlock.position(), QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     cursor.insertText(tabSettings.indentationString(0, previousIndent)); | 
					
						
							|  |  |  |     cursor.endEditBlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::wheelEvent(QWheelEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   d->clearVisibleCollapsedBlock(); | 
					
						
							|  |  |  |     if (e->modifiers() & Qt::ControlModifier) { | 
					
						
							|  |  |  |         const int delta = e->delta(); | 
					
						
							|  |  |  |         if (delta < 0) | 
					
						
							|  |  |  |             zoomOut(); | 
					
						
							|  |  |  |         else if (delta > 0) | 
					
						
							|  |  |  |             zoomIn(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QPlainTextEdit::wheelEvent(e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::zoomIn(int range) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   d->clearVisibleCollapsedBlock(); | 
					
						
							|  |  |  |     QFont f = font(); | 
					
						
							|  |  |  |     const int newSize = f.pointSize() + range; | 
					
						
							|  |  |  |     if (newSize <= 0) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2009-06-17 19:12:19 +02:00
										 |  |  |     emit requestFontSize(newSize); | 
					
						
							|  |  |  | //    f.setPointSize(newSize);
 | 
					
						
							|  |  |  | //    setFont(f);
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::zoomOut(int range) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     zoomIn(-range); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::isElectricCharacter(const QChar &) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::indentBlock(QTextDocument *, QTextBlock, QChar) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (cursor.hasSelection()) { | 
					
						
							|  |  |  |         QTextBlock block = doc->findBlock(qMin(cursor.selectionStart(), cursor.selectionEnd())); | 
					
						
							|  |  |  |         const QTextBlock end = doc->findBlock(qMax(cursor.selectionStart(), cursor.selectionEnd())).next(); | 
					
						
							|  |  |  |         do { | 
					
						
							|  |  |  |             indentBlock(doc, block, typedChar); | 
					
						
							|  |  |  |             block = block.next(); | 
					
						
							|  |  |  |         } while (block.isValid() && block != end); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         indentBlock(doc, cursor.block(), typedChar); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorPrivate::updateMarksBlock(const QTextBlock &block) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (const TextBlockUserData *userData = TextEditDocumentLayout::testUserData(block)) | 
					
						
							|  |  |  |        foreach (ITextMark *mrk, userData->marks()) { | 
					
						
							|  |  |  |             mrk->updateBlock(block); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorPrivate::updateMarksLineNumber() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextDocument *doc = q->document(); | 
					
						
							|  |  |  |     QTextBlock block = doc->begin(); | 
					
						
							|  |  |  |     int blockNumber = 0; | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         if (const TextBlockUserData *userData = TextEditDocumentLayout::testUserData(block)) | 
					
						
							|  |  |  |             foreach (ITextMark *mrk, userData->marks()) { | 
					
						
							|  |  |  |                 mrk->updateLineNumber(blockNumber + 1); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |         ++blockNumber; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | void BaseTextEditor::markBlocksAsChanged(QList<int> blockNumbers) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QTextBlock block = document()->begin(); | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         if (block.revision() < 0) | 
					
						
							|  |  |  |             block.setRevision(-block.revision() - 1); | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     foreach (const int blockNumber, blockNumbers) { | 
					
						
							|  |  |  |         QTextBlock block = document()->findBlockByNumber(blockNumber); | 
					
						
							|  |  |  |         if (block.isValid()) | 
					
						
							|  |  |  |             block.setRevision(-block.revision() - 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TextBlockUserData::MatchType TextBlockUserData::checkOpenParenthesis(QTextCursor *cursor, QChar c) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |     QTextBlock block = cursor->block(); | 
					
						
							|  |  |  |     if (!TextEditDocumentLayout::hasParentheses(block) || TextEditDocumentLayout::ifdefedOut(block)) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return NoMatch; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |     Parentheses parenList = TextEditDocumentLayout::parentheses(block); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     Parenthesis openParen, closedParen; | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |     QTextBlock closedParenParag = block; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const int cursorPos = cursor->position() - closedParenParag.position(); | 
					
						
							|  |  |  |     int i = 0; | 
					
						
							|  |  |  |     int ignore = 0; | 
					
						
							|  |  |  |     bool foundOpen = false; | 
					
						
							|  |  |  |     for (;;) { | 
					
						
							|  |  |  |         if (!foundOpen) { | 
					
						
							|  |  |  |             if (i >= parenList.count()) | 
					
						
							|  |  |  |                 return NoMatch; | 
					
						
							|  |  |  |             openParen = parenList.at(i); | 
					
						
							|  |  |  |             if (openParen.pos != cursorPos) { | 
					
						
							|  |  |  |                 ++i; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 foundOpen = true; | 
					
						
							|  |  |  |                 ++i; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (i >= parenList.count()) { | 
					
						
							|  |  |  |             for (;;) { | 
					
						
							|  |  |  |                 closedParenParag = closedParenParag.next(); | 
					
						
							|  |  |  |                 if (!closedParenParag.isValid()) | 
					
						
							|  |  |  |                     return NoMatch; | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |                 if (TextEditDocumentLayout::hasParentheses(closedParenParag) | 
					
						
							|  |  |  |                     && !TextEditDocumentLayout::ifdefedOut(closedParenParag)) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     parenList = TextEditDocumentLayout::parentheses(closedParenParag); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             i = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         closedParen = parenList.at(i); | 
					
						
							|  |  |  |         if (closedParen.type == Parenthesis::Opened) { | 
					
						
							|  |  |  |             ignore++; | 
					
						
							|  |  |  |             ++i; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (ignore > 0) { | 
					
						
							|  |  |  |                 ignore--; | 
					
						
							|  |  |  |                 ++i; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             cursor->clearSelection(); | 
					
						
							|  |  |  |             cursor->setPosition(closedParenParag.position() + closedParen.pos + 1, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ((c == QLatin1Char('{') && closedParen.chr != QLatin1Char('}')) | 
					
						
							|  |  |  |                 || (c == QLatin1Char('(') && closedParen.chr != QLatin1Char(')')) | 
					
						
							|  |  |  |                 || (c == QLatin1Char('[') && closedParen.chr != QLatin1Char(']')) | 
					
						
							|  |  |  |                 || (c == QLatin1Char('+') && closedParen.chr != QLatin1Char('-')) | 
					
						
							|  |  |  |                ) | 
					
						
							|  |  |  |                 return Mismatch; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return Match; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TextBlockUserData::MatchType TextBlockUserData::checkClosedParenthesis(QTextCursor *cursor, QChar c) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |     QTextBlock block = cursor->block(); | 
					
						
							|  |  |  |     if (!TextEditDocumentLayout::hasParentheses(block) || TextEditDocumentLayout::ifdefedOut(block)) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return NoMatch; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |     Parentheses parenList = TextEditDocumentLayout::parentheses(block); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     Parenthesis openParen, closedParen; | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |     QTextBlock openParenParag = block; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const int cursorPos = cursor->position() - openParenParag.position(); | 
					
						
							|  |  |  |     int i = parenList.count() - 1; | 
					
						
							|  |  |  |     int ignore = 0; | 
					
						
							|  |  |  |     bool foundClosed = false; | 
					
						
							|  |  |  |     for (;;) { | 
					
						
							|  |  |  |         if (!foundClosed) { | 
					
						
							|  |  |  |             if (i < 0) | 
					
						
							|  |  |  |                 return NoMatch; | 
					
						
							|  |  |  |             closedParen = parenList.at(i); | 
					
						
							|  |  |  |             if (closedParen.pos != cursorPos - 1) { | 
					
						
							|  |  |  |                 --i; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 foundClosed = true; | 
					
						
							|  |  |  |                 --i; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (i < 0) { | 
					
						
							|  |  |  |             for (;;) { | 
					
						
							|  |  |  |                 openParenParag = openParenParag.previous(); | 
					
						
							|  |  |  |                 if (!openParenParag.isValid()) | 
					
						
							|  |  |  |                     return NoMatch; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |                 if (TextEditDocumentLayout::hasParentheses(openParenParag) | 
					
						
							|  |  |  |                     && !TextEditDocumentLayout::ifdefedOut(openParenParag)) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     parenList = TextEditDocumentLayout::parentheses(openParenParag); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             i = parenList.count() - 1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         openParen = parenList.at(i); | 
					
						
							|  |  |  |         if (openParen.type == Parenthesis::Closed) { | 
					
						
							|  |  |  |             ignore++; | 
					
						
							|  |  |  |             --i; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (ignore > 0) { | 
					
						
							|  |  |  |                 ignore--; | 
					
						
							|  |  |  |                 --i; | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             cursor->clearSelection(); | 
					
						
							|  |  |  |             cursor->setPosition(openParenParag.position() + openParen.pos, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ((c == '}' && openParen.chr != '{')    || | 
					
						
							|  |  |  |                  (c == ')' && openParen.chr != '(')   || | 
					
						
							|  |  |  |                  (c == ']' && openParen.chr != '[')   || | 
					
						
							|  |  |  |                  (c == '-' && openParen.chr != '+')) | 
					
						
							|  |  |  |                 return Mismatch; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return Match; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | bool TextBlockUserData::findPreviousOpenParenthesis(QTextCursor *cursor, bool select) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextBlock block = cursor->block(); | 
					
						
							|  |  |  |     int position = cursor->position(); | 
					
						
							|  |  |  |     int ignore = 0; | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         Parentheses parenList = TextEditDocumentLayout::parentheses(block); | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |         if (!parenList.isEmpty() && !TextEditDocumentLayout::ifdefedOut(block)) { | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |             for (int i = parenList.count()-1; i >= 0; --i) { | 
					
						
							|  |  |  |                 Parenthesis paren = parenList.at(i); | 
					
						
							| 
									
										
										
										
											2009-02-04 19:08:10 +01:00
										 |  |  |                 if (block == cursor->block() && | 
					
						
							|  |  |  |                     (position - block.position() <= paren.pos + (paren.type == Parenthesis::Closed ? 1 : 0))) | 
					
						
							|  |  |  |                         continue; | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |                 if (paren.type == Parenthesis::Closed) { | 
					
						
							|  |  |  |                     ++ignore; | 
					
						
							|  |  |  |                 } else if (ignore > 0) { | 
					
						
							|  |  |  |                     --ignore; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     cursor->setPosition(block.position() + paren.pos, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor); | 
					
						
							|  |  |  |                     return true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         block = block.previous(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-24 18:08:22 +02:00
										 |  |  | bool TextBlockUserData::findPreviousBlockOpenParenthesis(QTextCursor *cursor, bool checkStartPosition) | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QTextBlock block = cursor->block(); | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |     int position = cursor->position(); | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |     int ignore = 0; | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         Parentheses parenList = TextEditDocumentLayout::parentheses(block); | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |         if (!parenList.isEmpty() && !TextEditDocumentLayout::ifdefedOut(block)) { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |             for (int i = parenList.count()-1; i >= 0; --i) { | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |                 Parenthesis paren = parenList.at(i); | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                 if (paren.chr != QLatin1Char('{') && paren.chr != QLatin1Char('}') | 
					
						
							|  |  |  |                     && paren.chr != QLatin1Char('+') && paren.chr != QLatin1Char('-')) | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |                 if (block == cursor->block()) { | 
					
						
							|  |  |  |                     if (position - block.position() <= paren.pos + (paren.type == Parenthesis::Closed ? 1 : 0)) | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                         continue; | 
					
						
							| 
									
										
										
										
											2009-04-29 16:46:54 +02:00
										 |  |  |                     if (checkStartPosition && paren.type == Parenthesis::Opened && paren.pos== cursor->position()) { | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |                         return true; | 
					
						
							| 
									
										
										
										
											2009-04-29 16:46:54 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                 if (paren.type == Parenthesis::Closed) { | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |                     ++ignore; | 
					
						
							|  |  |  |                 } else if (ignore > 0) { | 
					
						
							|  |  |  |                     --ignore; | 
					
						
							|  |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                     cursor->setPosition(block.position() + paren.pos); | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |                     return true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |         block = block.previous(); | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  | bool TextBlockUserData::findNextClosingParenthesis(QTextCursor *cursor, bool select) | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     QTextBlock block = cursor->block(); | 
					
						
							|  |  |  |     int position = cursor->position(); | 
					
						
							|  |  |  |     int ignore = 0; | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         Parentheses parenList = TextEditDocumentLayout::parentheses(block); | 
					
						
							|  |  |  |         if (!parenList.isEmpty() && !TextEditDocumentLayout::ifdefedOut(block)) { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |             for (int i = 0; i < parenList.count(); ++i) { | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |                 Parenthesis paren = parenList.at(i); | 
					
						
							|  |  |  |                 if (block == cursor->block() && | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                     (position - block.position() > paren.pos - (paren.type == Parenthesis::Opened ? 1 : 0))) | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 if (paren.type == Parenthesis::Opened) { | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |                     ++ignore; | 
					
						
							|  |  |  |                 } else if (ignore > 0) { | 
					
						
							|  |  |  |                     --ignore; | 
					
						
							|  |  |  |                 } else { | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                     cursor->setPosition(block.position() + paren.pos+1, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor); | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |                     return true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |         block = block.next(); | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool TextBlockUserData::findNextBlockClosingParenthesis(QTextCursor *cursor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextBlock block = cursor->block(); | 
					
						
							|  |  |  |     int position = cursor->position(); | 
					
						
							|  |  |  |     int ignore = 0; | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         Parentheses parenList = TextEditDocumentLayout::parentheses(block); | 
					
						
							|  |  |  |         if (!parenList.isEmpty() && !TextEditDocumentLayout::ifdefedOut(block)) { | 
					
						
							|  |  |  |             for (int i = 0; i < parenList.count(); ++i) { | 
					
						
							|  |  |  |                 Parenthesis paren = parenList.at(i); | 
					
						
							|  |  |  |                 if (paren.chr != QLatin1Char('{') && paren.chr != QLatin1Char('}') | 
					
						
							|  |  |  |                     && paren.chr != QLatin1Char('+') && paren.chr != QLatin1Char('-')) | 
					
						
							|  |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                 if (block == cursor->block() && | 
					
						
							|  |  |  |                     (position - block.position() > paren.pos - (paren.type == Parenthesis::Opened ? 1 : 0))) | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |                     continue; | 
					
						
							|  |  |  |                 if (paren.type == Parenthesis::Opened) { | 
					
						
							|  |  |  |                     ++ignore; | 
					
						
							|  |  |  |                 } else if (ignore > 0) { | 
					
						
							|  |  |  |                     --ignore; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     cursor->setPosition(block.position() + paren.pos+1); | 
					
						
							|  |  |  |                     return true; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | TextBlockUserData::MatchType TextBlockUserData::matchCursorBackward(QTextCursor *cursor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     cursor->clearSelection(); | 
					
						
							|  |  |  |     const QTextBlock block = cursor->block(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |     if (!TextEditDocumentLayout::hasParentheses(block) || TextEditDocumentLayout::ifdefedOut(block)) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return NoMatch; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int relPos = cursor->position() - block.position(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Parentheses parentheses = TextEditDocumentLayout::parentheses(block); | 
					
						
							|  |  |  |     const Parentheses::const_iterator cend = parentheses.constEnd(); | 
					
						
							|  |  |  |     for (Parentheses::const_iterator it = parentheses.constBegin();it != cend; ++it) { | 
					
						
							|  |  |  |         const Parenthesis &paren = *it; | 
					
						
							|  |  |  |         if (paren.pos == relPos - 1 | 
					
						
							|  |  |  |             && paren.type == Parenthesis::Closed) { | 
					
						
							|  |  |  |             return checkClosedParenthesis(cursor, paren.chr); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return NoMatch; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TextBlockUserData::MatchType TextBlockUserData::matchCursorForward(QTextCursor *cursor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     cursor->clearSelection(); | 
					
						
							|  |  |  |     const QTextBlock block = cursor->block(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-11 13:20:59 +01:00
										 |  |  |     if (!TextEditDocumentLayout::hasParentheses(block) || TextEditDocumentLayout::ifdefedOut(block)) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         return NoMatch; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int relPos = cursor->position() - block.position(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Parentheses parentheses = TextEditDocumentLayout::parentheses(block); | 
					
						
							|  |  |  |     const Parentheses::const_iterator cend = parentheses.constEnd(); | 
					
						
							|  |  |  |     for (Parentheses::const_iterator it = parentheses.constBegin();it != cend; ++it) { | 
					
						
							|  |  |  |         const Parenthesis &paren = *it; | 
					
						
							|  |  |  |         if (paren.pos == relPos | 
					
						
							|  |  |  |             && paren.type == Parenthesis::Opened) { | 
					
						
							|  |  |  |             return checkOpenParenthesis(cursor, paren.chr); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return NoMatch; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-29 16:12:19 +02:00
										 |  |  | void BaseTextEditor::highlightSearchResults(const QString &txt, Find::IFindSupport::FindFlags findFlags) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (d->m_searchExpr.pattern() == txt) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     d->m_searchExpr.setPattern(txt); | 
					
						
							| 
									
										
										
										
											2009-05-29 16:52:12 +02:00
										 |  |  |     d->m_searchExpr.setPatternSyntax((findFlags & Find::IFindSupport::FindRegularExpression) ? | 
					
						
							|  |  |  |                                      QRegExp::RegExp : QRegExp::FixedString); | 
					
						
							| 
									
										
										
										
											2009-05-29 16:12:19 +02:00
										 |  |  |     d->m_searchExpr.setCaseSensitivity((findFlags & Find::IFindSupport::FindCaseSensitively) ? | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                                        Qt::CaseSensitive : Qt::CaseInsensitive); | 
					
						
							|  |  |  |     d->m_findFlags = findFlags; | 
					
						
							|  |  |  |     viewport()->update(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setFindScope(const QTextCursor &scope) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (scope.isNull() != d->m_findScope.isNull()) { | 
					
						
							|  |  |  |         d->m_findScope = scope; | 
					
						
							|  |  |  |         viewport()->update(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  | void BaseTextEditor::_q_animateUpdate(int position, QRectF rect) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor(textCursor()); | 
					
						
							|  |  |  |     cursor.setPosition(position); | 
					
						
							|  |  |  |     viewport()->update(QRectF(cursorRect(cursor).topLeft() + rect.topLeft(), rect.size()).toAlignedRect()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BaseTextEditorAnimator::BaseTextEditorAnimator(QObject *parent) | 
					
						
							|  |  |  |         :QObject(parent) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_value = 0; | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |     m_timeline = new QTimeLine(256, this); | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  |     m_timeline->setCurveShape(QTimeLine::SineCurve); | 
					
						
							|  |  |  |     connect(m_timeline, SIGNAL(valueChanged(qreal)), this, SLOT(step(qreal))); | 
					
						
							|  |  |  |     connect(m_timeline, SIGNAL(finished()), this, SLOT(deleteLater())); | 
					
						
							|  |  |  |     m_timeline->start(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorAnimator::setData(QFont f, QPalette pal, const QString &text) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-05-04 11:10:22 +02:00
										 |  |  |     m_font = f; | 
					
						
							|  |  |  |     m_palette = pal; | 
					
						
							|  |  |  |     m_text = text; | 
					
						
							|  |  |  |     QFontMetrics fm(m_font); | 
					
						
							|  |  |  |     m_size = QSizeF(fm.width(m_text), fm.height()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorAnimator::draw(QPainter *p, const QPointF &pos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     p->setPen(m_palette.text().color()); | 
					
						
							|  |  |  |     QFont f = m_font; | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |     f.setPointSizeF(f.pointSizeF() * (1.0 + m_value/2)); | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  |     QFontMetrics fm(f); | 
					
						
							|  |  |  |     int width = fm.width(m_text); | 
					
						
							|  |  |  |     QRectF r((m_size.width()-width)/2, (m_size.height() - fm.height())/2, width, fm.height()); | 
					
						
							|  |  |  |     r.translate(pos); | 
					
						
							|  |  |  |     p->fillRect(r, m_palette.base()); | 
					
						
							|  |  |  |     p->setFont(f); | 
					
						
							|  |  |  |     p->drawText(r, m_text); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 19:02:58 +02:00
										 |  |  | bool BaseTextEditorAnimator::isRunning() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return m_timeline->state() == QTimeLine::Running; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  | QRectF BaseTextEditorAnimator::rect() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QFont f = m_font; | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |     f.setPointSizeF(f.pointSizeF() * (1.0 + m_value/2)); | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  |     QFontMetrics fm(f); | 
					
						
							|  |  |  |     int width = fm.width(m_text); | 
					
						
							|  |  |  |     return QRectF((m_size.width()-width)/2, (m_size.height() - fm.height())/2, width, fm.height()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorAnimator::step(qreal v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QRectF before = rect(); | 
					
						
							|  |  |  |     m_value = v; | 
					
						
							|  |  |  |     QRectF after = rect(); | 
					
						
							|  |  |  |     emit updateRequest(m_position, before.united(after)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorAnimator::finish() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     step(0); | 
					
						
							|  |  |  |     deleteLater(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void BaseTextEditor::_q_matchParentheses() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (isReadOnly()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextCursor backwardMatch = textCursor(); | 
					
						
							|  |  |  |     QTextCursor forwardMatch = textCursor(); | 
					
						
							|  |  |  |     const TextBlockUserData::MatchType backwardMatchType = TextBlockUserData::matchCursorBackward(&backwardMatch); | 
					
						
							|  |  |  |     const TextBlockUserData::MatchType forwardMatchType = TextBlockUserData::matchCursorForward(&forwardMatch); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-05 13:19:57 +01:00
										 |  |  |     QList<QTextEdit::ExtraSelection> extraSelections; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-27 13:01:28 +02:00
										 |  |  |     if (backwardMatchType == TextBlockUserData::NoMatch && forwardMatchType == TextBlockUserData::NoMatch) { | 
					
						
							|  |  |  |         setExtraSelections(ParenthesesMatchingSelection, extraSelections); // clear
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  |     int animatePosition = -1; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     if (backwardMatch.hasSelection()) { | 
					
						
							|  |  |  |         QTextEdit::ExtraSelection sel; | 
					
						
							|  |  |  |         if (backwardMatchType == TextBlockUserData::Mismatch) { | 
					
						
							|  |  |  |             sel.cursor = backwardMatch; | 
					
						
							|  |  |  |             sel.format = d->m_mismatchFormat; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |             if (d->m_displaySettings.m_animateMatchingParentheses) { | 
					
						
							|  |  |  |                 animatePosition = backwardMatch.selectionStart(); | 
					
						
							|  |  |  |             } else if (d->m_formatRange) { | 
					
						
							|  |  |  |                 sel.cursor = backwardMatch; | 
					
						
							|  |  |  |                 sel.format = d->m_rangeFormat; | 
					
						
							|  |  |  |                 extraSelections.append(sel); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             sel.cursor = backwardMatch; | 
					
						
							|  |  |  |             sel.format = d->m_matchFormat; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             sel.cursor.setPosition(backwardMatch.selectionStart()); | 
					
						
							|  |  |  |             sel.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |             extraSelections.append(sel); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             sel.cursor.setPosition(backwardMatch.selectionEnd()); | 
					
						
							|  |  |  |             sel.cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         extraSelections.append(sel); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (forwardMatch.hasSelection()) { | 
					
						
							|  |  |  |         QTextEdit::ExtraSelection sel; | 
					
						
							|  |  |  |         if (forwardMatchType == TextBlockUserData::Mismatch) { | 
					
						
							|  |  |  |             sel.cursor = forwardMatch; | 
					
						
							|  |  |  |             sel.format = d->m_mismatchFormat; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |             if (d->m_displaySettings.m_animateMatchingParentheses) { | 
					
						
							|  |  |  |                 animatePosition = forwardMatch.selectionEnd()-1; | 
					
						
							|  |  |  |             } else if (d->m_formatRange) { | 
					
						
							|  |  |  |                 sel.cursor = forwardMatch; | 
					
						
							|  |  |  |                 sel.format = d->m_rangeFormat; | 
					
						
							|  |  |  |                 extraSelections.append(sel); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             sel.cursor = forwardMatch; | 
					
						
							|  |  |  |             sel.format = d->m_matchFormat; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             sel.cursor.setPosition(forwardMatch.selectionStart()); | 
					
						
							|  |  |  |             sel.cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |             extraSelections.append(sel); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             sel.cursor.setPosition(forwardMatch.selectionEnd()); | 
					
						
							|  |  |  |             sel.cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         extraSelections.append(sel); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-06 11:18:56 +02:00
										 |  |  |     if (animatePosition >= 0) { | 
					
						
							|  |  |  |         foreach (QTextEdit::ExtraSelection sel, BaseTextEditor::extraSelections(ParenthesesMatchingSelection)) { | 
					
						
							|  |  |  |             if (sel.cursor.selectionStart() == animatePosition | 
					
						
							|  |  |  |                 || sel.cursor.selectionEnd() - 1 == animatePosition) { | 
					
						
							|  |  |  |                 animatePosition = -1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  |     if (animatePosition >= 0) { | 
					
						
							|  |  |  |         if (d->m_animator) | 
					
						
							|  |  |  |             d->m_animator->finish();  // one animation is enough
 | 
					
						
							|  |  |  |         d->m_animator = new BaseTextEditorAnimator(this); | 
					
						
							|  |  |  |         d->m_animator->setPosition(animatePosition); | 
					
						
							|  |  |  |         QPalette pal; | 
					
						
							|  |  |  |         pal.setBrush(QPalette::Text, d->m_matchFormat.foreground()); | 
					
						
							|  |  |  |         pal.setBrush(QPalette::Base, d->m_rangeFormat.background()); | 
					
						
							|  |  |  |         d->m_animator->setData(font(), pal, characterAt(d->m_animator->position())); | 
					
						
							|  |  |  |         connect(d->m_animator, SIGNAL(updateRequest(int,QRectF)), | 
					
						
							|  |  |  |                 this, SLOT(_q_animateUpdate(int,QRectF))); | 
					
						
							| 
									
										
										
										
											2009-05-06 11:18:56 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-28 18:34:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-06 11:18:56 +02:00
										 |  |  |     setExtraSelections(ParenthesesMatchingSelection, extraSelections); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  | void BaseTextEditor::_q_highlightBlocks() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BaseTextEditorPrivateHighlightBlocks highlightBlocksInfo; | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (d->extraAreaHighlightCollapseBlockNumber >= 0) { | 
					
						
							|  |  |  |         QTextBlock block = document()->findBlockByNumber(d->extraAreaHighlightCollapseBlockNumber); | 
					
						
							|  |  |  |         if (block.isValid()) { | 
					
						
							|  |  |  |             QTextCursor cursor(block); | 
					
						
							|  |  |  |             if (d->extraAreaHighlightCollapseColumn >= 0) | 
					
						
							| 
									
										
										
										
											2009-04-24 18:08:22 +02:00
										 |  |  |                 cursor.setPosition(cursor.position() + qMin(d->extraAreaHighlightCollapseColumn, | 
					
						
							| 
									
										
										
										
											2009-04-29 12:17:42 +02:00
										 |  |  |                                                             block.length()-1)); | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |             QTextCursor closeCursor; | 
					
						
							| 
									
										
										
										
											2009-04-24 18:08:22 +02:00
										 |  |  |             bool firstRun = true; | 
					
						
							| 
									
										
										
										
											2009-04-24 18:12:36 +02:00
										 |  |  |             while (TextBlockUserData::findPreviousBlockOpenParenthesis(&cursor, firstRun)) { | 
					
						
							| 
									
										
										
										
											2009-04-24 18:08:22 +02:00
										 |  |  |                 firstRun = false; | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |                 highlightBlocksInfo.open.prepend(cursor.blockNumber()); | 
					
						
							|  |  |  |                 highlightBlocksInfo.visualIndent.prepend(d->visualIndent(cursor.block())); | 
					
						
							|  |  |  |                 if (closeCursor.isNull()) | 
					
						
							|  |  |  |                     closeCursor = cursor; | 
					
						
							|  |  |  |                 if (TextBlockUserData::findNextBlockClosingParenthesis(&closeCursor)) | 
					
						
							|  |  |  |                     highlightBlocksInfo.close.append(closeCursor.blockNumber()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |     if (d->m_highlightBlocksInfo != highlightBlocksInfo) { | 
					
						
							|  |  |  |         d->m_highlightBlocksInfo = highlightBlocksInfo; | 
					
						
							|  |  |  |         viewport()->update(); | 
					
						
							| 
									
										
										
										
											2009-04-24 16:44:48 +02:00
										 |  |  |         d->m_extraArea->update(); | 
					
						
							| 
									
										
										
										
											2009-04-23 17:28:53 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | void BaseTextEditor::setActionHack(QObject *hack) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_actionHack = hack; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QObject *BaseTextEditor::actionHack() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return d->m_actionHack; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::changeEvent(QEvent *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QPlainTextEdit::changeEvent(e); | 
					
						
							|  |  |  |     if (e->type() == QEvent::ApplicationFontChange | 
					
						
							|  |  |  |         || e->type() == QEvent::FontChange) { | 
					
						
							|  |  |  |         if (d->m_extraArea) { | 
					
						
							|  |  |  |             QFont f = d->m_extraArea->font(); | 
					
						
							|  |  |  |             f.setPointSize(font().pointSize()); | 
					
						
							|  |  |  |             d->m_extraArea->setFont(f); | 
					
						
							|  |  |  |             slotUpdateExtraAreaWidth(); | 
					
						
							|  |  |  |             d->m_extraArea->update(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 17:24:35 +02:00
										 |  |  | void BaseTextEditor::maybeSelectLine() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |     if (!cursor.hasSelection()) { | 
					
						
							|  |  |  |         const QTextBlock &block = cursor.block(); | 
					
						
							|  |  |  |         if (block.next().isValid()) { | 
					
						
							|  |  |  |             cursor.setPosition(block.position()); | 
					
						
							|  |  |  |             cursor.setPosition(block.next().position(), QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             cursor.movePosition(QTextCursor::EndOfBlock); | 
					
						
							|  |  |  |             cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |             cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         setTextCursor(cursor); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-14 17:24:35 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // shift+del
 | 
					
						
							|  |  |  | void BaseTextEditor::cutLine() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     maybeSelectLine(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     cut(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 17:24:35 +02:00
										 |  |  | void BaseTextEditor::deleteLine() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     maybeSelectLine(); | 
					
						
							|  |  |  |     textCursor().removeSelectedText(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-05 13:19:57 +01:00
										 |  |  | void BaseTextEditor::setExtraSelections(ExtraSelectionKind kind, const QList<QTextEdit::ExtraSelection> &selections) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-05 13:19:57 +01:00
										 |  |  |     if (selections.isEmpty() && d->m_extraSelections[kind].isEmpty()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     d->m_extraSelections[kind] = selections; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<QTextEdit::ExtraSelection> all; | 
					
						
							|  |  |  |     for (int i = 0; i < NExtraSelectionKinds; ++i) | 
					
						
							|  |  |  |         all += d->m_extraSelections[i]; | 
					
						
							|  |  |  |     QPlainTextEdit::setExtraSelections(all); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-05 13:19:57 +01:00
										 |  |  | QList<QTextEdit::ExtraSelection> BaseTextEditor::extraSelections(ExtraSelectionKind kind) const | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-12-05 13:19:57 +01:00
										 |  |  |     return d->m_extraSelections[kind]; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // the blocks list must be sorted
 | 
					
						
							|  |  |  | void BaseTextEditor::setIfdefedOutBlocks(const QList<BaseTextEditor::BlockRange> &blocks) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextDocument *doc = document(); | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout()); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(documentLayout, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool needUpdate = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextBlock block = doc->firstBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int rangeNumber = 0; | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         if (rangeNumber < blocks.size()) { | 
					
						
							|  |  |  |             const BlockRange &range = blocks.at(rangeNumber); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (block.position() >= range.first && (block.position() <= range.last || !range.last)) { | 
					
						
							| 
									
										
										
										
											2009-01-15 16:52:12 +01:00
										 |  |  |                 needUpdate |= TextEditDocumentLayout::setIfdefedOut(block); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2009-01-15 16:52:12 +01:00
										 |  |  |                 needUpdate |= TextEditDocumentLayout::clearIfdefedOut(block); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |             if (block.contains(range.last)) | 
					
						
							|  |  |  |                 ++rangeNumber; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             needUpdate |= TextEditDocumentLayout::clearIfdefedOut(block); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (needUpdate) | 
					
						
							|  |  |  |         documentLayout->requestUpdate(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | void BaseTextEditor::format() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |     cursor.beginEditBlock(); | 
					
						
							|  |  |  |     indent(document(), cursor, QChar::Null); | 
					
						
							|  |  |  |     cursor.endEditBlock(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-21 10:37:00 +02:00
										 |  |  | void BaseTextEditor::rewrapParagraph() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const int paragraphWidth = displaySettings().m_wrapColumn; | 
					
						
							|  |  |  |     const QRegExp anyLettersOrNumbers = QRegExp("\\w"); | 
					
						
							|  |  |  |     const int tabSize = tabSettings().m_tabSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |     cursor.beginEditBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Find start of paragraph.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::MoveAnchor)) { | 
					
						
							|  |  |  |         QTextBlock block = cursor.block(); | 
					
						
							|  |  |  |         QString text = block.text(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // If this block is empty, move marker back to previous and terminate.
 | 
					
						
							|  |  |  |         if (!text.contains(anyLettersOrNumbers)) { | 
					
						
							|  |  |  |             cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::MoveAnchor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Find indent level of current block.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int indentLevel = 0; | 
					
						
							|  |  |  |     QString text = cursor.block().text(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i < text.length(); i++) { | 
					
						
							|  |  |  |         const QChar ch = text.at(i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ch == QLatin1Char(' ')) | 
					
						
							|  |  |  |             indentLevel++; | 
					
						
							|  |  |  |         else if (ch == QLatin1Char('\t')) | 
					
						
							|  |  |  |             indentLevel += tabSize - (indentLevel % tabSize); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // If there is a common prefix, it should be kept and expanded to all lines.
 | 
					
						
							|  |  |  |     // this allows nice reflowing of doxygen style comments.
 | 
					
						
							|  |  |  |     QTextCursor nextBlock = cursor; | 
					
						
							|  |  |  |     QString commonPrefix; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (nextBlock.movePosition(QTextCursor::NextBlock)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |          QString nText = nextBlock.block().text(); | 
					
						
							|  |  |  |          int maxLength = qMin(text.length(), nText.length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          for (int i = 0; i < maxLength; ++i) { | 
					
						
							|  |  |  |              const QChar ch = text.at(i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |              if (ch != nText[i] || ch.isLetterOrNumber()) | 
					
						
							|  |  |  |                  break; | 
					
						
							|  |  |  |              commonPrefix.append(ch); | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Find end of paragraph.
 | 
					
						
							|  |  |  |     while (cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor)) { | 
					
						
							|  |  |  |         QString text = cursor.block().text(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!text.contains(anyLettersOrNumbers)) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString selectedText = cursor.selectedText(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Preserve initial indent level.or common prefix.
 | 
					
						
							|  |  |  |     QString spacing; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (commonPrefix.isEmpty()) { | 
					
						
							|  |  |  |         spacing = tabSettings().indentationString(0, indentLevel); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         spacing = commonPrefix; | 
					
						
							|  |  |  |         indentLevel = commonPrefix.length(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int currentLength = indentLevel; | 
					
						
							|  |  |  |     QString result; | 
					
						
							|  |  |  |     result.append(spacing); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Remove existing instances of any common prefix from paragraph to
 | 
					
						
							|  |  |  |     // reflow.
 | 
					
						
							|  |  |  |     selectedText.remove(0, commonPrefix.length()); | 
					
						
							|  |  |  |     commonPrefix.prepend(QChar::ParagraphSeparator); | 
					
						
							|  |  |  |     selectedText.replace(commonPrefix, QLatin1String("\n")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // remove any repeated spaces, trim lines to PARAGRAPH_WIDTH width and
 | 
					
						
							|  |  |  |     // keep the same indentation level as first line in paragraph.
 | 
					
						
							|  |  |  |     QString currentWord; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i < selectedText.length(); ++i) { | 
					
						
							|  |  |  |         QChar ch = selectedText.at(i); | 
					
						
							|  |  |  |         if (ch.isSpace()) { | 
					
						
							|  |  |  |             if (!currentWord.isEmpty()) { | 
					
						
							|  |  |  |                 currentLength += currentWord.length() + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-21 10:37:00 +02:00
										 |  |  |                 if (currentLength > paragraphWidth) { | 
					
						
							| 
									
										
										
										
											2009-07-21 10:37:00 +02:00
										 |  |  |                     currentLength = currentWord.length() + 1 + indentLevel; | 
					
						
							| 
									
										
										
										
											2009-07-21 12:34:56 +02:00
										 |  |  |                     result.chop(1); // remove trailing space
 | 
					
						
							| 
									
										
										
										
											2009-07-21 10:37:00 +02:00
										 |  |  |                     result.append(QChar::ParagraphSeparator); | 
					
						
							|  |  |  |                     result.append(spacing); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 result.append(currentWord); | 
					
						
							| 
									
										
										
										
											2009-07-21 12:37:04 +02:00
										 |  |  |                 result.append(QLatin1Char(' ')); | 
					
						
							| 
									
										
										
										
											2009-07-21 10:37:00 +02:00
										 |  |  |                 currentWord.clear(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         currentWord.append(ch); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-07-21 12:34:56 +02:00
										 |  |  |     result.chop(1); | 
					
						
							| 
									
										
										
										
											2009-07-21 10:37:00 +02:00
										 |  |  |     result.append(QChar::ParagraphSeparator); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cursor.insertText(result); | 
					
						
							|  |  |  |     cursor.endEditBlock(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | void BaseTextEditor::unCommentSelection() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-17 19:12:19 +02:00
										 |  |  | void BaseTextEditor::showEvent(QShowEvent* e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!d->m_fontSettings.isEmpty()) { | 
					
						
							|  |  |  | 	setFontSettings(d->m_fontSettings); | 
					
						
							|  |  |  | 	d->m_fontSettings.clear(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QPlainTextEdit::showEvent(e); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setFontSettingsIfVisible(const TextEditor::FontSettings &fs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!isVisible()) { | 
					
						
							|  |  |  | 	d->m_fontSettings = fs; | 
					
						
							|  |  |  | 	return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     setFontSettings(fs); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | void BaseTextEditor::setFontSettings(const TextEditor::FontSettings &fs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QTextCharFormat textFormat = fs.toTextCharFormat(QLatin1String(Constants::C_TEXT)); | 
					
						
							|  |  |  |     const QTextCharFormat selectionFormat = fs.toTextCharFormat(QLatin1String(Constants::C_SELECTION)); | 
					
						
							|  |  |  |     const QTextCharFormat lineNumberFormat = fs.toTextCharFormat(QLatin1String(Constants::C_LINE_NUMBER)); | 
					
						
							|  |  |  |     const QTextCharFormat searchResultFormat = fs.toTextCharFormat(QLatin1String(Constants::C_SEARCH_RESULT)); | 
					
						
							| 
									
										
										
										
											2009-04-27 14:10:54 +02:00
										 |  |  |     d->m_searchScopeFormat = fs.toTextCharFormat(QLatin1String(Constants::C_SEARCH_SCOPE)); | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  |     const QTextCharFormat parenthesesFormat = fs.toTextCharFormat(QLatin1String(Constants::C_PARENTHESES)); | 
					
						
							| 
									
										
										
										
											2009-04-27 14:10:54 +02:00
										 |  |  |     d->m_currentLineFormat = fs.toTextCharFormat(QLatin1String(Constants::C_CURRENT_LINE)); | 
					
						
							|  |  |  |     d->m_currentLineNumberFormat = fs.toTextCharFormat(QLatin1String(Constants::C_CURRENT_LINE_NUMBER)); | 
					
						
							|  |  |  |     d->m_ifdefedOutFormat = fs.toTextCharFormat(QLatin1String(Constants::C_DISABLED_CODE)); | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  |     QFont font(textFormat.font()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QColor foreground = textFormat.foreground().color(); | 
					
						
							|  |  |  |     const QColor background = textFormat.background().color(); | 
					
						
							|  |  |  |     QPalette p = palette(); | 
					
						
							|  |  |  |     p.setColor(QPalette::Text, foreground); | 
					
						
							|  |  |  |     p.setColor(QPalette::Foreground, foreground); | 
					
						
							|  |  |  |     p.setColor(QPalette::Base, background); | 
					
						
							|  |  |  |     p.setColor(QPalette::Highlight, (selectionFormat.background().style() != Qt::NoBrush) ? | 
					
						
							|  |  |  |                selectionFormat.background().color() : | 
					
						
							|  |  |  |                QApplication::palette().color(QPalette::Highlight)); | 
					
						
							|  |  |  |     p.setColor(QPalette::HighlightedText, selectionFormat.foreground().color()); | 
					
						
							|  |  |  |     p.setBrush(QPalette::Inactive, QPalette::Highlight, p.highlight()); | 
					
						
							|  |  |  |     p.setBrush(QPalette::Inactive, QPalette::HighlightedText, p.highlightedText()); | 
					
						
							|  |  |  |     setPalette(p); | 
					
						
							|  |  |  |     setFont(font); | 
					
						
							|  |  |  |     setTabSettings(d->m_document->tabSettings()); // update tabs, they depend on the font
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Line numbers
 | 
					
						
							|  |  |  |     QPalette ep = d->m_extraArea->palette(); | 
					
						
							|  |  |  |     ep.setColor(QPalette::Dark, lineNumberFormat.foreground().color()); | 
					
						
							|  |  |  |     ep.setColor(QPalette::Background, lineNumberFormat.background().style() != Qt::NoBrush ? | 
					
						
							|  |  |  |                 lineNumberFormat.background().color() : background); | 
					
						
							|  |  |  |     d->m_extraArea->setPalette(ep); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Search results
 | 
					
						
							|  |  |  |     d->m_searchResultFormat.setBackground(searchResultFormat.background()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Matching braces
 | 
					
						
							|  |  |  |     d->m_matchFormat.setForeground(parenthesesFormat.foreground()); | 
					
						
							|  |  |  |     d->m_rangeFormat.setBackground(parenthesesFormat.background()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-15 16:10:15 +02:00
										 |  |  |     slotUpdateExtraAreaWidth();   // Adjust to new font width
 | 
					
						
							|  |  |  |     updateCurrentLineHighlight(); // Make sure it takes the new color
 | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setTabSettings(const TabSettings &ts) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_document->setTabSettings(ts); | 
					
						
							|  |  |  |     int charWidth = QFontMetrics(font()).width(QChar(' ')); | 
					
						
							|  |  |  |     setTabStopWidth(charWidth * ts.m_tabSize); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setDisplaySettings(const DisplaySettings &ds) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     setLineWrapMode(ds.m_textWrapping ? QPlainTextEdit::WidgetWidth : QPlainTextEdit::NoWrap); | 
					
						
							|  |  |  |     setLineNumbersVisible(ds.m_displayLineNumbers); | 
					
						
							|  |  |  |     setVisibleWrapColumn(ds.m_showWrapColumn ? ds.m_wrapColumn : 0); | 
					
						
							|  |  |  |     setCodeFoldingVisible(ds.m_displayFoldingMarkers); | 
					
						
							|  |  |  |     setHighlightCurrentLine(ds.m_highlightCurrentLine); | 
					
						
							| 
									
										
										
										
											2009-07-16 11:27:02 +02:00
										 |  |  |     setRevisionsVisible(ds.m_markTextChanges); | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (d->m_displaySettings.m_visualizeWhitespace != ds.m_visualizeWhitespace) { | 
					
						
							|  |  |  |         if (QSyntaxHighlighter *highlighter = baseTextDocument()->syntaxHighlighter()) | 
					
						
							|  |  |  |             highlighter->rehighlight(); | 
					
						
							|  |  |  |         QTextOption option =  document()->defaultTextOption(); | 
					
						
							|  |  |  |         if (ds.m_visualizeWhitespace) | 
					
						
							|  |  |  |             option.setFlags(option.flags() | QTextOption::ShowTabsAndSpaces); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             option.setFlags(option.flags() & ~QTextOption::ShowTabsAndSpaces); | 
					
						
							|  |  |  |         option.setFlags(option.flags() | QTextOption::AddSpaceForLineAndParagraphSeparators); | 
					
						
							|  |  |  |         document()->setDefaultTextOption(option); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     d->m_displaySettings = ds; | 
					
						
							| 
									
										
										
										
											2009-05-08 18:24:44 +02:00
										 |  |  |     if (!ds.m_highlightBlocks) { | 
					
						
							|  |  |  |         d->extraAreaHighlightCollapseBlockNumber = d->extraAreaHighlightCollapseColumn = -1; | 
					
						
							|  |  |  |         d->m_highlightBlocksInfo = BaseTextEditorPrivateHighlightBlocks(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-28 11:11:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 18:24:44 +02:00
										 |  |  |     slotCursorPositionChanged(); | 
					
						
							| 
									
										
										
										
											2009-04-29 16:46:54 +02:00
										 |  |  |     viewport()->update(); | 
					
						
							|  |  |  |     extraArea()->update(); | 
					
						
							| 
									
										
										
										
											2009-03-17 16:16:36 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setStorageSettings(const StorageSettings &storageSettings) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     d->m_document->setStorageSettings(storageSettings); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::collapse() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextDocument *doc = document(); | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout()); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(documentLayout, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QTextBlock block = textCursor().block(); | 
					
						
							| 
									
										
										
										
											2008-12-12 14:09:56 +01:00
										 |  |  |     QTextBlock curBlock = block; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     while (block.isValid()) { | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  |         if (TextBlockUserData::canCollapse(block) && block.next().isVisible()) { | 
					
						
							| 
									
										
										
										
											2008-12-12 18:25:24 +01:00
										 |  |  |             if (block == curBlock || block.next() == curBlock) | 
					
						
							| 
									
										
										
										
											2008-12-12 14:09:56 +01:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             if ((block.next().userState()) >> 8 <= (curBlock.previous().userState() >> 8)) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         block = block.previous(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (block.isValid()) { | 
					
						
							|  |  |  |         TextBlockUserData::doCollapse(block, false); | 
					
						
							|  |  |  |         d->moveCursorVisible(); | 
					
						
							|  |  |  |         documentLayout->requestUpdate(); | 
					
						
							|  |  |  |         documentLayout->emitDocumentSizeChanged(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::expand() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextDocument *doc = document(); | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout()); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(documentLayout, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     QTextBlock block = textCursor().block(); | 
					
						
							|  |  |  |     while (block.isValid() && !block.isVisible()) | 
					
						
							|  |  |  |         block = block.previous(); | 
					
						
							|  |  |  |     TextBlockUserData::doCollapse(block, true); | 
					
						
							|  |  |  |     d->moveCursorVisible(); | 
					
						
							|  |  |  |     documentLayout->requestUpdate(); | 
					
						
							|  |  |  |     documentLayout->emitDocumentSizeChanged(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::unCollapseAll() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextDocument *doc = document(); | 
					
						
							|  |  |  |     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout()); | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  |     QTC_ASSERT(documentLayout, return); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QTextBlock block = doc->firstBlock(); | 
					
						
							|  |  |  |     bool makeVisible = true; | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         if (block.isVisible() && TextBlockUserData::canCollapse(block) && block.next().isVisible()) { | 
					
						
							|  |  |  |             makeVisible = false; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     block = doc->firstBlock(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (block.isValid()) { | 
					
						
							|  |  |  |         if (TextBlockUserData::canCollapse(block)) | 
					
						
							|  |  |  |             TextBlockUserData::doCollapse(block, makeVisible); | 
					
						
							|  |  |  |         block = block.next(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     d->moveCursorVisible(); | 
					
						
							|  |  |  |     documentLayout->requestUpdate(); | 
					
						
							|  |  |  |     documentLayout->emitDocumentSizeChanged(); | 
					
						
							| 
									
										
										
										
											2009-02-17 16:14:52 +01:00
										 |  |  |     centerCursor(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setTextCodec(QTextCodec *codec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     baseTextDocument()->setCodec(codec); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QTextCodec *BaseTextEditor::textCodec() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return baseTextDocument()->codec(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::setReadOnly(bool b) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QPlainTextEdit::setReadOnly(b); | 
					
						
							|  |  |  |     if (b) | 
					
						
							|  |  |  |         setTextInteractionFlags(textInteractionFlags() | Qt::TextSelectableByKeyboard); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::cut() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (d->m_inBlockSelectionMode) { | 
					
						
							|  |  |  |         copy(); | 
					
						
							|  |  |  |         d->removeBlockSelection(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QPlainTextEdit::cut(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-04 18:37:02 +01:00
										 |  |  | void BaseTextEditor::paste() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (d->m_inBlockSelectionMode) { | 
					
						
							|  |  |  |         d->removeBlockSelection(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QPlainTextEdit::paste(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | QMimeData *BaseTextEditor::createMimeDataFromSelection() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (d->m_inBlockSelectionMode) { | 
					
						
							|  |  |  |         QMimeData *mimeData = new QMimeData; | 
					
						
							|  |  |  |         QString text = d->copyBlockSelection(); | 
					
						
							|  |  |  |         mimeData->setData(QLatin1String("application/vnd.nokia.qtcreator.blocktext"), text.toUtf8()); | 
					
						
							|  |  |  |         mimeData->setText(text); // for exchangeability
 | 
					
						
							|  |  |  |         return mimeData; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return QPlainTextEdit::createMimeDataFromSelection(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool BaseTextEditor::canInsertFromMimeData(const QMimeData *source) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return QPlainTextEdit::canInsertFromMimeData(source); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditor::insertFromMimeData(const QMimeData *source) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!isReadOnly() && source->hasFormat(QLatin1String("application/vnd.nokia.qtcreator.blocktext"))) { | 
					
						
							|  |  |  |         QString text = QString::fromUtf8(source->data(QLatin1String("application/vnd.nokia.qtcreator.blocktext"))); | 
					
						
							|  |  |  |         if (text.isEmpty()) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         QStringList lines = text.split(QLatin1Char('\n')); | 
					
						
							|  |  |  |         QTextCursor cursor = textCursor(); | 
					
						
							|  |  |  |         cursor.beginEditBlock(); | 
					
						
							|  |  |  |         int initialCursorPosition = cursor.position(); | 
					
						
							|  |  |  |         int column = cursor.position() - cursor.block().position(); | 
					
						
							|  |  |  |         cursor.insertText(lines.first()); | 
					
						
							|  |  |  |         for (int i = 1; i < lines.count(); ++i) { | 
					
						
							|  |  |  |             QTextBlock next = cursor.block().next(); | 
					
						
							|  |  |  |             if (next.isValid()) { | 
					
						
							|  |  |  |                 cursor.setPosition(next.position() + qMin(column, next.length()-1)); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 cursor.movePosition(QTextCursor::EndOfBlock); | 
					
						
							|  |  |  |                 cursor.insertBlock(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             int actualColumn = cursor.position() - cursor.block().position(); | 
					
						
							|  |  |  |             if (actualColumn < column) | 
					
						
							|  |  |  |                 cursor.insertText(QString(column - actualColumn, QLatin1Char(' '))); | 
					
						
							|  |  |  |             cursor.insertText(lines.at(i)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         cursor.setPosition(initialCursorPosition); | 
					
						
							|  |  |  |         cursor.endEditBlock(); | 
					
						
							|  |  |  |         setTextCursor(cursor); | 
					
						
							|  |  |  |         ensureCursorVisible(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     QPlainTextEdit::insertFromMimeData(source); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BaseTextEditorEditable::BaseTextEditorEditable(BaseTextEditor *editor) | 
					
						
							|  |  |  |   : e(editor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifndef TEXTEDITOR_STANDALONE
 | 
					
						
							|  |  |  |     using namespace Find; | 
					
						
							|  |  |  |     Aggregation::Aggregate *aggregate = new Aggregation::Aggregate; | 
					
						
							|  |  |  |     BaseTextFind *baseTextFind = new BaseTextFind(editor); | 
					
						
							| 
									
										
										
										
											2009-05-29 16:12:19 +02:00
										 |  |  |     connect(baseTextFind, SIGNAL(highlightAll(QString, Find::IFindSupport::FindFlags)), | 
					
						
							|  |  |  |             editor, SLOT(highlightSearchResults(QString, Find::IFindSupport::FindFlags))); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     connect(baseTextFind, SIGNAL(findScopeChanged(QTextCursor)), editor, SLOT(setFindScope(QTextCursor))); | 
					
						
							|  |  |  |     aggregate->add(baseTextFind); | 
					
						
							|  |  |  |     aggregate->add(editor); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_cursorPositionLabel = new Core::Utils::LineColumnLabel; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QHBoxLayout *l = new QHBoxLayout; | 
					
						
							|  |  |  |     QWidget *w = new QWidget; | 
					
						
							|  |  |  |     l->setMargin(0); | 
					
						
							| 
									
										
										
										
											2009-05-29 04:39:23 +10:00
										 |  |  |     l->setContentsMargins(5, 0, 5, 0); | 
					
						
							| 
									
										
										
										
											2009-06-16 13:42:33 +02:00
										 |  |  |     l->addStretch(0); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     l->addWidget(m_cursorPositionLabel); | 
					
						
							|  |  |  |     w->setLayout(l); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_toolBar = new QToolBar; | 
					
						
							|  |  |  |     m_toolBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); | 
					
						
							|  |  |  |     m_toolBar->addWidget(w); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     connect(editor, SIGNAL(cursorPositionChanged()), this, SLOT(updateCursorPosition())); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BaseTextEditorEditable::~BaseTextEditorEditable() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     delete m_toolBar; | 
					
						
							|  |  |  |     delete e; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-15 16:23:07 +02:00
										 |  |  | QWidget *BaseTextEditorEditable::toolBar() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     return m_toolBar; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BaseTextEditorEditable::find(const QString &) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BaseTextEditorEditable::currentLine() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return e->textCursor().blockNumber() + 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BaseTextEditorEditable::currentColumn() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = e->textCursor(); | 
					
						
							|  |  |  |     return cursor.position() - cursor.block().position() + 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QRect BaseTextEditorEditable::cursorRect(int pos) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor tc = e->textCursor(); | 
					
						
							|  |  |  |     if (pos >= 0) | 
					
						
							|  |  |  |         tc.setPosition(pos); | 
					
						
							|  |  |  |     QRect result = e->cursorRect(tc); | 
					
						
							|  |  |  |     result.moveTo(e->viewport()->mapToGlobal(result.topLeft())); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString BaseTextEditorEditable::contents() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return e->toPlainText(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString BaseTextEditorEditable::selectedText() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (e->textCursor().hasSelection()) | 
					
						
							|  |  |  |         return e->textCursor().selectedText(); | 
					
						
							|  |  |  |     return QString(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString BaseTextEditorEditable::textAt(int pos, int length) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor c = e->textCursor(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (pos < 0) | 
					
						
							|  |  |  |         pos = 0; | 
					
						
							|  |  |  |     c.movePosition(QTextCursor::End); | 
					
						
							|  |  |  |     if (pos + length > c.position()) | 
					
						
							|  |  |  |         length = c.position() - pos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     c.setPosition(pos); | 
					
						
							|  |  |  |     c.setPosition(pos + length, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return c.selectedText(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorEditable::remove(int length) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor tc = e->textCursor(); | 
					
						
							|  |  |  |     tc.setPosition(tc.position() + length, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     tc.removeSelectedText(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorEditable::insert(const QString &string) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor tc = e->textCursor(); | 
					
						
							|  |  |  |     tc.insertText(string); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorEditable::replace(int length, const QString &string) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor tc = e->textCursor(); | 
					
						
							|  |  |  |     tc.setPosition(tc.position() + length, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     tc.insertText(string); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorEditable::setCurPos(int pos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor tc = e->textCursor(); | 
					
						
							|  |  |  |     tc.setPosition(pos); | 
					
						
							|  |  |  |     e->setTextCursor(tc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorEditable::select(int toPos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor tc = e->textCursor(); | 
					
						
							|  |  |  |     tc.setPosition(toPos, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     e->setTextCursor(tc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BaseTextEditorEditable::updateCursorPosition() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const QTextCursor cursor = e->textCursor(); | 
					
						
							|  |  |  |     const QTextBlock block = cursor.block(); | 
					
						
							|  |  |  |     const int line = block.blockNumber() + 1; | 
					
						
							| 
									
										
										
										
											2009-06-09 19:45:18 +02:00
										 |  |  |     const int column = cursor.position() - block.position(); | 
					
						
							|  |  |  |     m_cursorPositionLabel->setText(tr("Line: %1, Col: %2").arg(line).arg(e->tabSettings().columnAt(block.text(), column)+1), | 
					
						
							| 
									
										
										
										
											2009-04-17 21:11:52 +02:00
										 |  |  |                                    tr("Line: %1, Col: 999").arg(e->blockCount())); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     m_contextHelpId.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!block.isVisible()) | 
					
						
							|  |  |  |         e->ensureCursorVisible(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString BaseTextEditorEditable::contextHelpId() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_contextHelpId.isEmpty()) | 
					
						
							|  |  |  |         emit const_cast<BaseTextEditorEditable*>(this)->contextHelpIdRequested(e->editableInterface(), | 
					
						
							|  |  |  |                                                                                e->textCursor().position()); | 
					
						
							|  |  |  |     return m_contextHelpId; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TextBlockUserData::~TextBlockUserData() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     TextMarks marks = m_marks; | 
					
						
							|  |  |  |     m_marks.clear(); | 
					
						
							|  |  |  |     foreach (ITextMark *mrk, marks) { | 
					
						
							|  |  |  |         mrk->removedFromEditor(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |