refactor: move saving of screen aliases to general deskflow.conf

This commit is contained in:
sithlord48 2026-06-20 09:59:35 -04:00 committed by Nick Bolton
parent 2d5cf33f16
commit 8010d8a8b2
6 changed files with 61 additions and 104 deletions

View file

@ -162,6 +162,15 @@ This section contains options used when in server mode it will begin with `[serv
- You can use both the ''switchDelay'' and ''switchDoubleTap'' options at the same time. Deskflow will switch when either requirement is satisfied.
### Screen Settings
Each screen will have a section where its configuration will be stored, if the screen was named "foo" the section will be named `[screen_foo]`
|Option | Valid Values |Description|
|:-------------------|:------------------:|:-----------|
| aliases | Comma separated list of hostnames | Names here will be used as alternatives for the computer. Names must be valid hostnames. |
### InternalConfig
This section contains options used when in server mode it will begin with `[internalConfig]`
@ -184,7 +193,6 @@ hotkeys\1\keys\1\key=83
hotkeys\1\keys\size=1
hotkeys\size=1
screens\1\name=
screens\10\aliasArray\size=0
screens\10\fixArray\1\fix=false
screens\10\fixArray\2\fix=false
screens\10\fixArray\3\fix=false
@ -214,7 +222,6 @@ screens\3\name=
screens\4\name=
screens\5\name=
screens\6\name=
screens\7\aliasArray\size=0
screens\7\fixArray\1\fix=false
screens\7\fixArray\2\fix=false
screens\7\fixArray\3\fix=false
@ -234,7 +241,6 @@ screens\7\switchCornerArray\3\switchCorner=false
screens\7\switchCornerArray\4\switchCorner=false
screens\7\switchCornerArray\size=4
screens\7\switchCornerSize=0
screens\8\aliasArray\size=0
screens\8\fixArray\1\fix=false
screens\8\fixArray\2\fix=false
screens\8\fixArray\3\fix=false
@ -254,7 +260,6 @@ screens\8\switchCornerArray\3\switchCorner=false
screens\8\switchCornerArray\4\switchCorner=false
screens\8\switchCornerArray\size=4
screens\8\switchCornerSize=0
screens\9\aliasArray\size=0
screens\9\fixArray\1\fix=false
screens\9\fixArray\2\fix=false
screens\9\fixArray\3\fix=false
@ -292,11 +297,10 @@ end
Comments are introduced by ''#'' and continue to the end of the line. ''name'' must be one of the following:
* ''screens''
* ''aliases''
* ''links''
* ''options''
The file is parsed top to bottom and names cannot be used before they've been defined in the <code>screens</code> or <code>aliases</code> sections. So the <code>links</code> and <code>aliases</code> must appear after the <code>screens</code> and <code>links</code> cannot refer to aliases unless the <code>aliases</code> appear before the <code>links</code>.
The file is parsed top to bottom and names cannot be used before they've been defined in the `screens` or as an alias in the general config. So the `links` must appear after the `screens`.
### The screens section
@ -333,21 +337,6 @@ A computer can have the following options:
|meta| shift ctrl alt meta super none | Map the server's meta modifer to different key on a client computer|
|super| shift ctrl alt meta super none | Map the server's super modifer to different key on a client computer|
### aliases section
''args'' is a list of computer names just like in the ''screens'' section except each computer is followed by a list of aliases, one per line, not followed by a colon. An ''alias'' is a computer name and must be unique. When searching for computers each alias is equivalent to the computer name it aliases. So a client can connect using its canonical computer name or any of its aliases.
```
section: aliases
larry:
larry.stooges.com
curly:
shemp
end
```
Computer ''larry'' is also known as ''larry.stooges.com'' and can connect as either name. Computer ''curly'' is also known as ''shemp'' (hey, it's just an example).
### links secion
''args'' is a list of computer names just like in the ''screens'' section except each computer is followed by a list of links, one per line. Each link has the form:
@ -597,6 +586,8 @@ Additionally, a name of the form `\uXXXX` where ''XXXX'' is a hexadecimal number
### Example textual configuration file
The alias section is no longer in the server config
This example comes from doc/deskflow-basic.conf
```

View file

@ -116,12 +116,13 @@ void Settings::cleanSettings()
m_settings->remove(key);
if (key.startsWith(QStringLiteral("internalConfig")))
continue;
if (!m_validKeys.contains(key))
if (const auto group = key.mid(0, key.indexOf('/')); !m_validKeys.contains(key) && m_validGroup.contains(group))
m_settings->remove(key);
if (m_settings->value(key).toString().isEmpty())
if (!m_settings->value(key).canConvert<QStringList>() && m_settings->value(key).toString().isEmpty()) {
m_settings->remove(key);
}
}
}
void Settings::cleanStateSettings()
{

View file

@ -123,6 +123,11 @@ public:
inline static const auto XdpRestoreToken = QStringLiteral("server/xdpRestoreToken");
};
struct Screen
{
inline static const auto Aliases = QStringLiteral("screen_%1/aliases");
};
// Enums types used in settings
// The use of enum classes is not use for these
// enum classes are more specific when used with QVariant
@ -166,6 +171,7 @@ public:
static NetworkProtocol networkProtocol();
static void save(bool emitSaving = true);
static QStringList validKeys();
static QStringList validGroups();
static QString portableSettingsFile();
Q_SIGNALS:
@ -204,6 +210,17 @@ private:
std::shared_ptr<QSettingsProxy> m_settingsProxy;
// clang-format off
inline static const QStringList m_validGroup = {
QStringLiteral("client")
, QStringLiteral("core")
, QStringLiteral("daemon")
, QStringLiteral("gui")
, QStringLiteral("log")
, QStringLiteral("security")
, QStringLiteral("server")
, QStringLiteral("internalConfig")
};
inline static const QStringList m_validKeys = {
Settings::Client::DynamicConnectionRetry
, Settings::Client::InvertYScroll

View file

@ -8,6 +8,7 @@
#include "Screen.h"
#include "config/ScreenConfig.h"
#include <common/Settings.h>
using enum ScreenConfig::Modifier;
using enum ScreenConfig::SwitchCorner;
@ -20,29 +21,34 @@ Screen::Screen(const QString &name)
void Screen::loadSettings(QSettingsProxy &settings)
{
setName(settings.value("name").toString());
const auto name = settings.value("name").toString();
setName(name);
if (name().isEmpty())
if (name.isEmpty())
return;
setSwitchCornerSize(settings.value("switchCornerSize").toInt());
readSettings(settings, aliases(), "alias", QString(""));
readSettings(settings, modifiers(), "modifier", static_cast<int>(DefaultMod), static_cast<int>(NumModifiers));
readSettings(settings, switchCorners(), "switchCorner", false, static_cast<int>(NumSwitchCorners));
readSettings(settings, fixes(), "fix", 0, static_cast<int>(NumFixes));
m_Aliases = Settings::value(Settings::Screen::Aliases.arg(name)).toStringList();
}
void Screen::saveSettings(QSettingsProxy &settings) const
{
settings.setValue("name", name());
if (name().isEmpty())
const auto screenName = name();
settings.setValue("name", screenName);
if (screenName.isEmpty())
return;
Settings::setValue(Settings::Screen::Aliases.arg(screenName), m_Aliases);
settings.setValue("switchCornerSize", switchCornerSize());
writeSettings(settings, aliases(), "alias");
writeSettings(settings, modifiers(), "modifier");
writeSettings(settings, switchCorners(), "switchCorner");
writeSettings(settings, fixes(), "fix");
@ -73,18 +79,6 @@ QString Screen::screensSection() const
return out;
}
QString Screen::aliasesSection() const
{
QString out;
if (!aliases().isEmpty()) {
out = QStringLiteral("\t%1:\n").arg(name());
for (const QString &alias : aliases())
out.append(QStringLiteral("\t\t%1\n").arg(alias));
}
return out;
}
bool Screen::operator==(const Screen &screen) const
{
return m_Name == screen.m_Name && m_Aliases == screen.m_Aliases && m_Modifiers == screen.m_Modifiers &&

View file

@ -167,15 +167,6 @@ QTextStream &operator<<(QTextStream &outStream, const ServerConfig &config)
outStream << "end" << Qt::endl << Qt::endl;
outStream << "section: aliases" << Qt::endl;
for (const Screen &s : config.screens()) {
if (!s.isNull())
outStream << s.aliasesSection();
}
outStream << "end" << Qt::endl << Qt::endl;
outStream << "section: links" << Qt::endl;
for (int i = 0; const auto &screen : config.screens()) {

View file

@ -46,6 +46,11 @@ bool Config::addScreen(const std::string &name)
// add name
m_nameToCanonicalName.try_emplace(name, name);
// add aliases
const auto aliases = Settings::value(Settings::Screen::Aliases.arg(QString::fromStdString(name))).toStringList();
for (const auto &alias : aliases)
m_nameToCanonicalName.try_emplace(alias.toStdString(), name);
return true;
}
@ -88,6 +93,12 @@ bool Config::renameScreen(const std::string &oldName, const std::string &newName
}
}
// Update Settings
const auto aliasList = Settings::value(Settings::Screen::Aliases.arg(QString::fromStdString(oldName))).toStringList();
if (aliasList.isEmpty())
return true;
Settings::setValue(Settings::Screen::Aliases.arg(QString::fromStdString(oldName)), QVariant());
Settings::setValue(Settings::Screen::Aliases.arg(QString::fromStdString(newName)), aliasList);
return true;
}
@ -109,6 +120,7 @@ void Config::removeScreen(const std::string &name)
index->second.remove(nameObj);
}
Settings::setValue(Settings::Screen::Aliases.arg(QString::fromStdString(name)), QVariant());
// remove aliases (and canonical name)
for (auto iter = m_nameToCanonicalName.begin(); iter != m_nameToCanonicalName.end();) {
if (iter->second == canonical) {
@ -554,10 +566,10 @@ void Config::readSection(ConfigReadContext &s)
readSectionOptions(s);
} else if (name == s_screens) {
readSectionScreens(s);
} else if (name == s_links) {
readSectionLinks(s);
} else if (name == s_aliases) {
readSectionAliases(s);
} else if (name == s_links) {
readSectionLinks(s);
} else {
throw ServerConfigReadException(s, "unknown section name \"%{1}\"", name);
}
@ -827,39 +839,14 @@ void Config::readSectionLinks(ConfigReadContext &s)
void Config::readSectionAliases(ConfigReadContext &s)
{
qWarning(
) << "Your server config has an alias section. Alias have moved to the general config this section will no be "
"parsed.";
std::string line;
std::string screen;
while (s.readLine(line)) {
// check for end of section
if (line == "end") {
return;
}
// see if it's the next screen
if (line[line.size() - 1] == ':') {
// strip :
screen = line.substr(0, line.size() - 1);
// verify we know about the screen
if (!isScreen(screen)) {
throw ServerConfigReadException(s, "unknown screen name \"%{1}\"", screen);
}
if (!isCanonicalName(screen)) {
throw ServerConfigReadException(s, "cannot use screen name alias here");
}
} else if (screen.empty()) {
throw ServerConfigReadException(s, "argument before first screen");
} else {
// verify validity of screen name
if (!isValidScreenName(line)) {
throw ServerConfigReadException(s, "invalid screen alias \"%{1}\"", line);
}
// add alias
if (!addAlias(screen, line)) {
throw ServerConfigReadException(s, "alias \"%{1}\" is already used", line);
}
}
}
throw ServerConfigReadException(s, "unexpected end of aliases section");
}
@ -1557,30 +1544,6 @@ std::ostream &operator<<(std::ostream &s, const Config &config)
}
s << "end" << std::endl;
// aliases section (if there are any)
if (config.m_map.size() != config.m_nameToCanonicalName.size()) {
// map canonical to alias
using CMNameMap = std::multimap<std::string, std::string, CaselessCmp>;
CMNameMap aliases;
for (auto index = config.m_nameToCanonicalName.begin(); index != config.m_nameToCanonicalName.end(); ++index) {
if (index->first != index->second) {
aliases.insert(std::make_pair(index->second, index->first));
}
}
// dump it
std::string screen;
s << "section: aliases" << std::endl;
for (CMNameMap::const_iterator index = aliases.begin(); index != aliases.end(); ++index) {
if (index->first != screen) {
screen = index->first;
s << "\t" << screen.c_str() << ":" << std::endl;
}
s << "\t\t" << index->second.c_str() << std::endl;
}
s << "end" << std::endl;
}
// options section
s << "section: options" << std::endl;
if (const Config::ScreenOptions *options = config.getOptions(""); options && options->size() > 0) {