Skip to content

Commit

Permalink
support multiple machine-specific configurations ("profiles")
Browse files Browse the repository at this point in the history
This makes Candle2 usable for driving multiple machines from the same computer, by making separate copies of the entire config file per machine.

By default, nothing will change; the file format is unchanged, and the current configuration is treated as a default profile. If multiple profiles are present at startup, the user is prompted to select one. If the environment variable $CANDLE_PROFILE is present and non-empty, that profile is used without prompting.

Profiles are stored in the app config directory, as urlencode(profilename) + ".ini". (URL-encoding the names allows profiles to be named without regard for the platform's file naming rules.)

There is currently no UI for managing profiles; they may be created by manually copying `settings.ini` to a new file in the same directory, or by setting $CANDLE_PROFILE to a profile that does not yet exist (it will be created with default settings).
  • Loading branch information
scgtrp committed Feb 28, 2024
1 parent 638a290 commit 0614221
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 16 deletions.
2 changes: 2 additions & 0 deletions src/candle2.pro
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ SOURCES += main.cpp\
parser/pointsegment.cpp \
tables/gcodetablemodel.cpp \
tables/heightmaptablemodel.cpp \
utils/profiles.cpp \
widgets/colorpicker.cpp \
widgets/combobox.cpp \
widgets/groupbox.cpp \
Expand Down Expand Up @@ -96,6 +97,7 @@ HEADERS += frmmain.h \
tables/gcodetablemodel.h \
tables/heightmaptablemodel.h \
utils/interpolation.h \
utils/profiles.h \
utils/util.h \
widgets/colorpicker.h \
widgets/combobox.h \
Expand Down
41 changes: 31 additions & 10 deletions src/frmmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@
#include <QtSerialPort/QSerialPortInfo>
#include <QStandardPaths>
#include <QThread>
#include <QInputDialog>

#include "frmmain.h"
#include "ui_frmmain.h"

#include "interface/SerialInterface.h"
#include "GrIP/GrIP.h"
#include "utils/profiles.h"


static const int ReceiveTimerInterval_ms = 10;
Expand Down Expand Up @@ -113,14 +115,8 @@ frmMain::frmMain(QWidget *parent) :
<< "G58"
<< "G59";


// Create settings path
std::string path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation).toStdString();
auto pos = path.rfind('/');
if (pos != std::string::npos) {
path.erase(pos);
}
m_settingsFileName = QString::fromStdString(path) + "/Candle2" + settings_file;
m_settingsFilePath = findConfigPath();
qDebug() << "settings file path: " << m_settingsFilePath;

// Loading settings
preloadSettings();
Expand Down Expand Up @@ -374,14 +370,39 @@ frmMain::frmMain(QWidget *parent) :
m_timerSend.start(SendTimerInterval_ms);
}

QString frmMain::findConfigPath() {
QString profileNameFromEnvironment = getenv("CANDLE_PROFILE");
if (profileNameFromEnvironment.length() > 0) {
return configPathForProfile(profileNameFromEnvironment);
}

const auto profiles = getProfileNames();
if (profiles.length() == 0) {
// first run, no profiles at all yet
return configPathForProfile(default_profile_name);
} else if (profiles.length() == 1) {
// only one profile exists, no point asking which one
return configPathForProfile(profiles[0]);
} else {
bool ok;
const auto pickedItem = QInputDialog::getItem(this, "Choose Profile", "Choose a profile:", profiles, 0, false, &ok);
if (ok) {
return configPathForProfile(pickedItem);
} else {
// user cancelled
exit(0);
}
}
}

void frmMain::UpdateComPorts()
{
// Clear combobox
ui->comboInterface->clear();
ui->comboHandwheel->clear();

// Add available ports to combobox
foreach (QSerialPortInfo info ,QSerialPortInfo::availablePorts())
foreach (QSerialPortInfo info, QSerialPortInfo::availablePorts())
{
ui->comboInterface->insertItem(0, info.portName());
ui->comboHandwheel->insertItem(0, info.portName());
Expand Down Expand Up @@ -468,7 +489,7 @@ double frmMain::toolZPosition()

void frmMain::preloadSettings()
{
QSettings set(m_settingsFileName, QSettings::IniFormat);
QSettings set(m_settingsFilePath, QSettings::IniFormat);
set.setIniCodec("UTF-8");

qApp->setStyleSheet(QString(qApp->styleSheet()).replace(QRegExp("font-size:\\s*\\d+"), "font-size: " + set.value("fontSize", "8").toString()));
Expand Down
6 changes: 2 additions & 4 deletions src/frmmain.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ private slots:
void jogStep();
void updateJogTitle();

QString findConfigPath();

Ui::frmMain *ui;
GcodeViewParse m_viewParser;
Expand Down Expand Up @@ -358,7 +359,7 @@ private slots:
frmSettings *m_settings;
frmAbout m_frmAbout;

QString m_settingsFileName;
QString m_settingsFilePath;
QString m_programFileName;
QString m_heightMapFileName;
QString m_lastFolder;
Expand Down Expand Up @@ -458,9 +459,6 @@ private slots:
// Size of internal GRBL buffer
static const int GRBL_BUFFERLENGTH = 127;

// Name of setting file
const QString settings_file = "/settings.ini";

QSerialPort m_serialHandWheel;
};

Expand Down
4 changes: 2 additions & 2 deletions src/frmmain_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

void frmMain::loadSettings()
{
QSettings set(m_settingsFileName, QSettings::IniFormat);
QSettings set(m_settingsFilePath, QSettings::IniFormat);
set.setIniCodec("UTF-8");

m_settingsLoading = true;
Expand Down Expand Up @@ -194,7 +194,7 @@ void frmMain::loadSettings()

void frmMain::saveSettings()
{
QSettings set(m_settingsFileName, QSettings::IniFormat);
QSettings set(m_settingsFilePath, QSettings::IniFormat);
set.setIniCodec("UTF-8");

set.setValue("ipaddress", m_settings->IPAddress());
Expand Down
20 changes: 20 additions & 0 deletions src/utils/profiles.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "profiles.h"
#include <QUrl>

// chosen for backward compatibility with pre-profiles versions, which always stored settings in `settings.ini`
const QString default_profile_name = "settings";

QStringList getProfileNames() {
const QDir configDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
const QStringList configFiles = configDir.entryList({"*.ini"}, QDir::Files);
QStringList rv;
for (QString configFile : configFiles) {
rv << QUrl::fromPercentEncoding(configFile.replace(QRegExp("\\.ini$"), "").toUtf8());
}
return rv;
}

QString configPathForProfile(QString profile_name) {
const QDir configDir = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
return configDir.filePath(QUrl::toPercentEncoding(profile_name) + ".ini");
}
11 changes: 11 additions & 0 deletions src/utils/profiles.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef PROFILES_H
#define PROFILES_H
#include <QStringList>
#include <QStandardPaths>
#include <QDir>

extern const QString default_profile_name;
QStringList getProfileNames();
QString configPathForProfile(QString profile_name);

#endif // PROFILES_H

0 comments on commit 0614221

Please sign in to comment.