ClangFormat: Fix UI issues

- 'Default' values remain so after save/load
 - the language is fixed to C++
 - the project settings are shown correctly
 - fix parsing configuration file
 - do not trigger slots when we fill the table

Change-Id: I91b477721b5084803324cd38d0cfeb9d5650dd9f
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Ivan Donchevskii
2019-04-25 10:40:08 +02:00
parent 57c48630a8
commit 2d8ce380c9
6 changed files with 149 additions and 80 deletions

View File

@@ -38,7 +38,7 @@ def full_ui_content(checks):
<widget class="QWidget" name="ClangFormat::ClangFormatChecksWidget">
<property name="maximumSize">
<size>
<width>450</width>
<width>480</width>
<height>16777215</height>
</size>
</property>
@@ -199,6 +199,11 @@ def createItem(key, value, index):
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
'''
if key == 'Language':
value_item += ''' <property name="enabled">
<bool>false</bool>
</property>
'''
if index > 0:
value_item += ''' <item>

View File

@@ -4,7 +4,7 @@
<widget class="QWidget" name="ClangFormat::ClangFormatChecksWidget">
<property name="maximumSize">
<size>
<width>450</width>
<width>480</width>
<height>16777215</height>
</size>
</property>
@@ -2045,6 +2045,9 @@
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<item>
<property name="text">
<string notr="true">Default</string>

View File

@@ -43,11 +43,11 @@
#include <texteditor/snippets/snippeteditor.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditorsettings.h>
#include <utils/executeondestruction.h>
#include <utils/qtcassert.h>
#include <QFile>
#include <QMessageBox>
#include <QScrollArea>
#include <sstream>
@@ -72,32 +72,8 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *proje
{
m_ui->setupUi(this);
QScrollArea *scrollArea = new QScrollArea();
m_checksWidget = new QWidget();
m_checks->setupUi(m_checksWidget);
scrollArea->setWidget(m_checksWidget);
scrollArea->setMaximumWidth(470);
initChecksAndPreview();
m_ui->horizontalLayout_2->addWidget(scrollArea);
for (QObject *child : m_checksWidget->children()) {
auto comboBox = qobject_cast<QComboBox *>(child);
if (comboBox != nullptr) {
connect(comboBox,
QOverload<int>::of(&QComboBox::currentIndexChanged),
this,
&ClangFormatConfigWidget::onTableChanged);
comboBox->installEventFilter(this);
continue;
}
auto button = qobject_cast<QPushButton *>(child);
if (button != nullptr)
connect(button, &QPushButton::clicked, this, &ClangFormatConfigWidget::onTableChanged);
}
m_preview = new TextEditor::SnippetEditorWidget(this);
m_ui->horizontalLayout_2->addWidget(m_preview);
if (m_project) {
m_ui->applyButton->show();
hideGlobalCheckboxes();
@@ -118,15 +94,53 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *proje
initialize();
});
initialize();
connectChecks();
}
void ClangFormatConfigWidget::initChecksAndPreview()
{
m_checksScrollArea = new QScrollArea();
m_checksWidget = new QWidget;
m_checks->setupUi(m_checksWidget);
m_checksScrollArea->setWidget(m_checksWidget);
m_checksScrollArea->setMaximumWidth(500);
m_ui->horizontalLayout_2->addWidget(m_checksScrollArea);
m_preview = new TextEditor::SnippetEditorWidget(this);
m_ui->horizontalLayout_2->addWidget(m_preview);
}
void ClangFormatConfigWidget::connectChecks()
{
for (QObject *child : m_checksWidget->children()) {
auto comboBox = qobject_cast<QComboBox *>(child);
if (comboBox != nullptr) {
connect(comboBox,
qOverload<int>(&QComboBox::currentIndexChanged),
this,
&ClangFormatConfigWidget::onTableChanged);
comboBox->installEventFilter(this);
continue;
}
auto button = qobject_cast<QPushButton *>(child);
if (button != nullptr)
connect(button, &QPushButton::clicked, this, &ClangFormatConfigWidget::onTableChanged);
}
}
void ClangFormatConfigWidget::onTableChanged()
{
if (m_disableTableUpdate)
return;
const std::string newConfig = tableToString(sender());
if (newConfig.empty())
return;
clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle();
const std::string oldConfig = clang::format::configurationAsText(style);
const std::string oldConfig = m_project ? currentProjectConfigText()
: currentGlobalConfigText();
saveConfig(newConfig);
fillTable();
updatePreview();
@@ -180,13 +194,13 @@ void ClangFormatConfigWidget::initialize()
if (!m_ui->overrideDefault->isChecked() && m_project) {
// Show the fallback configuration only globally.
m_checksWidget->hide();
m_checksScrollArea->hide();
m_preview->hide();
m_ui->verticalLayout->addStretch(1);
return;
}
m_checksWidget->show();
m_checksScrollArea->show();
m_preview->show();
Utils::FileName fileName;
@@ -238,12 +252,61 @@ static inline void trim(std::string &s)
rtrim(s);
}
static void fillPlainText(QPlainTextEdit *plainText, const std::string &text, size_t index)
{
if (index == std::string::npos) {
plainText->setPlainText("");
return;
}
size_t valueStart = text.find('\n', index + 1);
size_t valueEnd;
std::string value;
QTC_ASSERT(valueStart != std::string::npos, return;);
do {
valueEnd = text.find('\n', valueStart + 1);
if (valueEnd == std::string::npos)
break;
// Skip also 2 spaces - start with valueStart + 1 + 2.
std::string line = text.substr(valueStart + 3, valueEnd - valueStart - 3);
rtrim(line);
value += value.empty() ? line : '\n' + line;
valueStart = valueEnd;
} while (valueEnd < text.size() - 1 && text.at(valueEnd + 1) == ' ');
plainText->setPlainText(QString::fromStdString(value));
}
static void fillComboBoxOrLineEdit(QObject *object, const std::string &text, size_t index)
{
auto *comboBox = qobject_cast<QComboBox *>(object);
auto *lineEdit = qobject_cast<QLineEdit *>(object);
if (index == std::string::npos) {
if (comboBox)
comboBox->setCurrentIndex(0);
else
lineEdit->setText("");
return;
}
const size_t valueStart = text.find(':', index + 1);
QTC_ASSERT(valueStart != std::string::npos, return;);
const size_t valueEnd = text.find('\n', valueStart + 1);
QTC_ASSERT(valueEnd != std::string::npos, return;);
std::string value = text.substr(valueStart + 1, valueEnd - valueStart - 1);
trim(value);
if (comboBox)
comboBox->setCurrentText(QString::fromStdString(value));
else
lineEdit->setText(QString::fromStdString(value));
}
void ClangFormatConfigWidget::fillTable()
{
clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle();
Utils::ExecuteOnDestruction executeOnDestruction([this]() { m_disableTableUpdate = false; });
m_disableTableUpdate = true;
using namespace std;
const string configText = clang::format::configurationAsText(style);
const std::string configText = m_project ? currentProjectConfigText()
: currentGlobalConfigText();
for (QObject *child : m_checksWidget->children()) {
if (!qobject_cast<QComboBox *>(child) && !qobject_cast<QLineEdit *>(child)
@@ -251,52 +314,14 @@ void ClangFormatConfigWidget::fillTable()
continue;
}
const size_t index = configText.find(child->objectName().toStdString());
size_t index = configText.find('\n' + child->objectName().toStdString());
if (index == std::string::npos)
index = configText.find("\n " + child->objectName().toStdString());
auto *plainText = qobject_cast<QPlainTextEdit *>(child);
if (plainText) {
if (index == string::npos) {
plainText->setPlainText("");
continue;
}
size_t valueStart = configText.find('\n', index);
size_t valueEnd;
string value;
QTC_ASSERT(valueStart != string::npos, continue;);
do {
valueEnd = configText.find('\n', valueStart + 1);
if (valueEnd == string::npos)
break;
// Skip also 2 spaces - start with valueStart + 1 + 2.
string line = configText.substr(valueStart + 3, valueEnd - valueStart - 3);
rtrim(line);
value += value.empty() ? line : '\n' + line;
valueStart = valueEnd;
} while (valueEnd < configText.size() - 1 && configText.at(valueEnd + 1) == ' ');
plainText->setPlainText(QString::fromStdString(value));
} else {
auto *comboBox = qobject_cast<QComboBox *>(child);
auto *lineEdit = qobject_cast<QLineEdit *>(child);
if (index == string::npos) {
if (comboBox)
comboBox->setCurrentIndex(0);
else
lineEdit->setText("");
continue;
}
const size_t valueStart = configText.find(':', index);
QTC_ASSERT(valueStart != string::npos, continue;);
const size_t valueEnd = configText.find('\n', valueStart + 1);
QTC_ASSERT(valueEnd != string::npos, continue;);
string value = configText.substr(valueStart + 1, valueEnd - valueStart - 1);
trim(value);
if (comboBox)
comboBox->setCurrentText(QString::fromStdString(value));
else
lineEdit->setText(QString::fromStdString(value));
}
if (qobject_cast<QPlainTextEdit *>(child))
fillPlainText(qobject_cast<QPlainTextEdit *>(child), configText, index);
else
fillComboBoxOrLineEdit(child, configText, index);
}
}

View File

@@ -27,6 +27,8 @@
#include <texteditor/icodestylepreferencesfactory.h>
#include <QScrollArea>
#include <memory>
namespace ProjectExplorer {
@@ -59,6 +61,9 @@ private:
bool eventFilter(QObject *object, QEvent *event) override;
void initialize();
void initChecksAndPreview();
void connectChecks();
void fillTable();
std::string tableToString(QObject *sender);
@@ -70,9 +75,11 @@ private:
ProjectExplorer::Project *m_project;
QWidget *m_checksWidget;
QScrollArea *m_checksScrollArea;
TextEditor::SnippetEditorWidget *m_preview;
std::unique_ptr<Ui::ClangFormatChecksWidget> m_checks;
std::unique_ptr<Ui::ClangFormatConfigWidget> m_ui;
bool m_disableTableUpdate = false;
};
} // namespace ClangFormat

View File

@@ -318,6 +318,32 @@ clang::format::FormatStyle styleForFile(Utils::FileName fileName)
return styleForFile(fileName, true);
}
static std::string readFile(const QString &path)
{
QFile file(path);
if (!file.open(QFile::ReadOnly)) {
clang::format::FormatStyle defaultStyle = qtcStyle();
return clang::format::configurationAsText(defaultStyle);
}
const QByteArray content = file.readAll();
file.close();
return content.toStdString();
}
std::string currentProjectConfigText()
{
const QString configPath = projectPath().appendPath(Constants::SETTINGS_FILE_NAME).toString();
return readFile(configPath);
}
std::string currentGlobalConfigText()
{
const QString configPath = globalPath().appendPath(Constants::SETTINGS_FILE_NAME).toString();
return readFile(configPath);
}
clang::format::FormatStyle currentProjectStyle()
{
return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME), false);

View File

@@ -40,6 +40,9 @@ void createStyleFileIfNeeded(bool isGlobal);
QString currentProjectUniqueId();
std::string currentProjectConfigText();
std::string currentGlobalConfigText();
clang::format::FormatStyle currentProjectStyle();
clang::format::FormatStyle currentGlobalStyle();