mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-03 07:45:30 +08:00
qt 6.5.1 original
This commit is contained in:
40
examples/widgets/tools/settingseditor/CMakeLists.txt
Normal file
40
examples/widgets/tools/settingseditor/CMakeLists.txt
Normal file
@ -0,0 +1,40 @@
|
||||
# Copyright (C) 2022 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(settingseditor LANGUAGES CXX)
|
||||
|
||||
if(NOT DEFINED INSTALL_EXAMPLESDIR)
|
||||
set(INSTALL_EXAMPLESDIR "examples")
|
||||
endif()
|
||||
|
||||
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/tools/settingseditor")
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
qt_add_executable(settingseditor
|
||||
locationdialog.cpp locationdialog.h
|
||||
main.cpp
|
||||
mainwindow.cpp mainwindow.h
|
||||
settingstree.cpp settingstree.h
|
||||
variantdelegate.cpp variantdelegate.h
|
||||
)
|
||||
|
||||
set_target_properties(settingseditor PROPERTIES
|
||||
WIN32_EXECUTABLE TRUE
|
||||
MACOSX_BUNDLE TRUE
|
||||
)
|
||||
|
||||
target_link_libraries(settingseditor PRIVATE
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
install(TARGETS settingseditor
|
||||
RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
|
||||
)
|
@ -0,0 +1,46 @@
|
||||
[Field%201]
|
||||
Bottom=89
|
||||
Flags=MULTILINE|VSCROLL|READONLY
|
||||
Left=4
|
||||
Right=296
|
||||
State=No license agreement file found. Please contact support.
|
||||
Top=14
|
||||
Type=Text
|
||||
|
||||
[Field%202]
|
||||
Bottom=8
|
||||
Left=4
|
||||
Right=294
|
||||
Text=Press Page Down to see the rest of the agreement.
|
||||
Top=0
|
||||
Type=Label
|
||||
|
||||
[Field%203]
|
||||
Bottom=111
|
||||
Left=4
|
||||
Right=297
|
||||
Text=If you accept the terms of the agreement, select the first option below. You must accept the agreement to install this software. Click Next to continue.
|
||||
Top=92
|
||||
Type=Label
|
||||
|
||||
[Field%204]
|
||||
Bottom=129
|
||||
Flags=GROUP|NOTIFY
|
||||
Left=4
|
||||
Right=299
|
||||
Text=I &accept the terms in the License Agreement
|
||||
Top=120
|
||||
Type=RadioButton
|
||||
|
||||
[Field%205]
|
||||
Bottom=140
|
||||
Flags=NOTIFY
|
||||
Left=4
|
||||
Right=300
|
||||
State=1
|
||||
Text=I &do not accept the terms in the License Agreement
|
||||
Top=129
|
||||
Type=RadioButton
|
||||
|
||||
[Settings]
|
||||
NumFields=5
|
26
examples/widgets/tools/settingseditor/inifiles/qsa.ini
Normal file
26
examples/widgets/tools/settingseditor/inifiles/qsa.ini
Normal file
@ -0,0 +1,26 @@
|
||||
[Field%201]
|
||||
Bottom=65
|
||||
Left=0
|
||||
Right=299
|
||||
Text=QSA Build Options
|
||||
Top=9
|
||||
Type=Groupbox
|
||||
|
||||
[Field%202]
|
||||
Bottom=37
|
||||
Left=20
|
||||
Right=284
|
||||
Text=Don't compile QSA Workbench into QSA.
|
||||
Top=27
|
||||
Type=Checkbox
|
||||
|
||||
[Field%203]
|
||||
Bottom=56
|
||||
Left=20
|
||||
Right=247
|
||||
Text=Don't compile QSA Workbench nor QSA Editor into QSA.
|
||||
Top=45
|
||||
Type=Checkbox
|
||||
|
||||
[Settings]
|
||||
NumFields=3
|
193
examples/widgets/tools/settingseditor/locationdialog.cpp
Normal file
193
examples/widgets/tools/settingseditor/locationdialog.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "locationdialog.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QComboBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDir>
|
||||
#include <QPushButton>
|
||||
#include <QGroupBox>
|
||||
#include <QHeaderView>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QTableWidget>
|
||||
#include <QTableWidgetItem>
|
||||
|
||||
LocationDialog::LocationDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
formatComboBox = new QComboBox;
|
||||
formatComboBox->addItem(tr("Native"));
|
||||
formatComboBox->addItem(tr("INI"));
|
||||
|
||||
scopeComboBox = new QComboBox;
|
||||
scopeComboBox->addItem(tr("User"));
|
||||
scopeComboBox->addItem(tr("System"));
|
||||
|
||||
organizationComboBox = new QComboBox;
|
||||
organizationComboBox->addItem(tr("QtProject"));
|
||||
organizationComboBox->setEditable(true);
|
||||
|
||||
applicationComboBox = new QComboBox;
|
||||
applicationComboBox->addItem(tr("Any"));
|
||||
applicationComboBox->addItem(tr("Qt Creator"));
|
||||
applicationComboBox->addItem(tr("Application Example"));
|
||||
applicationComboBox->addItem(tr("Assistant"));
|
||||
applicationComboBox->addItem(tr("Designer"));
|
||||
applicationComboBox->addItem(tr("Linguist"));
|
||||
applicationComboBox->setEditable(true);
|
||||
applicationComboBox->setCurrentIndex(1);
|
||||
|
||||
formatLabel = new QLabel(tr("&Format:"));
|
||||
formatLabel->setBuddy(formatComboBox);
|
||||
|
||||
scopeLabel = new QLabel(tr("&Scope:"));
|
||||
scopeLabel->setBuddy(scopeComboBox);
|
||||
|
||||
organizationLabel = new QLabel(tr("&Organization:"));
|
||||
organizationLabel->setBuddy(organizationComboBox);
|
||||
|
||||
applicationLabel = new QLabel(tr("&Application:"));
|
||||
applicationLabel->setBuddy(applicationComboBox);
|
||||
|
||||
locationsGroupBox = new QGroupBox(tr("Setting Locations"));
|
||||
|
||||
const QStringList labels{tr("Location"), tr("Access")};
|
||||
|
||||
locationsTable = new QTableWidget;
|
||||
locationsTable->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
locationsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
locationsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
locationsTable->setColumnCount(2);
|
||||
locationsTable->setHorizontalHeaderLabels(labels);
|
||||
locationsTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
locationsTable->horizontalHeader()->resizeSection(1, 180);
|
||||
connect(locationsTable, &QTableWidget::itemActivated, this, &LocationDialog::itemActivated);
|
||||
|
||||
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
|
||||
connect(formatComboBox, &QComboBox::activated,
|
||||
this, &LocationDialog::updateLocationsTable);
|
||||
connect(scopeComboBox, &QComboBox::activated,
|
||||
this, &LocationDialog::updateLocationsTable);
|
||||
connect(organizationComboBox->lineEdit(),
|
||||
&QLineEdit::editingFinished,
|
||||
this, &LocationDialog::updateLocationsTable);
|
||||
connect(applicationComboBox->lineEdit(),
|
||||
&QLineEdit::editingFinished,
|
||||
this, &LocationDialog::updateLocationsTable);
|
||||
connect(applicationComboBox, &QComboBox::activated,
|
||||
this, &LocationDialog::updateLocationsTable);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
|
||||
QVBoxLayout *locationsLayout = new QVBoxLayout(locationsGroupBox);
|
||||
locationsLayout->addWidget(locationsTable);
|
||||
|
||||
QGridLayout *mainLayout = new QGridLayout(this);
|
||||
mainLayout->addWidget(formatLabel, 0, 0);
|
||||
mainLayout->addWidget(formatComboBox, 0, 1);
|
||||
mainLayout->addWidget(scopeLabel, 1, 0);
|
||||
mainLayout->addWidget(scopeComboBox, 1, 1);
|
||||
mainLayout->addWidget(organizationLabel, 2, 0);
|
||||
mainLayout->addWidget(organizationComboBox, 2, 1);
|
||||
mainLayout->addWidget(applicationLabel, 3, 0);
|
||||
mainLayout->addWidget(applicationComboBox, 3, 1);
|
||||
mainLayout->addWidget(locationsGroupBox, 4, 0, 1, 2);
|
||||
mainLayout->addWidget(buttonBox, 5, 0, 1, 2);
|
||||
|
||||
updateLocationsTable();
|
||||
|
||||
setWindowTitle(tr("Open Application Settings"));
|
||||
resize(650, 400);
|
||||
}
|
||||
|
||||
QSettings::Format LocationDialog::format() const
|
||||
{
|
||||
if (formatComboBox->currentIndex() == 0)
|
||||
return QSettings::NativeFormat;
|
||||
else
|
||||
return QSettings::IniFormat;
|
||||
}
|
||||
|
||||
QSettings::Scope LocationDialog::scope() const
|
||||
{
|
||||
if (scopeComboBox->currentIndex() == 0)
|
||||
return QSettings::UserScope;
|
||||
else
|
||||
return QSettings::SystemScope;
|
||||
}
|
||||
|
||||
QString LocationDialog::organization() const
|
||||
{
|
||||
return organizationComboBox->currentText();
|
||||
}
|
||||
|
||||
QString LocationDialog::application() const
|
||||
{
|
||||
if (applicationComboBox->currentText() == tr("Any"))
|
||||
return QString();
|
||||
else
|
||||
return applicationComboBox->currentText();
|
||||
}
|
||||
|
||||
void LocationDialog::itemActivated(QTableWidgetItem *)
|
||||
{
|
||||
buttonBox->button(QDialogButtonBox::Ok)->animateClick();
|
||||
}
|
||||
|
||||
void LocationDialog::updateLocationsTable()
|
||||
{
|
||||
locationsTable->setUpdatesEnabled(false);
|
||||
locationsTable->setRowCount(0);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (i == 0 && scope() == QSettings::SystemScope)
|
||||
continue;
|
||||
|
||||
QSettings::Scope actualScope = (i == 0) ? QSettings::UserScope
|
||||
: QSettings::SystemScope;
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
if (j == 0 && application().isEmpty())
|
||||
continue;
|
||||
|
||||
QString actualApplication;
|
||||
if (j == 0)
|
||||
actualApplication = application();
|
||||
QSettings settings(format(), actualScope, organization(),
|
||||
actualApplication);
|
||||
|
||||
int row = locationsTable->rowCount();
|
||||
locationsTable->setRowCount(row + 1);
|
||||
|
||||
QTableWidgetItem *item0 = new QTableWidgetItem(QDir::toNativeSeparators(settings.fileName()));
|
||||
|
||||
QTableWidgetItem *item1 = new QTableWidgetItem;
|
||||
bool disable = (settings.childKeys().isEmpty()
|
||||
&& settings.childGroups().isEmpty());
|
||||
|
||||
if (row == 0) {
|
||||
if (settings.isWritable()) {
|
||||
item1->setText(tr("Read-write"));
|
||||
disable = false;
|
||||
} else {
|
||||
item1->setText(tr("Read-only"));
|
||||
}
|
||||
buttonBox->button(QDialogButtonBox::Ok)->setDisabled(disable);
|
||||
} else {
|
||||
item1->setText(tr("Read-only fallback"));
|
||||
}
|
||||
|
||||
if (disable) {
|
||||
item0->setFlags(item0->flags() & ~Qt::ItemIsEnabled);
|
||||
item1->setFlags(item1->flags() & ~Qt::ItemIsEnabled);
|
||||
}
|
||||
|
||||
locationsTable->setItem(row, 0, item0);
|
||||
locationsTable->setItem(row, 1, item1);
|
||||
}
|
||||
}
|
||||
locationsTable->setUpdatesEnabled(true);
|
||||
}
|
49
examples/widgets/tools/settingseditor/locationdialog.h
Normal file
49
examples/widgets/tools/settingseditor/locationdialog.h
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef LOCATIONDIALOG_H
|
||||
#define LOCATIONDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSettings>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QComboBox;
|
||||
class QDialogButtonBox;
|
||||
class QGroupBox;
|
||||
class QLabel;
|
||||
class QTableWidget;
|
||||
class QTableWidgetItem;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class LocationDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LocationDialog(QWidget *parent = nullptr);
|
||||
|
||||
QSettings::Format format() const;
|
||||
QSettings::Scope scope() const;
|
||||
QString organization() const;
|
||||
QString application() const;
|
||||
|
||||
private slots:
|
||||
void updateLocationsTable();
|
||||
void itemActivated(QTableWidgetItem *);
|
||||
|
||||
private:
|
||||
QLabel *formatLabel;
|
||||
QLabel *scopeLabel;
|
||||
QLabel *organizationLabel;
|
||||
QLabel *applicationLabel;
|
||||
QComboBox *formatComboBox;
|
||||
QComboBox *scopeComboBox;
|
||||
QComboBox *organizationComboBox;
|
||||
QComboBox *applicationComboBox;
|
||||
QGroupBox *locationsGroupBox;
|
||||
QTableWidget *locationsTable;
|
||||
QDialogButtonBox *buttonBox;
|
||||
};
|
||||
|
||||
#endif
|
17
examples/widgets/tools/settingseditor/main.cpp
Normal file
17
examples/widgets/tools/settingseditor/main.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
QCoreApplication::setApplicationName("Settings Editor");
|
||||
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
|
||||
|
||||
MainWindow mainWin;
|
||||
mainWin.show();
|
||||
return app.exec();
|
||||
}
|
175
examples/widgets/tools/settingseditor/mainwindow.cpp
Normal file
175
examples/widgets/tools/settingseditor/mainwindow.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "locationdialog.h"
|
||||
#include "mainwindow.h"
|
||||
#include "settingstree.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
#include <QScreen>
|
||||
#include <QStandardPaths>
|
||||
#include <QStatusBar>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||
, settingsTree(new SettingsTree)
|
||||
{
|
||||
setCentralWidget(settingsTree);
|
||||
|
||||
createActions();
|
||||
|
||||
autoRefreshAct->setChecked(true);
|
||||
fallbacksAct->setChecked(true);
|
||||
|
||||
setWindowTitle(QCoreApplication::applicationName());
|
||||
const QRect availableGeometry = screen()->availableGeometry();
|
||||
adjustSize();
|
||||
move((availableGeometry.width() - width()) / 2, (availableGeometry.height() - height()) / 2);
|
||||
}
|
||||
|
||||
void MainWindow::openSettings()
|
||||
{
|
||||
if (!locationDialog)
|
||||
locationDialog = new LocationDialog(this);
|
||||
|
||||
if (locationDialog->exec() != QDialog::Accepted)
|
||||
return;
|
||||
|
||||
SettingsPtr settings(new QSettings(locationDialog->format(),
|
||||
locationDialog->scope(),
|
||||
locationDialog->organization(),
|
||||
locationDialog->application()));
|
||||
|
||||
setSettingsObject(settings);
|
||||
fallbacksAct->setEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::openIniFile()
|
||||
{
|
||||
const QString directory = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
|
||||
const QString fileName =
|
||||
QFileDialog::getOpenFileName(this, tr("Open INI File"),
|
||||
directory, tr("INI Files (*.ini *.conf)"));
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
SettingsPtr settings(new QSettings(fileName, QSettings::IniFormat));
|
||||
|
||||
setSettingsObject(settings);
|
||||
fallbacksAct->setEnabled(false);
|
||||
}
|
||||
|
||||
void MainWindow::openPropertyList()
|
||||
{
|
||||
const QString directory = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
|
||||
const QString fileName =
|
||||
QFileDialog::getOpenFileName(this, tr("Open Property List"),
|
||||
directory, tr("Property List Files (*.plist)"));
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
|
||||
SettingsPtr settings(new QSettings(fileName, QSettings::NativeFormat));
|
||||
setSettingsObject(settings);
|
||||
fallbacksAct->setEnabled(false);
|
||||
}
|
||||
|
||||
void MainWindow::openRegistryPath()
|
||||
{
|
||||
const QString path =
|
||||
QInputDialog::getText(this, tr("Open Registry Path"),
|
||||
tr("Enter the path in the Windows registry:"),
|
||||
QLineEdit::Normal, "HKEY_CURRENT_USER\\");
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
SettingsPtr settings(new QSettings(path, QSettings::NativeFormat));
|
||||
|
||||
setSettingsObject(settings);
|
||||
fallbacksAct->setEnabled(false);
|
||||
}
|
||||
|
||||
void MainWindow::about()
|
||||
{
|
||||
QMessageBox::about(this, tr("About Settings Editor"),
|
||||
tr("The <b>Settings Editor</b> example shows how to access "
|
||||
"application settings using Qt."));
|
||||
}
|
||||
|
||||
void MainWindow::createActions()
|
||||
{
|
||||
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
|
||||
|
||||
QAction *openSettingsAct = fileMenu->addAction(tr("&Open Application Settings..."), this, &MainWindow::openSettings);
|
||||
openSettingsAct->setShortcuts(QKeySequence::Open);
|
||||
|
||||
QAction *openIniFileAct = fileMenu->addAction(tr("Open I&NI File..."), this, &MainWindow::openIniFile);
|
||||
openIniFileAct->setShortcut(tr("Ctrl+N"));
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
QAction *openPropertyListAct = fileMenu->addAction(tr("Open Apple &Property List..."), this, &MainWindow::openPropertyList);
|
||||
openPropertyListAct->setShortcut(tr("Ctrl+P"));
|
||||
#endif // Q_OS_MACOS
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QAction *openRegistryPathAct = fileMenu->addAction(tr("Open Windows &Registry Path..."), this, &MainWindow::openRegistryPath);
|
||||
openRegistryPathAct->setShortcut(tr("Ctrl+G"));
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
fileMenu->addSeparator();
|
||||
|
||||
refreshAct = fileMenu->addAction(tr("&Refresh"), settingsTree, &SettingsTree::refresh);
|
||||
refreshAct->setShortcut(tr("Ctrl+R"));
|
||||
refreshAct->setEnabled(false);
|
||||
|
||||
fileMenu->addSeparator();
|
||||
|
||||
QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
|
||||
exitAct->setShortcuts(QKeySequence::Quit);
|
||||
|
||||
QMenu *optionsMenu = menuBar()->addMenu(tr("&Options"));
|
||||
|
||||
autoRefreshAct = optionsMenu->addAction(tr("&Auto-Refresh"));
|
||||
autoRefreshAct->setShortcut(tr("Ctrl+A"));
|
||||
autoRefreshAct->setCheckable(true);
|
||||
autoRefreshAct->setEnabled(false);
|
||||
connect(autoRefreshAct, &QAction::triggered,
|
||||
settingsTree, &SettingsTree::setAutoRefresh);
|
||||
connect(autoRefreshAct, &QAction::triggered,
|
||||
refreshAct, &QAction::setDisabled);
|
||||
|
||||
fallbacksAct = optionsMenu->addAction(tr("&Fallbacks"));
|
||||
fallbacksAct->setShortcut(tr("Ctrl+F"));
|
||||
fallbacksAct->setCheckable(true);
|
||||
fallbacksAct->setEnabled(false);
|
||||
connect(fallbacksAct, &QAction::triggered,
|
||||
settingsTree, &SettingsTree::setFallbacksEnabled);
|
||||
|
||||
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
|
||||
helpMenu->addAction(tr("&About"), this, &MainWindow::about);
|
||||
helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
|
||||
}
|
||||
|
||||
void MainWindow::setSettingsObject(const SettingsPtr &settings)
|
||||
{
|
||||
settings->setFallbacksEnabled(fallbacksAct->isChecked());
|
||||
settingsTree->setSettingsObject(settings);
|
||||
|
||||
refreshAct->setEnabled(true);
|
||||
autoRefreshAct->setEnabled(true);
|
||||
|
||||
QString niceName = QDir::cleanPath(settings->fileName());
|
||||
int pos = niceName.lastIndexOf(QLatin1Char('/'));
|
||||
if (pos != -1)
|
||||
niceName.remove(0, pos + 1);
|
||||
|
||||
if (!settings->isWritable())
|
||||
niceName = tr("%1 (read only)").arg(niceName);
|
||||
|
||||
setWindowTitle(tr("%1 - %2").arg(niceName, QCoreApplication::applicationName()));
|
||||
statusBar()->showMessage(tr("Opened \"%1\"").arg(QDir::toNativeSeparators(settings->fileName())));
|
||||
}
|
44
examples/widgets/tools/settingseditor/mainwindow.h
Normal file
44
examples/widgets/tools/settingseditor/mainwindow.h
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSharedPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QSettings;
|
||||
QT_END_NAMESPACE
|
||||
class LocationDialog;
|
||||
class SettingsTree;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
typedef QSharedPointer<QSettings> SettingsPtr;
|
||||
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void openSettings();
|
||||
void openIniFile();
|
||||
void openPropertyList();
|
||||
void openRegistryPath();
|
||||
void about();
|
||||
|
||||
private:
|
||||
void createActions();
|
||||
void setSettingsObject(const SettingsPtr &settings);
|
||||
|
||||
SettingsTree *settingsTree = nullptr;
|
||||
LocationDialog *locationDialog = nullptr;
|
||||
QAction *refreshAct = nullptr;
|
||||
QAction *autoRefreshAct = nullptr;
|
||||
QAction *fallbacksAct = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
18
examples/widgets/tools/settingseditor/settingseditor.pro
Normal file
18
examples/widgets/tools/settingseditor/settingseditor.pro
Normal file
@ -0,0 +1,18 @@
|
||||
QT += widgets
|
||||
requires(qtConfig(tablewidget))
|
||||
|
||||
HEADERS = locationdialog.h \
|
||||
mainwindow.h \
|
||||
settingstree.h \
|
||||
variantdelegate.h
|
||||
SOURCES = locationdialog.cpp \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
settingstree.cpp \
|
||||
variantdelegate.cpp
|
||||
|
||||
EXAMPLE_FILES = inifiles
|
||||
|
||||
# install
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/widgets/tools/settingseditor
|
||||
INSTALLS += target
|
231
examples/widgets/tools/settingseditor/settingstree.cpp
Normal file
231
examples/widgets/tools/settingseditor/settingstree.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "settingstree.h"
|
||||
#include "variantdelegate.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QHeaderView>
|
||||
#include <QScreen>
|
||||
#include <QSettings>
|
||||
|
||||
SettingsTree::SettingsTree(QWidget *parent)
|
||||
: QTreeWidget(parent),
|
||||
m_typeChecker(new TypeChecker)
|
||||
{
|
||||
setItemDelegate(new VariantDelegate(m_typeChecker, this));
|
||||
|
||||
setHeaderLabels({tr("Setting"), tr("Type"), tr("Value")});
|
||||
header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
||||
header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
|
||||
header()->setSectionResizeMode(2, QHeaderView::Stretch);
|
||||
|
||||
refreshTimer.setInterval(2000);
|
||||
|
||||
groupIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon),
|
||||
QIcon::Normal, QIcon::Off);
|
||||
groupIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirOpenIcon),
|
||||
QIcon::Normal, QIcon::On);
|
||||
keyIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon));
|
||||
|
||||
connect(&refreshTimer, &QTimer::timeout, this, &SettingsTree::maybeRefresh);
|
||||
}
|
||||
|
||||
SettingsTree::~SettingsTree() = default;
|
||||
|
||||
void SettingsTree::setSettingsObject(const SettingsPtr &newSettings)
|
||||
{
|
||||
settings = newSettings;
|
||||
clear();
|
||||
|
||||
if (settings.isNull()) {
|
||||
refreshTimer.stop();
|
||||
} else {
|
||||
refresh();
|
||||
if (autoRefresh)
|
||||
refreshTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
QSize SettingsTree::sizeHint() const
|
||||
{
|
||||
const QRect availableGeometry = screen()->availableGeometry();
|
||||
return QSize(availableGeometry.width() * 2 / 3, availableGeometry.height() * 2 / 3);
|
||||
}
|
||||
|
||||
void SettingsTree::setAutoRefresh(bool autoRefresh)
|
||||
{
|
||||
this->autoRefresh = autoRefresh;
|
||||
if (!settings.isNull()) {
|
||||
if (autoRefresh) {
|
||||
maybeRefresh();
|
||||
refreshTimer.start();
|
||||
} else {
|
||||
refreshTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsTree::setFallbacksEnabled(bool enabled)
|
||||
{
|
||||
if (!settings.isNull()) {
|
||||
settings->setFallbacksEnabled(enabled);
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsTree::maybeRefresh()
|
||||
{
|
||||
if (state() != EditingState)
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SettingsTree::refresh()
|
||||
{
|
||||
if (settings.isNull())
|
||||
return;
|
||||
|
||||
disconnect(this, &QTreeWidget::itemChanged,
|
||||
this, &SettingsTree::updateSetting);
|
||||
|
||||
settings->sync();
|
||||
updateChildItems(nullptr);
|
||||
|
||||
connect(this, &QTreeWidget::itemChanged,
|
||||
this, &SettingsTree::updateSetting);
|
||||
}
|
||||
|
||||
bool SettingsTree::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::WindowActivate) {
|
||||
if (isActiveWindow() && autoRefresh)
|
||||
maybeRefresh();
|
||||
}
|
||||
return QTreeWidget::event(event);
|
||||
}
|
||||
|
||||
void SettingsTree::updateSetting(QTreeWidgetItem *item)
|
||||
{
|
||||
QString key = item->text(0);
|
||||
QTreeWidgetItem *ancestor = item->parent();
|
||||
while (ancestor) {
|
||||
key.prepend(ancestor->text(0) + QLatin1Char('/'));
|
||||
ancestor = ancestor->parent();
|
||||
}
|
||||
|
||||
settings->setValue(key, item->data(2, Qt::UserRole));
|
||||
if (autoRefresh)
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SettingsTree::updateChildItems(QTreeWidgetItem *parent)
|
||||
{
|
||||
int dividerIndex = 0;
|
||||
|
||||
const QStringList childGroups = settings->childGroups();
|
||||
for (const QString &group : childGroups) {
|
||||
QTreeWidgetItem *child;
|
||||
int childIndex = findChild(parent, group, dividerIndex);
|
||||
if (childIndex != -1) {
|
||||
child = childAt(parent, childIndex);
|
||||
child->setText(1, QString());
|
||||
child->setText(2, QString());
|
||||
child->setData(2, Qt::UserRole, QVariant());
|
||||
moveItemForward(parent, childIndex, dividerIndex);
|
||||
} else {
|
||||
child = createItem(group, parent, dividerIndex);
|
||||
}
|
||||
child->setIcon(0, groupIcon);
|
||||
++dividerIndex;
|
||||
|
||||
settings->beginGroup(group);
|
||||
updateChildItems(child);
|
||||
settings->endGroup();
|
||||
}
|
||||
|
||||
const QStringList childKeys = settings->childKeys();
|
||||
for (const QString &key : childKeys) {
|
||||
QTreeWidgetItem *child;
|
||||
int childIndex = findChild(parent, key, 0);
|
||||
|
||||
if (childIndex == -1 || childIndex >= dividerIndex) {
|
||||
if (childIndex != -1) {
|
||||
child = childAt(parent, childIndex);
|
||||
for (int i = 0; i < child->childCount(); ++i)
|
||||
delete childAt(child, i);
|
||||
moveItemForward(parent, childIndex, dividerIndex);
|
||||
} else {
|
||||
child = createItem(key, parent, dividerIndex);
|
||||
}
|
||||
child->setIcon(0, keyIcon);
|
||||
++dividerIndex;
|
||||
} else {
|
||||
child = childAt(parent, childIndex);
|
||||
}
|
||||
|
||||
QVariant value = settings->value(key);
|
||||
if (value.userType() == QMetaType::UnknownType) {
|
||||
child->setText(1, "Invalid");
|
||||
} else {
|
||||
if (value.typeId() == QMetaType::QString) {
|
||||
const QString stringValue = value.toString();
|
||||
if (m_typeChecker->boolExp.match(stringValue).hasMatch()) {
|
||||
value.setValue(stringValue.compare("true", Qt::CaseInsensitive) == 0);
|
||||
} else if (m_typeChecker->signedIntegerExp.match(stringValue).hasMatch())
|
||||
value.setValue(stringValue.toInt());
|
||||
}
|
||||
|
||||
child->setText(1, value.typeName());
|
||||
}
|
||||
child->setText(2, VariantDelegate::displayText(value));
|
||||
child->setData(2, Qt::UserRole, value);
|
||||
}
|
||||
|
||||
while (dividerIndex < childCount(parent))
|
||||
delete childAt(parent, dividerIndex);
|
||||
}
|
||||
|
||||
QTreeWidgetItem *SettingsTree::createItem(const QString &text,
|
||||
QTreeWidgetItem *parent, int index)
|
||||
{
|
||||
QTreeWidgetItem *after = nullptr;
|
||||
if (index != 0)
|
||||
after = childAt(parent, index - 1);
|
||||
|
||||
QTreeWidgetItem *item;
|
||||
if (parent)
|
||||
item = new QTreeWidgetItem(parent, after);
|
||||
else
|
||||
item = new QTreeWidgetItem(this, after);
|
||||
|
||||
item->setText(0, text);
|
||||
item->setFlags(item->flags() | Qt::ItemIsEditable);
|
||||
return item;
|
||||
}
|
||||
|
||||
QTreeWidgetItem *SettingsTree::childAt(QTreeWidgetItem *parent, int index) const
|
||||
{
|
||||
return (parent ? parent->child(index) : topLevelItem(index));
|
||||
}
|
||||
|
||||
int SettingsTree::childCount(QTreeWidgetItem *parent) const
|
||||
{
|
||||
return (parent ? parent->childCount() : topLevelItemCount());
|
||||
}
|
||||
|
||||
int SettingsTree::findChild(QTreeWidgetItem *parent, const QString &text,
|
||||
int startIndex) const
|
||||
{
|
||||
for (int i = startIndex; i < childCount(parent); ++i) {
|
||||
if (childAt(parent, i)->text(0) == text)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SettingsTree::moveItemForward(QTreeWidgetItem *parent, int oldIndex,
|
||||
int newIndex)
|
||||
{
|
||||
for (int i = 0; i < oldIndex - newIndex; ++i)
|
||||
delete childAt(parent, newIndex);
|
||||
}
|
61
examples/widgets/tools/settingseditor/settingstree.h
Normal file
61
examples/widgets/tools/settingseditor/settingstree.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef SETTINGSTREE_H
|
||||
#define SETTINGSTREE_H
|
||||
|
||||
#include <QIcon>
|
||||
#include <QTimer>
|
||||
#include <QTreeWidget>
|
||||
#include <QSharedPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QSettings;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
struct TypeChecker;
|
||||
|
||||
class SettingsTree : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using SettingsPtr = QSharedPointer<QSettings>;
|
||||
using TypeCheckerPtr = QSharedPointer<TypeChecker>;
|
||||
|
||||
SettingsTree(QWidget *parent = nullptr);
|
||||
~SettingsTree();
|
||||
|
||||
void setSettingsObject(const SettingsPtr &settings);
|
||||
QSize sizeHint() const override;
|
||||
|
||||
public slots:
|
||||
void setAutoRefresh(bool autoRefresh);
|
||||
void setFallbacksEnabled(bool enabled);
|
||||
void maybeRefresh();
|
||||
void refresh();
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void updateSetting(QTreeWidgetItem *item);
|
||||
|
||||
private:
|
||||
void updateChildItems(QTreeWidgetItem *parent);
|
||||
QTreeWidgetItem *createItem(const QString &text, QTreeWidgetItem *parent,
|
||||
int index);
|
||||
QTreeWidgetItem *childAt(QTreeWidgetItem *parent, int index) const;
|
||||
int childCount(QTreeWidgetItem *parent) const;
|
||||
int findChild(QTreeWidgetItem *parent, const QString &text, int startIndex) const;
|
||||
void moveItemForward(QTreeWidgetItem *parent, int oldIndex, int newIndex);
|
||||
|
||||
SettingsPtr settings;
|
||||
TypeCheckerPtr m_typeChecker;
|
||||
QTimer refreshTimer;
|
||||
QIcon groupIcon;
|
||||
QIcon keyIcon;
|
||||
bool autoRefresh = false;
|
||||
};
|
||||
|
||||
#endif
|
377
examples/widgets/tools/settingseditor/variantdelegate.cpp
Normal file
377
examples/widgets/tools/settingseditor/variantdelegate.cpp
Normal file
@ -0,0 +1,377 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include "variantdelegate.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDateTime>
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
#include <QRegularExpressionValidator>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
static bool isPrintableChar(char c)
|
||||
{
|
||||
return uchar(c) >= 32 && uchar(c) < 128;
|
||||
}
|
||||
|
||||
static bool isPrintable(const QByteArray &ba)
|
||||
{
|
||||
return std::all_of(ba.cbegin(), ba.cend(), isPrintableChar);
|
||||
}
|
||||
|
||||
static QString byteArrayToString(const QByteArray &ba)
|
||||
{
|
||||
if (isPrintable(ba))
|
||||
return QString::fromLatin1(ba);
|
||||
QString result;
|
||||
for (char c : ba) {
|
||||
if (isPrintableChar(c)) {
|
||||
if (c == '\\')
|
||||
result += QLatin1Char(c);
|
||||
result += QLatin1Char(c);
|
||||
} else {
|
||||
const uint uc = uchar(c);
|
||||
result += "\\x";
|
||||
if (uc < 16)
|
||||
result += '0';
|
||||
result += QString::number(uc, 16);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TypeChecker::TypeChecker()
|
||||
{
|
||||
boolExp.setPattern("^(true)|(false)$");
|
||||
boolExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
|
||||
Q_ASSERT(boolExp.isValid());
|
||||
|
||||
byteArrayExp.setPattern(R"RX(^[\x00-\xff]*$)RX");
|
||||
charExp.setPattern("^.$");
|
||||
Q_ASSERT(charExp.isValid());
|
||||
colorExp.setPattern(R"RX(^\(([0-9]*),([0-9]*),([0-9]*),([0-9]*)\)$)RX");
|
||||
Q_ASSERT(colorExp.isValid());
|
||||
doubleExp.setPattern("");
|
||||
pointExp.setPattern(R"RX(^\((-?[0-9]*),(-?[0-9]*)\)$)RX");
|
||||
Q_ASSERT(pointExp.isValid());
|
||||
rectExp.setPattern(R"RX(^\((-?[0-9]*),(-?[0-9]*),(-?[0-9]*),(-?[0-9]*)\)$)RX");
|
||||
Q_ASSERT(rectExp.isValid());
|
||||
signedIntegerExp.setPattern("^-?[0-9]*$");
|
||||
Q_ASSERT(signedIntegerExp.isValid());
|
||||
sizeExp = pointExp;
|
||||
unsignedIntegerExp.setPattern("^[0-9]+$");
|
||||
Q_ASSERT(unsignedIntegerExp.isValid());
|
||||
|
||||
const QString datePattern = "([0-9]{,4})-([0-9]{,2})-([0-9]{,2})";
|
||||
dateExp.setPattern('^' + datePattern + '$');
|
||||
Q_ASSERT(dateExp.isValid());
|
||||
const QString timePattern = "([0-9]{,2}):([0-9]{,2}):([0-9]{,2})";
|
||||
timeExp.setPattern('^' + timePattern + '$');
|
||||
Q_ASSERT(timeExp.isValid());
|
||||
dateTimeExp.setPattern('^' + datePattern + 'T' + timePattern + '$');
|
||||
Q_ASSERT(dateTimeExp.isValid());
|
||||
}
|
||||
|
||||
VariantDelegate::VariantDelegate(const QSharedPointer<TypeChecker> &typeChecker,
|
||||
QObject *parent)
|
||||
: QStyledItemDelegate(parent),
|
||||
m_typeChecker(typeChecker)
|
||||
{
|
||||
}
|
||||
|
||||
void VariantDelegate::paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() == 2) {
|
||||
QVariant value = index.model()->data(index, Qt::UserRole);
|
||||
if (!isSupportedType(value.userType())) {
|
||||
QStyleOptionViewItem myOption = option;
|
||||
myOption.state &= ~QStyle::State_Enabled;
|
||||
QStyledItemDelegate::paint(painter, myOption, index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QWidget *VariantDelegate::createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem & /* option */,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() != 2)
|
||||
return nullptr;
|
||||
|
||||
QVariant originalValue = index.model()->data(index, Qt::UserRole);
|
||||
if (!isSupportedType(originalValue.userType()))
|
||||
return nullptr;
|
||||
|
||||
switch (originalValue.userType()) {
|
||||
case QMetaType::Bool:
|
||||
return new QCheckBox(parent);
|
||||
break;
|
||||
case QMetaType::Int:
|
||||
case QMetaType::LongLong: {
|
||||
auto spinBox = new QSpinBox(parent);
|
||||
spinBox->setRange(-32767, 32767);
|
||||
return spinBox;
|
||||
}
|
||||
case QMetaType::UInt:
|
||||
case QMetaType::ULongLong: {
|
||||
auto spinBox = new QSpinBox(parent);
|
||||
spinBox->setRange(0, 63335);
|
||||
return spinBox;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QLineEdit *lineEdit = new QLineEdit(parent);
|
||||
lineEdit->setFrame(false);
|
||||
|
||||
QRegularExpression regExp;
|
||||
|
||||
switch (originalValue.userType()) {
|
||||
case QMetaType::Bool:
|
||||
regExp = m_typeChecker->boolExp;
|
||||
break;
|
||||
case QMetaType::QByteArray:
|
||||
regExp = m_typeChecker->byteArrayExp;
|
||||
break;
|
||||
case QMetaType::QChar:
|
||||
regExp = m_typeChecker->charExp;
|
||||
break;
|
||||
case QMetaType::QColor:
|
||||
regExp = m_typeChecker->colorExp;
|
||||
break;
|
||||
case QMetaType::QDate:
|
||||
regExp = m_typeChecker->dateExp;
|
||||
break;
|
||||
case QMetaType::QDateTime:
|
||||
regExp = m_typeChecker->dateTimeExp;
|
||||
break;
|
||||
case QMetaType::Double:
|
||||
regExp = m_typeChecker->doubleExp;
|
||||
break;
|
||||
case QMetaType::Int:
|
||||
case QMetaType::LongLong:
|
||||
regExp = m_typeChecker->signedIntegerExp;
|
||||
break;
|
||||
case QMetaType::QPoint:
|
||||
regExp = m_typeChecker->pointExp;
|
||||
break;
|
||||
case QMetaType::QRect:
|
||||
regExp = m_typeChecker->rectExp;
|
||||
break;
|
||||
case QMetaType::QSize:
|
||||
regExp = m_typeChecker->sizeExp;
|
||||
break;
|
||||
case QMetaType::QTime:
|
||||
regExp = m_typeChecker->timeExp;
|
||||
break;
|
||||
case QMetaType::UInt:
|
||||
case QMetaType::ULongLong:
|
||||
regExp = m_typeChecker->unsignedIntegerExp;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (regExp.isValid()) {
|
||||
QValidator *validator = new QRegularExpressionValidator(regExp, lineEdit);
|
||||
lineEdit->setValidator(validator);
|
||||
}
|
||||
|
||||
return lineEdit;
|
||||
}
|
||||
|
||||
void VariantDelegate::setEditorData(QWidget *editor,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QVariant value = index.model()->data(index, Qt::UserRole);
|
||||
if (auto spinBox = qobject_cast<QSpinBox *>(editor)) {
|
||||
const auto userType = value.userType();
|
||||
if (userType == QMetaType::UInt || userType == QMetaType::ULongLong)
|
||||
spinBox->setValue(value.toUInt());
|
||||
else
|
||||
spinBox->setValue(value.toInt());
|
||||
} else if (auto checkBox = qobject_cast<QCheckBox *>(editor)) {
|
||||
checkBox->setChecked(value.toBool());
|
||||
} else if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor)) {
|
||||
if (value.userType() == QMetaType::QByteArray
|
||||
&& !isPrintable(value.toByteArray())) {
|
||||
lineEdit->setReadOnly(true);
|
||||
}
|
||||
lineEdit->setText(displayText(value));
|
||||
}
|
||||
}
|
||||
|
||||
void VariantDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
const QVariant originalValue = index.model()->data(index, Qt::UserRole);
|
||||
QVariant value;
|
||||
|
||||
if (auto spinBox = qobject_cast<QSpinBox *>(editor)) {
|
||||
value.setValue(spinBox->value());
|
||||
} else if (auto checkBox = qobject_cast<QCheckBox *>(editor)) {
|
||||
value.setValue(checkBox->isChecked());
|
||||
} else if (QLineEdit *lineEdit = qobject_cast<QLineEdit *>(editor)) {
|
||||
if (!lineEdit->isModified())
|
||||
return;
|
||||
|
||||
QString text = lineEdit->text();
|
||||
const QValidator *validator = lineEdit->validator();
|
||||
if (validator) {
|
||||
int pos;
|
||||
if (validator->validate(text, pos) != QValidator::Acceptable)
|
||||
return;
|
||||
}
|
||||
|
||||
QRegularExpressionMatch match;
|
||||
|
||||
switch (originalValue.userType()) {
|
||||
case QMetaType::QChar:
|
||||
value = text.at(0);
|
||||
break;
|
||||
case QMetaType::QColor:
|
||||
match = m_typeChecker->colorExp.match(text);
|
||||
value = QColor(qMin(match.captured(1).toInt(), 255),
|
||||
qMin(match.captured(2).toInt(), 255),
|
||||
qMin(match.captured(3).toInt(), 255),
|
||||
qMin(match.captured(4).toInt(), 255));
|
||||
break;
|
||||
case QMetaType::QDate:
|
||||
{
|
||||
QDate date = QDate::fromString(text, Qt::ISODate);
|
||||
if (!date.isValid())
|
||||
return;
|
||||
value = date;
|
||||
}
|
||||
break;
|
||||
case QMetaType::QDateTime:
|
||||
{
|
||||
QDateTime dateTime = QDateTime::fromString(text, Qt::ISODate);
|
||||
if (!dateTime.isValid())
|
||||
return;
|
||||
value = dateTime;
|
||||
}
|
||||
break;
|
||||
case QMetaType::QPoint:
|
||||
match = m_typeChecker->pointExp.match(text);
|
||||
value = QPoint(match.captured(1).toInt(), match.captured(2).toInt());
|
||||
break;
|
||||
case QMetaType::QRect:
|
||||
match = m_typeChecker->rectExp.match(text);
|
||||
value = QRect(match.captured(1).toInt(), match.captured(2).toInt(),
|
||||
match.captured(3).toInt(), match.captured(4).toInt());
|
||||
break;
|
||||
case QMetaType::QSize:
|
||||
match = m_typeChecker->sizeExp.match(text);
|
||||
value = QSize(match.captured(1).toInt(), match.captured(2).toInt());
|
||||
break;
|
||||
case QMetaType::QStringList:
|
||||
value = text.split(',');
|
||||
break;
|
||||
case QMetaType::QTime:
|
||||
{
|
||||
QTime time = QTime::fromString(text, Qt::ISODate);
|
||||
if (!time.isValid())
|
||||
return;
|
||||
value = time;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
value = text;
|
||||
value.convert(originalValue.metaType());
|
||||
}
|
||||
}
|
||||
|
||||
model->setData(index, displayText(value), Qt::DisplayRole);
|
||||
model->setData(index, value, Qt::UserRole);
|
||||
}
|
||||
|
||||
bool VariantDelegate::isSupportedType(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case QMetaType::Bool:
|
||||
case QMetaType::QByteArray:
|
||||
case QMetaType::QChar:
|
||||
case QMetaType::QColor:
|
||||
case QMetaType::QDate:
|
||||
case QMetaType::QDateTime:
|
||||
case QMetaType::Double:
|
||||
case QMetaType::Int:
|
||||
case QMetaType::LongLong:
|
||||
case QMetaType::QPoint:
|
||||
case QMetaType::QRect:
|
||||
case QMetaType::QSize:
|
||||
case QMetaType::QString:
|
||||
case QMetaType::QStringList:
|
||||
case QMetaType::QTime:
|
||||
case QMetaType::UInt:
|
||||
case QMetaType::ULongLong:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QString VariantDelegate::displayText(const QVariant &value)
|
||||
{
|
||||
switch (value.userType()) {
|
||||
case QMetaType::Bool:
|
||||
return value.toBool() ? "✓" : "☐";
|
||||
case QMetaType::QByteArray:
|
||||
return byteArrayToString(value.toByteArray());
|
||||
case QMetaType::QChar:
|
||||
case QMetaType::Double:
|
||||
case QMetaType::Int:
|
||||
case QMetaType::LongLong:
|
||||
case QMetaType::QString:
|
||||
case QMetaType::UInt:
|
||||
case QMetaType::ULongLong:
|
||||
return value.toString();
|
||||
case QMetaType::QColor:
|
||||
{
|
||||
QColor color = qvariant_cast<QColor>(value);
|
||||
return QString("(%1,%2,%3,%4)")
|
||||
.arg(color.red()).arg(color.green())
|
||||
.arg(color.blue()).arg(color.alpha());
|
||||
}
|
||||
case QMetaType::QDate:
|
||||
return value.toDate().toString(Qt::ISODate);
|
||||
case QMetaType::QDateTime:
|
||||
return value.toDateTime().toString(Qt::ISODate);
|
||||
case QMetaType::UnknownType:
|
||||
return "<Invalid>";
|
||||
case QMetaType::QPoint:
|
||||
{
|
||||
QPoint point = value.toPoint();
|
||||
return QString("(%1,%2)").arg(point.x()).arg(point.y());
|
||||
}
|
||||
case QMetaType::QRect:
|
||||
{
|
||||
QRect rect = value.toRect();
|
||||
return QString("(%1,%2,%3,%4)")
|
||||
.arg(rect.x()).arg(rect.y())
|
||||
.arg(rect.width()).arg(rect.height());
|
||||
}
|
||||
case QMetaType::QSize:
|
||||
{
|
||||
QSize size = value.toSize();
|
||||
return QString("(%1,%2)").arg(size.width()).arg(size.height());
|
||||
}
|
||||
case QMetaType::QStringList:
|
||||
return value.toStringList().join(',');
|
||||
case QMetaType::QTime:
|
||||
return value.toTime().toString(Qt::ISODate);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QString("<%1>").arg(value.typeName());
|
||||
}
|
53
examples/widgets/tools/settingseditor/variantdelegate.h
Normal file
53
examples/widgets/tools/settingseditor/variantdelegate.h
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#ifndef VARIANTDELEGATE_H
|
||||
#define VARIANTDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QRegularExpression>
|
||||
#include <QSharedPointer>
|
||||
|
||||
struct TypeChecker
|
||||
{
|
||||
TypeChecker();
|
||||
|
||||
QRegularExpression boolExp;
|
||||
QRegularExpression byteArrayExp;
|
||||
QRegularExpression charExp;
|
||||
QRegularExpression colorExp;
|
||||
QRegularExpression dateExp;
|
||||
QRegularExpression dateTimeExp;
|
||||
QRegularExpression doubleExp;
|
||||
QRegularExpression pointExp;
|
||||
QRegularExpression rectExp;
|
||||
QRegularExpression signedIntegerExp;
|
||||
QRegularExpression sizeExp;
|
||||
QRegularExpression timeExp;
|
||||
QRegularExpression unsignedIntegerExp;
|
||||
};
|
||||
|
||||
class VariantDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VariantDelegate(const QSharedPointer<TypeChecker> &typeChecker,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const override;
|
||||
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const override;
|
||||
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const override;
|
||||
|
||||
static bool isSupportedType(int type);
|
||||
static QString displayText(const QVariant &value);
|
||||
|
||||
private:
|
||||
QSharedPointer<TypeChecker> m_typeChecker;
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user