Merge branch '0.9.1-beta' of git@scm.dev.nokia.troll.no:creator/mainline into 0.9.1-beta

This commit is contained in:
dt
2008-12-05 14:30:48 +01:00
56 changed files with 1413 additions and 613 deletions

View File

@@ -814,21 +814,26 @@
a pointer to some private data structure, you will see a list of children,
signals and slots.
Similarily, instead of showing a bunch of pointers and ints,
a QHash or QMap will display its contents in an orderly fashion,
a QFileInfo will expose e.g. access data, and the otherwise
"opaque" QVariant gives access to the "real" contents.
The \gui{Locals and Watchers View} can be used to change the
contents of variables of simple data types like int or float
while the program is stopped. To do so, click into the 'Value'
column, modify the value there, and hit \key{Return}.
Similarly, instead of displaying many pointers and integers, Qt Creator's
debugger will display the contents of a QHash or QMap in an orderly manner.
Also, the debugger will display access data for QFileInfo and provide
access to the "real" contents of QVariant.
The \gui{Locals and Watchers} view can be used to change the contents of
variables of simple data types such as \c int or \c float when the program
is stopped. To do so, click on the \gui Value column, modify the value
with the inplace editor, and hit \key Enter (or \key Return).
\section2 Modules
The \gui{Modules View} is hidden by default and only useful in
By default, the \gui Modules view is hidden as it is only useful with the
experimental delayed debug information loading feature. You can turn this
feature on by selecting \gui{Fast Debugger Start}
The \gui Modules view is hidden by default and only useful in
connection with the experimental feature of delayed debug
information loading. This feature is accessible by selecting
\gui{Debug} and \gui{Fast Debugger Start}. When using the
@@ -849,14 +854,13 @@
commands
\section1 A Walkthrough for the Debugger Frontend
\section1 A short walk through the debugger frontend
In our \l{Writing a Simple Program with Qt Creator}{TextFinder}
example, we read a text file into a QString and then display it with a
QTextEdit. Suppose, you would like to look at this QString, \c{line},
and see what data it actually stores. Follow the steps described below
to place a break point and view the QString object's data.
In our \l{Writing a Simple Program with Qt Creator}{TextFinder} example, we
read a text file into a QString and then display it with a QTextEdit.
Suppose, you would like to look at this QString, \c{line}, and see what
data it actually stores. Follow the steps described below to place a
breakpoint and view the QString object's data.
\table
\row
@@ -864,14 +868,14 @@
\i \bold{Setting a Breakpoint}
First, we set a breakpoint on the line where we invoke
\l{QTextEdit::}{setPlainText()} by clicking between the line number and
the window border. Then, select \gui{Start Debugging} from the
\gui{Debug} menu or press \key{F5}.
\l{QTextEdit::}{setPlainText()} by clicking between the line number and the
window border. Then, select \gui{Start Debugging} from the \gui{Debug} menu
or press \key{F5}.
\endtable
Breakpoints are visible in the \gui{Breakpoints} view, shown below, in
\gui{Debug} mode. If you wish to remove a breakpoint, simply right
click on it and select \gui{Delete breakpoint} from the context menu.
\gui{Debug} mode. If you wish to remove a breakpoint, simply right-click on
it and select \gui{Delete breakpoint} from the context menu.
\image qtcreator-setting-breakpoint2.png
@@ -880,10 +884,10 @@
\image qtcreator-watcher.png
Suppose we modify our \c{on_findButton_clicked()} function to move back
to the start of the document and continue searching once the cursor
hits the end of the document. Adding this functionality can be done
with the code snippet below:
Suppose we modify our \c{on_findButton_clicked()} function to move back to
the start of the document and continue searching once the cursor hits the
end of the document. Adding this functionality can be done with the code
snippet below:
\code
void TextFinder::on_findButton_clicked()
@@ -915,9 +919,9 @@
}
\endcode
However, if you compile and run this code, the application will not
work correctly due to a logic error. To locate this logic error, you
can step through the code using the following buttons:
However, if you compile and run this code, the application will not work
correctly due to a logic error. To locate this logic error, you can step
through the code using the following buttons:
\image qtcreator-debugging-buttons.png
*/
@@ -931,20 +935,20 @@
\title Tips and Tricks
\bold{Quick mode switch}
\bold{Quickly Switching between Modes}
You can quickly switch between modes by pressing \key{Ctrl+1},
\key{Ctrl+2}, etc.
\key{Ctrl+2}, and so on.
\bold{Other keyboard shortcuts}
\bold{Keyboard Shortcuts}
There are a lot of other \l{keyboard-shortcuts}{keyboard shortcuts}.
Qt Creator provides a lot of useful keyboard shortcuts. A complete list can
be found \l{Keyboard Shortcuts}{here}.
\bold{Command line}
\bold{Running Qt Creator from the Command Line}
You can start Qt Creator from a command prompt with an already
existing session or \c{.pro} file by giving the name as argument on the
command line.
You can start Qt Creator from a command prompt with an existing session or
\c{.pro} file by giving the name as argument on the command line.
\bold{Sidebar}

View File

@@ -292,6 +292,7 @@ Use *Scope::useAt(unsigned index) const
void Scope::addUse(unsigned sourceOffset, Name *name)
{
#ifdef CPLUSPLUS_WITH_USES
if (++_useCount == _allocatedUses) {
_allocatedUses += 4;
_uses = reinterpret_cast<Use *>(realloc(_uses, _allocatedUses * sizeof(Use)));
@@ -303,6 +304,7 @@ void Scope::addUse(unsigned sourceOffset, Name *name)
else
lastVisibleSymbol = _symbols[_symbolCount];
_uses[_useCount].init(sourceOffset, name, lastVisibleSymbol);
#endif
}
CPLUSPLUS_END_NAMESPACE

View File

@@ -9,7 +9,8 @@ HEADERS += \
$$PWD/helpviewer.h \
$$PWD/contentwindow.h \
$$PWD/bookmarkmanager.h \
$$PWD/../namespace_global.h
$$PWD/../namespace_global.h \
$$PWD/indexwindow.h
SOURCES += \
$$PWD/filternamedialog.cpp \

View File

@@ -61,11 +61,11 @@ Icons::Icons()
{
}
QIcon Icons::iconForSymbol(Symbol *symbol) const
QIcon Icons::iconForSymbol(const Symbol *symbol) const
{
if (symbol->isFunction() || (symbol->isDeclaration() && symbol->type()->isFunction()))
{
Function *function = symbol->asFunction();
const Function *function = symbol->asFunction();
if (!function)
function = symbol->type()->asFunction();

View File

@@ -47,7 +47,7 @@ class CPLUSPLUS_EXPORT Icons
public:
Icons();
QIcon iconForSymbol(Symbol *symbol) const;
QIcon iconForSymbol(const Symbol *symbol) const;
QIcon keywordIcon() const;
QIcon macroIcon() const;

View File

@@ -235,9 +235,9 @@ bool ResolveExpression::visit(ExpressionListAST *)
return false;
}
bool ResolveExpression::visit(BinaryExpressionAST *)
bool ResolveExpression::visit(BinaryExpressionAST *ast)
{
// nothing to do.
accept(ast->left_expression);
return false;
}

View File

@@ -33,26 +33,65 @@
#include "filenamevalidatinglineedit.h"
#include <QtCore/QRegExp>
#include <QtCore/QDebug>
namespace Core {
namespace Utils {
FileNameValidatingLineEdit::FileNameValidatingLineEdit(QWidget *parent) :
BaseValidatingLineEdit(parent)
{
}
/* Validate a file base name, check for forbidden characters/strings. */
static const char *notAllowedChars = "/?:&\\*\"|#%<> ";
static const char *notAllowedSubStrings[] = {".."};
// Naming a file like a device name will break on Windows, even if it is
// "com1.txt". Since we are cross-platform, we generally disallow such file
// names.
static const char *notAllowedStrings[] = {"CON", "AUX", "PRN", "COM1", "COM2", "LPT1", "LPT2" };
static const QRegExp &windowsDeviceNoSubDirPattern()
{
static const QRegExp rc(QLatin1String("CON|AUX|PRN|COM1|COM2|LPT1|LPT2|NUL"),
Qt::CaseInsensitive);
Q_ASSERT(rc.isValid());
return rc;
}
bool FileNameValidatingLineEdit::validateFileName(const QString &name, QString *errorMessage /* = 0*/)
static const QRegExp &windowsDeviceSubDirPattern()
{
static const QRegExp rc(QLatin1String(".*[/\\\\]CON|.*[/\\\\]AUX|.*[/\\\\]PRN|.*[/\\\\]COM1|.*[/\\\\]COM2|.*[/\\\\]LPT1|.*[/\\\\]LPT2|.*[/\\\\]NUL"),
Qt::CaseInsensitive);
Q_ASSERT(rc.isValid());
return rc;
}
// ----------- FileNameValidatingLineEdit
FileNameValidatingLineEdit::FileNameValidatingLineEdit(QWidget *parent) :
BaseValidatingLineEdit(parent),
m_allowDirectories(false),
m_unused(0)
{
}
bool FileNameValidatingLineEdit::allowDirectories() const
{
return m_allowDirectories;
}
void FileNameValidatingLineEdit::setAllowDirectories(bool v)
{
m_allowDirectories = v;
}
/* Validate a file base name, check for forbidden characters/strings. */
#ifdef Q_OS_WIN
# define SLASHES "/\\"
#else
# define SLASHES "/"
#endif
static const char *notAllowedCharsSubDir = "?:&*\"|#%<> ";
static const char *notAllowedCharsNoSubDir = "?:&*\"|#%<> "SLASHES;
static const char *notAllowedSubStrings[] = {".."};
bool FileNameValidatingLineEdit::validateFileName(const QString &name,
bool allowDirectories,
QString *errorMessage /* = 0*/)
{
if (name.isEmpty()) {
if (errorMessage)
@@ -60,6 +99,7 @@ bool FileNameValidatingLineEdit::validateFileName(const QString &name, QString *
return false;
}
// Characters
const char *notAllowedChars = allowDirectories ? notAllowedCharsSubDir : notAllowedCharsNoSubDir;
for (const char *c = notAllowedChars; *c; c++)
if (name.contains(QLatin1Char(*c))) {
if (errorMessage)
@@ -76,22 +116,22 @@ bool FileNameValidatingLineEdit::validateFileName(const QString &name, QString *
return false;
}
}
// Strings
const int notAllowedStringCount = sizeof(notAllowedStrings)/sizeof(const char *);
for (int s = 0; s < notAllowedStringCount; s++) {
const QLatin1String notAllowedString(notAllowedStrings[s]);
if (name == notAllowedString) {
// Windows devices
bool matchesWinDevice = windowsDeviceNoSubDirPattern().exactMatch(name);
if (!matchesWinDevice && allowDirectories)
matchesWinDevice = windowsDeviceSubDirPattern().exactMatch(name);
if (matchesWinDevice) {
if (errorMessage)
*errorMessage = tr("The name must not be '%1'.").arg(QString(notAllowedString));
*errorMessage = tr("The name must not match that of a MS Windows device. (%1).").
arg(windowsDeviceNoSubDirPattern().pattern().replace(QLatin1Char('|'), QLatin1Char(',')));
return false;
}
}
return true;
}
bool FileNameValidatingLineEdit::validate(const QString &value, QString *errorMessage) const
{
return validateFileName(value, errorMessage);
return validateFileName(value, m_allowDirectories, errorMessage);
}
} // namespace Utils

View File

@@ -43,14 +43,23 @@ class QWORKBENCH_UTILS_EXPORT FileNameValidatingLineEdit : public BaseValidating
{
Q_OBJECT
Q_DISABLE_COPY(FileNameValidatingLineEdit)
Q_PROPERTY(bool allowDirectories READ allowDirectories WRITE setAllowDirectories)
public:
explicit FileNameValidatingLineEdit(QWidget *parent = 0);
static bool validateFileName(const QString &name, QString *errorMessage /* = 0*/);
static bool validateFileName(const QString &name,
bool allowDirectories = false,
QString *errorMessage = 0);
bool allowDirectories() const;
void setAllowDirectories(bool v);
protected:
virtual bool validate(const QString &value, QString *errorMessage) const;
private:
bool m_allowDirectories;
void *m_unused;
};
} // namespace Utils

View File

@@ -123,7 +123,7 @@ void FileWizardPage::slotActivated()
bool FileWizardPage::validateBaseName(const QString &name, QString *errorMessage /* = 0*/)
{
return FileNameValidatingLineEdit::validateFileName(name, errorMessage);
return FileNameValidatingLineEdit::validateFileName(name, false, errorMessage);
}
} // namespace Utils

View File

@@ -346,6 +346,21 @@ void NewClassWidget::setFormExtension(const QString &e)
m_d->m_formExtension = fixSuffix(e);
}
bool NewClassWidget::allowDirectories() const
{
return m_d->m_ui.headerFileLineEdit->allowDirectories();
}
void NewClassWidget::setAllowDirectories(bool v)
{
// We keep all in sync
if (allowDirectories() != v) {
m_d->m_ui.sourceFileLineEdit->setAllowDirectories(v);
m_d->m_ui.headerFileLineEdit->setAllowDirectories(v);
m_d->m_ui.formFileLineEdit->setAllowDirectories(v);
}
}
void NewClassWidget::slotValidChanged()
{
const bool newValid = isValid();

View File

@@ -73,6 +73,7 @@ class QWORKBENCH_UTILS_EXPORT NewClassWidget : public QWidget
Q_PROPERTY(QString formExtension READ formExtension WRITE setFormExtension DESIGNABLE true)
Q_PROPERTY(bool formInputCheckable READ formInputCheckable WRITE setFormInputCheckable DESIGNABLE true)
Q_PROPERTY(bool formInputChecked READ formInputChecked WRITE setFormInputChecked DESIGNABLE true)
Q_PROPERTY(bool allowDirectories READ allowDirectories WRITE setAllowDirectories)
// Utility "USER" property for wizards containing file names.
Q_PROPERTY(QStringList files READ files DESIGNABLE false USER true)
public:
@@ -97,7 +98,7 @@ public:
QString sourceExtension() const;
QString headerExtension() const;
QString formExtension() const;
bool allowDirectories() const;
bool isValid(QString *error = 0) const;
@@ -125,6 +126,7 @@ public slots:
void setSourceExtension(const QString &e);
void setHeaderExtension(const QString &e);
void setFormExtension(const QString &e);
void setAllowDirectories(bool v);
/* Suggest a class name from the base class by stripping the leading 'Q'
* character. This will happen automagically if the base class combo

View File

@@ -30,6 +30,7 @@
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef PATHCHOOSER_H
#define PATHCHOOSER_H

View File

@@ -45,7 +45,7 @@ ProjectNameValidatingLineEdit::ProjectNameValidatingLineEdit(QWidget *parent)
bool ProjectNameValidatingLineEdit::validateProjectName(const QString &name, QString *errorMessage /* = 0*/)
{
// Validation is file name + checking for dots
if (!FileNameValidatingLineEdit::validateFileName(name, errorMessage))
if (!FileNameValidatingLineEdit::validateFileName(name, false, errorMessage))
return false;
// We don't want dots in the directory name for some legacy Windows

View File

@@ -125,6 +125,7 @@ struct SynchronousProcessPrivate {
SynchronousProcessResponse m_result;
int m_hangTimerCount;
int m_maxHangTimerCount;
bool m_startFailure;
ChannelBuffer m_stdOut;
ChannelBuffer m_stdErr;
@@ -133,7 +134,8 @@ struct SynchronousProcessPrivate {
SynchronousProcessPrivate::SynchronousProcessPrivate() :
m_stdOutCodec(0),
m_hangTimerCount(0),
m_maxHangTimerCount(defaultMaxHangTimerCount)
m_maxHangTimerCount(defaultMaxHangTimerCount),
m_startFailure(false)
{
}
@@ -143,6 +145,7 @@ void SynchronousProcessPrivate::clearForRun()
m_stdOut.clearForRun();
m_stdErr.clearForRun();
m_result.clear();
m_startFailure = false;
}
// ----------- SynchronousProcess
@@ -221,11 +224,14 @@ SynchronousProcessResponse SynchronousProcess::run(const QString &binary,
qDebug() << '>' << Q_FUNC_INFO << binary << args;
m_d->clearForRun();
m_d->m_timer.start();
QApplication::setOverrideCursor(Qt::WaitCursor);
// On Windows, start failure is triggered immediately if the
// executable cannot be found in the path. Do not start the
// event loop in that case.
m_d->m_process.start(binary, args, QIODevice::ReadOnly);
if (!m_d->m_startFailure) {
m_d->m_timer.start();
QApplication::setOverrideCursor(Qt::WaitCursor);
m_d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
if (m_d->m_result.result == SynchronousProcessResponse::Finished || m_d->m_result.result == SynchronousProcessResponse::FinishedError) {
processStdOut(false);
@@ -237,6 +243,7 @@ SynchronousProcessResponse SynchronousProcess::run(const QString &binary,
m_d->m_timer.stop();
QApplication::restoreOverrideCursor();
}
if (debug)
qDebug() << '<' << Q_FUNC_INFO << binary << m_d->m_result;
@@ -246,13 +253,15 @@ SynchronousProcessResponse SynchronousProcess::run(const QString &binary,
void SynchronousProcess::slotTimeout()
{
if (++m_d->m_hangTimerCount > m_d->m_maxHangTimerCount) {
if (debug)
qDebug() << Q_FUNC_INFO << "HANG detected, killing";
m_d->m_process.kill();
m_d->m_result.result = SynchronousProcessResponse::Hang;
}
} else {
if (debug)
qDebug() << Q_FUNC_INFO << m_d->m_hangTimerCount;
}
}
void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
{
@@ -265,6 +274,8 @@ void SynchronousProcess::finished(int exitCode, QProcess::ExitStatus e)
m_d->m_result.exitCode = exitCode;
break;
case QProcess::CrashExit:
// Was hang detected before and killed?
if (m_d->m_result.result != SynchronousProcessResponse::Hang)
m_d->m_result.result = SynchronousProcessResponse::TerminatedAbnormally;
m_d->m_result.exitCode = -1;
break;
@@ -277,7 +288,10 @@ void SynchronousProcess::error(QProcess::ProcessError e)
m_d->m_hangTimerCount = 0;
if (debug)
qDebug() << Q_FUNC_INFO << e;
// Was hang detected before and killed?
if (m_d->m_result.result != SynchronousProcessResponse::Hang)
m_d->m_result.result = SynchronousProcessResponse::StartFailed;
m_d->m_startFailure = true;
m_d->m_eventLoop.quit();
}

View File

@@ -127,6 +127,7 @@ MainWindow::MainWindow() :
m_mimeDatabase(new MimeDatabase),
m_navigationWidget(0),
m_rightPaneWidget(0),
m_versionDialog(0),
m_activeContext(0),
m_pluginManager(0),
m_outputPane(new OutputPane(m_globalContext)),
@@ -1085,8 +1086,20 @@ void MainWindow::openRecentFile()
void MainWindow::aboutQtCreator()
{
VersionDialog versionDialog(this);
versionDialog.exec();
if (!m_versionDialog) {
m_versionDialog = new VersionDialog(this);
connect(m_versionDialog, SIGNAL(finished(int)),
this, SLOT(destroyVersionDialog()));
}
m_versionDialog->show();
}
void MainWindow::destroyVersionDialog()
{
if (m_versionDialog) {
m_versionDialog->deleteLater();
m_versionDialog = 0;
}
}
void MainWindow::aboutPlugins()

View File

@@ -83,6 +83,7 @@ class OutputPane;
class ProgressManager;
class ShortcutSettings;
class ViewManager;
class VersionDialog;
class CORE_EXPORT MainWindow : public QMainWindow
{
@@ -160,6 +161,7 @@ private slots:
void aboutPlugins();
void updateFocusWidget(QWidget *old, QWidget *now);
void toggleNavigation();
void destroyVersionDialog();
private:
void updateContextObject(IContext *context);
@@ -190,6 +192,7 @@ private:
NavigationWidget *m_navigationWidget;
RightPaneWidget *m_rightPaneWidget;
Core::BaseView *m_outputView;
VersionDialog *m_versionDialog;
IContext * m_activeContext;

View File

@@ -73,6 +73,7 @@ ClassNamePage::ClassNamePage(const QString &sourceSuffix,
m_newClassWidget->setBaseClassEditable(true);
m_newClassWidget->setFormInputVisible(false);
m_newClassWidget->setNamespacesEnabled(true);
m_newClassWidget->setAllowDirectories(true);
connect(m_newClassWidget, SIGNAL(validChanged()),
this, SLOT(slotValidChanged()));

View File

@@ -206,6 +206,7 @@ void CPPEditor::createToolBar(CPPEditorEditable *editable)
connect(m_methodCombo, SIGNAL(activated(int)), this, SLOT(jumpToMethod(int)));
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateMethodBoxIndex()));
connect(m_methodCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(updateMethodBoxToolTip()));
connect(file(), SIGNAL(changed()), this, SLOT(updateFileName()));
@@ -355,10 +356,16 @@ void CPPEditor::updateMethodBoxIndex()
if (lastIndex.isValid()) {
bool blocked = m_methodCombo->blockSignals(true);
m_methodCombo->setCurrentIndex(lastIndex.row());
updateMethodBoxToolTip();
(void) m_methodCombo->blockSignals(blocked);
}
}
void CPPEditor::updateMethodBoxToolTip()
{
m_methodCombo->setToolTip(m_methodCombo->currentText());
}
static bool isCompatible(Name *name, Name *otherName)
{
if (NameId *nameId = name->asNameId()) {

View File

@@ -115,7 +115,7 @@ private slots:
void updateFileName();
void jumpToMethod(int index);
void updateMethodBoxIndex();
void updateMethodBoxToolTip();
void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
private:

View File

@@ -0,0 +1,50 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "cppclassesfilter.h"
using namespace CppTools::Internal;
CppClassesFilter::CppClassesFilter(CppModelManager *manager, Core::EditorManager *editorManager)
: CppQuickOpenFilter(manager, editorManager)
{
setShortcutString("c");
setIncludedByDefault(false);
search.setSymbolsToSearchFor(SearchSymbols::Classes);
search.setSeparateScope(true);
}
CppClassesFilter::~CppClassesFilter()
{
}

View File

@@ -31,52 +31,28 @@
**
***************************************************************************/
#ifndef INDEXWINDOW_H
#define INDEXWINDOW_H
#ifndef CPPCLASSESFILTER_H
#define CPPCLASSESFILTER_H
#include <QtCore/QUrl>
#include <QtGui/QWidget>
#include <QtGui/QLineEdit>
#include <cppquickopenfilter.h>
QT_BEGIN_NAMESPACE
namespace CppTools {
namespace Internal {
class QHelpIndexWidget;
class QHelpEngine;
class IndexWindow : public QWidget
class CppClassesFilter : public CppQuickOpenFilter
{
Q_OBJECT
public:
IndexWindow(QHelpEngine *helpEngine, QWidget *parent = 0);
~IndexWindow();
CppClassesFilter(CppModelManager *manager, Core::EditorManager *editorManager);
~CppClassesFilter();
void setSearchLineEditText(const QString &text);
QString searchLineEditText() const
{
return m_searchLineEdit->text();
}
signals:
void linkActivated(const QUrl &link);
void linksActivated(const QMap<QString, QUrl> &links,
const QString &keyword);
void escapePressed();
private slots:
void filterIndices(const QString &filter);
void enableSearchLineEdit();
void disableSearchLineEdit();
private:
bool eventFilter(QObject *obj, QEvent *e);
void focusInEvent(QFocusEvent *e);
QLineEdit *m_searchLineEdit;
QHelpIndexWidget *m_indexWidget;
QHelpEngine *m_helpEngine;
QString trName() const { return tr("Classes"); }
QString name() const { return QLatin1String("Classes"); }
Priority priority() const { return Medium; }
};
QT_END_NAMESPACE
} // namespace Internal
} // namespace CppTools
#endif // INDEXWINDOW_H
#endif // CPPCLASSESFILTER_H

View File

@@ -60,7 +60,7 @@
using namespace CppTools::Internal;
CppHoverHandler::CppHoverHandler(CppModelManager *manager, QObject *parent)
: QObject(parent), m_manager(manager)
: QObject(parent), m_manager(manager), m_helpEngineNeedsSetup(false)
{
QFileInfo fi(ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>()->settings()->fileName());
m_helpEngine = new QHelpEngineCore(fi.absolutePath()
@@ -68,6 +68,7 @@ CppHoverHandler::CppHoverHandler(CppModelManager *manager, QObject *parent)
//m_helpEngine->setAutoSaveFilter(false);
m_helpEngine->setupData();
m_helpEngine->setCurrentFilter(tr("Unfiltered"));
m_helpEngineNeedsSetup = m_helpEngine->registeredDocumentations().count() == 0;
}
void CppHoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int pos)
@@ -234,6 +235,12 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
}
}
if (m_helpEngineNeedsSetup
&& m_helpEngine->registeredDocumentations().count() > 0) {
m_helpEngine->setupData();
m_helpEngineNeedsSetup = false;
}
if (!m_helpId.isEmpty() && !m_helpEngine->linksForIdentifier(m_helpId).isEmpty()) {
m_toolTip = QString(QLatin1String("<table><tr><td valign=middle><nobr>%1</td>"
"<td><img src=\":/cpptools/images/f1.svg\"></td></tr></table>")).arg(Qt::escape(m_toolTip));

View File

@@ -68,6 +68,7 @@ private:
QHelpEngineCore *m_helpEngine;
QString m_helpId;
QString m_toolTip;
bool m_helpEngineNeedsSetup;
};
} // namespace Internal

View File

@@ -129,9 +129,12 @@ public:
void setProjectFiles(const QStringList &files)
{ m_projectFiles = files; }
void operator()(QString &fileName)
void run(QString &fileName)
{ sourceNeeded(fileName, IncludeGlobal); }
void operator()(QString &fileName)
{ run(fileName); }
protected:
bool includeFile(const QString &absoluteFilePath, QByteArray *result)
{
@@ -254,7 +257,7 @@ protected:
}
virtual void startExpandingMacro(unsigned offset,
const rpp::Macro &macro,
const rpp::Macro &,
const QByteArray &originalText)
{
if (! m_currentDoc)
@@ -264,7 +267,7 @@ protected:
m_currentDoc->addMacroUse(offset, originalText.length());
}
virtual void stopExpandingMacro(unsigned offset, const rpp::Macro &macro)
virtual void stopExpandingMacro(unsigned, const rpp::Macro &)
{
if (! m_currentDoc)
return;
@@ -409,6 +412,8 @@ CppModelManager::CppModelManager(QObject *parent) :
CppModelManagerInterface(parent),
m_core(ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>())
{
m_dirty = true;
m_projectExplorer = ExtensionSystem::PluginManager::instance()
->getObject<ProjectExplorer::ProjectExplorerPlugin>();
@@ -417,6 +422,9 @@ CppModelManager::CppModelManager(QObject *parent) :
ProjectExplorer::SessionManager *session = m_projectExplorer->session();
Q_ASSERT(session != 0);
connect(session, SIGNAL(projectAdded(ProjectExplorer::Project*)),
this, SLOT(onProjectAdded(ProjectExplorer::Project*)));
connect(session, SIGNAL(aboutToRemoveProject(ProjectExplorer::Project *)),
this, SLOT(onAboutToRemoveProject(ProjectExplorer::Project *)));
@@ -448,7 +456,7 @@ Document::Ptr CppModelManager::document(const QString &fileName)
CppModelManager::DocumentTable CppModelManager::documents()
{ return m_documents; }
QStringList CppModelManager::projectFiles() const
QStringList CppModelManager::updateProjectFiles() const
{
QStringList files;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
@@ -460,7 +468,7 @@ QStringList CppModelManager::projectFiles() const
return files;
}
QStringList CppModelManager::includePaths() const
QStringList CppModelManager::updateIncludePaths() const
{
QStringList includePaths;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
@@ -472,7 +480,7 @@ QStringList CppModelManager::includePaths() const
return includePaths;
}
QStringList CppModelManager::frameworkPaths() const
QStringList CppModelManager::updateFrameworkPaths() const
{
QStringList frameworkPaths;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
@@ -484,7 +492,7 @@ QStringList CppModelManager::frameworkPaths() const
return frameworkPaths;
}
QByteArray CppModelManager::definedMacros() const
QByteArray CppModelManager::updateDefinedMacros() const
{
QByteArray macros;
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(m_projects);
@@ -496,7 +504,7 @@ QByteArray CppModelManager::definedMacros() const
return macros;
}
QMap<QString, QByteArray> CppModelManager::buildWorkingCopyList() const
QMap<QString, QByteArray> CppModelManager::buildWorkingCopyList()
{
QMap<QString, QByteArray> workingCopy;
QMapIterator<TextEditor::ITextEditor *, CppEditorSupport *> it(m_editorSupport);
@@ -527,8 +535,14 @@ QFuture<void> CppModelManager::refreshSourceFiles(const QStringList &sourceFiles
if (! sourceFiles.isEmpty() && qgetenv("QTCREATOR_NO_CODE_INDEXER").isNull()) {
const QMap<QString, QByteArray> workingCopy = buildWorkingCopyList();
QFuture<void> result = QtConcurrent::run(&CppModelManager::parse, this,
sourceFiles, workingCopy);
CppPreprocessor *preproc = new CppPreprocessor(this);
preproc->setProjectFiles(projectFiles());
preproc->setIncludePaths(includePaths());
preproc->setFrameworkPaths(frameworkPaths());
preproc->setWorkingCopy(workingCopy);
QFuture<void> result = QtConcurrent::run(&CppModelManager::parse,
preproc, sourceFiles);
if (sourceFiles.count() > 1) {
m_core->progressManager()->addTask(result, tr("Indexing"),
@@ -669,28 +683,35 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc)
sel.cursor = c;
selections.append(sel);
}
ed->setExtraExtraSelections(selections);
ed->setExtraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection, selections);
break;
}
}
}
void CppModelManager::onProjectAdded(ProjectExplorer::Project *)
{
m_dirty = true;
}
void CppModelManager::onAboutToRemoveProject(ProjectExplorer::Project *project)
{
m_dirty = true;
m_projects.remove(project);
GC();
}
void CppModelManager::onSessionUnloaded()
{
if (m_core->progressManager())
if (m_core->progressManager()) {
m_core->progressManager()->cancelTasks(CppTools::Constants::TASK_INDEX);
m_dirty = true;
}
}
void CppModelManager::parse(QFutureInterface<void> &future,
CppModelManager *model,
QStringList files,
QMap<QString, QByteArray> workingCopy)
CppPreprocessor *preproc,
QStringList files)
{
Q_ASSERT(! files.isEmpty());
@@ -699,14 +720,8 @@ void CppModelManager::parse(QFutureInterface<void> &future,
future.setProgressRange(0, files.size());
CppPreprocessor preproc(model);
preproc.setWorkingCopy(workingCopy);
preproc.setProjectFiles(model->projectFiles());
preproc.setIncludePaths(model->includePaths());
preproc.setFrameworkPaths(model->frameworkPaths());
QString conf = QLatin1String(pp_configuration_file);
(void) preproc(conf);
(void) preproc->run(conf);
const int STEP = 10;
@@ -725,7 +740,7 @@ void CppModelManager::parse(QFutureInterface<void> &future,
#endif
QString fileName = files.at(i);
preproc(fileName);
preproc->run(fileName);
if (! (i % STEP)) // Yields execution of the current thread.
QThread::yieldCurrentThread();
@@ -739,6 +754,8 @@ void CppModelManager::parse(QFutureInterface<void> &future,
// Restore the previous thread priority.
QThread::currentThread()->setPriority(QThread::NormalPriority);
delete preproc;
}
void CppModelManager::GC()
@@ -746,7 +763,7 @@ void CppModelManager::GC()
DocumentTable documents = m_documents;
QSet<QString> processed;
QStringList todo = m_projectFiles;
QStringList todo = projectFiles();
while (! todo.isEmpty()) {
QString fn = todo.last();

View File

@@ -58,6 +58,7 @@ namespace CppTools {
namespace Internal {
class CppEditorSupport;
class CppPreprocessor;
class CppHoverHandler;
class CppModelManager : public CppModelManagerInterface
@@ -97,18 +98,54 @@ private Q_SLOTS:
void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
void onAboutToRemoveProject(ProjectExplorer::Project *project);
void onSessionUnloaded();
void onProjectAdded(ProjectExplorer::Project *project);
private:
QMap<QString, QByteArray> buildWorkingCopyList() const;
QStringList projectFiles() const;
QStringList includePaths() const;
QStringList frameworkPaths() const;
QByteArray definedMacros() const;
QMap<QString, QByteArray> buildWorkingCopyList();
QStringList projectFiles()
{
ensureUpdated();
return m_projectFiles;
}
QStringList includePaths()
{
ensureUpdated();
return m_includePaths;
}
QStringList frameworkPaths()
{
ensureUpdated();
return m_frameworkPaths;
}
QByteArray definedMacros()
{
ensureUpdated();
return m_definedMacros;
}
QStringList updateProjectFiles() const;
QStringList updateIncludePaths() const;
QStringList updateFrameworkPaths() const;
QByteArray updateDefinedMacros() const;
void ensureUpdated() {
if (! m_dirty)
return;
m_projectFiles = updateProjectFiles();
m_includePaths = updateIncludePaths();
m_frameworkPaths = updateFrameworkPaths();
m_definedMacros = updateDefinedMacros();
m_dirty = false;
}
static void parse(QFutureInterface<void> &future,
CppModelManager *model,
QStringList files,
QMap<QString, QByteArray> workingCopy);
CppPreprocessor *preproc,
QStringList files);
private:
Core::ICore *m_core;
@@ -116,8 +153,12 @@ private:
CppHoverHandler *m_hoverHandler;
DocumentTable m_documents;
// List of available source files
// cache
bool m_dirty;
QStringList m_projectFiles;
QStringList m_includePaths;
QStringList m_frameworkPaths;
QByteArray m_definedMacros;
// editor integration
QMap<TextEditor::ITextEditor *, CppEditorSupport *> m_editorSupport;

View File

@@ -32,172 +32,13 @@
***************************************************************************/
#include "cppquickopenfilter.h"
#include "cppmodelmanager.h"
#include <Literals.h>
#include <Symbols.h>
#include <SymbolVisitor.h>
#include <Scope.h>
#include <cplusplus/Overview.h>
#include <cplusplus/Icons.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h>
#include <QtCore/QMultiMap>
#include <functional>
using namespace CPlusPlus;
namespace CppTools {
namespace Internal {
class SearchSymbols: public std::unary_function<Document::Ptr, QList<ModelItemInfo> >,
protected SymbolVisitor
{
Overview overview;
Icons icons;
QList<ModelItemInfo> items;
public:
QList<ModelItemInfo> operator()(Document::Ptr doc)
{ return operator()(doc, QString()); }
QList<ModelItemInfo> operator()(Document::Ptr doc, const QString &scope)
{
QString previousScope = switchScope(scope);
items.clear();
for (unsigned i = 0; i < doc->globalSymbolCount(); ++i) {
accept(doc->globalSymbolAt(i));
}
(void) switchScope(previousScope);
return items;
}
protected:
using SymbolVisitor::visit;
void accept(Symbol *symbol)
{ Symbol::visitSymbol(symbol, this); }
QString switchScope(const QString &scope)
{
QString previousScope = _scope;
_scope = scope;
return previousScope;
}
virtual bool visit(Enum *symbol)
{
QString name = symbolName(symbol);
QString previousScope = switchScope(name);
QIcon icon = icons.iconForSymbol(symbol);
Scope *members = symbol->members();
items.append(ModelItemInfo(name, QString(), ModelItemInfo::Enum,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
virtual bool visit(Function *symbol)
{
QString name = symbolName(symbol);
QString type = overview.prettyType(symbol->type());
QIcon icon = icons.iconForSymbol(symbol);
items.append(ModelItemInfo(name, type, ModelItemInfo::Method,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
return false;
}
virtual bool visit(Namespace *symbol)
{
QString name = symbolName(symbol);
QString previousScope = switchScope(name);
Scope *members = symbol->members();
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
#if 0
// This visit method would make function declaration be included in QuickOpen
virtual bool visit(Declaration *symbol)
{
if (symbol->type()->isFunction()) {
QString name = symbolName(symbol);
QString type = overview.prettyType(symbol->type());
//QIcon icon = ...;
items.append(ModelItemInfo(name, type, ModelItemInfo::Method,
QString::fromUtf8(symbol->fileName(), symbol->line()),
symbol->line()));
}
return false;
}
#endif
virtual bool visit(Class *symbol)
{
QString name = symbolName(symbol);
QString previousScope = switchScope(name);
QIcon icon = icons.iconForSymbol(symbol);
items.append(ModelItemInfo(name, QString(), ModelItemInfo::Class,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
Scope *members = symbol->members();
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
QString symbolName(Symbol *symbol) const
{
QString name = _scope;
if (! name.isEmpty())
name += QLatin1String("::");
QString symbolName = overview.prettyName(symbol->name());
if (symbolName.isEmpty()) {
QString type;
if (symbol->isNamespace()) {
type = QLatin1String("namespace");
} else if (symbol->isEnum()) {
type = QLatin1String("enum");
} else if (Class *c = symbol->asClass()) {
if (c->isUnion()) {
type = QLatin1String("union");
} else if (c->isStruct()) {
type = QLatin1String("struct");
} else {
type = QLatin1String("class");
}
} else {
type = QLatin1String("symbol");
}
symbolName = QLatin1String("<anonymous ");
symbolName += type;
symbolName += QLatin1String(">");
}
name += symbolName;
return name;
}
private:
QString _scope;
};
} // namespace Internal
} // namespace CppTools
using namespace CppTools::Internal;
CppQuickOpenFilter::CppQuickOpenFilter(CppModelManager *manager, Core::EditorManager *editorManager)
@@ -225,10 +66,9 @@ void CppQuickOpenFilter::onDocumentUpdated(CPlusPlus::Document::Ptr doc)
void CppQuickOpenFilter::onAboutToRemoveFiles(const QStringList &files)
{
foreach (QString file, files) {
foreach (const QString &file, files)
m_searchList.remove(file);
}
}
void CppQuickOpenFilter::refresh(QFutureInterface<void> &future)
{
@@ -245,7 +85,6 @@ QList<QuickOpen::FilterEntry> CppQuickOpenFilter::matchesFor(const QString &orig
return entries;
bool hasWildcard = (entry.contains('*') || entry.contains('?'));
SearchSymbols search;
QMutableMapIterator<QString, Info> it(m_searchList);
while (it.hasNext()) {
it.next();
@@ -276,6 +115,5 @@ QList<QuickOpen::FilterEntry> CppQuickOpenFilter::matchesFor(const QString &orig
void CppQuickOpenFilter::accept(QuickOpen::FilterEntry selection) const
{
ModelItemInfo info = qvariant_cast<CppTools::Internal::ModelItemInfo>(selection.internalData);
TextEditor::BaseTextEditor::openEditorAt(info.fileName, info.line);
}

View File

@@ -34,45 +34,18 @@
#ifndef CPPQUICKOPENFILTER_H
#define CPPQUICKOPENFILTER_H
#include "cppmodelmanager.h"
#include <cplusplus/CppDocument.h>
#include <coreplugin/editormanager/editormanager.h>
#include "searchsymbols.h"
#include <quickopen/iquickopenfilter.h>
#include <QtGui/QIcon>
#include <QFile>
#include <QMetaType>
namespace Core {
class EditorManager;
}
namespace CppTools {
namespace Internal {
struct ModelItemInfo
{
enum ItemType { Enum, Class, Method };
ModelItemInfo()
{ }
ModelItemInfo(const QString &symbolName,
const QString &symbolType,
ItemType type,
const QString &fileName,
int line,
const QIcon &icon)
: symbolName(symbolName),
symbolType(symbolType),
type(type),
fileName(fileName),
line(line),
icon(icon)
{ }
QString symbolName;
QString symbolType;
ItemType type;
QString fileName;
int line;
QIcon icon;
};
class CppModelManager;
class CppQuickOpenFilter : public QuickOpen::IQuickOpenFilter
{
@@ -82,12 +55,15 @@ public:
~CppQuickOpenFilter();
QString trName() const { return tr("Classes and Methods"); }
QString name() const { return "Classes and Methods"; }
QString name() const { return QLatin1String("Classes and Methods"); }
Priority priority() const { return Medium; }
QList<QuickOpen::FilterEntry> matchesFor(const QString &entry);
void accept(QuickOpen::FilterEntry selection) const;
void refresh(QFutureInterface<void> &future);
protected:
SearchSymbols search;
private slots:
void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
void onAboutToRemoveFiles(const QStringList &files);
@@ -114,6 +90,4 @@ private:
} // namespace Internal
} // namespace CppTools
Q_DECLARE_METATYPE(CppTools::Internal::ModelItemInfo)
#endif // CPPQUICKOPENFILTER_H

View File

@@ -32,6 +32,7 @@
***************************************************************************/
#include "cpptools.h"
#include "cppclassesfilter.h"
#include "cppcodecompletion.h"
#include "cpphoverhandler.h"
#include "cppmodelmanager.h"
@@ -87,6 +88,7 @@ bool CppToolsPlugin::initialize(const QStringList & /*arguments*/, QString *)
CppQuickOpenFilter *quickOpenFilter = new CppQuickOpenFilter(m_modelManager,
m_core->editorManager());
addAutoReleasedObject(quickOpenFilter);
addAutoReleasedObject(new CppClassesFilter(m_modelManager, m_core->editorManager()));
// Menus
Core::IActionContainer *mtools = am->actionContainer(Core::Constants::M_TOOLS);

View File

@@ -7,28 +7,24 @@ include(cpptools_dependencies.pri)
# DEFINES += QT_NO_CAST_FROM_ASCII
DEFINES += QT_NO_CAST_TO_ASCII
unix:QMAKE_CXXFLAGS_DEBUG += -O3
INCLUDEPATH += .
DEFINES += CPPTOOLS_LIBRARY
CONFIG += help
include(rpp/rpp.pri)|error("Can't find RPP")
HEADERS += \
cpptools_global.h \
cppquickopenfilter.h
SOURCES += \
cppquickopenfilter.cpp \
cpptoolseditorsupport.cpp
HEADERS += cpptools_global.h \
cppquickopenfilter.h \
cppclassesfilter.h \
searchsymbols.h
SOURCES += cppquickopenfilter.cpp \
cpptoolseditorsupport.cpp \
cppclassesfilter.cpp \
searchsymbols.cpp
# Input
SOURCES += cpptools.cpp \
cppmodelmanager.cpp \
cppcodecompletion.cpp \
cpphoverhandler.cpp
HEADERS += cpptools.h \
cppmodelmanager.h \
cppcodecompletion.h \
@@ -36,5 +32,4 @@ HEADERS += cpptools.h \
cppmodelmanagerinterface.h \
cpptoolseditorsupport.h \
cpptoolsconstants.h
RESOURCES += cpptools.qrc

View File

@@ -0,0 +1,204 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "searchsymbols.h"
#include <Literals.h>
#include <Scope.h>
using namespace CPlusPlus;
using namespace CppTools::Internal;
SearchSymbols::SearchSymbols():
symbolsToSearchFor(Classes | Functions | Enums),
separateScope(false)
{
}
void SearchSymbols::setSymbolsToSearchFor(SymbolTypes types)
{
symbolsToSearchFor = types;
}
void SearchSymbols::setSeparateScope(bool separateScope)
{
this->separateScope = separateScope;
}
QList<ModelItemInfo> SearchSymbols::operator()(Document::Ptr doc, const QString &scope)
{
QString previousScope = switchScope(scope);
items.clear();
for (unsigned i = 0; i < doc->globalSymbolCount(); ++i) {
accept(doc->globalSymbolAt(i));
}
(void) switchScope(previousScope);
return items;
}
QString SearchSymbols::switchScope(const QString &scope)
{
QString previousScope = _scope;
_scope = scope;
return previousScope;
}
bool SearchSymbols::visit(Enum *symbol)
{
if (!(symbolsToSearchFor & Enums))
return false;
QString name = symbolName(symbol);
QString scopedName = scopedSymbolName(name);
QString previousScope = switchScope(scopedName);
appendItem(separateScope ? name : scopedName,
separateScope ? previousScope : QString(),
ModelItemInfo::Enum, symbol);
Scope *members = symbol->members();
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
bool SearchSymbols::visit(Function *symbol)
{
if (!(symbolsToSearchFor & Functions))
return false;
QString name = symbolName(symbol);
QString scopedName = scopedSymbolName(name);
QString type = overview.prettyType(symbol->type(),
separateScope ? symbol->name() : 0);
appendItem(separateScope ? type : scopedName,
separateScope ? _scope : type,
ModelItemInfo::Method, symbol);
return false;
}
bool SearchSymbols::visit(Namespace *symbol)
{
QString name = findOrInsert(scopedSymbolName(symbol));
QString previousScope = switchScope(name);
Scope *members = symbol->members();
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
#if 0
bool SearchSymbols::visit(Declaration *symbol)
{
if (symbol->type()->isFunction()) {
QString name = scopedSymbolName(symbol);
QString type = overview.prettyType(symbol->type());
appendItems(name, type, ModelItemInfo::Method, symbol->fileName());
}
return false;
}
#endif
bool SearchSymbols::visit(Class *symbol)
{
if (!(symbolsToSearchFor & Classes))
return false;
QString name = symbolName(symbol);
QString scopedName = scopedSymbolName(name);
QString previousScope = switchScope(scopedName);
appendItem(separateScope ? name : scopedName,
separateScope ? previousScope : QString(),
ModelItemInfo::Class, symbol);
Scope *members = symbol->members();
for (unsigned i = 0; i < members->symbolCount(); ++i) {
accept(members->symbolAt(i));
}
(void) switchScope(previousScope);
return false;
}
QString SearchSymbols::scopedSymbolName(const QString &symbolName) const
{
QString name = _scope;
if (! name.isEmpty())
name += QLatin1String("::");
name += symbolName;
return name;
}
QString SearchSymbols::scopedSymbolName(const Symbol *symbol) const
{
return scopedSymbolName(symbolName(symbol));
}
QString SearchSymbols::symbolName(const Symbol *symbol) const
{
QString symbolName = overview.prettyName(symbol->name());
if (symbolName.isEmpty()) {
QString type;
if (symbol->isNamespace()) {
type = QLatin1String("namespace");
} else if (symbol->isEnum()) {
type = QLatin1String("enum");
} else if (const Class *c = symbol->asClass()) {
if (c->isUnion()) {
type = QLatin1String("union");
} else if (c->isStruct()) {
type = QLatin1String("struct");
} else {
type = QLatin1String("class");
}
} else {
type = QLatin1String("symbol");
}
symbolName = QLatin1String("<anonymous ");
symbolName += type;
symbolName += QLatin1String(">");
}
return symbolName;
}
void SearchSymbols::appendItem(const QString &name,
const QString &info,
ModelItemInfo::ItemType type,
const CPlusPlus::Symbol *symbol)
{
const QIcon icon = icons.iconForSymbol(symbol);
items.append(ModelItemInfo(name, info, type,
QString::fromUtf8(symbol->fileName(), symbol->fileNameLength()),
symbol->line(),
icon));
}

View File

@@ -0,0 +1,145 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.2, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef SEARCHSYMBOLS_H
#define SEARCHSYMBOLS_H
#include <cplusplus/CppDocument.h>
#include <cplusplus/Icons.h>
#include <cplusplus/Overview.h>
#include <Symbols.h>
#include <SymbolVisitor.h>
#include <QIcon>
#include <QMetaType>
#include <QString>
namespace CppTools {
namespace Internal {
struct ModelItemInfo
{
enum ItemType { Enum, Class, Method };
ModelItemInfo()
{ }
ModelItemInfo(const QString &symbolName,
const QString &symbolType,
ItemType type,
const QString &fileName,
int line,
const QIcon &icon)
: symbolName(symbolName),
symbolType(symbolType),
type(type),
fileName(fileName),
line(line),
icon(icon)
{ }
QString symbolName;
QString symbolType;
ItemType type;
QString fileName;
int line;
QIcon icon;
};
class SearchSymbols: public std::unary_function<CPlusPlus::Document::Ptr, QList<ModelItemInfo> >,
protected CPlusPlus::SymbolVisitor
{
public:
enum SymbolType {
Classes = 0x1,
Functions = 0x2,
Enums = 0x4
};
Q_DECLARE_FLAGS(SymbolTypes, SymbolType)
SearchSymbols();
void setSymbolsToSearchFor(SymbolTypes types);
void setSeparateScope(bool separateScope);
QList<ModelItemInfo> operator()(CPlusPlus::Document::Ptr doc)
{ return operator()(doc, QString()); }
QList<ModelItemInfo> operator()(CPlusPlus::Document::Ptr doc, const QString &scope);
protected:
using SymbolVisitor::visit;
void accept(CPlusPlus::Symbol *symbol)
{ CPlusPlus::Symbol::visitSymbol(symbol, this); }
QString switchScope(const QString &scope);
virtual bool visit(CPlusPlus::Enum *symbol);
virtual bool visit(CPlusPlus::Function *symbol);
virtual bool visit(CPlusPlus::Namespace *symbol);
#if 0
// This visit method would make function declaration be included in QuickOpen
virtual bool visit(CPlusPlus::Declaration *symbol);
#endif
virtual bool visit(CPlusPlus::Class *symbol);
QString scopedSymbolName(const QString &symbolName) const;
QString scopedSymbolName(const CPlusPlus::Symbol *symbol) const;
QString symbolName(const CPlusPlus::Symbol *symbol) const;
void appendItem(const QString &name,
const QString &info,
ModelItemInfo::ItemType type,
const CPlusPlus::Symbol *symbol);
private:
QString findOrInsert(const QString &s)
{ return *strings.insert(s); }
QSet<QString> strings; // Used to avoid QString duplication
QString _scope;
CPlusPlus::Overview overview;
CPlusPlus::Icons icons;
QList<ModelItemInfo> items;
SymbolTypes symbolsToSearchFor;
bool separateScope;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(SearchSymbols::SymbolTypes)
} // namespace Internal
} // namespace CppTools
Q_DECLARE_METATYPE(CppTools::Internal::ModelItemInfo)
#endif // SEARCHSYMBOLS_H

View File

@@ -317,10 +317,20 @@ void DebuggerManager::init()
m_debugDumpersAction = new QAction(this);
m_debugDumpersAction->setText(tr("Debug Custom Dumpers"));
m_debugDumpersAction->setToolTip(tr("This is an internal tool to "
"make debugging the Custom Data Dumper code easier. "
"Using this action is in general not needed unless you "
"want do debug Qt Creator itself."));
m_debugDumpersAction->setCheckable(true);
m_skipKnownFramesAction = new QAction(this);
m_skipKnownFramesAction->setText(tr("Skip Known Frames When Stepping"));
m_skipKnownFramesAction->setToolTip(tr("After checking this option"
"'Step Into' combines in certain situations several steps, "
"leading to 'less noisy' debugging. So will, e.g., the atomic "
"reference counting code be skipped, and a single 'Step Into' "
"for a signal emission will end up directly in the slot connected "
"to it"));
m_skipKnownFramesAction->setCheckable(true);
m_useCustomDumpersAction = new QAction(this);
@@ -330,13 +340,6 @@ void DebuggerManager::init()
m_useCustomDumpersAction->setCheckable(true);
m_useCustomDumpersAction->setChecked(true);
m_useCustomDumpersAction = new QAction(this);
m_useCustomDumpersAction->setText(tr("Use Custom Display for Qt Objects"));
m_useCustomDumpersAction->setToolTip(tr("Checking this will make the debugger "
"try to use code to format certain data (QObject, QString, ...) nicely. "));
m_useCustomDumpersAction->setCheckable(true);
m_useCustomDumpersAction->setChecked(true);
m_useFastStartAction = new QAction(this);
m_useFastStartAction->setText(tr("Fast Debugger Start"));
m_useFastStartAction->setToolTip(tr("Checking this will make the debugger "

View File

@@ -1276,7 +1276,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
m_currentFrame = frame.findChild("addr").data() + '%' +
frame.findChild("func").data() + '%';
QApplication::alert(q->mainWindow(), 200);
QApplication::alert(q->mainWindow(), 3000);
sendCommand("-file-list-exec-source-files", GdbQuerySources);
sendCommand("-break-list", BreakList);
QVariant var = QVariant::fromValue<GdbMi>(data);

View File

@@ -63,6 +63,7 @@ FormClassWizardPage::FormClassWizardPage(QWidget * parent) :
m_ui->newClassWidget->setBaseClassInputVisible(false);
m_ui->newClassWidget->setNamespacesEnabled(true);
m_ui->newClassWidget->setAllowDirectories(true);
connect(m_ui->newClassWidget, SIGNAL(validChanged()), this, SLOT(slotValidChanged()));

View File

@@ -162,6 +162,9 @@ int BaseTextFind::replaceAll(const QString &before, const QString &after,
QTextDocument::FindFlags findFlags)
{
QTextCursor editCursor = textCursor();
if (!m_findScope.isNull())
editCursor.setPosition(m_findScope.selectionStart());
else
editCursor.movePosition(QTextCursor::Start);
editCursor.beginEditBlock();
int count = 0;

View File

@@ -80,16 +80,16 @@ void CommitData::clear()
panelInfo.clear();
panelData.clear();
commitFiles.clear();
notUpdatedFiles.clear();
stagedFiles.clear();
unstagedFiles.clear();
untrackedFiles.clear();
}
QDebug operator<<(QDebug d, const CommitData &data)
{
d << data.panelInfo << data.panelData;
d.nospace() << "Commit: " << data.commitFiles << " Not updated: "
<< data.notUpdatedFiles << " Untracked: " << data.untrackedFiles;
d.nospace() << "Commit: " << data.stagedFiles << " Not updated: "
<< data.unstagedFiles << " Untracked: " << data.untrackedFiles;
return d;
}

View File

@@ -71,8 +71,8 @@ struct CommitData
void clear();
GitSubmitEditorPanelInfo panelInfo;
GitSubmitEditorPanelData panelData;
QStringList commitFiles;
QStringList notUpdatedFiles;
QStringList stagedFiles;
QStringList unstagedFiles;
QStringList untrackedFiles;
};

View File

@@ -35,6 +35,7 @@
#include "gitplugin.h"
#include "gitconstants.h"
#include "commitdata.h"
#include "gitsubmiteditor.h"
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -51,7 +52,9 @@
#include <QtCore/QFuture>
#include <QtCore/QTime>
#include <QtGui/QErrorMessage>
#include <QtGui/QMessageBox>
#include <QtGui/QMainWindow> // for msg box parent
#include <QtGui/QPushButton>
using namespace Git;
using namespace Git::Internal;
@@ -77,12 +80,24 @@ inline Core::IEditor* locateEditor(const Core::ICore *core, const char *property
return 0;
}
static inline QString msgRepositoryNotFound(const QString &dir)
{
return GitClient::tr("Unable to determine the repository for %1.").arg(dir);
}
static inline QString msgParseFilesFailed()
{
return GitClient::tr("Unable to parse the file output.");
}
// Format a command for the status window
static QString formatCommand(const QString &binary, const QStringList &args)
{
const QString timeStamp = QTime::currentTime().toString(QLatin1String("HH:mm"));
return GitClient::tr("%1 Executing: %2 %3\n").arg(timeStamp, binary, args.join(QString(QLatin1Char(' '))));
}
// ---------------- GitClient
GitClient::GitClient(GitPlugin* plugin, Core::ICore *core) :
m_msgWait(tr("Waiting for data...")),
m_plugin(plugin),
@@ -311,6 +326,19 @@ bool GitClient::synchronousAdd(const QString &workingDirectory, const QStringLis
bool GitClient::synchronousReset(const QString &workingDirectory,
const QStringList &files)
{
QString errorMessage;
const bool rc = synchronousReset(workingDirectory, files, &errorMessage);
if (!rc) {
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup(false);
}
return rc;
}
bool GitClient::synchronousReset(const QString &workingDirectory,
const QStringList &files,
QString *errorMessage)
{
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << workingDirectory << files;
@@ -325,9 +353,25 @@ bool GitClient::synchronousReset(const QString &workingDirectory,
// Note that git exits with 1 even if the operation is successful
// Assume real failure if the output does not contain "foo.cpp modified"
if (!rc && !output.contains(QLatin1String("modified"))) {
const QString errorMessage = tr("Unable to reset %n file(s) in %1: %2", 0, files.size()).
arg(workingDirectory, QString::fromLocal8Bit(errorText));
m_plugin->outputWindow()->append(errorMessage);
*errorMessage = tr("Unable to reset %n file(s) in %1: %2", 0, files.size()).arg(workingDirectory, QString::fromLocal8Bit(errorText));
return false;
}
return true;
}
bool GitClient::synchronousCheckout(const QString &workingDirectory,
const QStringList &files,
QString *errorMessage)
{
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << workingDirectory << files;
QByteArray outputText;
QByteArray errorText;
QStringList arguments;
arguments << QLatin1String("checkout") << QLatin1String("--") << files;
const bool rc = synchronousGit(workingDirectory, arguments, &outputText, &errorText);
if (!rc) {
*errorMessage = tr("Unable to checkout %n file(s) in %1: %2", 0, files.size()).arg(workingDirectory, QString::fromLocal8Bit(errorText));
return false;
}
return true;
@@ -365,15 +409,17 @@ void GitClient::executeGit(const QString &workingDirectory, const QStringList &a
command->execute(arguments, workingDirectory, environment);
}
bool GitClient::synchronousGit(const QString &workingDirectory
, const QStringList &arguments
, QByteArray* outputText
, QByteArray* errorText)
bool GitClient::synchronousGit(const QString &workingDirectory,
const QStringList &arguments,
QByteArray* outputText,
QByteArray* errorText,
bool logCommandToWindow)
{
if (Git::Constants::debug)
qDebug() << "synchronousGit" << workingDirectory << arguments;
const QString binary = QLatin1String(kGitCommand);
if (logCommandToWindow)
m_plugin->outputWindow()->append(formatCommand(binary, arguments));
QProcess process;
@@ -456,10 +502,11 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory,
#<tab>modified:<blanks>git.pro
\endcode
*/
static bool parseFiles(const QStringList &lines, CommitData *d)
static bool parseFiles(const QString &output, CommitData *d)
{
enum State { None, CommitFiles, NotUpdatedFiles, UntrackedFiles };
const QStringList lines = output.split(QLatin1Char('\n'));
const QString branchIndicator = QLatin1String(kBranchIndicatorC);
const QString commitIndicator = QLatin1String("# Changes to be committed:");
const QString notUpdatedIndicator = QLatin1String("# Changed but not updated:");
@@ -492,10 +539,10 @@ static bool parseFiles(const QStringList &lines, CommitData *d)
const QString fileSpec = line.mid(2).trimmed();
switch (s) {
case CommitFiles:
d->commitFiles.push_back(trimFileSpecification(fileSpec));
d->stagedFiles.push_back(trimFileSpecification(fileSpec));
break;
case NotUpdatedFiles:
d->notUpdatedFiles.push_back(trimFileSpecification(fileSpec));
d->unstagedFiles.push_back(trimFileSpecification(fileSpec));
break;
case UntrackedFiles:
d->untrackedFiles.push_back(QLatin1String("untracked: ") + fileSpec);
@@ -509,7 +556,7 @@ static bool parseFiles(const QStringList &lines, CommitData *d)
}
}
}
return !d->commitFiles.empty() || !d->notUpdatedFiles.empty() || !d->untrackedFiles.empty();
return !d->stagedFiles.empty() || !d->unstagedFiles.empty() || !d->untrackedFiles.empty();
}
bool GitClient::getCommitData(const QString &workingDirectory,
@@ -525,7 +572,7 @@ bool GitClient::getCommitData(const QString &workingDirectory,
// Find repo
const QString repoDirectory = GitClient::findRepositoryForDirectory(workingDirectory);
if (repoDirectory.isEmpty()) {
*errorMessage = tr("Unable to determine the repository for %1.").arg(workingDirectory);
*errorMessage = msgRepositoryNotFound(workingDirectory);
return false;
}
@@ -551,7 +598,7 @@ bool GitClient::getCommitData(const QString &workingDirectory,
case StatusChanged:
break;
case StatusUnchanged:
*errorMessage = tr("There are no modified files.");
*errorMessage = msgNoChangedFiles();
return false;
case StatusFailed:
return false;
@@ -575,9 +622,8 @@ bool GitClient::getCommitData(const QString &workingDirectory,
// #
// # list of files...
const QStringList lines = output.split(QLatin1Char('\n'));
if (!parseFiles(lines, d)) {
*errorMessage = tr("Unable to parse the file output.");
if (!parseFiles(output, d)) {
*errorMessage = msgParseFilesFailed();
return false;
}
@@ -638,6 +684,129 @@ bool GitClient::addAndCommit(const QString &repositoryDirectory,
return rc;
}
static inline bool askWithInformativeText(QWidget *parent,
const QString &title,
const QString &msg,
const QString &inf,
bool defaultValue)
{
QMessageBox msgBox(QMessageBox::Question, title, msg, QMessageBox::Yes|QMessageBox::No, parent);
msgBox.setInformativeText(inf);
msgBox.setDefaultButton(defaultValue ? QMessageBox::Yes : QMessageBox::No);
return msgBox.exec() == QMessageBox::Yes;
}
/* Revert: This function can be called with a file list (to revert single
* files) or a single directory (revert all). Qt Creator currently has only
* 'revert single' in its VCS menus, but the code is prepared to deal with
* reverting a directory pending a sophisticated selection dialog in the
* VCSBase plugin. */
GitClient::RevertResult GitClient::revertI(QStringList files, bool *ptrToIsDirectory, QString *errorMessage)
{
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << files;
if (files.empty())
return RevertCanceled;
// Figure out the working directory
const QFileInfo firstFile(files.front());
const bool isDirectory = firstFile.isDir();
if (ptrToIsDirectory)
*ptrToIsDirectory = isDirectory;
const QString workingDirectory = isDirectory ? firstFile.absoluteFilePath() : firstFile.absolutePath();
const QString repoDirectory = GitClient::findRepositoryForDirectory(workingDirectory);
if (repoDirectory.isEmpty()) {
*errorMessage = msgRepositoryNotFound(workingDirectory);
return RevertFailed;
}
// Check for changes
QString output;
switch (gitStatus(repoDirectory, false, &output, errorMessage)) {
case StatusChanged:
break;
case StatusUnchanged:
return RevertUnchanged;
case StatusFailed:
return RevertFailed;
}
CommitData d;
if (!parseFiles(output, &d)) {
*errorMessage = msgParseFilesFailed();
return RevertFailed;
}
// If we are looking at files, make them relative to the repository
// directory to match them in the status output list.
if (!isDirectory) {
const QDir repoDir(repoDirectory);
const QStringList::iterator cend = files.end();
for (QStringList::iterator it = files.begin(); it != cend; ++it)
*it = repoDir.relativeFilePath(*it);
}
// From the status output, determine all modified [un]staged files.
const QString modifiedPattern = QLatin1String("modified: ");
const QStringList allStagedFiles = GitSubmitEditor::statusListToFileList(d.stagedFiles.filter(modifiedPattern));
const QStringList allUnstagedFiles = GitSubmitEditor::statusListToFileList(d.unstagedFiles.filter(modifiedPattern));
// Unless a directory was passed, filter all modified files for the
// argument file list.
QStringList stagedFiles = allStagedFiles;
QStringList unstagedFiles = allUnstagedFiles;
if (!isDirectory) {
const QSet<QString> filesSet = files.toSet();
stagedFiles = allStagedFiles.toSet().intersect(filesSet).toList();
unstagedFiles = allUnstagedFiles.toSet().intersect(filesSet).toList();
}
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << d.stagedFiles << d.unstagedFiles << allStagedFiles << allUnstagedFiles << stagedFiles << unstagedFiles;
if (stagedFiles.empty() && unstagedFiles.empty())
return RevertUnchanged;
// Ask to revert (to do: Handle lists with a selection dialog)
const QMessageBox::StandardButton answer
= QMessageBox::question(m_core->mainWindow(),
tr("Revert"),
tr("The file has been changed. Do you want to revert it?"),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::No);
if (answer == QMessageBox::No)
return RevertCanceled;
// Unstage the staged files
if (!stagedFiles.empty() && !synchronousReset(repoDirectory, stagedFiles, errorMessage))
return RevertFailed;
// Finally revert!
if (!synchronousCheckout(repoDirectory, stagedFiles + unstagedFiles, errorMessage))
return RevertFailed;
return RevertOk;
}
void GitClient::revert(const QStringList &files)
{
bool isDirectory;
QString errorMessage;
switch (revertI(files, &isDirectory, &errorMessage)) {
case RevertOk:
case RevertCanceled:
break;
case RevertUnchanged: {
const QString msg = (isDirectory || files.size() > 1) ? msgNoChangedFiles() : tr("The file is not modified.");
m_plugin->outputWindow()->append(msg);
m_plugin->outputWindow()->popup();
}
break;
case RevertFailed:
m_plugin->outputWindow()->append(errorMessage);
m_plugin->outputWindow()->popup();
break;
}
}
void GitClient::pull(const QString &workingDirectory)
{
executeGit(workingDirectory, QStringList(QLatin1String("pull")), m_plugin->outputWindow(), 0, true);
@@ -648,6 +817,11 @@ void GitClient::push(const QString &workingDirectory)
executeGit(workingDirectory, QStringList(QLatin1String("push")), m_plugin->outputWindow(), 0, true);
}
QString GitClient::msgNoChangedFiles()
{
return tr("There are no modified files.");
}
void GitClient::stash(const QString &workingDirectory)
{
// Check for changes and stash
@@ -657,7 +831,7 @@ void GitClient::stash(const QString &workingDirectory)
executeGit(workingDirectory, QStringList(QLatin1String("stash")), m_plugin->outputWindow(), 0, true);
break;
case StatusUnchanged:
m_plugin->outputWindow()->append(tr("There are no modified files."));
m_plugin->outputWindow()->append(msgNoChangedFiles());
m_plugin->outputWindow()->popup();
break;
case StatusFailed:
@@ -694,8 +868,8 @@ QString GitClient::readConfig(const QString &workingDirectory, const QStringList
arguments << QLatin1String("config") << configVar;
QByteArray outputText;
if (synchronousGit(workingDirectory, arguments, &outputText))
return QString::fromLocal8Bit(outputText);
if (synchronousGit(workingDirectory, arguments, &outputText, 0, false))
return QString::fromLocal8Bit(outputText).remove(QLatin1Char('\r'));
return QString();
}

View File

@@ -90,11 +90,14 @@ public:
void addFile(const QString &workingDirectory, const QString &fileName);
bool synchronousAdd(const QString &workingDirectory, const QStringList &files);
bool synchronousReset(const QString &workingDirectory, const QStringList &files);
bool synchronousReset(const QString &workingDirectory, const QStringList &files, QString *errorMessage);
bool synchronousCheckout(const QString &workingDirectory, const QStringList &files, QString *errorMessage);
void pull(const QString &workingDirectory);
void push(const QString &workingDirectory);
void stash(const QString &workingDirectory);
void stashPop(const QString &workingDirectory);
void revert(const QStringList &files);
void branchList(const QString &workingDirectory);
void stashList(const QString &workingDirectory);
@@ -113,19 +116,21 @@ public:
const QStringList &checkedFiles,
const QStringList &origCommitFiles);
GitSettings settings() const;
void setSettings(const GitSettings &s);
public slots:
void show(const QString &source, const QString &id);
private:
enum StatusResult { StatusChanged, StatusUnchanged, StatusFailed };
StatusResult gitStatus(const QString &workingDirectory,
bool untracked,
QString *output = 0,
QString *errorMessage = 0);
GitSettings settings() const;
void setSettings(const GitSettings &s);
static QString msgNoChangedFiles();
public slots:
void show(const QString &source, const QString &id);
private:
VCSBase::VCSBaseEditor *createVCSEditor(const QString &kind,
QString title,
const QString &source,
@@ -143,7 +148,11 @@ private:
bool synchronousGit(const QString &workingDirectory,
const QStringList &arguments,
QByteArray* outputText = 0,
QByteArray* errorText = 0);
QByteArray* errorText = 0,
bool logCommandToWindow = true);
enum RevertResult { RevertOk, RevertUnchanged, RevertCanceled, RevertFailed };
RevertResult revertI(QStringList files, bool *isDirectory, QString *errorMessage);
const QString m_msgWait;
GitPlugin *m_plugin;

View File

@@ -118,7 +118,9 @@ GitPlugin::GitPlugin() :
m_undoFileAction(0),
m_undoProjectAction(0),
m_showAction(0),
m_addAction(0),
m_stageAction(0),
m_unstageAction(0),
m_revertAction(0),
m_commitAction(0),
m_pullAction(0),
m_pushAction(0),
@@ -311,11 +313,23 @@ bool GitPlugin::initialize(const QStringList &arguments, QString *error_message)
connect(m_undoFileAction, SIGNAL(triggered()), this, SLOT(undoFileChanges()));
gitContainer->addAction(command);
m_addAction = new QAction(tr("Add File"), this);
command = actionManager->registerAction(m_addAction, "Git.Add", globalcontext);
m_stageAction = new QAction(tr("Stage file for commit"), this);
command = actionManager->registerAction(m_stageAction, "Git.Stage", globalcontext);
command->setDefaultKeySequence(QKeySequence(tr("Alt+G,Alt+A")));
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_addAction, SIGNAL(triggered()), this, SLOT(addFile()));
connect(m_stageAction, SIGNAL(triggered()), this, SLOT(stageFile()));
gitContainer->addAction(command);
m_unstageAction = new QAction(tr("Unstage file from commit"), this);
command = actionManager->registerAction(m_unstageAction, "Git.Unstage", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_unstageAction, SIGNAL(triggered()), this, SLOT(unstageFile()));
gitContainer->addAction(command);
m_revertAction = new QAction(tr("Revert..."), this);
command = actionManager->registerAction(m_revertAction, "Git.Revert", globalcontext);
command->setAttribute(Core::ICommand::CA_UpdateText);
connect(m_revertAction, SIGNAL(triggered()), this, SLOT(revertFile()));
gitContainer->addAction(command);
gitContainer->addAction(createSeparator(actionManager, globalcontext, QLatin1String("Git.Sep.Project"), this));
@@ -537,14 +551,28 @@ void GitPlugin::undoProjectChanges()
m_gitClient->hardReset(workingDirectory, QString());
}
void GitPlugin::addFile()
void GitPlugin::stageFile()
{
QFileInfo fileInfo = currentFile();
QString fileName = fileInfo.fileName();
QString workingDirectory = fileInfo.absolutePath();
const QFileInfo fileInfo = currentFile();
const QString fileName = fileInfo.fileName();
const QString workingDirectory = fileInfo.absolutePath();
m_gitClient->addFile(workingDirectory, fileName);
}
void GitPlugin::unstageFile()
{
const QFileInfo fileInfo = currentFile();
const QString fileName = fileInfo.fileName();
const QString workingDirectory = fileInfo.absolutePath();
m_gitClient->synchronousReset(workingDirectory, QStringList(fileName));
}
void GitPlugin::revertFile()
{
const QFileInfo fileInfo = currentFile();
m_gitClient->revert(QStringList(fileInfo.absoluteFilePath()));
}
void GitPlugin::startCommit()
{
if (m_changeTmpFile) {
@@ -570,7 +598,7 @@ void GitPlugin::startCommit()
// Store repository for diff and the original list of
// files to be able to unstage files the user unchecks
m_submitRepository = data.panelInfo.repository;
m_submitOrigCommitFiles = GitSubmitEditor::statusListToFileList(data.commitFiles);
m_submitOrigCommitFiles = GitSubmitEditor::statusListToFileList(data.stagedFiles);
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << data << commitTemplate;
@@ -602,7 +630,7 @@ Core::IEditor *GitPlugin::openSubmitEditor(const QString &fileName, const Commit
Q_ASSERT(submitEditor);
// The actions are for some reason enabled by the context switching
// mechanism. Disable them correctly.
m_submitCurrentAction->setEnabled(!cd.commitFiles.empty());
m_submitCurrentAction->setEnabled(!cd.stagedFiles.empty());
m_diffSelectedFilesAction->setEnabled(false);
m_undoAction->setEnabled(false);
m_redoAction->setEnabled(false);
@@ -722,7 +750,9 @@ void GitPlugin::updateActions()
m_logAction->setText(tr("Log %1").arg(fileName));
m_blameAction->setText(tr("Blame %1").arg(fileName));
m_undoFileAction->setText(tr("Undo changes for %1").arg(fileName));
m_addAction->setText(tr("Add %1").arg(fileName));
m_stageAction->setText(tr("Stage %1 for commit").arg(fileName));
m_unstageAction->setText(tr("Unstage %1 from commit").arg(fileName));
m_revertAction->setText(tr("Revert %1...").arg(fileName));
if (repository.isEmpty()) {
// If the file is not in a repository, the corresponding project will
// be neither and we can disable everything and return
@@ -731,7 +761,9 @@ void GitPlugin::updateActions()
m_logAction->setEnabled(false);
m_blameAction->setEnabled(false);
m_undoFileAction->setEnabled(false);
m_addAction->setEnabled(false);
m_stageAction->setEnabled(false);
m_unstageAction->setEnabled(false);
m_revertAction->setEnabled(false);
m_diffProjectAction->setEnabled(false);
m_diffProjectAction->setText(tr("Diff Project"));
m_statusProjectAction->setText(tr("Status Project"));
@@ -747,7 +779,9 @@ void GitPlugin::updateActions()
m_logAction->setEnabled(true);
m_blameAction->setEnabled(true);
m_undoFileAction->setEnabled(true);
m_addAction->setEnabled(true);
m_stageAction->setEnabled(true);
m_unstageAction->setEnabled(true);
m_revertAction->setEnabled(true);
}
if (m_projectExplorer && m_projectExplorer->currentNode()

View File

@@ -116,7 +116,9 @@ private slots:
void logProject();
void undoFileChanges();
void undoProjectChanges();
void addFile();
void stageFile();
void unstageFile();
void revertFile();
void showCommit();
void startCommit();
@@ -144,7 +146,9 @@ private:
QAction *m_undoFileAction;
QAction *m_undoProjectAction;
QAction *m_showAction;
QAction *m_addAction;
QAction *m_stageAction;
QAction *m_unstageAction;
QAction *m_revertAction;
QAction *m_commitAction;
QAction *m_pullAction;
QAction *m_pushAction;

View File

@@ -67,9 +67,9 @@ void GitSubmitEditor::setCommitData(const CommitData &d)
submitEditorWidget()->setPanelData(d.panelData);
submitEditorWidget()->setPanelInfo(d.panelInfo);
addFiles(d.commitFiles, true, true);
addFiles(d.stagedFiles, true, true);
// Not Updated: Initially unchecked
addFiles(d.notUpdatedFiles, false, true);
addFiles(d.unstagedFiles, false, true);
addFiles(d.untrackedFiles, false, true);
}

View File

@@ -16,8 +16,8 @@ HEADERS += helpplugin.h \
searchwidget.h \
helpfindsupport.h \
help_global.h \
helpindexfilter.h \
indexwindow.h
helpindexfilter.h
SOURCES += helpplugin.cpp \
docsettingspage.cpp \
filtersettingspage.cpp \
@@ -26,6 +26,7 @@ SOURCES += helpplugin.cpp \
searchwidget.cpp \
helpfindsupport.cpp \
helpindexfilter.cpp
FORMS += docsettingspage.ui \
filtersettingspage.ui
RESOURCES += help.qrc

View File

@@ -405,17 +405,17 @@ void PerforcePlugin::extensionsInitialized()
void PerforcePlugin::openCurrentFile()
{
runP4Cmd(QStringList() << QLatin1String("edit") << currentFileName(), QStringList(), true);
vcsOpen(currentFileName());
}
void PerforcePlugin::addCurrentFile()
{
runP4Cmd(QStringList() << QLatin1String("add") << currentFileName(), QStringList(), true);
vcsAdd(currentFileName());
}
void PerforcePlugin::deleteCurrentFile()
{
runP4Cmd(QStringList() << QLatin1String("delete") << currentFileName(), QStringList(), true);
vcsDelete(currentFileName());
}
void PerforcePlugin::revertCurrentFile()
@@ -426,7 +426,7 @@ void PerforcePlugin::revertCurrentFile()
QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(m_coreInstance, fileName);
QStringList args;
args << QLatin1String("diff") << QLatin1String("-sa");
PerforceResponse result = runP4Cmd(args, QStringList(), false, true, codec);
PerforceResponse result = runP4Cmd(args, QStringList(), CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (result.error)
return;
@@ -444,7 +444,7 @@ void PerforcePlugin::revertCurrentFile()
foreach (Core::IFile *file, files) {
fm->blockFileChange(file);
}
PerforceResponse result2 = runP4Cmd(QStringList() << QLatin1String("revert") << fileName, QStringList(), true);
PerforceResponse result2 = runP4Cmd(QStringList() << QLatin1String("revert") << fileName, QStringList(), CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
Core::IFile::ReloadBehavior tempBehavior =
Core::IFile::ReloadAll;
foreach (Core::IFile *file, files) {
@@ -489,7 +489,7 @@ void PerforcePlugin::printOpenedFileList()
Core::IEditor *e = m_coreInstance->editorManager()->currentEditor();
if (e)
e->widget()->setFocus();
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("opened"), QStringList(), true);
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("opened"), QStringList(), CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
}
#ifdef USE_P4_API
@@ -522,7 +522,8 @@ void PerforcePlugin::submit()
return;
}
PerforceResponse result = runP4Cmd(QStringList()<< QLatin1String("change") << QLatin1String("-o"), QStringList(), false);
PerforceResponse result = runP4Cmd(QStringList()<< QLatin1String("change") << QLatin1String("-o"), QStringList(),
CommandToWindow|StdErrToWindow|ErrorToWindow);
if (result.error) {
delete m_changeTmpFile;
m_changeTmpFile = 0;
@@ -550,7 +551,8 @@ void PerforcePlugin::submit()
foreach (const QString &f, files)
nativeFiles << QDir::toNativeSeparators(f);
PerforceResponse result2 = runP4Cmd(QStringList(QLatin1String("fstat")), nativeFiles, false);
PerforceResponse result2 = runP4Cmd(QStringList(QLatin1String("fstat")), nativeFiles,
CommandToWindow|StdErrToWindow|ErrorToWindow);
if (result2.error) {
delete m_changeTmpFile;
m_changeTmpFile = 0;
@@ -597,8 +599,10 @@ void PerforcePlugin::printPendingChanges()
PendingChangesDialog dia(pendingChangesData(), m_coreInstance->mainWindow());
qApp->restoreOverrideCursor();
if (dia.exec() == QDialog::Accepted) {
int i = dia.changeNumber();
PerforceResponse result = runP4Cmd(QStringList()<<"submit"<<"-c"<<QString::number(i), QStringList(), true);
const int i = dia.changeNumber();
QStringList args(QLatin1String("submit"));
args << QLatin1String("-c") << QString::number(i);
runP4Cmd(args, QStringList(), CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
}
}
@@ -628,7 +632,8 @@ void PerforcePlugin::annotate(const QString &fileName)
QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(m_coreInstance, fileName);
QStringList args;
args << QLatin1String("annotate") << QLatin1String("-cqi") << fileName;
const PerforceResponse result = runP4Cmd(args, QStringList(), false, true, codec);
const PerforceResponse result = runP4Cmd(args, QStringList(),
CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (!result.error) {
const QFileInfo fi(fileName);
showOutputInEditor(tr("p4 annotate %1").arg(fi.fileName()), result.stdOut, VCSBase::AnnotateOutput, codec);
@@ -654,7 +659,8 @@ void PerforcePlugin::filelog(const QString &fileName)
QTextCodec *codec = VCSBase::VCSBaseEditor::getCodec(m_coreInstance, fileName);
QStringList args;
args << QLatin1String("filelog") << QLatin1String("-li") << fileName;
const PerforceResponse result = runP4Cmd(args, QStringList(), false, true, codec);
const PerforceResponse result = runP4Cmd(args, QStringList(),
CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (!result.error) {
const QFileInfo fi(fileName);
showOutputInEditor(tr("p4 filelog %1").arg(fi.fileName()), result.stdOut, VCSBase::LogOutput, codec);
@@ -718,18 +724,19 @@ bool PerforcePlugin::managesDirectory(const QString &directory) const
QStringList args;
args << QLatin1String("fstat") << QLatin1String("-m1") << p4Path;
const PerforceResponse result = runP4Cmd(args, QStringList(), false, false);
const PerforceResponse result = runP4Cmd(args, QStringList(), 0u);
return result.stdOut.contains("depotFile") || result.stdErr.contains("... - no such file(s)");
}
QString PerforcePlugin::findTopLevelForDirectory(const QString & /* dir */) const
{
// First check with p4 client -o
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("client") << QLatin1String("-o"), QStringList(), false, false);
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("client") << QLatin1String("-o"), QStringList(), 0u);
if (result.error)
return QString::null;
QRegExp regExp(QLatin1String("(\\n|\\r\\n|\\r)Root:\\s*(.*)(\\n|\\r\\n|\\r)"));
Q_ASSERT(regExp.isValid());
regExp.setMinimal(true);
if (regExp.indexIn(result.stdOut) != -1) {
QString file = regExp.cap(2).trimmed();
@@ -741,20 +748,24 @@ QString PerforcePlugin::findTopLevelForDirectory(const QString & /* dir */) cons
bool PerforcePlugin::vcsOpen(const QString &fileName)
{
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("edit") << QDir::toNativeSeparators(fileName), QStringList(), true);
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("edit") << QDir::toNativeSeparators(fileName), QStringList(),
CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
return !result.error;
}
bool PerforcePlugin::vcsAdd(const QString &fileName)
{
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("add") << fileName, QStringList(), true);
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("add") << fileName, QStringList(),
CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
return !result.error;
}
bool PerforcePlugin::vcsDelete(const QString &fileName)
{
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("revert") << fileName, QStringList(), true);
PerforceResponse result2 = runP4Cmd(QStringList() << QLatin1String("delete") << fileName, QStringList(), true);
PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("revert") << fileName, QStringList(),
CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
PerforceResponse result2 = runP4Cmd(QStringList() << QLatin1String("delete") << fileName, QStringList(),
CommandToWindow|StdOutToWindow|StdErrToWindow|ErrorToWindow);
// TODO need to carefully parse the actual messages from perforce
// or do a fstat before to decide what to do
@@ -767,8 +778,7 @@ bool PerforcePlugin::vcsDelete(const QString &fileName)
PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args,
const QStringList &extraArgs,
bool showStdOutInOutputWindow,
bool showStdErrInOutputWindow,
unsigned logFlags,
QTextCodec *outputCodec) const
{
if (Perforce::Constants::debug)
@@ -801,12 +811,14 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args,
}
actualArgs << args;
response.command = m_settings.p4Command;
response.command += blank;
response.command += actualArgs.join(QString(blank));
if (logFlags & CommandToWindow) {
QString command = m_settings.p4Command;
command += blank;
command += actualArgs.join(QString(blank));
const QString timeStamp = QTime::currentTime().toString(QLatin1String("HH:mm"));
const QString outputText = tr("%1 Executing: %2\n").arg(timeStamp, response.command);
const QString outputText = tr("%1 Executing: %2\n").arg(timeStamp, command);
showOutput(outputText, false);
}
// Run, connect stderr to the output window
Core::Utils::SynchronousProcess process;
@@ -815,13 +827,13 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args,
process.setEnvironment(environment());
// connect stderr to the output window if desired
if (showStdErrInOutputWindow) {
if (logFlags & StdErrToWindow) {
process.setStdErrBufferedSignalsEnabled(true);
connect(&process, SIGNAL(stdErrBuffered(QString,bool)), m_perforceOutputWindow, SLOT(append(QString,bool)));
}
// connect stdout to the output window if desired
if (showStdOutInOutputWindow) {
if (logFlags & StdOutToWindow) {
process.setStdOutBufferedSignalsEnabled(true);
connect(&process, SIGNAL(stdOutBuffered(QString,bool)), m_perforceOutputWindow, SLOT(append(QString,bool)));
}
@@ -847,13 +859,15 @@ PerforceResponse PerforcePlugin::runP4Cmd(const QStringList &args,
response.message = tr("Could not start perforce '%1'. Please check your settings in the preferences.").arg(m_settings.p4Command);
break;
case Core::Utils::SynchronousProcessResponse::Hang:
response.message = tr("Subversion did not respond within timeout limit (%1 ms).").arg(p4Timeout );
response.message = tr("Perforce did not respond within timeout limit (%1 ms).").arg(p4Timeout );
break;
}
if (response.error)
if (response.error) {
if (Perforce::Constants::debug)
qDebug() << response.message;
if (logFlags & ErrorToWindow)
m_perforceOutputWindow->append(response.message, true);
}
return response;
}
@@ -923,7 +937,7 @@ void PerforcePlugin::p4Diff(const QStringList &files, QString diffname)
}
}
const PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("diff") << QLatin1String("-du"), files, false, codec);
const PerforceResponse result = runP4Cmd(QStringList() << QLatin1String("diff") << QLatin1String("-du"), files, CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (result.error)
return;
@@ -948,7 +962,7 @@ void PerforcePlugin::describe(const QString & source, const QString &n)
QTextCodec *codec = source.isEmpty() ? static_cast<QTextCodec *>(0) : VCSBase::VCSBaseEditor::getCodec(m_coreInstance, source);
QStringList args;
args << QLatin1String("describe") << QLatin1String("-du") << n;
const PerforceResponse result = runP4Cmd(args, QStringList(), codec);
const PerforceResponse result = runP4Cmd(args, QStringList(), CommandToWindow|StdErrToWindow|ErrorToWindow, codec);
if (!result.error)
showOutputInEditor(tr("p4 describe %1").arg(n), result.stdOut, VCSBase::DiffOutput, codec);
}

View File

@@ -86,7 +86,6 @@ private:
struct PerforceResponse
{
bool error;
QString command;
QString stdOut;
QString stdErr;
QString message;
@@ -161,12 +160,15 @@ private:
Core::IEditor *showOutputInEditor(const QString& title, const QString output,
int editorType,
QTextCodec *codec = 0);
// Verbosity flags for runP4Cmd.
enum RunLogFlags { CommandToWindow = 0x1, StdOutToWindow = 0x2, StdErrToWindow = 0x4, ErrorToWindow = 0x8 };
// args are passed as command line arguments
// extra args via a tempfile and the option -x "temp-filename"
PerforceResponse runP4Cmd(const QStringList &args,
const QStringList &extraArgs = QStringList(),
bool showStdOutInOutputWindow = false,
bool showStdErrInOutputWindow = true,
unsigned logFlags = CommandToWindow|StdErrToWindow|ErrorToWindow,
QTextCodec *outputCodec = 0) const;
void openFiles(const QStringList &files);

View File

@@ -104,8 +104,9 @@
<widget class="QLabel" name="filesLabel">
<property name="text">
<string>The following files will be added:
f1
f2
</string>
</property>
<property name="textInteractionFlags">

View File

@@ -35,6 +35,7 @@
#include "consoleappwizard.h"
#include "modulespage.h"
#include <QtCore/QDebug>
#include <utils/projectintropage.h>
namespace Qt4ProjectManager {
@@ -51,13 +52,11 @@ ConsoleAppWizardDialog::ConsoleAppWizardDialog(const QString &templateName,
setWindowIcon(icon);
setWindowTitle(templateName);
Core::BaseFileWizard::setupWizard(this);
setOptions(QWizard::IndependentPages | QWizard::HaveNextButtonOnLastPage);
m_introPage->setDescription(tr("This wizard generates a Qt4 console application "
"project. The application derives from QCoreApplication and does not "
"present a GUI. You can press 'Finish' at any point in time."));
m_introPage->setFinalPage(true);
addPage(m_introPage);
m_modulesPage->setModuleSelected(QLatin1String("core"));

View File

@@ -63,7 +63,6 @@ GuiAppWizardDialog::GuiAppWizardDialog(const QString &templateName,
setWindowIcon(icon);
setWindowTitle(templateName);
Core::BaseFileWizard::setupWizard(this);
setOptions(QWizard::IndependentPages);
m_introPage->setDescription(tr("This wizard generates a Qt4 GUI application "
"project. The application derives by default from QApplication "

View File

@@ -79,6 +79,7 @@
#include <QtGui/QToolBar>
#include <QtGui/QToolTip>
#include <QtGui/QInputDialog>
#include <QtGui/QMenu>
using namespace TextEditor;
using namespace TextEditor::Internal;
@@ -487,10 +488,6 @@ ITextEditable *BaseTextEditor::editableInterface() const
d->m_editable, SIGNAL(contentsChanged()));
connect(this, SIGNAL(changed()),
d->m_editable, SIGNAL(changed()));
connect(this,
SIGNAL(markRequested(TextEditor::ITextEditor *, int)),
d->m_editable,
SIGNAL(markRequested(TextEditor::ITextEditor *, int)));
}
return d->m_editable;
}
@@ -501,7 +498,8 @@ void BaseTextEditor::currentEditorChanged(Core::IEditor *editor)
if (editor == d->m_editable) {
if (d->m_document->hasDecodingError()) {
Core::EditorManager::instance()->showEditorInfoBar(QLatin1String(Constants::SELECT_ENCODING),
tr("<b>Error:</b> Could not decode \"%1\" with \"%2\"-encoding. Editing not possible.").arg(displayName()).arg(QString::fromLatin1(d->m_document->codec()->name())),
tr("<b>Error:</b> Could not decode \"%1\" with \"%2\"-encoding. Editing not possible.")
.arg(displayName()).arg(QString::fromLatin1(d->m_document->codec()->name())),
tr("Select Encoding"),
this, SLOT(selectEncoding()));
}
@@ -531,7 +529,6 @@ void BaseTextEditor::selectEncoding()
}
}
void DocumentMarker::updateMark(ITextMark *mark)
{
TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(document->documentLayout());
@@ -598,8 +595,79 @@ void BaseTextEditor::slotSelectionChanged()
viewport()->update();
if (!d->m_inBlockSelectionMode)
d->m_blockSelectionExtraX = 0;
if (!d->m_selectBlockAnchor.isNull() && !textCursor().hasSelection())
d->m_selectBlockAnchor = QTextCursor();
}
void BaseTextEditor::gotoBlockStart()
{
QTextCursor cursor = textCursor();
if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, false))
setTextCursor(cursor);
}
void BaseTextEditor::gotoBlockEnd()
{
QTextCursor cursor = textCursor();
if (TextBlockUserData::findNextClosingParenthesis(&cursor, false))
setTextCursor(cursor);
}
void BaseTextEditor::gotoBlockStartWithSelection()
{
QTextCursor cursor = textCursor();
if (TextBlockUserData::findPreviousOpenParenthesis(&cursor, true))
setTextCursor(cursor);
}
void BaseTextEditor::gotoBlockEndWithSelection()
{
QTextCursor cursor = textCursor();
if (TextBlockUserData::findNextClosingParenthesis(&cursor, true))
setTextCursor(cursor);
}
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;
setTextCursor(cursor);
}
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);
setTextCursor(cursor);
}
void BaseTextEditor::keyPressEvent(QKeyEvent *e)
{
@@ -633,6 +701,11 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
e->accept();
return;
}
} else if (e == QKeySequence::Paste) {
if (!ro) {
d->removeBlockSelection();
// continue
}
}
}
@@ -693,6 +766,8 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
break;
case Qt::Key_Home:
if (!(e == QKeySequence::MoveToStartOfDocument) && !(e == QKeySequence::SelectStartOfDocument)) {
if ((e->modifiers() & (Qt::AltModifier | Qt::ShiftModifier)) == (Qt::AltModifier | Qt::ShiftModifier))
d->m_lastEventWasBlockSelectionEvent = true;
handleHomeKey(e->modifiers() & Qt::ShiftModifier);
e->accept();
return;
@@ -708,6 +783,7 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
return;
}
// fall through
case Qt::Key_End:
case Qt::Key_Right:
case Qt::Key_Left:
#ifndef Q_OS_MAC
@@ -795,6 +871,15 @@ skip_event:
delete e;
}
void BaseTextEditor::setTextCursor(const QTextCursor &cursor)
{
// workaround for QTextControl bug
bool selectionChange = cursor.hasSelection() || textCursor().hasSelection();
QPlainTextEdit::setTextCursor(cursor);
if (selectionChange)
slotSelectionChanged();
}
void BaseTextEditor::gotoLine(int line, int column)
{
const int blockNumber = line - 1;
@@ -2343,6 +2428,12 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e)
} else {
d->extraAreaToggleMarkBlockNumber = cursor.blockNumber();
}
} else if (e->button() == Qt::RightButton) {
QMenu * contextMenu = new QMenu(this);
emit d->m_editable->markContextMenuRequested(editableInterface(), cursor.blockNumber(), contextMenu);
if (!contextMenu->isEmpty())
contextMenu->exec(e->globalPos());
delete contextMenu;
}
} else if (d->extraAreaSelectionAnchorBlockNumber >= 0) {
QTextCursor selection = cursor;
@@ -2377,7 +2468,7 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e)
d->extraAreaToggleMarkBlockNumber = -1;
if (cursor.blockNumber() == n) {
int line = n + 1;
emit markRequested(editableInterface(), line);
emit d->m_editable->markRequested(editableInterface(), line);
}
}
}
@@ -2386,6 +2477,9 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e)
void BaseTextEditor::slotCursorPositionChanged()
{
QList<QTextEdit::ExtraSelection> extraSelections;
setExtraSelections(ParenthesesMatchingSelection, extraSelections); // clear
if (d->m_parenthesesMatchingEnabled)
d->m_parenthesesMatchingTimer->start(50);
if (d->m_highlightCurrentLine) {
QTextEdit::ExtraSelection sel;
@@ -2396,11 +2490,7 @@ void BaseTextEditor::slotCursorPositionChanged()
extraSelections.append(sel);
}
if (d->m_parenthesesMatchingEnabled)
d->m_parenthesesMatchingTimer->start(50);
d->m_extraSelections = extraSelections;
setExtraSelections(d->m_extraSelections + d->m_extraExtraSelections);
setExtraSelections(CurrentLineSelection, extraSelections);
}
QTextBlock TextBlockUserData::testCollapse(const QTextBlock& block)
@@ -2908,6 +2998,61 @@ TextBlockUserData::MatchType TextBlockUserData::checkClosedParenthesis(QTextCurs
}
}
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);
if (!parenList.isEmpty()) {
for (int i = parenList.count()-1; i >= 0; --i) {
Parenthesis paren = parenList.at(i);
if (block == cursor->block() && position - block.position() <= paren.pos + 1)
continue;
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;
}
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()) {
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;
}
TextBlockUserData::MatchType TextBlockUserData::matchCursorBackward(QTextCursor *cursor)
{
cursor->clearSelection();
@@ -2987,7 +3132,7 @@ void BaseTextEditor::_q_matchParentheses()
if (backwardMatchType == TextBlockUserData::NoMatch && forwardMatchType == TextBlockUserData::NoMatch)
return;
QList<QTextEdit::ExtraSelection> extraSelections = d->m_extraSelections;
QList<QTextEdit::ExtraSelection> extraSelections;
if (backwardMatch.hasSelection()) {
QTextEdit::ExtraSelection sel;
@@ -3040,8 +3185,7 @@ void BaseTextEditor::_q_matchParentheses()
}
extraSelections.append(sel);
}
d->m_extraSelections = extraSelections;
setExtraSelections(d->m_extraSelections + d->m_extraExtraSelections);
setExtraSelections(ParenthesesMatchingSelection, extraSelections);
}
void BaseTextEditor::setActionHack(QObject *hack)
@@ -3088,15 +3232,21 @@ void BaseTextEditor::deleteLine()
cut();
}
void BaseTextEditor::setExtraExtraSelections(const QList<QTextEdit::ExtraSelection> &selections)
void BaseTextEditor::setExtraSelections(ExtraSelectionKind kind, const QList<QTextEdit::ExtraSelection> &selections)
{
d->m_extraExtraSelections = selections;
setExtraSelections(d->m_extraSelections + d->m_extraExtraSelections);
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);
}
QList<QTextEdit::ExtraSelection> BaseTextEditor::extraExtraSelections() const
QList<QTextEdit::ExtraSelection> BaseTextEditor::extraSelections(ExtraSelectionKind kind) const
{
return d->m_extraExtraSelections;
return d->m_extraSelections[kind];
}
@@ -3152,13 +3302,16 @@ void BaseTextEditor::collapse()
TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(doc->documentLayout());
Q_ASSERT(documentLayout);
QTextBlock block = textCursor().block();
qDebug() << "collapse at block" << block.blockNumber();
while (block.isValid()) {
if (TextBlockUserData::canCollapse(block)) {
if ((block.next().userState()) >> 8 == (textCursor().block().userState() >> 8))
qDebug() << "test block" << block.blockNumber();
if (TextBlockUserData::canCollapse(block) && block.next().isVisible()) {
if ((block.next().userState()) >> 8 <= (textCursor().block().userState() >> 8))
break;
}
block = block.previous();
}
qDebug() << "found" << block.blockNumber();
if (block.isValid()) {
TextBlockUserData::doCollapse(block, false);
d->moveCursorVisible();
@@ -3238,6 +3391,14 @@ void BaseTextEditor::cut()
QPlainTextEdit::cut();
}
void BaseTextEditor::paste()
{
if (d->m_inBlockSelectionMode) {
d->removeBlockSelection();
}
QPlainTextEdit::paste();
}
QMimeData *BaseTextEditor::createMimeDataFromSelection() const
{
if (d->m_inBlockSelectionMode) {

View File

@@ -169,6 +169,8 @@ public:
static MatchType checkClosedParenthesis(QTextCursor *cursor, QChar c);
static MatchType matchCursorBackward(QTextCursor *cursor);
static MatchType matchCursorForward(QTextCursor *cursor);
static bool findPreviousOpenParenthesis(QTextCursor *cursor, bool select = false);
static bool findNextClosingParenthesis(QTextCursor *cursor, bool select = false);
private:
@@ -298,6 +300,8 @@ public:
void setReadOnly(bool b);
void setTextCursor(const QTextCursor &cursor);
public slots:
void setDisplayName(const QString &title);
virtual void setFontSettings(const TextEditor::FontSettings &);
@@ -305,6 +309,7 @@ public slots:
virtual void unCommentSelection();
virtual void setStorageSettings(const TextEditor::StorageSettings &);
void paste();
void cut();
void zoomIn(int range = 1);
@@ -316,6 +321,14 @@ public slots:
void expand();
void selectEncoding();
void gotoBlockStart();
void gotoBlockEnd();
void gotoBlockStartWithSelection();
void gotoBlockEndWithSelection();
void selectBlockUp();
void selectBlockDown();
signals:
void changed();
@@ -356,7 +369,6 @@ private:
Internal::BaseTextEditorPrivate *d;
friend class Internal::BaseTextEditorPrivate;
public:
QWidget *extraArea() const;
virtual int extraAreaWidth(int *markWidthPtr = 0) const;
@@ -372,8 +384,16 @@ public:
void ensureCursorVisible();
void setExtraExtraSelections(const QList<QTextEdit::ExtraSelection> &selections);
QList<QTextEdit::ExtraSelection> extraExtraSelections() const;
enum ExtraSelectionKind {
CurrentLineSelection,
ParenthesesMatchingSelection,
CodeWarningsSelection,
CodeSemanticsSelection,
OtherSelection,
NExtraSelectionKinds
};
void setExtraSelections(ExtraSelectionKind kind, const QList<QTextEdit::ExtraSelection> &selections);
QList<QTextEdit::ExtraSelection> extraSelections(ExtraSelectionKind kind) const;
struct BlockRange {
BlockRange():first(0), last(-1){}
@@ -418,7 +438,6 @@ protected slots:
signals:
void markRequested(TextEditor::ITextEditor *editor, int line);
void requestBlockUpdate(const QTextBlock &);
void requestAutoCompletion(ITextEditable *editor, bool forced);

View File

@@ -204,8 +204,7 @@ public:
QObject *m_actionHack;
QList<QTextEdit::ExtraSelection> m_extraSelections;
QList<QTextEdit::ExtraSelection> m_extraExtraSelections;
QList<QTextEdit::ExtraSelection> m_extraSelections[BaseTextEditor::NExtraSelectionKinds];
// block selection mode
bool m_inBlockSelectionMode;
@@ -216,6 +215,7 @@ public:
void removeBlockSelection(const QString &text = QString());
QTextCursor m_findScope;
QTextCursor m_selectBlockAnchor;
void moveCursorVisible();
};

View File

@@ -44,6 +44,7 @@
#include <QtGui/QIcon>
QT_BEGIN_NAMESPACE
class QMenu;
class QTextBlock;
QT_END_NAMESPACE
@@ -124,6 +125,7 @@ public:
signals:
void contentsChanged();
void markRequested(TextEditor::ITextEditor *editor, int line);
void markContextMenuRequested(TextEditor::ITextEditor *editor, int line, QMenu *menu);
void tooltipRequested(TextEditor::ITextEditor *editor, const QPoint &globalPos, int position);
void contextHelpIdRequested(TextEditor::ITextEditor *editor, int position);
};

View File

@@ -67,6 +67,9 @@ TextEditorActionHandler::TextEditorActionHandler(Core::ICore *core,
= m_collapseAction = m_expandAction
= m_deleteLineAction = m_selectEncodingAction
= m_increaseFontSizeAction = m_decreaseFontSizeAction
= m_gotoBlockStartAction = m_gotoBlockStartWithSelectionAction
= m_gotoBlockEndAction = m_gotoBlockEndWithSelectionAction
= m_selectBlockUpAction = m_selectBlockDownAction
= 0;
m_contextId << m_core->uniqueIDManager()->uniqueIdentifier(context);
@@ -161,13 +164,11 @@ void TextEditorActionHandler::createActions()
command = am->registerAction(m_collapseAction, Constants::COLLAPSE, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+<")));
connect(m_collapseAction, SIGNAL(triggered()), this, SLOT(collapse()));
advancedMenu->addAction(command);
m_expandAction = new QAction(tr("Expand"), this);
command = am->registerAction(m_expandAction, Constants::EXPAND, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+>")));
connect(m_expandAction, SIGNAL(triggered()), this, SLOT(expand()));
advancedMenu->addAction(command);
m_unCollapseAllAction = new QAction(tr("(Un)&Collapse All"), this);
command = am->registerAction(m_unCollapseAllAction, Constants::UN_COLLAPSE_ALL, m_contextId);
@@ -185,6 +186,36 @@ void TextEditorActionHandler::createActions()
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+-")));
connect(m_decreaseFontSizeAction, SIGNAL(triggered()), this, SLOT(decreaseFontSize()));
advancedMenu->addAction(command);
m_gotoBlockStartAction = new QAction(tr("Goto Block Start"), this);
command = am->registerAction(m_gotoBlockStartAction, Constants::GOTO_BLOCK_START, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+[")));
connect(m_gotoBlockStartAction, SIGNAL(triggered()), this, SLOT(gotoBlockStart()));
m_gotoBlockEndAction = new QAction(tr("Goto Block End"), this);
command = am->registerAction(m_gotoBlockEndAction, Constants::GOTO_BLOCK_END, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+]")));
connect(m_gotoBlockEndAction, SIGNAL(triggered()), this, SLOT(gotoBlockEnd()));
m_gotoBlockStartWithSelectionAction = new QAction(tr("Goto Block Start With Selection"), this);
command = am->registerAction(m_gotoBlockStartWithSelectionAction, Constants::GOTO_BLOCK_START_WITH_SELECTION, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+{")));
connect(m_gotoBlockStartWithSelectionAction, SIGNAL(triggered()), this, SLOT(gotoBlockStartWithSelection()));
m_gotoBlockEndWithSelectionAction = new QAction(tr("Goto Block End With Selection"), this);
command = am->registerAction(m_gotoBlockEndWithSelectionAction, Constants::GOTO_BLOCK_END_WITH_SELECTION, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+}")));
connect(m_gotoBlockEndWithSelectionAction, SIGNAL(triggered()), this, SLOT(gotoBlockEndWithSelection()));
m_selectBlockUpAction= new QAction(tr("Select Block Up"), this);
command = am->registerAction(m_selectBlockUpAction, Constants::SELECT_BLOCK_UP, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+U")));
connect(m_selectBlockUpAction, SIGNAL(triggered()), this, SLOT(selectBlockUp()));
m_selectBlockDownAction= new QAction(tr("Select Block Down"), this);
command = am->registerAction(m_selectBlockDownAction, Constants::SELECT_BLOCK_DOWN, m_contextId);
command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+U")));
connect(m_selectBlockDownAction, SIGNAL(triggered()), this, SLOT(selectBlockDown()));
}
bool TextEditorActionHandler::supportsAction(const QString & /*id */) const
@@ -229,35 +260,30 @@ void TextEditorActionHandler::updateActions()
void TextEditorActionHandler::updateActions(UpdateMode um)
{
if (m_pasteAction)
if (!m_initialized)
return;
m_pasteAction->setEnabled(um != NoEditor);
if (m_selectAllAction)
m_selectAllAction->setEnabled(um != NoEditor);
if (m_gotoAction)
m_gotoAction->setEnabled(um != NoEditor);
if (m_selectEncodingAction)
m_selectEncodingAction->setEnabled(um != NoEditor);
if (m_printAction)
m_printAction->setEnabled(um != NoEditor);
if (m_formatAction)
m_formatAction->setEnabled((m_optionalActions & Format) && um != NoEditor);
if (m_unCommentSelectionAction)
m_unCommentSelectionAction->setEnabled((m_optionalActions & UnCommentSelection) && um != NoEditor);
if (m_collapseAction)
m_collapseAction->setEnabled(um != NoEditor);
if (m_expandAction)
m_expandAction->setEnabled(um != NoEditor);
if (m_unCollapseAllAction)
m_unCollapseAllAction->setEnabled((m_optionalActions & UnCollapseAll) && um != NoEditor);
if (m_decreaseFontSizeAction)
m_decreaseFontSizeAction->setEnabled(um != NoEditor);
if (m_increaseFontSizeAction)
m_increaseFontSizeAction->setEnabled(um != NoEditor);
if (m_visualizeWhitespaceAction) {
m_gotoBlockStartAction->setEnabled(um != NoEditor);
m_gotoBlockStartWithSelectionAction->setEnabled(um != NoEditor);
m_gotoBlockEndAction->setEnabled(um != NoEditor);
m_gotoBlockEndWithSelectionAction->setEnabled(um != NoEditor);
m_selectBlockUpAction->setEnabled(um != NoEditor);
m_selectBlockDownAction->setEnabled(um != NoEditor);
m_visualizeWhitespaceAction->setEnabled(um != NoEditor);
if (m_currentEditor)
m_visualizeWhitespaceAction->setChecked(m_currentEditor->displaySettings().m_visualizeWhitespace);
}
if (m_textWrappingAction) {
m_textWrappingAction->setEnabled(um != NoEditor);
if (m_currentEditor)
@@ -365,54 +391,31 @@ void TextEditorActionHandler::setTextWrapping(bool checked)
}
}
void TextEditorActionHandler::unCommentSelection()
{
if (m_currentEditor)
m_currentEditor->unCommentSelection();
}
void TextEditorActionHandler::deleteLine()
{
if (m_currentEditor)
m_currentEditor->deleteLine();
}
void TextEditorActionHandler::unCollapseAll()
{
if (m_currentEditor)
m_currentEditor->unCollapseAll();
}
void TextEditorActionHandler::collapse()
{
if (m_currentEditor)
m_currentEditor->collapse();
}
void TextEditorActionHandler::expand()
{
if (m_currentEditor)
m_currentEditor->expand();
}
void TextEditorActionHandler::selectEncoding()
{
if (m_currentEditor)
m_currentEditor->selectEncoding();
}
void TextEditorActionHandler::increaseFontSize()
{
if (m_currentEditor)
m_currentEditor->zoomIn();
}
void TextEditorActionHandler::decreaseFontSize()
{
if (m_currentEditor)
m_currentEditor->zoomOut();
#define FUNCTION(funcname) void TextEditorActionHandler::funcname ()\
{\
if (m_currentEditor)\
m_currentEditor->funcname ();\
}
#define FUNCTION2(funcname, funcname2) void TextEditorActionHandler::funcname ()\
{\
if (m_currentEditor)\
m_currentEditor->funcname2 ();\
}
FUNCTION(unCommentSelection)
FUNCTION(deleteLine)
FUNCTION(unCollapseAll)
FUNCTION(collapse)
FUNCTION(expand)
FUNCTION2(increaseFontSize, zoomIn)
FUNCTION2(decreaseFontSize, zoomOut)
FUNCTION(selectEncoding)
FUNCTION(gotoBlockStart)
FUNCTION(gotoBlockEnd)
FUNCTION(gotoBlockStartWithSelection)
FUNCTION(gotoBlockEndWithSelection)
FUNCTION(selectBlockUp)
FUNCTION(selectBlockDown)
void TextEditorActionHandler::updateCurrentEditor(Core::IContext *object)
{

View File

@@ -109,6 +109,12 @@ private slots:
void selectEncoding();
void increaseFontSize();
void decreaseFontSize();
void gotoBlockStart();
void gotoBlockEnd();
void gotoBlockStartWithSelection();
void gotoBlockEndWithSelection();
void selectBlockUp();
void selectBlockDown();
void updateCurrentEditor(Core::IContext *object);
private:
@@ -131,6 +137,12 @@ private:
QAction *m_selectEncodingAction;
QAction *m_increaseFontSizeAction;
QAction *m_decreaseFontSizeAction;
QAction *m_gotoBlockStartAction;
QAction *m_gotoBlockEndAction;
QAction *m_gotoBlockStartWithSelectionAction;
QAction *m_gotoBlockEndWithSelectionAction;
QAction *m_selectBlockUpAction;
QAction *m_selectBlockDownAction;
uint m_optionalActions;
QPointer<BaseTextEditor> m_currentEditor;

View File

@@ -48,9 +48,17 @@ const char * const UN_COLLAPSE_ALL = "TextEditor.UnCollapseAll";
const char * const AUTO_INDENT_SELECTION = "TextEditor.AutoIndentSelection";
const char * const INCREASE_FONT_SIZE = "TextEditor.IncreaseFontSize";
const char * const DECREASE_FONT_SIZE = "TextEditor.DecreaseFontSize";
const char * const GOTO_BLOCK_START = "TextEditor.GotoBlockStart";
const char * const GOTO_BLOCK_START_WITH_SELECTION = "TextEditor.GotoBlockStartWithSelection";
const char * const GOTO_BLOCK_END = "TextEditor.GotoBlockEnd";
const char * const GOTO_BLOCK_END_WITH_SELECTION = "TextEditor.GotoBlockEndWithSelection";
const char * const SELECT_BLOCK_UP = "TextEditor.SelectBlockUp";
const char * const SELECT_BLOCK_DOWN = "TextEditor.SelectBlockDown";
const char * const DELETE_LINE = "TextEditor.DeleteLine";
const char * const DELETE_WORD = "TextEditor.DeleteWord";
const char * const SELECT_ENCODING = "TextEditor.SelectEncoding";
const char * const GOTO_OPENING_PARENTHESIS = "TextEditor.GotoOpeningParenthesis";
const char * const GOTO_CLOSING_PARENTHESIS = "TextEditor.GotoOpeningParenthesis";
const char * const C_TEXTEDITOR_MIMETYPE_TEXT = "text/plain";
const char * const C_TEXTEDITOR_MIMETYPE_XML = "application/xml";

View File

@@ -225,24 +225,13 @@ void VCSBaseEditor::mouseMoveEvent(QMouseEvent *e)
sel.format.setFontUnderline(true);
change = changeUnderCursor(cursor);
sel.format.setProperty(QTextFormat::UserProperty, change);
bool found = false;
foreach (QTextEdit::ExtraSelection es, extraSelections()) {
if (es.format.stringProperty(QTextFormat::UserProperty) == sel.format.stringProperty(QTextFormat::UserProperty)) {
found = true;
break;
}
}
if (!found) {
setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel);
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>() << sel);
viewport()->setCursor(Qt::PointingHandCursor);
}
} else {
if (!extraSelections().isEmpty()) {
setExtraSelections(QList<QTextEdit::ExtraSelection>());
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>());
viewport()->setCursor(Qt::IBeamCursor);
}
}
}
TextEditor::BaseTextEditor::mouseMoveEvent(e);
}