Merge branch 'master' of ../mainline into dui-editor

This commit is contained in:
Roberto Raggi
2009-04-27 12:40:33 +02:00
27 changed files with 1838 additions and 1526 deletions

View File

@@ -9,6 +9,8 @@
simple means for plugin cooperation that allow plugins to provide
hooks for other plugin's extensions.
To get an overview of what parts of QtCreator are extensible, have a look at the \l{Common Extension Tasks} page.
\section1 Core Libraries
There are a few core libraries used by many parts of Qt Creator.
@@ -19,12 +21,12 @@
\o Description
\row
\o \l{Aggregation}{Aggregation}
\o \l{Aggregation}
\o Adds functionality for "glueing" QObjects of different
types together, so you can "cast" between them.
\row
\o \l{ExtensionSystem}{ExtensionSystem}
\o \l{ExtensionSystem}
\o Implements the plugin loader framework. Provides a base class for plugins and
basic mechanisms for plugin interaction like an object pool.
@@ -43,10 +45,18 @@
\o Description
\row
\o \l{Core} {Core}
\o \l{Core}
\o The core plugin. Provides the main window and managers for editors,
actions, mode windows and files, just to mention the most important ones.
\row
\o \l{Find}
\o Support for searching text in arbitrary widgets, and arbitrary other things.
\row
\o \l{QuickOpen}
\o Hooks for providing content for Locator.
\endtable
*/
@@ -79,3 +89,85 @@
\generatelist functionindex
*/
/*!
\page common_extension_tasks.html
\title Common Extension Tasks
\table
\header
\o Task
\o Details
\o API
\row
\o Add a menu / menu entry.
\o You can extend existing menus or create new ones.
\o \l{Core::ActionManager}, \l{Core::Command}, \l{Core::ICore::actionManager()}
\row
\o Add a configurable keyboard shortcut.
\o Registerng shortcuts makes it possible for users to configure them in the common shortcut settings dialog.
\o \l{Core::ActionManager}, \l{Core::Command}, \l{Core::ICore::actionManager()}
\row
\o Add a mode.
\o Modes correspond to complete screens of controls, specialized for a task.
\o \l{Core::IMode}, \l{Core::BaseMode}
\row
\o Add a new editor type.
\o Like an editor for xml files.
\o \l{Core::IEditorFactory}, \l{Core::IEditor}, \l{Core::IFile}
\row
\o Add a "New" wizard.
\o That is added to the list when users do File->New..., allows you to basically do whatever you want.
\o \l{Core::IWizard}, \l{Core::StandardFileWizard}, \l{Core::BaseFileWizard}, \l{Core::BaseFileWizardParameters}
\row
\o Add support for a new version control system.
\o Version control systems provided by QtCreator itself are Perforce, Git and Subversion.
\o \l{Core::IVersionControl}
\row
\o Add a view to the navigation sidebar.
\o The one which shows the project tree, filesystem, open documents or bookmarks.
\o \l{Core::INavigationWidgetFactory}
\row
\o Add a preferences page to the preferences dialog.
\o Add a new page to existing or new category in Tools->Options.
\o \l{Core::IOptionsPage}
\row
\o Add a find filter for the find dialog.
\o Implement any kind of search term based search.
\o \l{Find::IFindFilter}, \l{Find::SearchResultWindow}, \l{Find::ResultWindowItem}
\row
\o Add support for the find tool bar to a widget.
\o The widget that has focus is asked if it supports text search, you can provide that for widgets under your control.
\o \l{Find::IFindSupport}, \l{Find::BaseTextFind}
\row
\o Add a completely new project type.
\o
\o
\row
\o Add a new type of build step.
\o
\o
\row
\o Add a new filter to Locator.
\o For a text typed in by the user you provide a list of things to show in the popup. When the user selects an entry you are requested to do whatever you want.
\o \l{QuickOpen::IQuickOpenFilter}, \l{QuickOpen::FilterEntry}, \l{QuickOpen::BaseFileFilter}
\row
\o
\o
\o
\endtable
*/

View File

@@ -7,13 +7,15 @@ headerdirs = . \
../../src/libs/aggregation \
../../src/libs/extensionsystem \
../../src/plugins/coreplugin \
../../src/plugins/coreplugin/actionmanager
../../src/plugins/find \
../../src/plugins/quickopen
sourcedirs = . \
../../src/libs/aggregation \
../../src/libs/extensionsystem \
../../src/plugins/coreplugin \
../../src/plugins/coreplugin/actionmanager
../../src/plugins/find \
../../src/plugins/quickopen
headers.fileextesnions = "*.h"
sources.fileextensions = "*.cpp *.qdoc"

View File

@@ -44,3 +44,5 @@ macx {
OTHER_FILES = qtcreator.qdoc \
qtcreator.qdocconf
OTHER_FILES += api/qtcreator-api.qdoc \
api/qtcreator-api.qdocconf

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -36,7 +36,6 @@
/*!
\class Core::Command
\mainclass
\ingroup qwb
\brief The class...
@@ -197,7 +196,6 @@ QString CommandPrivate::stringWithAppendedShortcut(const QString &str) const
/*!
\class Shortcut
\ingroup qwb
*/
/*!
@@ -309,7 +307,6 @@ bool Shortcut::isActive() const
/*!
\class Action
\ingroup qwb
*/
/*!
@@ -401,7 +398,6 @@ QKeySequence Action::keySequence() const
/*!
\class OverrideableAction
\ingroup qwb
*/
/*!

View File

@@ -42,7 +42,6 @@ using namespace Core::Internal;
/*!
\class CommandsFile
\brief The CommandsFile class provides a collection of import and export commands.
\ingroup qwb
\inheaderfile commandsfile.h
*/

View File

@@ -38,7 +38,6 @@ using namespace Core;
/*!
\class BaseMode
\mainclass
\ingroup qwb
\inheaderfile basemode.h
\brief A base implementation of the mode interface IMode.

View File

@@ -33,42 +33,6 @@
using namespace Core;
/*!
\class BaseView
\mainclass
\ingroup qwb
\inheaderfile baseview.h
\brief A base implementation of IView.
The BaseView class can be used directly for most IView implementations.
It has setter functions for the views properties, and a convenience constructor
for the most important ones.
The ownership of the widget is given to the BaseView, so when the BaseView is destroyed it
deletes its widget.
A typical use case is to do the following in the init method of a plugin:
\code
bool MyPlugin::init(QString *error_message)
{
[...]
addObject(new Core::BaseView("myplugin.myview",
new MyWidget,
QList<int>() << myContextId,
Qt::LeftDockWidgetArea,
this));
[...]
}
\endcode
*/
/*!
\fn BaseView::BaseView()
Creates a View with empty view name, no widget, empty context, NoDockWidgetArea,
no menu group and empty default shortcut. You should use the setter functions
to give the view a meaning.
*/
BaseView::BaseView(QObject *parent)
: IView(parent),
m_viewName(""),
@@ -78,66 +42,37 @@ BaseView::BaseView(QObject *parent)
{
}
/*!
\fn BaseView::~BaseView()
Destructor also destroys the widget.
*/
BaseView::~BaseView()
{
delete m_widget;
}
/*!
\fn const QList<int> &BaseView::context() const
*/
QList<int> BaseView::context() const
{
return m_context;
}
/*!
\fn QWidget *BaseView::widget()
*/
QWidget *BaseView::widget()
{
return m_widget;
}
/*!
\fn const char *BaseView::uniqueViewName() const
*/
const char *BaseView::uniqueViewName() const
{
return m_viewName;
}
/*!
\fn IView::ViewPosition BaseView::defaultPosition() const
*/
IView::ViewPosition BaseView::defaultPosition() const
{
return m_defaultPosition;
}
/*!
\fn void BaseView::setUniqueViewName(const char *name)
\a name
*/
void BaseView::setUniqueViewName(const char *name)
{
m_viewName = name;
}
/*!
\fn QWidget *BaseView::setWidget(QWidget *widget)
The BaseView takes the ownership of the \a widget. The previously
set widget (if existent) is not deleted but returned, and responsibility
for deleting it moves to the caller of this method.
*/
QWidget *BaseView::setWidget(QWidget *widget)
{
QWidget *oldWidget = m_widget;
@@ -145,21 +80,11 @@ QWidget *BaseView::setWidget(QWidget *widget)
return oldWidget;
}
/*!
\fn void BaseView::setContext(const QList<int> &context)
\a context
*/
void BaseView::setContext(const QList<int> &context)
{
m_context = context;
}
/*!
\fn void BaseView::setDefaultPosition(IView::ViewPosition position)
\a position
*/
void BaseView::setDefaultPosition(IView::ViewPosition position)
{
m_defaultPosition = position;

View File

@@ -4,7 +4,6 @@ DEFINES += CORE_LIBRARY
QT += xml \
script \
svg
include(../../qworkbenchplugin.pri)
include(../../libs/utils/utils.pri)
include(../../shared/scriptwrapper/scriptwrapper.pri)
@@ -72,7 +71,9 @@ SOURCES += mainwindow.cpp \
sidebar.cpp \
fileiconprovider.cpp \
mimedatabase.cpp \
icore.cpp
icore.cpp \
editormanager/ieditor.cpp \
dialogs/ioptionspage.cpp
HEADERS += mainwindow.h \
welcomemode.h \
welcomemode_p.h \
@@ -160,12 +161,9 @@ FORMS += dialogs/newdialog.ui \
welcomemode.ui
RESOURCES += core.qrc \
fancyactionbar.qrc
linux-* {
linux-* {
images.files = images/qtcreator_logo_*.png
images.path = /share/pixmaps
images.path = /share/pixmaps
INSTALLS += images
}
OTHER_FILES += Core.pluginspec

View File

@@ -0,0 +1,46 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** 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.
**
** GNU Lesser General Public License Usage
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#include "ioptionspage.h"
/*!
\class Core::IOptionsPage
\mainclass
\brief The IOptionsPage is an interface for providing options pages.
Guidelines for implementing:
\list
\o id() is an id used for filtering when calling ICore:: showOptionsDialog()
\o trName() is the (translated) name for display.
\o category() is the category used for filtering when calling ICore:: showOptionsDialog()
\o trCategory() is the translated category
\o apply() is called to store the settings. It should detect if any changes have been
made and store those.
\endlist
*/

View File

@@ -38,21 +38,6 @@
namespace Core {
/*!
\class Core::IOptionsPage
\brief The IOptionsPage is an interface for providing options pages.
Guidelines for implementing:
\list
\o id() is an id used for filtering when calling ICore:: showOptionsDialog()
\o trName() is the (translated) name for display.
\o category() is the category used for filtering when calling ICore:: showOptionsDialog()
\o trCategory() is the translated category
\o apply() is called to store the settings. It should detect if any changes have been
made and store those.
\endlist
*/
class CORE_EXPORT IOptionsPage : public QObject
{
Q_OBJECT

View File

@@ -91,7 +91,7 @@ EditMode::~EditMode()
QString EditMode::name() const
{
return QLatin1String("Edit");
return tr("Edit");
}
QIcon EditMode::icon() const

View File

@@ -0,0 +1,55 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** 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.
**
** GNU Lesser General Public License Usage
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#include "ieditor.h"
/*!
\class Core::IEditor
\brief The IEditor is an interface for providing different editors for different file types.
Classes that implement this interface are for example the editors for
C++ files, ui-files and resource files.
Whenever a user wants to edit or create a file, the EditorManager scans all
EditorFactoryInterfaces for suitable editors. The selected EditorFactory
is then asked to create an editor, which must implement this interface.
Guidelines for implementing:
\list
\o displayName() is used as a user visible description of the document (usually filename w/o path).
\o kind() must be the same value as the kind() of the corresponding EditorFactory.
\o The changed() signal should be emitted when the modified state of the document changes
(so /bold{not} every time the document changes, but /bold{only once}).
\o If duplication is supported, you need to ensure that all duplicates
return the same file().
\endlist
\sa Core::EditorFactoryInterface Core::IContext
*/

View File

@@ -40,31 +40,6 @@ QT_END_NAMESPACE
namespace Core {
/*!
\class Core::IEditor
\brief The IEditor is an interface for providing different editors for different file types.
Classes that implement this interface are for example the editors for
C++ files, ui-files and resource files.
Whenever a user wants to edit or create a file, the EditorManager scans all
EditorFactoryInterfaces for suitable editors. The selected EditorFactory
is then asked to create an editor, which must implement this interface.
Guidelines for implementing:
\list
\o displayName() is used as a user visible description of the document (usually filename w/o path).
\o kind() must be the same value as the kind() of the corresponding EditorFactory.
\o The changed() signal should be emitted when the modified state of the document changes
(so /bold{not} every time the document changes, but /bold{only once}).
\o If duplication is supported, you need to ensure that all duplicates
return the same file().
\endlist
\sa Core::EditorFactoryInterface Core::IContext
*/
class CORE_EXPORT IEditor : public IContext
{
Q_OBJECT
@@ -85,8 +60,8 @@ public:
virtual QByteArray saveState() const = 0;
virtual bool restoreState(const QByteArray &state) = 0;
virtual int currentLine() const { return 0; };
virtual int currentColumn() const { return 0; };
virtual int currentLine() const { return 0; }
virtual int currentColumn() const { return 0; }
virtual QToolBar *toolBar() = 0;

View File

@@ -56,7 +56,6 @@ using namespace Core::Internal;
/*!
\class FileManager
\mainclass
\ingroup qwb
\inheaderfile filemanager.h
\brief Manages a set of IFile objects.
@@ -549,7 +548,7 @@ void FileManager::saveRecentFiles()
The current file is e.g. the file currently opened when an editor is active,
or the selected file in case a Project Explorer is active ...
\see currentFile
\sa currentFile
*/
void FileManager::setCurrentFile(const QString &filePath)
{
@@ -565,7 +564,7 @@ void FileManager::setCurrentFile(const QString &filePath)
The current file is e.g. the file currently opened when an editor is active,
or the selected file in case a Project Explorer is active ...
\see setCurrentFile
\sa setCurrentFile
*/
QString FileManager::currentFile() const
{

View File

@@ -52,7 +52,7 @@ struct WelcomeModePrivate
QWidget *m_widget;
QWidget *m_welcomePage;
Ui::welcomePage ui;
Ui::WelcomePage ui;
WelcomeMode::WelcomePageData lastData;
};

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>welcomePage</class>
<widget class="QWidget" name="welcomePage">
<class>Core::Internal::WelcomePage</class>
<widget class="QWidget" name="Core::Internal::WelcomePage">
<property name="geometry">
<rect>
<x>0</x>

View File

@@ -47,6 +47,20 @@
#include <QtCore/QtPlugin>
#include <QtCore/QSettings>
/*!
\namespace Find
The Find namespace provides everything that has to do with search term based searches.
*/
/*!
\namespace Find::Internal
\internal
*/
/*!
\namespace Find::Internal::ItemDataRoles
\internal
*/
Q_DECLARE_METATYPE(Find::IFindFilter*)
namespace {

View File

@@ -154,7 +154,7 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen
if (QApplication::clipboard()->supportsFindBuffer()) {
m_enterFindStringAction = new QAction(tr("Enter Find String"), this);
cmd = am->registerAction(m_enterFindStringAction, tr("Find.EnterFindString"), globalcontext);
cmd = am->registerAction(m_enterFindStringAction, QLatin1String("Find.EnterFindString"), globalcontext);
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+E")));
mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
connect(m_enterFindStringAction, SIGNAL(triggered()), this, SLOT(putSelectionToFindClipboard()));

View File

@@ -114,9 +114,9 @@ bool CoreListenerCheckingForRunningBuild::coreAboutToClose()
QPushButton *closeAnyway = box.addButton(tr("Cancel Build && Close"), QMessageBox::AcceptRole);
QPushButton *cancelClose = box.addButton(tr("Don't Close"), QMessageBox::RejectRole);
box.setDefaultButton(cancelClose);
box.setWindowTitle(tr("Close QtCreator?"));
box.setWindowTitle(tr("Close Qt Creator?"));
box.setText(tr("A project is currently being built."));
box.setInformativeText(tr("Do you want to cancel the build process and close QtCreator anyway?"));
box.setInformativeText(tr("Do you want to cancel the build process and close Qt Creator anyway?"));
box.exec();
return (box.clickedButton() == closeAnyway);
}

View File

@@ -268,10 +268,10 @@ QString QtVersionManager::qtVersionForQMake(const QString &qmakePath)
if (!qmake.waitForFinished())
return false;
QString output = qmake.readAllStandardOutput();
QRegExp regexp("(QMake version|Qmake version:)[\\s]*([\\d.]*)");
QRegExp regexp("(QMake version|QMake version:)[\\s]*([\\d.]*)", Qt::CaseInsensitive);
regexp.indexIn(output);
if (regexp.cap(2).startsWith("2.")) {
QRegExp regexp2("Using Qt version[\\s]*([\\d\\.]*)");
QRegExp regexp2("Using Qt version[\\s]*([\\d\\.]*)", Qt::CaseInsensitive);
regexp2.indexIn(output);
return regexp2.cap(1);
}

View File

@@ -51,10 +51,18 @@
#include <extensionsystem/pluginmanager.h>
#include <qtconcurrent/QtConcurrentTools>
/*!
\namespace QuickOpen
The QuickOpen namespace provides the hooks for Locator content.
*/
/*!
\namespace QuickOpen::Internal
\internal
*/
using namespace QuickOpen;
using namespace QuickOpen::Internal;
namespace {
static bool filterLessThan(const IQuickOpenFilter *first, const IQuickOpenFilter *second)
{

View File

@@ -135,6 +135,7 @@ ITextEditor *BaseTextEditor::openEditorAt(const QString &fileName,
texteditor->gotoLine(line, column);
return texteditor;
}
return 0;
}
@@ -161,9 +162,8 @@ BaseTextEditor::BaseTextEditor(QWidget *parent)
d->extraAreaSelectionAnchorBlockNumber
= d->extraAreaToggleMarkBlockNumber
= d->extraAreaHighlightCollapseBlockNumber
= d->extraAreaHighlightFadingBlockNumber
= d->extraAreaHighlightCollapseColumn
= -1;
d->extraAreaCollapseAlpha = 255;
d->visibleCollapsedBlockNumber = d->suggestedVisibleCollapsedBlockNumber = -1;
@@ -199,13 +199,6 @@ BaseTextEditor::BaseTextEditor(QWidget *parent)
slotCursorPositionChanged();
setFrameStyle(QFrame::NoFrame);
d->extraAreaTimeLine = new QTimeLine(150, this);
d->extraAreaTimeLine->setFrameRange(0, 255);
connect(d->extraAreaTimeLine, SIGNAL(frameChanged(int)), this,
SLOT(setCollapseIndicatorAlpha(int)));
connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)),
this, SLOT(currentEditorChanged(Core::IEditor*)));
}
@@ -1227,7 +1220,7 @@ void BaseTextEditor::setHighlightBlocks(bool b)
if (d->m_highlightBlocks == b)
return;
d->m_highlightBlocks = b;
d->m_highlightBlocksInfo = BaseTextEditorPrivateHighlightBlocks();
d->extraAreaHighlightCollapseBlockNumber = -1;
_q_highlightBlocks();
}
@@ -1487,6 +1480,8 @@ bool BaseTextEditor::viewportEvent(QEvent *event)
setTextCursor(cursorForPosition(ce->pos()));
} else if (event->type() == QEvent::ToolTip) {
const QHelpEvent *he = static_cast<QHelpEvent*>(event);
if (QApplication::keyboardModifiers() & Qt::ControlModifier)
return true; // eat tooltip event when control is pressed
const QPoint &pos = he->pos();
// Allow plugins to show tooltips
@@ -1512,14 +1507,22 @@ void BaseTextEditor::resizeEvent(QResizeEvent *e)
QRect(cr.left(), cr.top(), extraAreaWidth(), cr.height())));
}
QRect BaseTextEditor::collapseBox(const QTextBlock &block)
QRect BaseTextEditor::collapseBox()
{
QRectF br = blockBoundingGeometry(block).translated(contentOffset());
int collapseBoxWidth = fontMetrics().lineSpacing() + 1;
return QRect(d->m_extraArea->width() - collapseBoxWidth + collapseBoxWidth/4,
int(br.top()) + collapseBoxWidth/4,
2 * (collapseBoxWidth/4) + 1, 2 * (collapseBoxWidth/4) + 1);
if (d->m_highlightBlocksInfo.isEmpty() || d->extraAreaHighlightCollapseBlockNumber < 0)
return QRect();
QTextBlock begin = document()->findBlockByNumber(d->m_highlightBlocksInfo.open.last());
QTextBlock end= document()->findBlockByNumber(d->m_highlightBlocksInfo.close.first());
if (!begin.isValid() || !end.isValid())
return QRect();
QRectF br = blockBoundingGeometry(begin).translated(contentOffset());
QRectF er = blockBoundingGeometry(end).translated(contentOffset());
int collapseBoxWidth = fontMetrics().lineSpacing() + 1;
return QRect(d->m_extraArea->width() - collapseBoxWidth,
int(br.top()),
collapseBoxWidth,
er.bottom() - br.top());
}
QTextBlock BaseTextEditor::collapsedBlockAt(const QPoint &pos, QRect *box) const {
@@ -1703,9 +1706,8 @@ void BaseTextEditorPrivate::moveCursorVisible(bool ensureVisible)
static QColor calcBlendColor(const QColor &baseColor, int factor = 1)
{
const int blendBase = (baseColor.value() > 128) ? 0 : 255;
const int blendBase = (baseColor.value() > 128) ? 0 : 255;
// Darker backgrounds may need a bit more contrast
// (this calculation is temporary solution until we have a setting for this color)
const int blendFactor = (baseColor.value() > 128) ? 8 : 16;
QColor blendColor = baseColor;
@@ -1791,7 +1793,7 @@ void BaseTextEditor::paintEvent(QPaintEvent *e)
QRectF r = blockBoundingRect(block).translated(offset);
if (d->m_highlightBlocks) {
if (!d->m_highlightBlocksInfo.isEmpty()) {
int n = block.blockNumber();
int depth = 0;
@@ -2169,6 +2171,9 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e)
TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout());
QTC_ASSERT(documentLayout, return);
int cursorBlockNumber = textCursor().blockNumber();
const QColor baseColor = palette().base().color();
QPalette pal = d->m_extraArea->palette();
pal.setCurrentColorGroup(QPalette::Active);
QPainter painter(d->m_extraArea);
@@ -2188,12 +2193,12 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e)
painter.fillRect(e->rect().intersected(QRect(0, 0, extraAreaWidth, INT_MAX)),
pal.color(QPalette::Background));
QTextBlock block = firstVisibleBlock();
int blockNumber = block.blockNumber();
int top = (int)blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top;
#if 0
int extraAreaHighlightCollapseEndBlockNumber = -1;
int extraAreaHighlightCollapseBlockNumber = d->extraAreaHighlightCollapseBlockNumber;
@@ -2208,7 +2213,7 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e)
else
extraAreaHighlightCollapseEndBlockNumber = extraAreaHighlightCollapseBlockNumber;
}
#endif
while (block.isValid() && top <= e->rect().bottom()) {
@@ -2274,68 +2279,57 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e)
}
if (d->m_codeFoldingVisible) {
const QRect box(extraAreaWidth + collapseBoxWidth/4, top + collapseBoxWidth/4,
2 * (collapseBoxWidth/4) + 1, 2 * (collapseBoxWidth/4) + 1);
const QPoint boxCenter = box.center();
const QRect r(extraAreaWidth+2, top, collapseBoxWidth-4, bottom - top);
bool drawBox = !nextBlock.isVisible();
QColor textColorAlpha = pal.text().color();
textColorAlpha.setAlpha(d->extraAreaCollapseAlpha);
QColor textColorInactive = pal.text().color();
textColorInactive.setAlpha(100);
QColor textColor = pal.text().color();
textColor.setAlpha(qMax(textColorInactive.alpha(), d->extraAreaCollapseAlpha));
const QPen pen( (blockNumber >= extraAreaHighlightCollapseBlockNumber
&& blockNumber <= extraAreaHighlightCollapseEndBlockNumber) ?
textColorAlpha : pal.base().color());
const QPen boxPen((blockNumber == extraAreaHighlightCollapseBlockNumber) ?
textColor : textColorInactive);
const QPen endPen((blockNumber == extraAreaHighlightCollapseEndBlockNumber) ?
textColorAlpha : pal.base().color());
const QPen previousPen((blockNumber-1 >= extraAreaHighlightCollapseBlockNumber
&& blockNumber-1 < extraAreaHighlightCollapseEndBlockNumber) ?
textColorAlpha : pal.base().color());
const QPen nextPen((blockNumber+1 > extraAreaHighlightCollapseBlockNumber
&& blockNumber+1 <= extraAreaHighlightCollapseEndBlockNumber) ?
textColorAlpha : pal.base().color());
TextBlockUserData *nextBlockUserData = TextEditDocumentLayout::testUserData(nextBlock);
bool collapseNext = nextBlockUserData
&& nextBlockUserData->collapseMode()
== TextBlockUserData::CollapseThis
&& !nextBlockUserData->ifdefedOut();
bool nextHasClosingCollapse = nextBlockUserData
&& nextBlockUserData->hasClosingCollapseInside()
&& nextBlockUserData->ifdefedOut();
bool drawBox = ((collapseAfter || collapseNext) && !nextHasClosingCollapse);
if (braceDepth || (collapseNext && nextBlock.isVisible())) {
painter.setPen((hasClosingCollapse || !nextBlock.isVisible())? nextPen : pen);
painter.drawLine(boxCenter.x(), boxCenter.y(), boxCenter.x(), bottom - 1);
int minBraceDepth = qMax(braceDepth, previousBraceDepth);
if (minBraceDepth > 0) {
QColor color = calcBlendColor(baseColor, minBraceDepth);
if (!d->m_highlightBlocksInfo.isEmpty()
&& blockNumber >= d->m_highlightBlocksInfo.open.last()
&& blockNumber <= d->m_highlightBlocksInfo.close.first())
color = color.light();
painter.fillRect(r, color);
}
bool drawDown = !d->m_highlightBlocksInfo.isEmpty()
&& blockNumber == d->m_highlightBlocksInfo.open.last();
bool drawUp = !d->m_highlightBlocksInfo.isEmpty()
&& blockNumber == d->m_highlightBlocksInfo.close.first();
if (previousBraceDepth || collapseThis) {
painter.setPen((collapseAfter || collapseNext) ? previousPen : pen);
painter.drawLine(boxCenter.x(), top, boxCenter.x(), boxCenter.y());
}
if (drawBox) {
painter.setPen(boxPen);
painter.setBrush(pal.base());
painter.drawRect(box.adjusted(0, 0, -1, -1));
if (!nextBlock.isVisible())
painter.drawLine(boxCenter.x(), box.top() + 2, boxCenter.x(), box.bottom() - 2);
painter.drawLine(box.left() + 2, boxCenter.y(), box.right() - 2, boxCenter.y());
} else if (hasClosingCollapse || collapseAfter || collapseNext) {
painter.setPen(endPen);
painter.drawLine(boxCenter.x() + 1, boxCenter.y(), box.right() - 1, boxCenter.y());
if (drawBox || drawDown || drawUp) {
painter.setRenderHint(QPainter::Antialiasing, true);
painter.translate(.5, .5);
painter.setPen(pal.text().color());
painter.setBrush(pal.text().color());
if (drawBox) {
QPointF points1[3] = { QPointF(r.left(), r.center().y()-1),
QPointF(r.center().x(), r.top()),
QPointF(r.right(), r.center().y()-1) };
QPointF points2[3] = { QPointF(r.left(), r.center().y()+1),
QPointF(r.center().x(), r.bottom()-1),
QPointF(r.right(), r.center().y()+1) };
painter.drawPolygon(points1, 3);
painter.drawPolygon(points2, 3);
} else if (drawUp) {
QPointF points[3] = { QPointF(r.left(), r.bottom()-1),
QPointF(r.center().x(), r.center().y()),
QPointF(r.right(), r.bottom()-1) };
painter.drawPolygon(points, 3);
} else if(drawDown) {
QPointF points[3] = { QPointF(r.left(), r.top()),
QPointF(r.center().x(), r.center().y()),
QPointF(r.right(), r.top()) };
painter.drawPolygon(points, 3);
}
painter.translate(-.5, -.5);
painter.setRenderHint(QPainter::Antialiasing, false);
}
}
painter.restore();
}
@@ -2353,12 +2347,34 @@ void BaseTextEditor::extraAreaPaintEvent(QPaintEvent *e)
if (d->m_lineNumbersVisible) {
const QString &number = QString::number(blockNumber + 1);
if (blockNumber == cursorBlockNumber) {
painter.save();
painter.setPen(pal.color(QPalette::Background).value() < 128 ? Qt::white : Qt::black);
}
painter.drawText(markWidth, top, extraAreaWidth - markWidth - 4, fm.height(), Qt::AlignRight, number);
if (blockNumber == cursorBlockNumber)
painter.restore();
}
block = nextVisibleBlock;
blockNumber = nextVisibleBlockNumber;
}
if (d->m_codeFoldingVisible) {
painter.drawLine(extraAreaWidth, 0,
extraAreaWidth, viewport()->height());
painter.drawLine(extraAreaWidth + collapseBoxWidth - 1, 0,
extraAreaWidth + collapseBoxWidth - 1, viewport()->height());
QRect cb = collapseBox();
// if (!cb.isEmpty()) {
// QPen pen(baseColor.value() < 128 ? Qt::white : Qt::black);
// pen.setWidth(2);
// painter.setPen(pen);
// painter.setRenderHint(QPainter::Antialiasing, true);
// painter.translate(.5, .5);
// painter.drawRoundedRect(QRect(cb.adjusted(0, 0,-2, -2)), 4, 4);
// }
}
}
void BaseTextEditor::slotModificationChanged(bool m)
@@ -2429,6 +2445,9 @@ void BaseTextEditor::slotCursorPositionChanged()
setExtraSelections(CurrentLineSelection, extraSelections);
if (d->m_highlightBlocks) {
QTextCursor cursor = textCursor();
d->extraAreaHighlightCollapseBlockNumber = cursor.blockNumber();
d->extraAreaHighlightCollapseColumn = cursor.position() - cursor.block().position();
d->m_highlightBlocksTimer->start(100);
}
}
@@ -2450,12 +2469,6 @@ void BaseTextEditor::slotUpdateBlockNotify(const QTextBlock &block)
}
}
void BaseTextEditor::setCollapseIndicatorAlpha(int alpha)
{
d->extraAreaCollapseAlpha = alpha;
d->m_extraArea->update();
}
void BaseTextEditor::timerEvent(QTimerEvent *e)
{
if (e->timerId() == d->autoScrollTimer.timerId()) {
@@ -2545,13 +2558,9 @@ void BaseTextEditor::mousePressEvent(QMouseEvent *e)
void BaseTextEditor::extraAreaLeaveEvent(QEvent *)
{
if (d->extraAreaHighlightCollapseBlockNumber >= 0) {
d->extraAreaHighlightFadingBlockNumber = d->extraAreaHighlightCollapseBlockNumber;
d->extraAreaHighlightCollapseBlockNumber = -1; // missing mouse move event from Qt
d->extraAreaTimeLine->setDirection(QTimeLine::Backward);
if (d->extraAreaTimeLine->state() != QTimeLine::Running)
d->extraAreaTimeLine->start();
}
// fake missing mouse move event from Qt
QMouseEvent me(QEvent::MouseMove, QPoint(-1, -1), Qt::NoButton, 0, 0);
extraAreaMouseEvent(&me);
}
void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e)
@@ -2562,43 +2571,48 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e)
int markWidth;
extraAreaWidth(&markWidth);
if (e->type() == QEvent::MouseMove && e->buttons() == 0) { // mouse tracking
if (d->m_codeFoldingVisible
&& e->type() == QEvent::MouseMove && e->buttons() == 0) { // mouse tracking
// Update which folder marker is highlighted
const int highlightBlockNumber = d->extraAreaHighlightCollapseBlockNumber;
const int highlightColumn = d->extraAreaHighlightCollapseColumn;
d->extraAreaHighlightCollapseBlockNumber = -1;
d->extraAreaHighlightCollapseColumn = -1;
if (d->m_codeFoldingVisible
&& TextBlockUserData::canCollapse(cursor.block())
&& !TextBlockUserData::hasClosingCollapseInside(cursor.block().next())
&& collapseBox(cursor.block()).contains(e->pos()))
if (d->m_highlightBlocks) {
QTextCursor cursor = textCursor();
d->extraAreaHighlightCollapseBlockNumber = cursor.blockNumber();
// Set whether the mouse cursor is a hand or normal arrow
bool hand = (e->pos().x() <= markWidth || d->extraAreaHighlightCollapseBlockNumber >= 0);
if (hand != (d->m_extraArea->cursor().shape() == Qt::PointingHandCursor))
d->m_extraArea->setCursor(hand ? Qt::PointingHandCursor : Qt::ArrowCursor);
// Start fading in or out the highlighted folding marker
if (highlightBlockNumber != d->extraAreaHighlightCollapseBlockNumber) {
d->extraAreaTimeLine->stop();
d->extraAreaTimeLine->setDirection(d->extraAreaHighlightCollapseBlockNumber >= 0?
QTimeLine::Forward : QTimeLine::Backward);
if (d->extraAreaTimeLine->direction() == QTimeLine::Backward)
d->extraAreaHighlightFadingBlockNumber = highlightBlockNumber;
else
d->extraAreaHighlightFadingBlockNumber = -1;
if (d->extraAreaTimeLine->state() != QTimeLine::Running)
d->extraAreaTimeLine->start();
d->extraAreaHighlightCollapseColumn = cursor.position() - cursor.block().position();
}
int collapseBoxWidth = fontMetrics().lineSpacing() + 1;
if (e->pos().x() > extraArea()->width() - collapseBoxWidth) {
d->extraAreaHighlightCollapseBlockNumber = cursor.blockNumber();
if (!TextBlockUserData::hasClosingCollapse(cursor.block()))
d->extraAreaHighlightCollapseColumn = cursor.block().length()-1;
}
if (highlightBlockNumber != d->extraAreaHighlightCollapseBlockNumber
|| highlightColumn != d->extraAreaHighlightCollapseColumn)
d->m_highlightBlocksTimer->start(100);
}
if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonDblClick) {
if (e->button() == Qt::LeftButton) {
if (d->m_codeFoldingVisible && TextBlockUserData::canCollapse(cursor.block())
&& !TextBlockUserData::hasClosingCollapseInside(cursor.block().next())
&& collapseBox(cursor.block()).contains(e->pos())) {
toggleBlockVisible(cursor.block());
d->moveCursorVisible(false);
int collapseBoxWidth = fontMetrics().lineSpacing() + 1;
if (d->m_codeFoldingVisible && e->pos().x() > extraArea()->width() - collapseBoxWidth) {
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);
}
} else if (d->m_marksVisible && e->pos().x() > markWidth) {
QTextCursor selection = cursor;
selection.setVisualNavigation(true);
@@ -3153,37 +3167,10 @@ bool TextBlockUserData::findPreviousOpenParenthesis(QTextCursor *cursor, bool se
return false;
}
bool TextBlockUserData::findNextClosingParenthesis(QTextCursor *cursor, bool select)
bool TextBlockUserData::findPreviousBlockOpenParenthesis(QTextCursor *cursor, bool checkStartPosition)
{
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 (block == cursor->block() && position - block.position() >= paren.pos)
continue;
if (paren.type == Parenthesis::Opened) {
++ignore;
} else if (ignore > 0) {
--ignore;
} else {
cursor->setPosition(block.position() + paren.pos+1, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor);
return true;
}
}
}
block = block.next();
}
return false;
}
bool TextBlockUserData::findPreviousBlockOpenParenthesis(QTextCursor *cursor)
{
QTextBlock block = cursor->block();
int position = cursor->position();
int position = cursor->position() + (checkStartPosition ? 1 : 0 );
int ignore = 0;
while (block.isValid()) {
Parentheses parenList = TextEditDocumentLayout::parentheses(block);
@@ -3194,7 +3181,7 @@ bool TextBlockUserData::findPreviousBlockOpenParenthesis(QTextCursor *cursor)
&& paren.chr != QLatin1Char('+') && paren.chr != QLatin1Char('-'))
continue;
if (block == cursor->block() &&
(position - block.position() <= paren.pos))
(position - block.position() <= paren.pos + (paren.type == Parenthesis::Closed ? 1 : 0)))
continue;
if (paren.type == Parenthesis::Closed) {
++ignore;
@@ -3211,6 +3198,34 @@ bool TextBlockUserData::findPreviousBlockOpenParenthesis(QTextCursor *cursor)
return false;
}
bool TextBlockUserData::findNextClosingParenthesis(QTextCursor *cursor, bool select)
{
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 (block == cursor->block() &&
(position - block.position() > paren.pos - (paren.type == Parenthesis::Opened ? 1 : 0)))
continue;
if (paren.type == Parenthesis::Opened) {
++ignore;
} else if (ignore > 0) {
--ignore;
} else {
cursor->setPosition(block.position() + paren.pos+1, select ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor);
return true;
}
}
}
block = block.next();
}
return false;
}
bool TextBlockUserData::findNextBlockClosingParenthesis(QTextCursor *cursor)
{
QTextBlock block = cursor->block();
@@ -3224,7 +3239,8 @@ bool TextBlockUserData::findNextBlockClosingParenthesis(QTextCursor *cursor)
if (paren.chr != QLatin1Char('{') && paren.chr != QLatin1Char('}')
&& paren.chr != QLatin1Char('+') && paren.chr != QLatin1Char('-'))
continue;
if (block == cursor->block() && position - block.position() >= paren.pos)
if (block == cursor->block() &&
(position - block.position() > paren.pos - (paren.type == Parenthesis::Opened ? 1 : 0)))
continue;
if (paren.type == Parenthesis::Opened) {
++ignore;
@@ -3378,18 +3394,33 @@ void BaseTextEditor::_q_matchParentheses()
void BaseTextEditor::_q_highlightBlocks()
{
QTextCursor cursor = textCursor();
QTextCursor closeCursor = cursor;
BaseTextEditorPrivateHighlightBlocks highlightBlocksInfo;
while (TextBlockUserData::findPreviousBlockOpenParenthesis(&cursor)) {
highlightBlocksInfo.open.prepend(cursor.blockNumber());
highlightBlocksInfo.visualIndent.prepend(d->visualIndent(cursor.block()));
if (TextBlockUserData::findNextBlockClosingParenthesis(&closeCursor))
highlightBlocksInfo.close.append(closeCursor.blockNumber());
if (d->extraAreaHighlightCollapseBlockNumber >= 0) {
QTextBlock block = document()->findBlockByNumber(d->extraAreaHighlightCollapseBlockNumber);
if (block.isValid()) {
QTextCursor cursor(block);
if (d->extraAreaHighlightCollapseColumn >= 0)
cursor.setPosition(cursor.position() + qMin(d->extraAreaHighlightCollapseColumn,
block.length()));
QTextCursor closeCursor;
bool firstRun = true;
while (TextBlockUserData::findPreviousBlockOpenParenthesis(&cursor, firstRun)) {
firstRun = false;
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());
}
}
}
if (d->m_highlightBlocksInfo != highlightBlocksInfo) {
d->m_highlightBlocksInfo = highlightBlocksInfo;
viewport()->update();
d->m_extraArea->update();
}
}

View File

@@ -167,7 +167,7 @@ public:
static bool findPreviousOpenParenthesis(QTextCursor *cursor, bool select = false);
static bool findNextClosingParenthesis(QTextCursor *cursor, bool select = false);
static bool findPreviousBlockOpenParenthesis(QTextCursor *cursor);
static bool findPreviousBlockOpenParenthesis(QTextCursor *cursor, bool checkStartPosition = false);
static bool findNextBlockClosingParenthesis(QTextCursor *cursor);
@@ -370,7 +370,6 @@ private slots:
void restoreCursorPosition();
void highlightSearchResults(const QString &txt, QTextDocument::FindFlags findFlags);
void setFindScope(const QTextCursor &);
void setCollapseIndicatorAlpha(int);
void currentEditorChanged(Core::IEditor *editor);
private:
@@ -460,7 +459,7 @@ private:
void saveCurrentCursorPositionForNavigation();
void toggleBlockVisible(const QTextBlock &block);
QRect collapseBox(const QTextBlock &block);
QRect collapseBox();
QTextBlock collapsedBlockAt(const QPoint &pos, QRect *box = 0) const;

View File

@@ -33,7 +33,6 @@
#include "basetexteditor.h"
#include <QtCore/QBasicTimer>
#include <QtCore/QTimeLine>
#include <QtCore/QSharedData>
#include <QtGui/QTextEdit>
@@ -119,6 +118,7 @@ struct BaseTextEditorPrivateHighlightBlocks
QList<int> open;
QList<int> close;
QList<int> visualIndent;
inline bool isEmpty() const { return open.isEmpty() || close.isEmpty() || visualIndent.isEmpty(); }
inline bool operator==(const BaseTextEditorPrivateHighlightBlocks &o) const {
return (open == o.open && close == o.close && visualIndent == o.visualIndent);
}
@@ -178,9 +178,7 @@ public:
int extraAreaSelectionAnchorBlockNumber;
int extraAreaToggleMarkBlockNumber;
int extraAreaHighlightCollapseBlockNumber;
int extraAreaCollapseAlpha;
int extraAreaHighlightFadingBlockNumber;
QTimeLine *extraAreaTimeLine;
int extraAreaHighlightCollapseColumn;
QBasicTimer collapsedBlockTimer;
int visibleCollapsedBlockNumber;

View File

@@ -40,7 +40,7 @@ static const char * const showWrapColumnKey = "ShowWrapColumn";
static const char * const wrapColumnKey = "WrapColumn";
static const char * const visualizeWhitespaceKey = "VisualizeWhitespace";
static const char * const displayFoldingMarkersKey = "DisplayFoldingMarkersV2";
static const char * const highlightCurrentLineKey = "HighlightCurrentLineKey";
static const char * const highlightCurrentLineKey = "HighlightCurrentLineKeyV2";
static const char * const highlightBlocksKey = "HighlightBlocksKeyV2";
static const char * const groupPostfix = "DisplaySettings";
@@ -53,7 +53,7 @@ DisplaySettings::DisplaySettings() :
m_wrapColumn(80),
m_visualizeWhitespace(false),
m_displayFoldingMarkers(false),
m_highlightCurrentLine(true),
m_highlightCurrentLine(false),
m_highlightBlocks(true)
{
}