Skip to content

Commit 8bf6c85

Browse files
committed
WIP: New system for project settings
Still missing: - Group settings and encoding/decoding (if necessary) - Database upgrade - Compatibility warning for db version > app version For #168
1 parent dc4cb71 commit 8bf6c85

11 files changed

+451
-278
lines changed

src/comp_tables/fold_composite_column.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -339,12 +339,12 @@ QStringList HikerListCompositeColumn::formatAndSortIntoStringList(QSet<BufferRow
339339
QStringList stringList;
340340

341341
QString defaultHikerString = QString();
342-
const ProjectSetting<int>* defaultHiker = getProjectSettings()->defaultHiker;
342+
ProjectSetting<int>& defaultHiker = getProjectSettings()->defaultHiker;
343343
const HikersTable* hikersTable = (HikersTable*) contentColumn->table;
344344

345345
// Check whether default hiker is set and get name if so
346-
if (defaultHiker->isNotNull()) {
347-
ValidItemID defaultHikerID = VALID_ITEM_ID(defaultHiker->get());
346+
if (defaultHiker.isPresent()) {
347+
ValidItemID defaultHikerID = VALID_ITEM_ID(defaultHiker.get());
348348
BufferRowIndex defaultHikerRowIndex = hikersTable->getBufferIndexForPrimaryKey(defaultHikerID);
349349
if (rowIndexSet.contains(defaultHikerRowIndex)) {
350350
QVariant content = contentColumn->getValueAt(defaultHikerRowIndex);

src/db/database.cpp

+5-8
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@
3838
Database::Database() :
3939
databaseLoaded(false),
4040
tables(QList<Table*>()),
41-
mainWindowStatusBar(nullptr),
42-
projectSettings(new ProjectSettings())
41+
mainWindowStatusBar(nullptr)
4342
{
4443
tripsTable = new TripsTable();
4544
hikersTable = new HikersTable();
@@ -50,6 +49,7 @@ Database::Database() :
5049
ascentsTable = new AscentsTable(peaksTable->primaryKeyColumn, tripsTable->primaryKeyColumn);
5150
photosTable = new PhotosTable(ascentsTable->primaryKeyColumn);
5251
participatedTable = new ParticipatedTable(ascentsTable->primaryKeyColumn, hikersTable->primaryKeyColumn);
52+
settingsTable = new SettingsTable();
5353

5454
tables.append(tripsTable);
5555
tables.append(hikersTable);
@@ -60,6 +60,9 @@ Database::Database() :
6060
tables.append(ascentsTable);
6161
tables.append(photosTable);
6262
tables.append(participatedTable);
63+
tables.append(settingsTable);
64+
65+
projectSettings = new ProjectSettings(settingsTable);
6366

6467

6568
QSqlDatabase::addDatabase("QSQLITE");
@@ -70,7 +73,6 @@ Database::Database() :
7073
*/
7174
Database::~Database() {
7275
qDeleteAll(getTableList());
73-
delete projectSettings;
7476
}
7577

7678

@@ -85,7 +87,6 @@ void Database::reset()
8587
for (Table* table : tables) {
8688
table->resetBuffer();
8789
}
88-
projectSettings->resetBuffer();
8990

9091
QSqlDatabase::database().close();
9192

@@ -121,9 +122,6 @@ void Database::createNew(QWidget* parent, const QString& filepath)
121122
for (Table* table : tables) {
122123
table->createTableInSql(parent);
123124
}
124-
projectSettings->createTableInSql(parent);
125-
projectSettings->initBuffer(parent, true);
126-
projectSettings->insertDefaults(parent);
127125

128126
// All tables still empty of course, but this doubles as a table format check
129127
populateBuffers(parent, true);
@@ -150,7 +148,6 @@ void Database::openExisting(QWidget* parent, const QString& filepath)
150148
databaseLoaded = true;
151149

152150
populateBuffers(parent);
153-
projectSettings->initBuffer(parent);
154151
}
155152

156153
/**

src/db/database.h

+3
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ class Database {
8383
PhotosTable* photosTable;
8484
/** The participated table. */
8585
ParticipatedTable* participatedTable;
86+
87+
/** The project settings table. */
88+
SettingsTable* settingsTable;
8689

8790
/** The project settings, based on a table. */
8891
ProjectSettings* projectSettings;

src/db/tables/settings_table.cpp

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
/*
2+
* Copyright 2023 Simon Vetter
3+
*
4+
* This file is part of PeakAscentLogger.
5+
*
6+
* PeakAscentLogger is free software: you can redistribute it and/or modify it under the terms
7+
* of the GNU General Public License as published by the Free Software Foundation,
8+
* either version 3 of the License, or (at your option) any later version.
9+
*
10+
* PeakAscentLogger is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
* See the GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License along with PeakAscentLogger.
15+
* If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
/**
19+
* @file settings_table.cpp
20+
*
21+
* This file defines the SettingsTable class.
22+
*/
23+
24+
#include "settings_table.h"
25+
26+
#include "src/settings/project_settings.h"
27+
28+
29+
30+
/**
31+
* Creates a new SettingsTable.
32+
*/
33+
SettingsTable::SettingsTable() :
34+
Table("ProjectSettings", "Project settings", false),
35+
// name uiName type nullable primaryKey foreignKey table
36+
primaryKeyColumn (new Column("projectSettingID", QString(), ID, false, true, nullptr, this)),
37+
settingKeyColumn (new Column("settingKey", QString(), String, false, false, nullptr, this)),
38+
settingValueColumn (new Column("settingValue", QString(), String, false, false, nullptr, this))
39+
{
40+
addColumn(primaryKeyColumn);
41+
addColumn(settingKeyColumn);
42+
addColumn(settingValueColumn);
43+
}
44+
45+
46+
47+
/**
48+
* Indicates whether the given setting is present in the project settings table.
49+
*
50+
* @param setting The setting to check.
51+
* @param parent The parent window. Can be nullptr, in which case no cleanup is performed for duplicate settings.
52+
* @return True if the setting is present, false otherwise.
53+
*/
54+
bool SettingsTable::settingIsPresent(const GenericProjectSetting* setting, QWidget* parent)
55+
{
56+
return findSettingID(setting, parent).isValid();
57+
}
58+
59+
/**
60+
* Returns the current value of the given setting in the project settings table.
61+
*
62+
* If the parent window is given, the setting is added to the project settings table using the
63+
* default value if it is not present.
64+
*
65+
* @param setting The setting to look up.
66+
* @param parent The parent window. Can be nullptr, in which case no cleanup is performed for duplicate settings.
67+
* @return The current value of the setting.
68+
*/
69+
QVariant SettingsTable::getSetting(const GenericProjectSetting* setting, QWidget* parent)
70+
{
71+
ItemID id = findSettingID(setting);
72+
if (id.isInvalid()) {
73+
if (!parent) {
74+
return setting->defaultValue;
75+
}
76+
77+
QList<ColumnDataPair> columnDataPairs = QList<ColumnDataPair>();
78+
columnDataPairs.append({settingKeyColumn, setting->key});
79+
columnDataPairs.append({settingValueColumn, setting->defaultValue});
80+
BufferRowIndex newBufferIndex = addRow(parent, columnDataPairs);
81+
id = primaryKeyColumn->getValueAt(newBufferIndex);
82+
}
83+
84+
return settingValueColumn->getValueFor(FORCE_VALID(id));
85+
}
86+
87+
88+
/**
89+
* Adds or updates the the setting in the project settings table with the given value.
90+
*
91+
* @param parent The parent window. Cannot be nullptr.
92+
* @param setting The setting to add or update.
93+
* @param value The new value for the setting.
94+
*/
95+
void SettingsTable::setSetting(QWidget* parent, const GenericProjectSetting* setting, QVariant value)
96+
{
97+
ItemID id = findSettingID(setting, parent);
98+
if (id.isValid()) {
99+
// Update setting
100+
updateCellInNormalTable(parent, FORCE_VALID(id), settingValueColumn, value);
101+
} else {
102+
// Add setting
103+
QList<ColumnDataPair> columnDataPairs = QList<ColumnDataPair>();
104+
columnDataPairs.append({settingKeyColumn, setting->key});
105+
columnDataPairs.append({settingValueColumn, setting->defaultValue});
106+
BufferRowIndex newBufferIndex = addRow(parent, columnDataPairs);
107+
id = primaryKeyColumn->getValueAt(newBufferIndex);
108+
}
109+
}
110+
111+
/**
112+
* Removes the setting from the project settings table entirely.
113+
*
114+
* @param parent The parent window. Cannot be nullptr.
115+
* @param setting The setting to remove.
116+
*/
117+
void SettingsTable::removeSetting(QWidget* parent, const GenericProjectSetting* setting)
118+
{
119+
ItemID id = findSettingID(setting, parent);
120+
if (id.isInvalid()) return;
121+
removeMatchingRows(parent, settingKeyColumn, FORCE_VALID(id));
122+
}
123+
124+
125+
126+
/**
127+
* Finds the projectSettingID (primary key) of the given setting in the database.
128+
*
129+
* @param setting The setting to look up.
130+
* @param parent The parent window. Can be nullptr, in which case no cleanup is performed for duplicate settings.
131+
* @return The projectSettingID of the setting, or an invalid ItemID if the setting is not present.
132+
*/
133+
ItemID SettingsTable::findSettingID(const GenericProjectSetting* setting, QWidget* parent)
134+
{
135+
QList<BufferRowIndex> bufferRowIndices = getMatchingBufferRowIndices(settingKeyColumn, setting->key);
136+
137+
if (bufferRowIndices.size() == 1) {
138+
return VALID_ITEM_ID();
139+
}
140+
141+
BufferRowIndex settingIndex = bufferRowIndices.last();
142+
if (bufferRowIndices.size() > 1) {
143+
QString error = "WARNING: Found " + QString::number(bufferRowIndices.size()) + " entries for project setting " + setting->key + ".";
144+
if (parent) {
145+
error += " Cleaning up.";
146+
}
147+
qDebug().noquote() << error;
148+
if (parent) {
149+
for (const BufferRowIndex& rowIndex : bufferRowIndices) {
150+
if (rowIndex == settingIndex) continue; // Leave the last one in place
151+
ValidItemID id = VALID_ITEM_ID(primaryKeyColumn->getValueAt(rowIndex));
152+
removeMatchingRows(parent, settingKeyColumn, id);
153+
}
154+
}
155+
}
156+
157+
return VALID_ITEM_ID(primaryKeyColumn->getValueAt(settingIndex));
158+
}

src/db/tables/settings_table.h

+14-29
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
/**
1919
* @file settings_table.h
2020
*
21-
* This file defines the SettingsTable class.
21+
* This file declares the SettingsTable class.
2222
*/
2323

2424
#ifndef SETTINGS_TABLE_H
@@ -29,7 +29,7 @@
2929
#include <QWidget>
3030
#include <QVariant>
3131

32-
template<typename T> class ProjectSetting;
32+
class GenericProjectSetting;
3333

3434

3535

@@ -39,37 +39,22 @@ template<typename T> class ProjectSetting;
3939
class SettingsTable : public Table {
4040
/** The primary key column. */
4141
Column* primaryKeyColumn;
42+
/** The column for key strings which identify settings. */
43+
Column* settingKeyColumn;
44+
/** The column for setting values, encoded as strings. */
45+
Column* settingValueColumn;
4246

4347
public:
44-
/**
45-
* Creates a new SettingsTable.
46-
*/
47-
inline SettingsTable() :
48-
Table("ProjectSettings", "Project settings", false),
49-
primaryKeyColumn (new Column("projectSettingsID", QString(), ID, false, true, nullptr, this))
50-
{
51-
addColumn(primaryKeyColumn);
52-
}
48+
SettingsTable();
5349

54-
protected:
55-
/**
56-
* Updates the given setting.
57-
*
58-
* @param parent The parent window.
59-
* @param setting The setting to update.
60-
* @param value The new value for the setting.
61-
* @param rowIndex The row index of the setting to update.
62-
*/
63-
template<typename T>
64-
inline void updateSetting(QWidget* parent, const ProjectSetting<T>* setting, QVariant value, int rowIndex = 0)
65-
{
66-
assert(rowIndex < 2);
67-
68-
ValidItemID primaryKey = VALID_ITEM_ID(primaryKeyColumn->getValueAt(BufferRowIndex(rowIndex)));
69-
updateCellInNormalTable(parent, primaryKey, setting, value);
70-
}
50+
bool settingIsPresent(const GenericProjectSetting* setting, QWidget* parent = nullptr);
51+
QVariant getSetting(const GenericProjectSetting* setting, QWidget* parent = nullptr);
7152

72-
template<typename T> friend class ProjectSetting;
53+
void setSetting(QWidget* parent, const GenericProjectSetting* setting, QVariant value);
54+
void removeSetting(QWidget* parent, const GenericProjectSetting* setting);
55+
56+
private:
57+
ItemID findSettingID(const GenericProjectSetting* setting, QWidget* parent = nullptr);
7358
};
7459

7560

src/dialogs/ascent_dialog.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ AscentDialog::AscentDialog(QWidget* parent, Database* db, DialogPurpose purpose,
104104
handle_elevationGainSpecifiedChanged();
105105
elevationGainSpinner->setValue(Settings::ascentDialog_initialElevationGain.get());
106106
// Set initial hiker
107-
ItemID defaultHikerID = db->projectSettings->defaultHiker->get();
107+
ItemID defaultHikerID = db->projectSettings->defaultHiker.get();
108108
if (defaultHikerID.isValid()) {
109109
Hiker* hiker = db->getHiker(FORCE_VALID(defaultHikerID));
110110
hikersModel.addHiker(hiker);

src/dialogs/hiker_dialog.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ void openDeleteHikerDialogAndExecute(QWidget* parent, Database* db, BufferRowInd
204204
if (!proceed) return;
205205
}
206206

207-
if (db->projectSettings->defaultHiker->get() == ID_GET(hikerID)) {
208-
db->projectSettings->defaultHiker->setToNull(parent);
207+
if (db->projectSettings->defaultHiker.get() == ID_GET(hikerID)) {
208+
db->projectSettings->defaultHiker.clear(parent);
209209
}
210210

211211
db->removeRow(parent, db->hikersTable, hikerID);

0 commit comments

Comments
 (0)