Commit ed6abae4 authored by Michael Dönnebrink's avatar Michael Dönnebrink
Browse files

QmlJSEditor: Add option to automatically format QML/JS file on save



Change-Id: Ide1810efdef98595705daa32c83fecc2ad367a49
Reviewed-by: Riitta-Leena Miettinen's avatarLeena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: default avatarThomas Hartmann <Thomas.Hartmann@theqtcompany.com>
parent 410211e0
......@@ -23,7 +23,7 @@
**
****************************************************************************/
#include "quicktoolbarsettingspage.h"
#include "qmljseditingsettingspage.h"
#include "qmljseditorconstants.h"
#include <qmljstools/qmljstoolsconstants.h>
......@@ -37,97 +37,158 @@
using namespace QmlJSEditor;
using namespace QmlJSEditor::Internal;
QuickToolBarSettings::QuickToolBarSettings()
: enableContextPane(false),
pinContextPane(false)
QmlJsEditingSettings::QmlJsEditingSettings()
: m_enableContextPane(false),
m_pinContextPane(false),
m_autoFormatOnSave(false),
m_autoFormatOnlyCurrentProject(false)
{}
void QuickToolBarSettings::set()
void QmlJsEditingSettings::set()
{
if (get() != *this)
toSettings(Core::ICore::settings());
}
void QuickToolBarSettings::fromSettings(QSettings *settings)
void QmlJsEditingSettings::fromSettings(QSettings *settings)
{
settings->beginGroup(QLatin1String(QmlJSEditor::Constants::SETTINGS_CATEGORY_QML));
enableContextPane = settings->value(
QLatin1String(QmlJSEditor::Constants::QML_CONTEXTPANE_KEY), QVariant(false)).toBool();
pinContextPane = settings->value(
QLatin1String(QmlJSEditor::Constants::QML_CONTEXTPANEPIN_KEY), QVariant(false)).toBool();
m_enableContextPane = settings->value(
QLatin1String(QmlJSEditor::Constants::QML_CONTEXTPANE_KEY),
QVariant(false)).toBool();
m_pinContextPane = settings->value(
QLatin1String(QmlJSEditor::Constants::QML_CONTEXTPANEPIN_KEY),
QVariant(false)).toBool();
m_autoFormatOnSave = settings->value(
QLatin1String(QmlJSEditor::Constants::AUTO_FORMAT_ON_SAVE),
QVariant(false)).toBool();
m_autoFormatOnlyCurrentProject = settings->value(
QLatin1String(QmlJSEditor::Constants::AUTO_FORMAT_ONLY_CURRENT_PROJECT),
QVariant(false)).toBool();
settings->endGroup();
}
void QuickToolBarSettings::toSettings(QSettings *settings) const
void QmlJsEditingSettings::toSettings(QSettings *settings) const
{
settings->beginGroup(QLatin1String(QmlJSEditor::Constants::SETTINGS_CATEGORY_QML));
settings->setValue(QLatin1String(QmlJSEditor::Constants::QML_CONTEXTPANE_KEY), enableContextPane);
settings->setValue(QLatin1String(QmlJSEditor::Constants::QML_CONTEXTPANEPIN_KEY), pinContextPane);
settings->setValue(QLatin1String(QmlJSEditor::Constants::QML_CONTEXTPANE_KEY),
m_enableContextPane);
settings->setValue(QLatin1String(QmlJSEditor::Constants::QML_CONTEXTPANEPIN_KEY),
m_pinContextPane);
settings->setValue(QLatin1String(QmlJSEditor::Constants::AUTO_FORMAT_ON_SAVE),
m_autoFormatOnSave);
settings->setValue(QLatin1String(QmlJSEditor::Constants::AUTO_FORMAT_ONLY_CURRENT_PROJECT),
m_autoFormatOnlyCurrentProject);
settings->endGroup();
}
bool QuickToolBarSettings::equals(const QuickToolBarSettings &other) const
bool QmlJsEditingSettings::equals(const QmlJsEditingSettings &other) const
{
return enableContextPane == other.enableContextPane
&& pinContextPane == other.pinContextPane;
return m_enableContextPane == other.m_enableContextPane
&& m_pinContextPane == other.m_pinContextPane
&& m_autoFormatOnSave == other.m_autoFormatOnSave
&& m_autoFormatOnlyCurrentProject == other.m_autoFormatOnlyCurrentProject;
}
bool QmlJsEditingSettings::enableContextPane() const
{
return m_enableContextPane;
}
void QmlJsEditingSettings::setEnableContextPane(const bool enableContextPane)
{
m_enableContextPane = enableContextPane;
}
bool QmlJsEditingSettings::pinContextPane() const
{
return m_pinContextPane;
}
void QmlJsEditingSettings::setPinContextPane(const bool pinContextPane)
{
m_pinContextPane = pinContextPane;
}
bool QmlJsEditingSettings::autoFormatOnSave() const
{
return m_autoFormatOnSave;
}
void QmlJsEditingSettings::setAutoFormatOnSave(const bool autoFormatOnSave)
{
m_autoFormatOnSave = autoFormatOnSave;
}
bool QmlJsEditingSettings::autoFormatOnlyCurrentProject() const
{
return m_autoFormatOnlyCurrentProject;
}
void QmlJsEditingSettings::setAutoFormatOnlyCurrentProject(const bool autoFormatOnlyCurrentProject)
{
m_autoFormatOnlyCurrentProject = autoFormatOnlyCurrentProject;
}
QuickToolBarSettingsPageWidget::QuickToolBarSettingsPageWidget(QWidget *parent) :
QmlJsEditingSettignsPageWidget::QmlJsEditingSettignsPageWidget(QWidget *parent) :
QWidget(parent)
{
m_ui.setupUi(this);
}
QuickToolBarSettings QuickToolBarSettingsPageWidget::settings() const
QmlJsEditingSettings QmlJsEditingSettignsPageWidget::settings() const
{
QuickToolBarSettings ds;
ds.enableContextPane = m_ui.textEditHelperCheckBox->isChecked();
ds.pinContextPane = m_ui.textEditHelperCheckBoxPin->isChecked();
return ds;
QmlJsEditingSettings s;
s.setEnableContextPane(m_ui.textEditHelperCheckBox->isChecked());
s.setPinContextPane(m_ui.textEditHelperCheckBoxPin->isChecked());
s.setAutoFormatOnSave(m_ui.autoFormatOnSave->isChecked());
s.setAutoFormatOnlyCurrentProject(m_ui.autoFormatOnlyCurrentProject->isChecked());
return s;
}
void QuickToolBarSettingsPageWidget::setSettings(const QuickToolBarSettings &s)
void QmlJsEditingSettignsPageWidget::setSettings(const QmlJsEditingSettings &s)
{
m_ui.textEditHelperCheckBox->setChecked(s.enableContextPane);
m_ui.textEditHelperCheckBoxPin->setChecked(s.pinContextPane);
m_ui.textEditHelperCheckBox->setChecked(s.enableContextPane());
m_ui.textEditHelperCheckBoxPin->setChecked(s.pinContextPane());
m_ui.autoFormatOnSave->setChecked(s.autoFormatOnSave());
m_ui.autoFormatOnlyCurrentProject->setChecked(s.autoFormatOnlyCurrentProject());
}
QuickToolBarSettings QuickToolBarSettings::get()
QmlJsEditingSettings QmlJsEditingSettings::get()
{
QuickToolBarSettings settings;
QmlJsEditingSettings settings;
settings.fromSettings(Core::ICore::settings());
return settings;
}
QuickToolBarSettingsPage::QuickToolBarSettingsPage() :
QmlJsEditingSettingsPage::QmlJsEditingSettingsPage() :
m_widget(0)
{
setId("C.QmlToolbar");
setDisplayName(tr("Qt Quick ToolBar"));
setId("C.QmlJsEditing");
setDisplayName(tr("QML/JS Editing"));
setCategory(Constants::SETTINGS_CATEGORY_QML);
setDisplayCategory(QCoreApplication::translate("QmlJSEditor",
QmlJSEditor::Constants::SETTINGS_TR_CATEGORY_QML));
setCategoryIcon(Utils::Icon(QmlJSTools::Constants::SETTINGS_CATEGORY_QML_ICON));
}
QWidget *QuickToolBarSettingsPage::widget()
QWidget *QmlJsEditingSettingsPage::widget()
{
if (!m_widget) {
m_widget = new QuickToolBarSettingsPageWidget;
m_widget->setSettings(QuickToolBarSettings::get());
m_widget = new QmlJsEditingSettignsPageWidget;
m_widget->setSettings(QmlJsEditingSettings::get());
}
return m_widget;
}
void QuickToolBarSettingsPage::apply()
void QmlJsEditingSettingsPage::apply()
{
if (!m_widget) // page was never shown
return;
m_widget->settings().set();
}
void QuickToolBarSettingsPage::finish()
void QmlJsEditingSettingsPage::finish()
{
delete m_widget;
}
......@@ -25,7 +25,7 @@
#pragma once
#include "ui_quicktoolbarsettingspage.h"
#include "ui_qmljseditingsettingspage.h"
#include <coreplugin/dialogs/ioptionspage.h>
#include <QPointer>
#include <QWidget>
......@@ -36,61 +36,77 @@ QT_END_NAMESPACE
namespace QmlJSEditor {
class QuickToolBarSettings {
class QmlJsEditingSettings {
public:
QuickToolBarSettings();
QmlJsEditingSettings();
static QuickToolBarSettings get();
static QmlJsEditingSettings get();
void set();
void fromSettings(QSettings *);
void toSettings(QSettings *) const;
bool equals(const QuickToolBarSettings &other) const;
bool enableContextPane;
bool pinContextPane;
bool equals(const QmlJsEditingSettings &other) const;
bool enableContextPane() const;
void setEnableContextPane(const bool enableContextPane);
bool pinContextPane() const;
void setPinContextPane(const bool pinContextPane);
bool autoFormatOnSave() const;
void setAutoFormatOnSave(const bool autoFormatOnSave);
bool autoFormatOnlyCurrentProject() const;
void setAutoFormatOnlyCurrentProject(const bool autoFormatOnlyCurrentProject);
private:
bool m_enableContextPane;
bool m_pinContextPane;
bool m_autoFormatOnSave;
bool m_autoFormatOnlyCurrentProject;
};
inline bool operator==(const QuickToolBarSettings &s1, const QuickToolBarSettings &s2)
inline bool operator==(const QmlJsEditingSettings &s1, const QmlJsEditingSettings &s2)
{ return s1.equals(s2); }
inline bool operator!=(const QuickToolBarSettings &s1, const QuickToolBarSettings &s2)
inline bool operator!=(const QmlJsEditingSettings &s1, const QmlJsEditingSettings &s2)
{ return !s1.equals(s2); }
class QuickToolBarSettings;
class QmlJsEditingSettings;
namespace Internal {
class QuickToolBarSettingsPageWidget : public QWidget
class QmlJsEditingSettignsPageWidget : public QWidget
{
Q_OBJECT
public:
explicit QuickToolBarSettingsPageWidget(QWidget *parent = 0);
explicit QmlJsEditingSettignsPageWidget(QWidget *parent = 0);
QuickToolBarSettings settings() const;
void setSettings(const QuickToolBarSettings &);
QmlJsEditingSettings settings() const;
void setSettings(const QmlJsEditingSettings &);
static QuickToolBarSettings get();
static QmlJsEditingSettings get();
private:
Ui::QuickToolBarSettingsPage m_ui;
Ui::QmlJsEditingSettingsPage m_ui;
};
class QuickToolBarSettingsPage : public Core::IOptionsPage
class QmlJsEditingSettingsPage : public Core::IOptionsPage
{
Q_OBJECT
public:
QuickToolBarSettingsPage();
QmlJsEditingSettingsPage();
QWidget *widget();
void apply();
void finish();
private:
QPointer<QuickToolBarSettingsPageWidget> m_widget;
QPointer<QmlJsEditingSettignsPageWidget> m_widget;
};
} // namespace Internal
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QmlJSEditor::Internal::QuickToolBarSettingsPage</class>
<widget class="QWidget" name="QmlJSEditor::Internal::QuickToolBarSettingsPage">
<class>QmlJSEditor::Internal::QmlJsEditingSettingsPage</class>
<widget class="QWidget" name="QmlJSEditor::Internal::QmlJsEditingSettingsPage">
<property name="geometry">
<rect>
<x>0</x>
......@@ -14,8 +14,8 @@
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Qt Quick Toolbars</string>
</property>
......@@ -40,7 +40,7 @@
</layout>
</widget>
</item>
<item row="1" column="0">
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -48,13 +48,56 @@
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>207</height>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Automatic Formatting on File Save</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="autoFormatOnSave">
<property name="text">
<string>Enable auto format on file save</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="autoFormatOnlyCurrentProject">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Restrict to files contained in the current project</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
<connections>
<connection>
<sender>autoFormatOnSave</sender>
<signal>toggled(bool)</signal>
<receiver>autoFormatOnlyCurrentProject</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>216</x>
<y>40</y>
</hint>
<hint type="destinationlabel">
<x>216</x>
<y>63</y>
</hint>
</hints>
</connection>
</connections>
</ui>
......@@ -17,7 +17,7 @@ HEADERS += \
qmloutlinemodel.h \
qmltaskmanager.h \
qmljsoutlinetreeview.h \
quicktoolbarsettingspage.h \
qmljseditingsettingspage.h \
quicktoolbar.h \
qmljscomponentnamedialog.h \
qmljsfindreferences.h \
......@@ -46,7 +46,7 @@ SOURCES += \
qmltaskmanager.cpp \
qmljsquickfixes.cpp \
qmljsoutlinetreeview.cpp \
quicktoolbarsettingspage.cpp \
qmljseditingsettingspage.cpp \
quicktoolbar.cpp \
qmljscomponentnamedialog.cpp \
qmljsfindreferences.cpp \
......@@ -62,5 +62,5 @@ SOURCES += \
qmljseditordocument.cpp
FORMS += \
quicktoolbarsettingspage.ui \
qmljseditingsettingspage.ui \
qmljscomponentnamedialog.ui
......@@ -26,6 +26,9 @@ QtcPlugin {
"qmljscomponentnamedialog.cpp",
"qmljscomponentnamedialog.h",
"qmljscomponentnamedialog.ui",
"qmljseditingsettingspage.cpp",
"qmljseditingsettingspage.h",
"qmljseditingsettingspage.ui",
"qmljseditor.cpp",
"qmljseditor.h",
"qmljseditor_global.h",
......@@ -68,9 +71,6 @@ QtcPlugin {
"qmltaskmanager.h",
"quicktoolbar.cpp",
"quicktoolbar.h",
"quicktoolbarsettingspage.cpp",
"quicktoolbarsettingspage.h",
"quicktoolbarsettingspage.ui",
]
Export {
......
......@@ -57,5 +57,8 @@ const char QML_CONTEXTPANEPIN_KEY[] = "QmlJSEditor.ContextPanePinned";
const char QML_UI_FILE_WARNING[] = "QmlJSEditor.QmlUiFileWarning";
const char AUTO_FORMAT_ON_SAVE[] = "QmlJSEditor.AutoFormatOnSave";
const char AUTO_FORMAT_ONLY_CURRENT_PROJECT[] = "QmlJSEditor.AutoFormatOnlyCurrentProject";
} // namespace Constants
} // namespace QmlJSEditor
......@@ -23,18 +23,18 @@
**
****************************************************************************/
#include "qmljseditorplugin.h"
#include "qmljshighlighter.h"
#include "qmljseditingsettingspage.h"
#include "qmljseditor.h"
#include "qmljseditorconstants.h"
#include "qmljseditordocument.h"
#include "qmljseditorplugin.h"
#include "qmljshighlighter.h"
#include "qmljsoutline.h"
#include "qmljspreviewrunner.h"
#include "qmljsquickfixassist.h"
#include "qmljssnippetprovider.h"
#include "qmltaskmanager.h"
#include "quicktoolbar.h"
#include "quicktoolbarsettingspage.h"
#include "qmljsquickfixassist.h"
#include <qmljs/qmljsicons.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
......@@ -50,6 +50,8 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/taskhub.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <texteditor/texteditorconstants.h>
#include <utils/qtcassert.h>
......@@ -193,11 +195,14 @@ bool QmlJSEditorPlugin::initialize(const QStringList & /*arguments*/, QString *e
addAutoReleasedObject(new QmlJSOutlineWidgetFactory);
addAutoReleasedObject(new QuickToolBar);
addAutoReleasedObject(new QuickToolBarSettingsPage);
addAutoReleasedObject(new QmlJsEditingSettingsPage);
connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
this, &QmlJSEditorPlugin::currentEditorChanged);
connect(EditorManager::instance(), &Core::EditorManager::aboutToSave,
this, &QmlJSEditorPlugin::autoFormatOnSave);
return true;
}
......@@ -234,9 +239,25 @@ void QmlJSEditorPlugin::renameUsages()
void QmlJSEditorPlugin::reformatFile()
{
if (m_currentDocument) {
QTC_ASSERT(!m_currentDocument->isSemanticInfoOutdated(), return);
QmlJS::Document::Ptr document = m_currentDocument->semanticInfo().document;
QmlJS::Snapshot snapshot = QmlJS::ModelManagerInterface::instance()->snapshot();
if (m_currentDocument->isSemanticInfoOutdated()) {
QmlJS::Document::MutablePtr latestDocument;
const QString &newText = QmlJS::reformat(m_currentDocument->semanticInfo().document);
const QString fileName = m_currentDocument->filePath().toString();
latestDocument = snapshot.documentFromSource(QString::fromUtf8(m_currentDocument->contents()),
fileName,
QmlJS::ModelManagerInterface::guessLanguageOfFile(fileName));
latestDocument->parseQml();
snapshot.insert(latestDocument);
document = latestDocument;
}
if (!document->isParsedCorrectly())
return;
const QString &newText = QmlJS::reformat(document);
QTextCursor tc(m_currentDocument->document());
tc.movePosition(QTextCursor::Start);
tc.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
......@@ -296,4 +317,25 @@ void QmlJSEditorPlugin::checkCurrentEditorSemanticInfoUpToDate()
m_reformatFileAction->setEnabled(semanticInfoUpToDate);
}
void QmlJSEditorPlugin::autoFormatOnSave(Core::IDocument *document)
{
if (!QmlJsEditingSettings::get().autoFormatOnSave())
return;
// Check that we are dealing with a QML/JS editor
if (document->id() != Constants::C_QMLJSEDITOR_ID)
return;
// Check if file is contained in the current project (if wished)
if (QmlJsEditingSettings::get().autoFormatOnlyCurrentProject()) {
const ProjectExplorer::Project *pro = ProjectExplorer::ProjectTree::currentProject();
if (!pro || !pro->files(ProjectExplorer::Project::SourceFiles).contains(
document->filePath().toString())) {
return;
}
}
reformatFile();
}
} // namespace QmlJSEditor
......@@ -38,6 +38,7 @@ namespace Utils { class JsonSchemaManager; }
namespace Core {
class Command;
class ActionContainer;
class IDocument;
class IEditor;
}
......@@ -82,6 +83,7 @@ private:
void currentEditorChanged(Core::IEditor *editor);
void runSemanticScan();
void checkCurrentEditorSemanticInfoUpToDate();
void autoFormatOnSave(Core::IDocument *document);
Core::Command *addToolAction(QAction *a, Core::Context &context, Core::Id id,
Core::ActionContainer *c1, const QString &keySequence);
......
......@@ -24,7 +24,7 @@
****************************************************************************/
#include "quicktoolbar.h"
#include "quicktoolbarsettingspage.h"
#include "qmljseditingsettingspage.h"
#include <utils/changeset.h>
#include <qmleditorwidgets/contextpanewidget.h>
......@@ -114,7 +114,7 @@ QuickToolBar::~QuickToolBar()
void QuickToolBar::apply(TextEditor::TextEditorWidget *editorWidget, Document::Ptr document, const ScopeChain *scopeChain, Node *node, bool update, bool force)
{
if (!QuickToolBarSettings::get().enableContextPane && !force && !update) {
if (!QmlJsEditingSettings::get().enableContextPane() && !force && !update) {
contextWidget()->hide();
return;
}
......@@ -219,10 +219,10 @@ void QuickToolBar::apply(TextEditor::TextEditorWidget *editorWidget, Document::P
if (!update)
contextWidget()->setType(m_prototypes);
if (!update)
contextWidget()->activate(p3 , p1, p2, QuickToolBarSettings::get().pinContextPane);
contextWidget()->activate(p3 , p1, p2, QmlJsEditingSettings::get().pinContextPane());
else
contextWidget()->rePosition(p3 , p1, p2, QuickToolBarSettings::get().pinContextPane);
contextWidget()->setOptions(QuickToolBarSettings::get().enableContextPane, QuickToolBarSettings::get().pinContextPane);
contextWidget()->rePosition(p3 , p1, p2, QmlJsEditingSettings::get().pinContextPane());
contextWidget()->setOptions(QmlJsEditingSettings::get().enableContextPane(), QmlJsEditingSettings::get().pinContextPane());
contextWidget()->setPath(document->path());
contextWidget()->setProperties(&propertyReader);
m_doc = document;
......@@ -404,16 +404,16 @@ void QuickToolBar::onPropertyRemovedAndChange(const QString &remove, const QStri
void QuickToolBar::onPinnedChanged(bool b)
{
QuickToolBarSettings settings = QuickToolBarSettings::get();