Commit d411c076 authored by David Schulz's avatar David Schulz Committed by Erik Verbruggen

C++ Preprocessor additions widget.

Introducing a Widget with a SnippetEditor and a C++ Highlighter which
should provide additional information to the C++ preprocessor for a
specific file.

Change-Id: I27f9498c7e52d1493d6ea92a02a2c6d26130fe07
Reviewed-by: default avatarErik Verbruggen <erik.verbruggen@digia.com>
parent 1a8ef7f3
......@@ -67,29 +67,7 @@ ToolTip *ToolTip::instance()
void ToolTip::show(const QPoint &pos, const TipContent &content, QWidget *w, const QRect &rect)
{
ToolTip *t = instance();
if (t->acceptShow(content, pos, w, rect)) {
QWidget *target = 0;
if (HostOsInfo::isWindowsHost())
target = QApplication::desktop()->screen(Internal::screenNumber(pos, w));
else
target = w;
switch (content.typeId()) {
case TextContent::TEXT_CONTENT_ID:
t->m_tip = new TextTip(target);
break;
case ColorContent::COLOR_CONTENT_ID:
t->m_tip = new ColorTip(target);
break;
case WidgetContent::WIDGET_CONTENT_ID:
t->m_tip = new WidgetTip(target);
break;
}
t->setUp(pos, content, w, rect);
qApp->installEventFilter(t);
t->showTip();
}
instance()->showInternal(pos, content, w, rect);
}
void ToolTip::show(const QPoint &pos, const TipContent &content, QWidget *w)
......@@ -214,6 +192,32 @@ void ToolTip::hideTipImmediately()
qApp->removeEventFilter(this);
}
void ToolTip::showInternal(const QPoint &pos, const TipContent &content, QWidget *w, const QRect &rect)
{
if (acceptShow(content, pos, w, rect)) {
QWidget *target = 0;
if (HostOsInfo::isWindowsHost())
target = QApplication::desktop()->screen(Internal::screenNumber(pos, w));
else
target = w;
switch (content.typeId()) {
case TextContent::TEXT_CONTENT_ID:
m_tip = new TextTip(target);
break;
case ColorContent::COLOR_CONTENT_ID:
m_tip = new ColorTip(target);
break;
case WidgetContent::WIDGET_CONTENT_ID:
m_tip = new WidgetTip(target);
break;
}
setUp(pos, content, w, rect);
qApp->installEventFilter(this);
showTip();
}
}
void ToolTip::placeTip(const QPoint &pos, QWidget *w)
{
QRect screen = Internal::screenGeometry(pos, w);
......@@ -254,7 +258,7 @@ bool ToolTip::eventFilter(QObject *o, QEvent *event)
}
#endif
case QEvent::Leave:
if (o == m_tip)
if (o == m_tip && !m_tip->isAncestorOf(qApp->focusWidget()))
hideTipWithDelay();
break;
case QEvent::Enter:
......
......@@ -60,6 +60,8 @@ class TipContent;
class QTCREATOR_UTILS_EXPORT ToolTip : public QObject
{
Q_OBJECT
protected:
ToolTip();
public:
~ToolTip();
......@@ -73,11 +75,13 @@ public:
static void hide();
static bool isVisible();
private slots:
protected slots:
void hideTipImmediately();
protected:
void showInternal(const QPoint &pos, const TipContent &content, QWidget *w, const QRect &rect);
private:
ToolTip();
bool acceptShow(const TipContent &content, const QPoint &pos, QWidget *w, const QRect &rect);
bool validateContent(const TipContent &content);
void setUp(const QPoint &pos, const TipContent &content, QWidget *w, const QRect &rect);
......
......@@ -34,6 +34,7 @@
#include "cppeditorplugin.h"
#include "cppfollowsymbolundercursor.h"
#include "cpphighlighter.h"
#include "cpppreprocessoradditionwidget.h"
#include "cppquickfixassistant.h"
#include <coreplugin/actionmanager/actioncontainer.h>
......@@ -52,6 +53,10 @@
#include <cpptools/doxygengenerator.h>
#include <cpptools/cpptoolssettings.h>
#include <cpptools/symbolfinder.h>
#include <cpptools/cppmodelmanager.h>
#include <projectexplorer/session.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/nodesvisitor.h>
#include <texteditor/basetextdocument.h>
#include <texteditor/basetextdocumentlayout.h>
#include <texteditor/codeassist/basicproposalitem.h>
......@@ -78,6 +83,7 @@
#include <QComboBox>
#include <QTreeView>
#include <QSortFilterProxyModel>
#include <QToolButton>
enum {
UPDATE_OUTLINE_INTERVAL = 500,
......@@ -641,6 +647,10 @@ void CPPEditorWidget::createToolBar(CPPEditor *editor)
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateUses()));
connect(this, SIGNAL(textChanged()), this, SLOT(updateUses()));
QToolButton *hashButton = new QToolButton(this);
hashButton->setText(QLatin1String("#"));
connect(hashButton, SIGNAL(clicked()), this, SLOT(showPreProcessorWidget()));
editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, hashButton);
editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, m_outlineCombo);
}
......@@ -691,6 +701,20 @@ void CPPEditorWidget::selectAll()
void CPPEditorWidget::setMimeType(const QString &mt)
{
const QString &fileName = editor()->document()->filePath();
// Check if this editor belongs to a project
QList<ProjectPart::Ptr> projectParts = m_modelManager->projectPart(fileName);
if (projectParts.isEmpty())
projectParts = m_modelManager->projectPartFromDependencies(fileName);
if (!projectParts.isEmpty()) {
if (ProjectExplorer::Project *project = projectParts.first()->project) {
QByteArray additionalDefines = project->additionalCppDefines()
.value(projectParts.first()->projectFile).toByteArray();
m_modelManager->cppEditorSupport(editor())->snapshotUpdater()->setEditorDefines(
additionalDefines);
}
}
BaseTextEditorWidget::setMimeType(mt);
setObjCEnabled(mt == QLatin1String(CppTools::Constants::OBJECTIVE_C_SOURCE_MIMETYPE)
|| mt == QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE));
......@@ -1941,4 +1965,31 @@ void CPPEditorWidget::onCommentsSettingsChanged(const CppTools::CommentsSettings
m_commentsSettings = settings;
}
void CPPEditorWidget::showPreProcessorWidget()
{
const QString &fileName = editor()->document()->filePath();
// Check if this editor belongs to a project
QList<ProjectPart::Ptr> projectParts = m_modelManager->projectPart(fileName);
if (projectParts.isEmpty())
projectParts = m_modelManager->projectPartFromDependencies(fileName);
if (projectParts.isEmpty())
projectParts << m_modelManager->fallbackProjectPart();
PreProcessorAdditionPopUp::instance()->show(this, projectParts);
connect(PreProcessorAdditionPopUp::instance(),
SIGNAL(finished(QByteArray)),
SLOT(preProcessorWidgetFinished(QByteArray)));
}
void CPPEditorWidget::preProcessorWidgetFinished(const QByteArray &additionalDefines)
{
PreProcessorAdditionPopUp::instance()->disconnect(this);
QSharedPointer<SnapshotUpdater> updater
= m_modelManager->cppEditorSupport(editor())->snapshotUpdater();
updater->setEditorDefines(additionalDefines);
updater->update(m_modelManager->workingCopy());
}
#include <cppeditor.moc>
......@@ -187,6 +187,9 @@ private Q_SLOTS:
void onCommentsSettingsChanged(const CppTools::CommentsSettings &settings);
void showPreProcessorWidget();
void preProcessorWidgetFinished(const QByteArray &additionalDefines);
private:
void markSymbols(const QTextCursor &tc, const CppTools::SemanticInfo &info);
bool sortedOutline() const;
......@@ -257,6 +260,7 @@ private:
CppTools::CommentsSettings m_commentsSettings;
QScopedPointer<FollowSymbolUnderCursor> m_followSymbolUnderCursor;
QString m_preProcessorAdditions;
};
} // namespace Internal
......
......@@ -24,7 +24,8 @@ HEADERS += cppeditorplugin.h \
cppincludehierarchymodel.h \
cppincludehierarchyitem.h \
cppincludehierarchytreeview.h \
cppvirtualfunctionassistprovider.h
cppvirtualfunctionassistprovider.h \
cpppreprocessoradditionwidget.h
SOURCES += cppeditorplugin.cpp \
cppautocompleter.cpp \
......@@ -47,7 +48,8 @@ SOURCES += cppeditorplugin.cpp \
cppincludehierarchymodel.cpp \
cppincludehierarchyitem.cpp \
cppincludehierarchytreeview.cpp \
cppvirtualfunctionassistprovider.cpp
cppvirtualfunctionassistprovider.cpp \
cpppreprocessoradditionwidget.cpp
RESOURCES += cppeditor.qrc
......@@ -63,3 +65,6 @@ equals(TEST, 1) {
DEFINES += SRCDIR=\\\"$$PWD\\\"
}
FORMS += \
cpppreprocessoradditionwidget.ui
......@@ -50,6 +50,9 @@ QtcPlugin {
"cppincludehierarchytreeview.h",
"cppoutline.cpp",
"cppoutline.h",
"cpppreprocessoradditionwidget.cpp",
"cpppreprocessoradditionwidget.h",
"cpppreprocessoradditionwidget.ui",
"cppquickfixassistant.cpp",
"cppquickfixassistant.h",
"cppquickfix.cpp",
......
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "cpppreprocessoradditionwidget.h"
#include "ui_cpppreprocessoradditionwidget.h"
#include "cppsnippetprovider.h"
#include "utils/tooltip/tipcontents.h"
#include "utils/tooltip/tooltip.h"
#include "projectexplorer/project.h"
#include <QDebug>
using namespace CppEditor::Internal;
PreProcessorAdditionWidget::PreProcessorAdditionWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::CppPreProcessorAdditionWidget)
{
ui->setupUi(this);
CppEditor::Internal::CppSnippetProvider prov;
prov.decorateEditor(ui->additionalEdit);
setAttribute(Qt::WA_QuitOnClose, false);
setFocusPolicy(Qt::StrongFocus);
}
PreProcessorAdditionWidget::~PreProcessorAdditionWidget()
{
emit finished();
delete ui;
}
PreProcessorAdditionPopUp *PreProcessorAdditionPopUp::instance()
{
static PreProcessorAdditionPopUp inst;
return &inst;
}
void PreProcessorAdditionPopUp::show(QWidget *parent,
const QList<CppTools::ProjectPart::Ptr> &projectParts)
{
widget = new PreProcessorAdditionWidget();
originalPartAdditions.clear();
foreach (CppTools::ProjectPart::Ptr projectPart, projectParts) {
ProjectPartAddition addition;
addition.projectPart = projectPart;
widget->ui->projectComboBox->addItem(projectPart->displayName);
addition.additionalDefines = projectPart->project
->additionalCppDefines().value(projectPart->projectFile).toByteArray();
originalPartAdditions << addition;
}
partAdditions = originalPartAdditions;
widget->ui->additionalEdit->setPlainText(QLatin1String(
partAdditions[widget->ui->projectComboBox->currentIndex()].additionalDefines));
QPoint pos = parent->mapToGlobal(parent->rect().topRight());
pos.setX(pos.x() - widget->width());
showInternal(pos, Utils::WidgetContent(widget, true), parent, QRect());
connect(widget->ui->additionalEdit, SIGNAL(textChanged()), SLOT(textChanged()));
connect(widget->ui->projectComboBox, SIGNAL(currentIndexChanged(int)),
SLOT(projectChanged(int)));
connect(widget, SIGNAL(finished()), SLOT(finish()));
connect(widget->ui->buttonBox, SIGNAL(accepted()), SLOT(apply()));
connect(widget->ui->buttonBox, SIGNAL(rejected()), SLOT(cancel()));
}
bool PreProcessorAdditionPopUp::eventFilter(QObject *o, QEvent *event)
{
// Filter out some events that would hide the widget, when they would be handled by the ToolTip
switch (event->type()) {
case QEvent::Leave:
// This event would hide the ToolTip because the view isn't a child of the WidgetContent
if (widget->ui->projectComboBox->view() == qApp->focusWidget())
return false;
break;
case QEvent::KeyPress:
case QEvent::KeyRelease:
case QEvent::ShortcutOverride:
// Catch the escape key to close the widget
if (static_cast<QKeyEvent *>(event)->key() == Qt::Key_Escape) {
hideTipImmediately();
return true;
}
break;
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::Wheel:
// This event would hide the ToolTip because the viewport isn't a child of the WidgetContent
if (o == widget->ui->projectComboBox->view()->viewport())
return false;
break;
default:
break;
}
return Utils::ToolTip::eventFilter(o, event);
}
void PreProcessorAdditionPopUp::textChanged()
{
partAdditions[widget->ui->projectComboBox->currentIndex()].additionalDefines
= widget->ui->additionalEdit->toPlainText().toLatin1();
}
void PreProcessorAdditionPopUp::finish()
{
widget->disconnect(this);
foreach (ProjectPartAddition partAddition, originalPartAdditions) {
QVariantMap settings = partAddition.projectPart->project->additionalCppDefines();
if (!settings[partAddition.projectPart->projectFile].toString().isEmpty()
&& !partAddition.additionalDefines.isEmpty()) {
settings[partAddition.projectPart->projectFile] = partAddition.additionalDefines;
partAddition.projectPart->project->setAdditionalCppDefines(settings);
}
}
emit finished(originalPartAdditions[widget->ui->projectComboBox->currentIndex()].additionalDefines);
}
void PreProcessorAdditionPopUp::projectChanged(int index)
{
widget->ui->additionalEdit->setPlainText(QLatin1String(partAdditions[index].additionalDefines));
}
void PreProcessorAdditionPopUp::apply()
{
originalPartAdditions = partAdditions;
hideTipImmediately();
}
void PreProcessorAdditionPopUp::cancel()
{
partAdditions = originalPartAdditions;
hideTipImmediately();
}
PreProcessorAdditionPopUp::PreProcessorAdditionPopUp()
: widget(0)
{}
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef CPPPREPROCESSORADDITIONWIDGET_H
#define CPPPREPROCESSORADDITIONWIDGET_H
#include <cpptools/cppmodelmanagerinterface.h>
#include <utils/tooltip/tooltip.h>
#include <QWidget>
#include <QVariantMap>
#include <QPointer>
namespace Ui {
class CppPreProcessorAdditionWidget;
}
namespace CppEditor {
namespace Internal {
class PreProcessorAdditionWidget : public QWidget
{
Q_OBJECT
public:
explicit PreProcessorAdditionWidget(QWidget *parent = 0);
~PreProcessorAdditionWidget();
Ui::CppPreProcessorAdditionWidget *ui;
signals:
void finished();
};
class PreProcessorAdditionPopUp : public Utils::ToolTip
{
Q_OBJECT
public:
~PreProcessorAdditionPopUp(){}
static PreProcessorAdditionPopUp *instance();
void show(QWidget *parent, const QList<CppTools::ProjectPart::Ptr> &projectPartAdditions);
bool eventFilter(QObject *o, QEvent *event);
signals:
void finished(const QByteArray &additionalDefines);
private slots:
void textChanged();
void finish();
void projectChanged(int index);
void apply();
void cancel();
protected:
explicit PreProcessorAdditionPopUp();
private:
struct ProjectPartAddition {
CppTools::ProjectPart::Ptr projectPart;
QByteArray additionalDefines;
};
PreProcessorAdditionWidget* widget;
QList<ProjectPartAddition> originalPartAdditions;
QList<ProjectPartAddition> partAdditions;
};
} // namespace CPPEditor
} // namespace Internal
#endif // CPPPREPROCESSORADDITIONWIDGET_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CppPreProcessorAdditionWidget</class>
<widget class="QWidget" name="CppPreProcessorAdditionWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>415</width>
<height>395</height>
</rect>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="windowTitle">
<string>PP</string>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="projectLabel">
<property name="text">
<string>Project:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="projectComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="separator">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="additionalLabel">
<property name="text">
<string>Additional</string>
</property>
</widget>
</item>
<item>
<widget class="TextEditor::SnippetEditorWidget" name="additionalEdit"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>TextEditor::SnippetEditorWidget</class>
<extends>QPlainTextEdit</extends>
<header>texteditor/snippets/snippeteditor.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
......@@ -71,6 +71,7 @@ const char TARGET_KEY_PREFIX[] = "ProjectExplorer.Project.Target.";
const char TARGET_COUNT_KEY[] = "ProjectExplorer.Project.TargetCount";
const char EDITOR_SETTINGS_KEY[] = "ProjectExplorer.Project.EditorSettings";
const char PLUGIN_SETTINGS_KEY[] = "ProjectExplorer.Project.PluginSettings";
const char CPP_SETTINGS_KEY[] = "ProjectExplorer.Project.CppSettings";
} // namespace
namespace ProjectExplorer {
......@@ -90,6 +91,7 @@ public:
Core::Context m_projectContext;
Core::Context m_projectLanguages;
QVariantMap m_pluginSettings;
QVariantMap m_additionalCppDefines;
SettingsAccessor *m_accessor;
};
......@@ -329,6 +331,7 @@ QVariantMap Project::toMap() const
map.insert(QLatin1String(EDITOR_SETTINGS_KEY), d->m_editorConfiguration->toMap());
map.insert(QLatin1String(PLUGIN_SETTINGS_KEY), d->m_pluginSettings);
map.insert(QLatin1String(CPP_SETTINGS_KEY), d->m_additionalCppDefines);
return map;
}
......@@ -356,6 +359,8 @@ bool Project::fromMap(const QVariantMap &map)
if (map.contains(QLatin1String(PLUGIN_SETTINGS_KEY)))
d->m_pluginSettings = map.value(QLatin1String(PLUGIN_SETTINGS_KEY)).toMap();
if (map.contains(QLatin1String(CPP_SETTINGS_KEY)))
d->m_additionalCppDefines = map.value(QLatin1String(CPP_SETTINGS_KEY)).toMap();
bool ok;
int maxI(map.value(QLatin1String(TARGET_COUNT_KEY), 0).toInt(&ok));
......@@ -460,6 +465,16 @@ void Project::setNamedSettings(const QString &name, const QVariant &value)
d->m_pluginSettings.insert(name, value);
}
QVariantMap Project::additionalCppDefines() const
{
return d->m_additionalCppDefines;
}
void Project::setAdditionalCppDefines(const QVariantMap value) const
{
d->m_additionalCppDefines = value;
}
bool Project::needsConfiguration() const
{
return false;
......
......@@ -123,6 +123,9 @@ public:
QVariant namedSettings(const QString &name) const;
void setNamedSettings(const QString &name, const QVariant &value);
QVariantMap additionalCppDefines() const;
void setAdditionalCppDefines(const QVariantMap value) const;
virtual bool needsConfiguration() const;
virtual void configureAsExampleProject(const QStringList &platforms);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment