Skip to content

Commit 16e2bc9

Browse files
committed
Refactor environment.cpp
1 parent 53468f9 commit 16e2bc9

File tree

6 files changed

+181
-63
lines changed

6 files changed

+181
-63
lines changed

src/environment.cpp

Lines changed: 102 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,87 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
#define _POSIX_C_SOURCE 200809L
3+
#include <iostream>
4+
#include <fstream>
35
#include <QDebug>
46
#include <QFile>
57
#include <QString>
68
#include <QTextStream>
79
#include <cstring>
10+
#include <vector>
11+
#include <memory>
12+
#include "log.h"
813

9-
QString environment_get(const char *key)
14+
class Line
1015
{
11-
QString filename = qgetenv("HOME") + "/.config/labwc/environment";
12-
QFile inputFile(filename);
13-
inputFile.open(QIODevice::ReadOnly);
14-
if (!inputFile.isOpen()) {
15-
return nullptr;
16-
}
16+
public:
17+
Line();
18+
~Line();
1719

18-
QTextStream stream(&inputFile);
19-
QString line;
20-
while (stream.readLineInto(&line)) {
21-
if (line.isEmpty() || line.startsWith("#")) {
22-
continue;
23-
}
20+
QString data;
21+
bool isKeyValuePair;
22+
QString key;
23+
QString value;
24+
};
25+
26+
static std::vector<std::unique_ptr<Line>> lines;
27+
28+
Line::Line(void)
29+
{
30+
isKeyValuePair = false;
31+
}
32+
33+
Line::~Line(void) { };
2434

25-
QStringList elements = line.split('=');
26-
if (elements.count() != 2) {
35+
// TODO: should be envGet()
36+
QString environment_get(QString key)
37+
{
38+
for (auto &line : lines) {
39+
if (!line->isKeyValuePair)
2740
continue;
28-
}
29-
if (elements[0].trimmed() == QString(key)) {
30-
return elements[1].trimmed();
31-
}
41+
if (line->key == key)
42+
return line->value;
3243
}
3344
return nullptr;
3445
}
3546

47+
int environment_get_int(QString key)
48+
{
49+
qDebug() << "key=" << key;
50+
for (auto &line : lines) {
51+
qDebug() << "line->key=" << line->key << " key=" << key;
52+
if (!line->isKeyValuePair)
53+
continue;
54+
if (line->key == key)
55+
return atoi(line->value.toStdString().c_str());
56+
}
57+
return -1;
58+
}
59+
60+
// TODO: use std::string instead of const char *
3661
void environment_set(const char *key, const char *value)
3762
{
38-
if (!key || !*key) {
39-
return;
40-
}
41-
if (!value || !*value) {
42-
return;
43-
}
44-
/* set cursor for labwc - should cover 'replace' or 'append' */
45-
char xcur[4096] = { 0 };
46-
strcpy(xcur, key);
47-
strcat(xcur, "=");
48-
char filename[4096];
49-
char bufname[4096];
50-
char *home = getenv("HOME");
51-
snprintf(filename, sizeof(filename), "%s/%s", home, ".config/labwc/environment");
52-
snprintf(bufname, sizeof(bufname), "%s/%s", home, ".config/labwc/buf");
53-
FILE *fe = fopen(filename, "r");
54-
FILE *fw = fopen(bufname, "a");
55-
if ((fe == NULL) || (fw == NULL)) {
56-
perror("Unable to open file!");
63+
if (!key || !*key) {
64+
return;
65+
}
66+
if (!value || !*value) {
5767
return;
5868
}
59-
char chunk[128];
60-
while (fgets(chunk, sizeof(chunk), fe) != NULL) {
61-
if (strstr(chunk, xcur) != NULL) {
69+
for (auto &line : lines) {
70+
if (!line->isKeyValuePair) {
6271
continue;
63-
} else {
64-
fprintf(fw, "%s", chunk);
72+
}
73+
if (line->key == key) {
74+
// Modify existing key=value pair
75+
line->value = QString(value);
76+
return;
6577
}
6678
}
67-
fclose(fe);
68-
if (value) {
69-
fprintf(fw, "%s\n", strcat(xcur, value));
70-
}
71-
fclose(fw);
72-
rename(bufname, filename);
79+
80+
// Append
81+
lines.push_back(std::make_unique<Line>());
82+
lines.back()->isKeyValuePair = true;
83+
lines.back()->key = QString(key);
84+
lines.back()->value = QString(value);
7385
}
7486

7587
void environment_set_num(const char *key, int value)
@@ -79,3 +91,44 @@ void environment_set_num(const char *key, int value)
7991

8092
environment_set(key, buffer);
8193
}
94+
95+
static void processLine(QString line)
96+
{
97+
lines.push_back(std::make_unique<Line>());
98+
lines.back()->data = line;
99+
if (line.isEmpty() || line.startsWith("#") || !line.contains("=")) {
100+
return;
101+
}
102+
lines.back()->isKeyValuePair = true;
103+
QStringList elements = line.split('=');
104+
lines.back()->key = elements[0].trimmed();
105+
lines.back()->value = elements[1].trimmed();
106+
}
107+
108+
void environmentInit(std::string filename)
109+
{
110+
if (access(filename.c_str(), F_OK)) {
111+
info("environment file not found '{}'", filename);
112+
return;
113+
}
114+
115+
std::string line;
116+
std::ifstream stream(filename);
117+
while (getline(stream, line)) {
118+
processLine(QString(line.c_str()));
119+
}
120+
stream.close();
121+
}
122+
123+
void environmentSave(std::string filename)
124+
{
125+
std::ofstream ofs(filename);
126+
for (auto &line : lines) {
127+
if (!line->isKeyValuePair) {
128+
ofs << line->data.toStdString() << std::endl;
129+
} else {
130+
ofs << line->key.toStdString() << "=" << line->value.toStdString() << std::endl;
131+
}
132+
}
133+
ofs.close();
134+
}

src/environment.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@
33
#define ENVIRONMENT_H
44
#include <QString>
55

6-
QString environment_get(const char *key);
6+
QString environment_get(QString key);
7+
int environment_get_int(QString key);
8+
79
void environment_set(const char *key, const char *value);
810
void environment_set_num(const char *key, int value);
911

12+
void environmentInit(std::string filename);
13+
void environmentSave(std::string filename);
14+
1015
#endif /* ENVIRONMENT_H */

src/main.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "log.h"
1010
#include "settings.h"
11+
#include "environment.h"
1112

1213
extern "C" {
1314
#include "xml.h"
@@ -77,6 +78,12 @@ int main(int argc, char *argv[])
7778

7879
std::string config_home = std::getenv("HOME") + std::string("/.config/labwc");
7980
std::string config_dir = std::getenv("LABWC_CONFIG_DIR") ?: config_home;
81+
82+
// TODO: do the mkdir -p here
83+
84+
std::string environment_file = config_dir + "/environment";
85+
environmentInit(environment_file);
86+
8087
std::string config_file = config_dir + "/rc.xml";
8188
initConfig(config_file);
8289

src/maindialog.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ void MainDialog::activate()
108108
/* Labwc Theme */
109109
QStringList labwcThemes = findLabwcThemes();
110110
ui->openboxTheme->addItems(labwcThemes);
111-
ui->openboxTheme->setCurrentIndex(labwcThemes.indexOf(getStr(m_settings, "/labwc_config/theme/name")));
111+
ui->openboxTheme->setCurrentIndex(
112+
labwcThemes.indexOf(getStr(m_settings, "/labwc_config/theme/name")));
112113

113114
/* Corner Radius */
114115
ui->cornerRadius->setValue(getInt(m_settings, "/labwc_config/theme/cornerRadius"));
@@ -126,22 +127,24 @@ void MainDialog::activate()
126127
/* # BEHAVIOUR */
127128
QStringList policies = { "", "Automatic", "Cascade", "Center", "Cursor" };
128129
ui->placementPolicy->addItems(policies);
129-
ui->placementPolicy->setCurrentIndex(policies.indexOf(getStr(m_settings, "/labwc_config/placement/policy")));
130+
ui->placementPolicy->setCurrentIndex(
131+
policies.indexOf(getStr(m_settings, "/labwc_config/placement/policy")));
130132

131133
/* # MOUSE & TOUCHPAD */
132134

133135
/* Cursor Theme */
134136
QStringList cursorThemes = findIconThemes(LAB_ICON_THEME_TYPE_CURSOR);
135137
ui->cursorTheme->addItems(cursorThemes);
136-
ui->cursorTheme->setCurrentIndex(cursorThemes.indexOf(getenv("XCURSOR_THEME") ?: (char *)""));
138+
ui->cursorTheme->setCurrentIndex(cursorThemes.indexOf(getStr(m_settings, "XCURSOR_THEME")));
137139

138140
/* Cursor Size */
139-
ui->cursorSize->setValue(atoi(getenv("XCURSOR_SIZE") ?: "24"));
141+
ui->cursorSize->setValue(getInt(m_settings, "XCURSOR_SIZE"));
140142

141143
/* Natural Scroll */
142144
ui->naturalScroll->addItem("no");
143145
ui->naturalScroll->addItem("yes");
144-
ui->naturalScroll->setCurrentIndex(getBool(m_settings, "/labwc_config/libinput/device/naturalScroll"));
146+
ui->naturalScroll->setCurrentIndex(
147+
getBool(m_settings, "/labwc_config/libinput/device/naturalScroll"));
145148

146149
/* # LANGUAGE */
147150

@@ -165,7 +168,6 @@ void setInt(std::vector<std::shared_ptr<Setting>> &settings, QString name, int v
165168
if (value != std::get<int>(setting->value())) {
166169
info("'{} has changed to '{}'", name.toStdString(), value);
167170
xpath_add_node(name.toStdString().c_str());
168-
//xml_save();
169171
xml_set_num(name.toStdString().c_str(), value);
170172
}
171173
}
@@ -183,7 +185,6 @@ void setStr(std::vector<std::shared_ptr<Setting>> &settings, QString name, QStri
183185
if (value != std::get<QString>(setting->value())) {
184186
info("'{} has changed to '{}'", name.toStdString(), value.toStdString());
185187
xpath_add_node(name.toStdString().c_str());
186-
//xml_save();
187188
xml_set(name.toStdString().c_str(), value.toStdString().c_str());
188189
}
189190
}
@@ -236,7 +237,6 @@ void setBool(std::vector<std::shared_ptr<Setting>> &settings, QString name, QStr
236237
if (boolValue != std::get<int>(setting->value())) {
237238
info("'{} has changed to '{}'", name.toStdString(), value.toStdString());
238239
xpath_add_node(name.toStdString().c_str());
239-
//xml_save();
240240
xml_set(name.toStdString().c_str(), value.toStdString().c_str());
241241
}
242242
}
@@ -255,7 +255,7 @@ void MainDialog::onApply()
255255
xml_save();
256256

257257
/* ~/.config/labwc/environment */
258-
environment_set("XCURSOR_THEME", ui->cursorTheme->currentText().toLatin1().data());
258+
environment_set("XCURSOR_THEME", TEXT(ui->cursorTheme));
259259
environment_set_num("XCURSOR_SIZE", ui->cursorSize->value());
260260

261261
/*
@@ -268,6 +268,12 @@ void MainDialog::onApply()
268268
environment_set("XKB_DEFAULT_VARIANT", "");
269269
}
270270

271+
// TODO: Get filename in a more consistent way - share common code with main.cpp
272+
std::string config_home = std::getenv("HOME") + std::string("/.config/labwc");
273+
std::string config_dir = std::getenv("LABWC_CONFIG_DIR") ?: config_home;
274+
std::string environment_file = config_dir + "/environment";
275+
environmentSave(environment_file);
276+
271277
/* reconfigure labwc */
272278
if (!fork()) {
273279
execl("/bin/sh", "/bin/sh", "-c", "labwc -r", (void *)NULL);

src/settings.cpp

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,21 @@
22
#include <variant>
33
#include "log.h"
44
#include "settings.h"
5+
#include "environment.h"
56

67
extern "C" {
78
#include "xml.h"
89
}
910

11+
#define DEFAULT_XCURSOR_SIZE 24
12+
int xcursor_size(void)
13+
{
14+
bool success = false;
15+
int size = QString(qgetenv("XCURSOR_SIZE")).toInt(&success);
16+
return success ? size : DEFAULT_XCURSOR_SIZE;
17+
}
18+
#undef DEFAULT_XCURSOR_SIZE
19+
1020
void initSettings(std::vector<std::shared_ptr<Setting>> &settings)
1121
{
1222
// Appearance
@@ -26,9 +36,12 @@ void initSettings(std::vector<std::shared_ptr<Setting>> &settings)
2636

2737
// Mouse & Touchpad
2838
settings.push_back(std::make_shared<Setting>("XCURSOR_THEME", LAB_FILE_TYPE_ENVIRONMENT,
29-
LAB_VALUE_TYPE_STRING, "Adwaita"));
39+
LAB_VALUE_TYPE_STRING,
40+
getenv("XCURSOR_THEME") ?: (char *)"Adwaita"));
41+
3042
settings.push_back(std::make_shared<Setting>("XCURSOR_SIZE", LAB_FILE_TYPE_ENVIRONMENT,
31-
LAB_VALUE_TYPE_INT, 24));
43+
LAB_VALUE_TYPE_INT, xcursor_size()));
44+
3245
settings.push_back(std::make_shared<Setting>("/labwc_config/libinput/device/naturalScroll",
3346
LAB_FILE_TYPE_RCXML, LAB_VALUE_TYPE_BOOL, 0));
3447

@@ -43,6 +56,7 @@ Setting::Setting(QString name, enum settingFileType fileType, enum settingValueT
4356
{
4457
m_valueOrigin = LAB_VALUE_ORIGIN_DEFAULT;
4558

59+
// Use values from rc.xml if different from default
4660
if (m_fileType == LAB_FILE_TYPE_RCXML) {
4761
switch (m_valueType) {
4862
case LAB_VALUE_TYPE_STRING: {
@@ -76,6 +90,41 @@ Setting::Setting(QString name, enum settingFileType fileType, enum settingValueT
7690
break;
7791
}
7892
}
93+
94+
// Use values from environment file if different from default
95+
if (m_fileType == LAB_FILE_TYPE_ENVIRONMENT) {
96+
switch (m_valueType) {
97+
case LAB_VALUE_TYPE_STRING: {
98+
QString value = QString(environment_get(m_name));
99+
if (!value.isNull() && (value != std::get<QString>(m_value))) {
100+
m_valueOrigin = LAB_VALUE_ORIGIN_USER_OVERRIDE;
101+
m_value = value;
102+
info("[user-override] {}: {}", m_name.toStdString(), value.toStdString());
103+
}
104+
break;
105+
}
106+
case LAB_VALUE_TYPE_INT: {
107+
bool success = false;
108+
int value = environment_get_int(m_name);
109+
if (value == -1) {
110+
// There was no environment file - or it did not contain the key
111+
break;
112+
}
113+
if (value != std::get<int>(m_value)) {
114+
m_valueOrigin = LAB_VALUE_ORIGIN_USER_OVERRIDE;
115+
m_value = value;
116+
info("[user-override] {}: {}", m_name.toStdString(), value);
117+
}
118+
break;
119+
}
120+
case LAB_VALUE_TYPE_BOOL: {
121+
// do we need this?
122+
break;
123+
}
124+
default:
125+
break;
126+
}
127+
}
79128
};
80129

81130
std::shared_ptr<Setting> retrieve(std::vector<std::shared_ptr<Setting>> &settings, QString name)

0 commit comments

Comments
 (0)