Commit 3fc72220 authored by Eike Ziller's avatar Eike Ziller

Get rid of FancyLineEdit::validate

Use aggregation instead of inheritance for customization of validation.
Gets rid of a few additional classes.

Change-Id: Iaf8f12026c40a55bfde98b3786100f8ac431d750
Reviewed-by: default avatarEike Ziller <eike.ziller@theqtcompany.com>
parent e8862cd2
......@@ -69,6 +69,9 @@ ClassNameValidatingLineEdit::ClassNameValidatingLineEdit(QWidget *parent) :
FancyLineEdit(parent),
d(new ClassNameValidatingLineEditPrivate)
{
setValidationFunction([this](FancyLineEdit *edit, QString *errorMessage) {
return validateClassName(edit, errorMessage);
});
updateRegExp();
}
......@@ -104,10 +107,11 @@ void ClassNameValidatingLineEdit::setNamespaceDelimiter(const QString &delimiter
d->m_namespaceDelimiter = delimiter;
}
bool ClassNameValidatingLineEdit::validate(const QString &value, QString *errorMessage) const
bool ClassNameValidatingLineEdit::validateClassName(FancyLineEdit *edit, QString *errorMessage) const
{
QTC_ASSERT(d->m_nameRegexp.isValid(), return false);
const QString value = edit->text();
if (!d->m_namespacesEnabled && value.contains(d->m_namespaceDelimiter)) {
if (errorMessage)
*errorMessage = tr("The class name must not contain namespace delimiters.");
......
......@@ -68,7 +68,7 @@ signals:
void updateFileName(const QString &t);
protected:
bool validate(const QString &value, QString *errorMessage) const;
bool validateClassName(FancyLineEdit *edit, QString *errorMessage) const;
void handleChanged(const QString &t);
QString fixInputString(const QString &string);
......
......@@ -98,6 +98,7 @@ public:
bool m_iconEnabled[2];
HistoryCompleter *m_historyCompleter;
FancyLineEdit::ValidationFunction m_validationFunction;
bool m_isFiltering;
QString m_lastFilterText;
......@@ -115,6 +116,7 @@ FancyLineEditPrivate::FancyLineEditPrivate(FancyLineEdit *parent) :
QObject(parent),
m_lineEdit(parent),
m_historyCompleter(0),
m_validationFunction(FancyLineEdit::defaultValidationFunction()),
m_isFiltering(false),
m_okTextColor(FancyLineEdit::textColor(parent)),
m_errorTextColor(Qt::red),
......@@ -413,12 +415,22 @@ void FancyLineEdit::setTextColor(QWidget *w, const QColor &c)
w->setPalette(palette);
}
bool FancyLineEdit::validate(const QString &value, QString *errorMessage) const
void FancyLineEdit::setValidationFunction(const FancyLineEdit::ValidationFunction &fn)
{
d->m_validationFunction = fn;
}
FancyLineEdit::ValidationFunction FancyLineEdit::defaultValidationFunction()
{
return &FancyLineEdit::validateWithValidator;
}
bool FancyLineEdit::validateWithValidator(FancyLineEdit *edit, QString *errorMessage)
{
Q_UNUSED(errorMessage);
if (const QValidator *v = validator()) {
QString tmp = value;
int pos = cursorPosition();
if (const QValidator *v = edit->validator()) {
QString tmp = edit->text();
int pos = edit->cursorPosition();
return v->validate(tmp, pos) == QValidator::Acceptable;
}
return true;
......@@ -453,7 +465,7 @@ void FancyLineEdit::onTextChanged(const QString &t)
const bool isDisplayingInitialText = !d->m_initialText.isEmpty() && t == d->m_initialText;
const State newState = isDisplayingInitialText ?
DisplayingInitialText :
(validate(t, &d->m_errorMessage) ? Valid : Invalid);
(d->m_validationFunction(this, &d->m_errorMessage) ? Valid : Invalid);
setToolTip(d->m_errorMessage);
// Changed..figure out if valid changed. DisplayingInitialText is not valid,
// but should not show error color. Also trigger on the first change.
......
......@@ -36,6 +36,8 @@
#include <QAbstractButton>
#include <functional>
QT_BEGIN_NAMESPACE
class QEvent;
QT_END_NAMESPACE
......@@ -127,6 +129,8 @@ public:
// Validation
// line edit, (out)errorMessage -> valid?
typedef std::function<bool(FancyLineEdit *, QString *)> ValidationFunction;
enum State { Invalid, DisplayingInitialText, Valid };
State state() const;
......@@ -145,6 +149,9 @@ public:
static QColor textColor(const QWidget *w);
static void setTextColor(QWidget *w, const QColor &c);
void setValidationFunction(const ValidationFunction &fn);
static ValidationFunction defaultValidationFunction();
protected slots:
// Custom behaviour can be added here.
virtual void handleChanged(const QString &) {}
......@@ -167,10 +174,10 @@ private slots:
protected:
void resizeEvent(QResizeEvent *e);
virtual bool validate(const QString &value, QString *errorMessage) const;
virtual QString fixInputString(const QString &string);
private:
static bool validateWithValidator(FancyLineEdit *edit, QString *errorMessage);
// Unimplemented, to force the user to make a decision on
// whether to use setHistoryCompleter() or setSpecialCompleter().
void setCompleter(QCompleter *);
......
......@@ -71,6 +71,10 @@ FileNameValidatingLineEdit::FileNameValidatingLineEdit(QWidget *parent) :
m_allowDirectories(false),
m_forceFirstCapitalLetter(false)
{
setValidationFunction([this](FancyLineEdit *edit, QString *errorMessage) {
return validateFileNameExtension(edit->text(), requiredExtensions(), errorMessage)
&& validateFileName(edit->text(), allowDirectories(), errorMessage);
});
}
bool FileNameValidatingLineEdit::allowDirectories() const
......@@ -148,12 +152,6 @@ bool FileNameValidatingLineEdit::validateFileName(const QString &name,
return true;
}
bool FileNameValidatingLineEdit::validate(const QString &value, QString *errorMessage) const
{
return validateFileNameExtension(value, requiredExtensions(), errorMessage)
&& validateFileName(value, allowDirectories(), errorMessage);
}
QString FileNameValidatingLineEdit::fixInputString(const QString &string)
{
if (!forceFirstCapitalLetter())
......
......@@ -75,7 +75,6 @@ public:
void setRequiredExtensions(const QStringList &extensionList);
protected:
virtual bool validate(const QString &value, QString *errorMessage) const;
virtual QString fixInputString(const QString &string);
private:
......
......@@ -30,7 +30,6 @@
#include "pathchooser.h"
#include "fancylineedit.h"
#include "environment.h"
#include "qtcassert.h"
......@@ -55,32 +54,6 @@
namespace Utils {
// ------------------ PathValidatingLineEdit
class PathValidatingLineEdit : public FancyLineEdit
{
public:
explicit PathValidatingLineEdit(PathChooser *chooser, QWidget *parent = 0);
protected:
virtual bool validate(const QString &value, QString *errorMessage) const;
private:
PathChooser *m_chooser;
};
PathValidatingLineEdit::PathValidatingLineEdit(PathChooser *chooser, QWidget *parent) :
FancyLineEdit(parent),
m_chooser(chooser)
{
QTC_ASSERT(chooser, return);
}
bool PathValidatingLineEdit::validate(const QString &value, QString *errorMessage) const
{
return m_chooser->validatePath(value, errorMessage);
}
// ------------------ BinaryVersionToolTipEventFilter
// Event filter to be installed on a lineedit used for entering
// executables, taking the arguments to print the version ('--version').
......@@ -176,12 +149,12 @@ private:
class PathChooserPrivate
{
public:
PathChooserPrivate(PathChooser *chooser);
PathChooserPrivate();
QString expandedPath(const QString &path) const;
QHBoxLayout *m_hLayout;
PathValidatingLineEdit *m_lineEdit;
FancyLineEdit *m_lineEdit;
PathChooser::Kind m_acceptingKind;
QString m_dialogTitleOverride;
......@@ -191,15 +164,13 @@ public:
Environment m_environment;
BinaryVersionToolTipEventFilter *m_binaryVersionToolTipEventFilter;
QList<QAbstractButton *> m_buttons;
PathChooser::PathValidator m_additionalValidator;
};
PathChooserPrivate::PathChooserPrivate(PathChooser *chooser) :
PathChooserPrivate::PathChooserPrivate() :
m_hLayout(new QHBoxLayout),
m_lineEdit(new PathValidatingLineEdit(chooser)),
m_lineEdit(new FancyLineEdit),
m_acceptingKind(PathChooser::ExistingDirectory),
m_binaryVersionToolTipEventFilter(0),
m_additionalValidator([](const QString &, QString *) { return true; })
m_binaryVersionToolTipEventFilter(0)
{
}
......@@ -232,7 +203,7 @@ QString PathChooserPrivate::expandedPath(const QString &input) const
PathChooser::PathChooser(QWidget *parent) :
QWidget(parent),
d(new PathChooserPrivate(this))
d(new PathChooserPrivate)
{
d->m_hLayout->setContentsMargins(0, 0, 0, 0);
......@@ -252,6 +223,8 @@ PathChooser::PathChooser(QWidget *parent) :
setFocusProxy(d->m_lineEdit);
setFocusPolicy(d->m_lineEdit->focusPolicy());
setEnvironment(Environment::systemEnvironment());
d->m_lineEdit->setValidationFunction(defaultValidationFunction());
}
PathChooser::~PathChooser()
......@@ -462,13 +435,14 @@ void PathChooser::triggerChanged()
d->m_lineEdit->triggerChanged();
}
void PathChooser::setAdditionalPathValidator(const PathChooser::PathValidator &pathValidator)
FancyLineEdit::ValidationFunction PathChooser::defaultValidationFunction() const
{
d->m_additionalValidator = pathValidator;
return std::bind(&PathChooser::validatePath, this, std::placeholders::_1, std::placeholders::_2);
}
bool PathChooser::validatePath(const QString &path, QString *errorMessage)
bool PathChooser::validatePath(FancyLineEdit *edit, QString *errorMessage) const
{
const QString path = edit->text();
QString expandedPath = d->expandedPath(path);
if (path.isEmpty()) {
......@@ -586,14 +560,16 @@ bool PathChooser::validatePath(const QString &path, QString *errorMessage)
;
}
if (!d->m_additionalValidator(path, errorMessage))
return false;
if (errorMessage)
*errorMessage = tr("Full path: <b>%1</b>").arg(QDir::toNativeSeparators(expandedPath));
return true;
}
void PathChooser::setValidationFunction(const FancyLineEdit::ValidationFunction &fn)
{
d->m_lineEdit->setValidationFunction(fn);
}
QString PathChooser::label()
{
return tr("Path:");
......
......@@ -31,12 +31,11 @@
#ifndef PATHCHOOSER_H
#define PATHCHOOSER_H
#include "fancylineedit.h"
#include "fileutils.h"
#include <QWidget>
#include <functional>
QT_BEGIN_NAMESPACE
class QAbstractButton;
class QLineEdit;
......@@ -110,7 +109,8 @@ public:
/** Returns the suggested label title when used in a form layout. */
static QString label();
bool validatePath(const QString &path, QString *errorMessage = 0);
FancyLineEdit::ValidationFunction defaultValidationFunction() const;
void setValidationFunction(const FancyLineEdit::ValidationFunction &fn);
/** Return the home directory, which needs some fixing under Windows. */
static QString homePath();
......@@ -140,10 +140,8 @@ public:
void triggerChanged();
typedef std::function<bool(const QString &, QString *)> PathValidator;
void setAdditionalPathValidator(const PathValidator &pathValidator);
private:
bool validatePath(FancyLineEdit *edit, QString *errorMessage) const;
// Returns overridden title or the one from <title>
QString makeDialogTitle(const QString &title);
......
......@@ -31,6 +31,7 @@
#include "projectintropage.h"
#include "ui_projectintropage.h"
#include "filenamevalidatinglineedit.h"
#include "wizard.h"
#include <QDir>
......@@ -89,6 +90,9 @@ ProjectIntroPage::ProjectIntroPage(QWidget *parent) :
hideStatusLabel();
d->m_ui.nameLineEdit->setInitialText(tr("<Enter_Name>"));
d->m_ui.nameLineEdit->setFocus();
d->m_ui.nameLineEdit->setValidationFunction([this](FancyLineEdit *edit, QString *errorString) {
return ProjectIntroPage::validateProjectName(edit->text(), errorString);
});
d->m_ui.projectLabel->setVisible(d->m_forceSubProject);
d->m_ui.projectComboBox->setVisible(d->m_forceSubProject);
d->m_ui.pathChooser->setDisabled(d->m_forceSubProject);
......@@ -247,6 +251,26 @@ int ProjectIntroPage::projectIndex() const
return d->m_ui.projectComboBox->currentIndex();
}
bool ProjectIntroPage::validateProjectName(const QString &name, QString *errorMessage /* = 0*/)
{
// Validation is file name + checking for dots
if (!FileNameValidatingLineEdit::validateFileName(name, false, errorMessage))
return false;
int pos = FileUtils::indexOfQmakeUnfriendly(name);
if (pos >= 0) {
if (errorMessage)
*errorMessage = tr("Invalid character \"%1\" found.").arg(name.at(pos));
return false;
}
if (name.contains(QLatin1Char('.'))) {
if (errorMessage)
*errorMessage = tr("Invalid character '.'.");
return false;
}
return true;
}
void ProjectIntroPage::displayStatusMessage(StatusLabelMode m, const QString &s)
{
switch (m) {
......
......@@ -67,6 +67,8 @@ public:
void setProjectDirectories(const QStringList &directoryList);
int projectIndex() const;
static bool validateProjectName(const QString &name, QString *errorMessage /* = 0*/);
signals:
void activated();
......
......@@ -60,7 +60,7 @@
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::ProjectNameValidatingLineEdit" name="nameLineEdit"/>
<widget class="Utils::FancyLineEdit" name="nameLineEdit"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="pathLabel">
......@@ -119,9 +119,9 @@
</widget>
<customwidgets>
<customwidget>
<class>Utils::ProjectNameValidatingLineEdit</class>
<class>Utils::FancyLineEdit</class>
<extends>QLineEdit</extends>
<header location="global">utils/projectnamevalidatinglineedit.h</header>
<header location="global">utils/fancylineedit.h</header>
</customwidget>
<customwidget>
<class>Utils::PathChooser</class>
......
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** 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 The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "projectnamevalidatinglineedit.h"
#include "filenamevalidatinglineedit.h"
#include "fileutils.h"
namespace Utils {
ProjectNameValidatingLineEdit::ProjectNameValidatingLineEdit(QWidget *parent)
: FancyLineEdit(parent)
{
}
bool ProjectNameValidatingLineEdit::validateProjectName(const QString &name, QString *errorMessage /* = 0*/)
{
// Validation is file name + checking for dots
if (!FileNameValidatingLineEdit::validateFileName(name, false, errorMessage))
return false;
int pos = FileUtils::indexOfQmakeUnfriendly(name);
if (pos >= 0) {
if (errorMessage)
*errorMessage = tr("Invalid character \"%1\" found.").arg(name.at(pos));
return false;
}
if (name.contains(QLatin1Char('.'))) {
if (errorMessage)
*errorMessage = tr("Invalid character '.'.");
return false;
}
return true;
}
bool ProjectNameValidatingLineEdit::validate(const QString &value, QString *errorMessage) const
{
return validateProjectName(value, errorMessage);
}
} // namespace Utils
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** 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 The Qt Company. For licensing terms and
** conditions see http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/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 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#ifndef PROJECTNAMEVALIDATINGLINEEDIT_H
#define PROJECTNAMEVALIDATINGLINEEDIT_H
#include "fancylineedit.h"
namespace Utils {
class QTCREATOR_UTILS_EXPORT ProjectNameValidatingLineEdit : public FancyLineEdit
{
Q_OBJECT
public:
explicit ProjectNameValidatingLineEdit(QWidget *parent = 0);
static bool validateProjectName(const QString &name, QString *errorMessage /* = 0*/);
protected:
virtual bool validate(const QString &value, QString *errorMessage) const;
};
} // namespace Utils
#endif // PROJECTNAMEVALIDATINGLINEEDIT_H
......@@ -26,7 +26,6 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/filesystemwatcher.cpp \
$$PWD/projectintropage.cpp \
$$PWD/filenamevalidatinglineedit.cpp \
$$PWD/projectnamevalidatinglineedit.cpp \
$$PWD/codegeneration.cpp \
$$PWD/newclasswidget.cpp \
$$PWD/classnamevalidatinglineedit.cpp \
......@@ -115,7 +114,6 @@ HEADERS += \
$$PWD/filesystemwatcher.h \
$$PWD/projectintropage.h \
$$PWD/filenamevalidatinglineedit.h \
$$PWD/projectnamevalidatinglineedit.h \
$$PWD/codegeneration.h \
$$PWD/newclasswidget.h \
$$PWD/classnamevalidatinglineedit.h \
......
......@@ -138,8 +138,6 @@ QtcLibrary {
"projectintropage.cpp",
"projectintropage.h",
"projectintropage.ui",
"projectnamevalidatinglineedit.cpp",
"projectnamevalidatinglineedit.h",
"proxyaction.cpp",
"proxyaction.h",
"proxycredentialsdialog.cpp",
......
......@@ -54,21 +54,6 @@ using namespace Utils;
namespace Core {
namespace Internal {
class KeySequenceValidator : public FancyLineEdit
{
public:
KeySequenceValidator(QWidget *parent, CommandMappings *mappings)
: FancyLineEdit(parent), m_mappings(mappings)
{}
bool validate(const QString &, QString *) const
{
return !m_mappings->hasConflicts();
}
CommandMappings *m_mappings;
};
class CommandMappingsPrivate
{
public:
......@@ -106,11 +91,14 @@ public:
targetEditGroup = new QGroupBox(CommandMappings::tr("Target Identifier"), m_widget);
targetEdit = new KeySequenceValidator(targetEditGroup, q);
targetEdit = new FancyLineEdit(targetEditGroup);
targetEdit->setAutoHideButton(FancyLineEdit::Right, true);
targetEdit->setPlaceholderText(QString());
targetEdit->installEventFilter(q);
targetEdit->setFiltering(true);
targetEdit->setValidationFunction([this](FancyLineEdit *, QString *) {
return !q->hasConflicts();
});
resetButton = new QPushButton(targetEditGroup);
resetButton->setToolTip(CommandMappings::tr("Reset to default."));
......
......@@ -478,6 +478,11 @@ QbsBuildStepConfigWidget::QbsBuildStepConfigWidget(QbsBuildStep *step) :
m_ui = new Ui::QbsBuildStepConfigWidget;
m_ui->setupUi(this);
m_ui->propertyEdit->setValidationFunction([this](Utils::FancyLineEdit *edit,
QString *errorMessage) {
return validateProperties(edit, errorMessage);
});
connect(m_ui->buildVariantComboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(changeBuildVariant(int)));
connect(m_ui->dryRunCheckBox, SIGNAL(toggled(bool)), this, SLOT(changeDryRun(bool)));
......@@ -489,7 +494,6 @@ QbsBuildStepConfigWidget::QbsBuildStepConfigWidget(QbsBuildStep *step) :
&QbsBuildStepConfigWidget::changeInstall);
connect(m_ui->cleanInstallRootCheckBox, &QCheckBox::toggled, this,
&QbsBuildStepConfigWidget::changeCleanInstallRoot);
connect(m_ui->propertyEdit, SIGNAL(propertiesChanged()), this, SLOT(changeProperties()));
connect(m_ui->qmlDebuggingLibraryCheckBox, SIGNAL(toggled(bool)),
this, SLOT(linkQmlDebuggingLibraryChecked(bool)));
connect(QtSupport::QtVersionManager::instance(), SIGNAL(dumpUpdatedFor(Utils::FileName)),
......@@ -532,10 +536,9 @@ void QbsBuildStepConfigWidget::updateState()
m_ui->buildVariantComboBox->setCurrentIndex