/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see .
*/
// SPDX-License-Identifier: GPL-2.0-or-later
#include "wiringrules.h"
#include
#include
#include
namespace {
const QString element_name = QStringLiteral("wiring_rules");
const QString max_wires_attribute = QStringLiteral("max_wires_per_terminal");
const QString report_attribute = QStringLiteral("one_wire_per_report");
//The master switch is read on every wire drawn, so it is read from
//the settings once and kept; setMasterEnabled() keeps both in step.
int master_cache = -1;
//Same for the application's rules
bool application_cached = false;
WiringRules::Settings application_cache;
}
/**
@brief WiringRules::masterEnabled
@return false when the user turned every rule of this feature off for
every project (Settings > General). On by default: a project still has
to turn a rule on before anything changes.
*/
bool WiringRules::masterEnabled()
{
if (master_cache < 0) {
master_cache = QSettings().value(settings_key, true).toBool() ? 1 : 0;
}
return master_cache == 1;
}
/**
@brief WiringRules::setMasterEnabled
Save the master switch.
@param enabled
*/
void WiringRules::setMasterEnabled(bool enabled)
{
QSettings().setValue(settings_key, enabled);
master_cache = enabled ? 1 : 0;
}
/**
@brief WiringRules::applicationSettings
@return the rules set for every project in Settings > General; a
project that sets its own (Settings::own) uses those instead.
*/
WiringRules::Settings WiringRules::applicationSettings()
{
if (!application_cached) {
const QSettings settings;
application_cache = Settings();
application_cache.max_wires = qMax(0, settings.value(max_wires_key, 0).toInt());
application_cache.one_wire_per_report = settings.value(one_wire_per_report_key, false).toBool();
application_cached = true;
}
return application_cache;
}
/**
@brief WiringRules::setApplicationSettings
Save the rules set for every project.
@param settings
*/
void WiringRules::setApplicationSettings(const Settings &settings)
{
QSettings qsettings;
qsettings.setValue(max_wires_key, qMax(0, settings.max_wires));
qsettings.setValue(one_wire_per_report_key, settings.one_wire_per_report);
application_cache = settings;
application_cache.own = false;
application_cached = true;
}
/**
@brief WiringRules::effective
@return the rules that apply to a project: its own when it sets them,
otherwise the application's.
*/
WiringRules::Settings WiringRules::effective(const Settings &project, const Settings &application)
{
Settings result = project.own ? project : application;
result.own = project.own;
return result;
}
/**
@brief WiringRules::fromXml
@param project_root : the root element of a project
@return the rules stored in the child of \a project_root,
which the project then uses instead of the application's (Settings::own);
the default, which follows the application, when there is none.
*/
WiringRules::Settings WiringRules::fromXml(const QDomElement &project_root)
{
Settings settings;
const QDomElement rules = project_root.firstChildElement(element_name);
if (rules.isNull()) {
return settings;
}
settings.own = true;
settings.max_wires = qMax(0, rules.attribute(max_wires_attribute, QStringLiteral("0")).toInt());
settings.one_wire_per_report = rules.attribute(report_attribute) == QLatin1String("true");
return settings;
}
/**
@brief WiringRules::toXml
Write \a settings as a child of \a project_root, only
when the project sets its own rules: a project that follows the
application's saves exactly as before.
*/
void WiringRules::toXml(const Settings &settings, QDomElement &project_root)
{
if (!settings.own) {
return;
}
QDomElement rules = project_root.ownerDocument().createElement(element_name);
if (settings.max_wires > 0) {
rules.setAttribute(max_wires_attribute, settings.max_wires);
}
if (settings.one_wire_per_report) {
rules.setAttribute(report_attribute, QStringLiteral("true"));
}
project_root.appendChild(rules);
}
/**
@brief WiringRules::limit
@param settings : the project's rules
@param master_enabled : the master switch, masterEnabled()
@param is_report : the terminal belongs to a folio report
@return the most wires the terminal may take, 0 for no limit.
*/
int WiringRules::limit(const Settings &settings, bool master_enabled, bool is_report)
{
if (!master_enabled) {
return 0;
}
if (is_report && settings.one_wire_per_report) {
return 1;
}
return settings.max_wires;
}
/**
@brief WiringRules::hasRoom
@param limit : WiringRules::limit()
@param wires : the wires the terminal already has
@return true if one more wire may be connected
*/
bool WiringRules::hasRoom(int limit, int wires)
{
return limit <= 0 || wires < limit;
}