Polish the settings editor example.

- Set QtProject as organization.
- Remove unneeded member variables.
- Use member initialization in the constructor.
- Use new connection syntax in createActions()
  to assemble the menu there, removing the createMenus()
  function.
- Introduce a QSharedPointer to ensure settings are deleted.
  Previously, the settings were parented on the tree widget,
  which is a hack of sorts.
- Fix OS X macros.

Change-Id: Ibbc6bfb03eb5c7eda077b1a3aa3f1707667f7f13
Reviewed-by: Topi Reiniö <topi.reinio@digia.com>
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
This commit is contained in:
Friedemann Kleint 2015-08-27 17:23:55 +02:00
parent 2e02130e39
commit 47e4ae86a8
7 changed files with 151 additions and 161 deletions

View File

@ -54,17 +54,18 @@ LocationDialog::LocationDialog(QWidget *parent)
scopeComboBox->addItem(tr("System"));
organizationComboBox = new QComboBox;
organizationComboBox->addItem(tr("Qt"));
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(3);
applicationComboBox->setCurrentIndex(1);
formatLabel = new QLabel(tr("&Format:"));
formatLabel->setBuddy(formatComboBox);
@ -91,28 +92,30 @@ LocationDialog::LocationDialog(QWidget *parent)
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);
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(formatComboBox, SIGNAL(activated(int)),
this, SLOT(updateLocationsTable()));
connect(scopeComboBox, SIGNAL(activated(int)),
this, SLOT(updateLocationsTable()));
typedef void (QComboBox::*QComboIntSignal)(int);
connect(formatComboBox, static_cast<QComboIntSignal>(&QComboBox::activated),
this, &LocationDialog::updateLocationsTable);
connect(scopeComboBox, static_cast<QComboIntSignal>(&QComboBox::activated),
this, &LocationDialog::updateLocationsTable);
connect(organizationComboBox->lineEdit(),
SIGNAL(editingFinished()),
this, SLOT(updateLocationsTable()));
&QLineEdit::editingFinished,
this, &LocationDialog::updateLocationsTable);
connect(applicationComboBox->lineEdit(),
SIGNAL(editingFinished()),
this, SLOT(updateLocationsTable()));
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
&QLineEdit::editingFinished,
this, &LocationDialog::updateLocationsTable);
connect(applicationComboBox, static_cast<QComboIntSignal>(&QComboBox::activated),
this, &LocationDialog::updateLocationsTable);
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
QVBoxLayout *locationsLayout = new QVBoxLayout;
QVBoxLayout *locationsLayout = new QVBoxLayout(locationsGroupBox);
locationsLayout->addWidget(locationsTable);
locationsGroupBox->setLayout(locationsLayout);
QGridLayout *mainLayout = new QGridLayout;
QGridLayout *mainLayout = new QGridLayout(this);
mainLayout->addWidget(formatLabel, 0, 0);
mainLayout->addWidget(formatComboBox, 0, 1);
mainLayout->addWidget(scopeLabel, 1, 0);
@ -123,7 +126,6 @@ LocationDialog::LocationDialog(QWidget *parent)
mainLayout->addWidget(applicationComboBox, 3, 1);
mainLayout->addWidget(locationsGroupBox, 4, 0, 1, 2);
mainLayout->addWidget(buttonBox, 5, 0, 1, 2);
setLayout(mainLayout);
updateLocationsTable();
@ -155,11 +157,16 @@ QString LocationDialog::organization() const
QString LocationDialog::application() const
{
if (applicationComboBox->currentText() == tr("Any"))
return "";
return QString();
else
return applicationComboBox->currentText();
}
void LocationDialog::itemActivated(QTableWidgetItem *)
{
buttonBox->button(QDialogButtonBox::Ok)->animateClick();
}
void LocationDialog::updateLocationsTable()
{
locationsTable->setUpdatesEnabled(false);
@ -184,8 +191,7 @@ void LocationDialog::updateLocationsTable()
int row = locationsTable->rowCount();
locationsTable->setRowCount(row + 1);
QTableWidgetItem *item0 = new QTableWidgetItem;
item0->setText(settings.fileName());
QTableWidgetItem *item0 = new QTableWidgetItem(QDir::toNativeSeparators(settings.fileName()));
QTableWidgetItem *item1 = new QTableWidgetItem;
bool disable = (settings.childKeys().isEmpty()

View File

@ -50,6 +50,7 @@ class QDialogButtonBox;
class QGroupBox;
class QLabel;
class QTableWidget;
class QTableWidgetItem;
QT_END_NAMESPACE
class LocationDialog : public QDialog
@ -66,6 +67,7 @@ public:
private slots:
void updateLocationsTable();
void itemActivated(QTableWidgetItem *);
private:
QLabel *formatLabel;

View File

@ -45,6 +45,9 @@
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();

View File

@ -45,20 +45,20 @@
#include "settingstree.h"
MainWindow::MainWindow()
: settingsTree(new SettingsTree)
, locationDialog(Q_NULLPTR)
{
settingsTree = new SettingsTree;
setCentralWidget(settingsTree);
locationDialog = 0;
createActions();
createMenus();
autoRefreshAct->setChecked(true);
fallbacksAct->setChecked(true);
setWindowTitle(tr("Settings Editor"));
resize(500, 600);
setWindowTitle(QCoreApplication::applicationName());
const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
adjustSize();
move((availableGeometry.width() - width()) / 2, (availableGeometry.height() - height()) / 2);
}
void MainWindow::openSettings()
@ -66,50 +66,61 @@ void MainWindow::openSettings()
if (!locationDialog)
locationDialog = new LocationDialog(this);
if (locationDialog->exec()) {
QSettings *settings = new QSettings(locationDialog->format(),
if (locationDialog->exec() != QDialog::Accepted)
return;
SettingsPtr settings(new QSettings(locationDialog->format(),
locationDialog->scope(),
locationDialog->organization(),
locationDialog->application());
locationDialog->application()));
setSettingsObject(settings);
fallbacksAct->setEnabled(true);
}
}
void MainWindow::openIniFile()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open INI File"),
"", tr("INI Files (*.ini *.conf)"));
if (!fileName.isEmpty()) {
QSettings *settings = new QSettings(fileName, QSettings::IniFormat);
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()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Property List"),
"", tr("Property List Files (*.plist)"));
if (!fileName.isEmpty()) {
QSettings *settings = new QSettings(fileName, QSettings::NativeFormat);
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()
{
QString path = QInputDialog::getText(this, tr("Open Registry Path"),
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()) {
QSettings *settings = new QSettings(path, QSettings::NativeFormat);
if (path.isEmpty())
return;
SettingsPtr settings(new QSettings(path, QSettings::NativeFormat));
setSettingsObject(settings);
fallbacksAct->setEnabled(false);
}
}
void MainWindow::about()
{
@ -120,88 +131,59 @@ void MainWindow::about()
void MainWindow::createActions()
{
openSettingsAct = new QAction(tr("&Open Application Settings..."), this);
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
QAction *openSettingsAct = fileMenu->addAction(tr("&Open Application Settings..."), this, &MainWindow::openSettings);
openSettingsAct->setShortcuts(QKeySequence::Open);
connect(openSettingsAct, SIGNAL(triggered()), this, SLOT(openSettings()));
openIniFileAct = new QAction(tr("Open I&NI File..."), this);
QAction *openIniFileAct = fileMenu->addAction(tr("Open I&NI File..."), this, &MainWindow::openIniFile);
openIniFileAct->setShortcut(tr("Ctrl+N"));
connect(openIniFileAct, SIGNAL(triggered()), this, SLOT(openIniFile()));
openPropertyListAct = new QAction(tr("Open Mac &Property List..."), this);
#ifdef Q_OS_OSX
QAction *openPropertyListAct = fileMenu->addAction(tr("Open Apple &Property List..."), this, &MainWindow::openPropertyList);
openPropertyListAct->setShortcut(tr("Ctrl+P"));
connect(openPropertyListAct, SIGNAL(triggered()),
this, SLOT(openPropertyList()));
#endif // Q_OS_OSX
openRegistryPathAct = new QAction(tr("Open Windows &Registry Path..."),
this);
#ifdef Q_OS_WIN
QAction *openRegistryPathAct = fileMenu->addAction(tr("Open Windows &Registry Path..."), this, &MainWindow::openRegistryPath);
openRegistryPathAct->setShortcut(tr("Ctrl+G"));
connect(openRegistryPathAct, SIGNAL(triggered()),
this, SLOT(openRegistryPath()));
#endif // Q_OS_WIN
refreshAct = new QAction(tr("&Refresh"), this);
fileMenu->addSeparator();
refreshAct = fileMenu->addAction(tr("&Refresh"), settingsTree, &SettingsTree::refresh);
refreshAct->setShortcut(tr("Ctrl+R"));
refreshAct->setEnabled(false);
connect(refreshAct, SIGNAL(triggered()), settingsTree, SLOT(refresh()));
exitAct = new QAction(tr("E&xit"), this);
fileMenu->addSeparator();
QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
autoRefreshAct = new QAction(tr("&Auto-Refresh"), this);
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, SIGNAL(triggered(bool)),
settingsTree, SLOT(setAutoRefresh(bool)));
connect(autoRefreshAct, SIGNAL(triggered(bool)),
refreshAct, SLOT(setDisabled(bool)));
connect(autoRefreshAct, &QAction::triggered,
settingsTree, &SettingsTree::setAutoRefresh);
connect(autoRefreshAct, &QAction::triggered,
refreshAct, &QAction::setDisabled);
fallbacksAct = new QAction(tr("&Fallbacks"), this);
fallbacksAct = optionsMenu->addAction(tr("&Fallbacks"));
fallbacksAct->setShortcut(tr("Ctrl+F"));
fallbacksAct->setCheckable(true);
fallbacksAct->setEnabled(false);
connect(fallbacksAct, SIGNAL(triggered(bool)),
settingsTree, SLOT(setFallbacksEnabled(bool)));
connect(fallbacksAct, &QAction::triggered,
settingsTree, &SettingsTree::setFallbacksEnabled);
aboutAct = new QAction(tr("&About"), this);
connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
aboutQtAct = new QAction(tr("About &Qt"), this);
connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
#ifndef Q_OS_MAC
openPropertyListAct->setEnabled(false);
#endif
#ifndef Q_OS_WIN
openRegistryPathAct->setEnabled(false);
#endif
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(tr("&About"), this, &MainWindow::about);
helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openSettingsAct);
fileMenu->addAction(openIniFileAct);
fileMenu->addAction(openPropertyListAct);
fileMenu->addAction(openRegistryPathAct);
fileMenu->addSeparator();
fileMenu->addAction(refreshAct);
fileMenu->addSeparator();
fileMenu->addAction(exitAct);
optionsMenu = menuBar()->addMenu(tr("&Options"));
optionsMenu->addAction(autoRefreshAct);
optionsMenu->addAction(fallbacksAct);
menuBar()->addSeparator();
helpMenu = menuBar()->addMenu(tr("&Help"));
helpMenu->addAction(aboutAct);
helpMenu->addAction(aboutQtAct);
}
void MainWindow::setSettingsObject(QSettings *settings)
void MainWindow::setSettingsObject(const SettingsPtr &settings)
{
settings->setFallbacksEnabled(fallbacksAct->isChecked());
settingsTree->setSettingsObject(settings);
@ -209,14 +191,14 @@ void MainWindow::setSettingsObject(QSettings *settings)
refreshAct->setEnabled(true);
autoRefreshAct->setEnabled(true);
QString niceName = settings->fileName();
niceName.replace("\\", "/");
int pos = niceName.lastIndexOf("/");
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).arg(tr("Settings Editor")));
setWindowTitle(tr("%1 - %2").arg(niceName, QCoreApplication::applicationName()));
statusBar()->showMessage(tr("Opened \"%1\"").arg(QDir::toNativeSeparators(settings->fileName())));
}

View File

@ -42,10 +42,10 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSharedPointer>
QT_BEGIN_NAMESPACE
class QAction;
class QMenu;
class QSettings;
QT_END_NAMESPACE
class LocationDialog;
@ -56,6 +56,8 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
typedef QSharedPointer<QSettings> SettingsPtr;
MainWindow();
private slots:
@ -67,25 +69,13 @@ private slots:
private:
void createActions();
void createMenus();
void setSettingsObject(QSettings *settings);
void setSettingsObject(const SettingsPtr &settings);
SettingsTree *settingsTree;
LocationDialog *locationDialog;
QMenu *fileMenu;
QMenu *optionsMenu;
QMenu *helpMenu;
QAction *openSettingsAct;
QAction *openIniFileAct;
QAction *openPropertyListAct;
QAction *openRegistryPathAct;
QAction *refreshAct;
QAction *exitAct;
QAction *autoRefreshAct;
QAction *fallbacksAct;
QAction *aboutAct;
QAction *aboutQtAct;
};
#endif

View File

@ -45,18 +45,18 @@
SettingsTree::SettingsTree(QWidget *parent)
: QTreeWidget(parent)
, autoRefresh(false)
{
setItemDelegate(new VariantDelegate(this));
QStringList labels;
labels << tr("Setting") << tr("Type") << tr("Value");
setHeaderLabels(labels);
header()->setSectionResizeMode(0, QHeaderView::Stretch);
header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
header()->setSectionResizeMode(2, QHeaderView::Stretch);
settings = 0;
refreshTimer.setInterval(2000);
autoRefresh = false;
groupIcon.addPixmap(style()->standardPixmap(QStyle::SP_DirClosedIcon),
QIcon::Normal, QIcon::Off);
@ -64,34 +64,37 @@ SettingsTree::SettingsTree(QWidget *parent)
QIcon::Normal, QIcon::On);
keyIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon));
connect(&refreshTimer, SIGNAL(timeout()), this, SLOT(maybeRefresh()));
connect(&refreshTimer, &QTimer::timeout, this, &SettingsTree::maybeRefresh);
}
void SettingsTree::setSettingsObject(QSettings *settings)
SettingsTree::~SettingsTree()
{
delete this->settings;
this->settings = settings;
}
void SettingsTree::setSettingsObject(const SettingsPtr &newSettings)
{
settings = newSettings;
clear();
if (settings) {
settings->setParent(this);
if (settings.isNull()) {
refreshTimer.stop();
} else {
refresh();
if (autoRefresh)
refreshTimer.start();
} else {
refreshTimer.stop();
}
}
QSize SettingsTree::sizeHint() const
{
return QSize(800, 600);
const QRect availableGeometry = QApplication::desktop()->availableGeometry(this);
return QSize(availableGeometry.width() * 2 / 3, availableGeometry.height() * 2 / 3);
}
void SettingsTree::setAutoRefresh(bool autoRefresh)
{
this->autoRefresh = autoRefresh;
if (settings) {
if (!settings.isNull()) {
if (autoRefresh) {
maybeRefresh();
refreshTimer.start();
@ -103,7 +106,7 @@ void SettingsTree::setAutoRefresh(bool autoRefresh)
void SettingsTree::setFallbacksEnabled(bool enabled)
{
if (settings) {
if (!settings.isNull()) {
settings->setFallbacksEnabled(enabled);
refresh();
}
@ -117,17 +120,17 @@ void SettingsTree::maybeRefresh()
void SettingsTree::refresh()
{
if (!settings)
if (settings.isNull())
return;
disconnect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
this, SLOT(updateSetting(QTreeWidgetItem*)));
disconnect(this, &QTreeWidget::itemChanged,
this, &SettingsTree::updateSetting);
settings->sync();
updateChildItems(0);
connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
this, SLOT(updateSetting(QTreeWidgetItem*)));
connect(this, &QTreeWidget::itemChanged,
this, &SettingsTree::updateSetting);
}
bool SettingsTree::event(QEvent *event)
@ -144,7 +147,7 @@ void SettingsTree::updateSetting(QTreeWidgetItem *item)
QString key = item->text(0);
QTreeWidgetItem *ancestor = item->parent();
while (ancestor) {
key.prepend(ancestor->text(0) + "/");
key.prepend(ancestor->text(0) + QLatin1Char('/'));
ancestor = ancestor->parent();
}
@ -162,8 +165,8 @@ void SettingsTree::updateChildItems(QTreeWidgetItem *parent)
int childIndex = findChild(parent, group, dividerIndex);
if (childIndex != -1) {
child = childAt(parent, childIndex);
child->setText(1, "");
child->setText(2, "");
child->setText(1, QString());
child->setText(2, QString());
child->setData(2, Qt::UserRole, QVariant());
moveItemForward(parent, childIndex, dividerIndex);
} else {
@ -177,7 +180,7 @@ void SettingsTree::updateChildItems(QTreeWidgetItem *parent)
settings->endGroup();
}
foreach (QString key, settings->childKeys()) {
foreach (const QString &key, settings->childKeys()) {
QTreeWidgetItem *child;
int childIndex = findChild(parent, key, 0);

View File

@ -44,6 +44,7 @@
#include <QIcon>
#include <QTimer>
#include <QTreeWidget>
#include <QSharedPointer>
QT_BEGIN_NAMESPACE
class QSettings;
@ -54,9 +55,12 @@ class SettingsTree : public QTreeWidget
Q_OBJECT
public:
SettingsTree(QWidget *parent = 0);
typedef QSharedPointer<QSettings> SettingsPtr;
void setSettingsObject(QSettings *settings);
SettingsTree(QWidget *parent = 0);
~SettingsTree();
void setSettingsObject(const SettingsPtr &settings);
QSize sizeHint() const Q_DECL_OVERRIDE;
public slots:
@ -80,7 +84,7 @@ private:
int findChild(QTreeWidgetItem *parent, const QString &text, int startIndex);
void moveItemForward(QTreeWidgetItem *parent, int oldIndex, int newIndex);
QSettings *settings;
SettingsPtr settings;
QTimer refreshTimer;
bool autoRefresh;
QIcon groupIcon;