The complete source code of IdealIRC
http://www.idealirc.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
9.4 KiB
325 lines
9.4 KiB
/*
|
|
* IdealIRC - Internet Relay Chat client
|
|
* Copyright (C) 2021 Tom-Andre Barstad.
|
|
* This software is licensed under the Software Attribution License.
|
|
* See LICENSE for more information.
|
|
*/
|
|
|
|
#include "ConfigMgr.h"
|
|
#include "config.h"
|
|
#include <QHashIterator>
|
|
#include <unordered_map>
|
|
#include <stdexcept>
|
|
|
|
namespace {
|
|
using DefaultMap = std::unordered_map<std::string,std::string>;
|
|
|
|
/*
|
|
* Default settings in case it is not found in the config file.
|
|
* scripts and prefix-colors have no default settings.
|
|
*/
|
|
|
|
#if defined(Q_OS_WIN32) | defined(Q_OS_WIN64)
|
|
constexpr auto DefaultFontName = "Fixedsys";
|
|
#else
|
|
constexpr auto DefaultFontName = "Monospace";
|
|
#endif
|
|
|
|
const DefaultMap defaultGeometry {
|
|
{ "X", "-1" },
|
|
{ "Y", "-1" },
|
|
{ "Width", "1024" },
|
|
{ "Height", "768" },
|
|
{ "Maximized", "0" }
|
|
};
|
|
|
|
const DefaultMap defaultConnection {
|
|
{ "SSL", "0" }
|
|
};
|
|
|
|
const DefaultMap defaultCommon {
|
|
{ "ShowOptions", "1" },
|
|
{ "Reconnect", "0" },
|
|
{ "ReconnectDelay", "1" },
|
|
{ "RejoinChannelsOnConnect", "0" },
|
|
{ "ShowWhoisActiveWindow", "1" },
|
|
{ "ShowModeInMessage", "1" },
|
|
{ "TrayNotify", "1" },
|
|
{ "TrayNotifyDelay", "5" },
|
|
{ "ShowTimestamp", "1" },
|
|
{ "TimestampFormat", "[HH:mm]" },
|
|
{ "ManualKeepaliveEnabled", "0" },
|
|
{ "ManualKeepalive", "10" },
|
|
{ "Font", DefaultFontName },
|
|
{ "FontSize", "12" },
|
|
{ "BgImageEnabled", "0" },
|
|
{ "BgImageOpacity", "100" },
|
|
{ "SSLSelfsigned", "0" },
|
|
{ "SSLCNMismatch", "0" },
|
|
{ "ButtonBarPosition", "N" },
|
|
{ "ToolbarHidden", "0" }
|
|
};
|
|
|
|
const DefaultMap defaultColor {
|
|
{ "Action", "#840084" },
|
|
{ "CTCP", "#FF0000" },
|
|
{ "Highlight", "#848400" },
|
|
{ "Invite", "#008400" },
|
|
{ "Join", "#008400" },
|
|
{ "Kick", "#008400" },
|
|
{ "Mode", "#008400" },
|
|
{ "Nick", "#008400" },
|
|
{ "Normal", "#000000" },
|
|
{ "Notice", "#840000" },
|
|
{ "OwnText", "#008484" },
|
|
{ "Part", "#008400" },
|
|
{ "ProgramInfo", "#000084" },
|
|
{ "Quit", "#000084" },
|
|
{ "ServerInfo", "#008400" },
|
|
{ "Topic", "#008400" },
|
|
{ "Wallops", "#FF0000" },
|
|
{ "TextviewBackground", "#FFFFFF" },
|
|
{ "InputBackground", "#FFFFFF" },
|
|
{ "InputForeground", "#000000" },
|
|
{ "ListboxBackground", "#FFFFFF" },
|
|
{ "ListboxForeground", "#000000" },
|
|
{ "Links", "#0000FF" },
|
|
{ "WindowButtonNormal", "#000000" },
|
|
{ "WindowButtonActivity", "#000088" },
|
|
{ "WindowButtonMessage", "#0000FF" },
|
|
{ "WindowButtonAttention", "#FF0000" }
|
|
};
|
|
|
|
const DefaultMap defaultLogging {
|
|
{ "Channels", "0" },
|
|
{ "Privates", "0" },
|
|
{ "Path", "Path" }
|
|
};
|
|
|
|
/*
|
|
* These won't follow the ordinary style of parameter names,
|
|
* but rather the names of the various IRCv3 extensions.
|
|
*/
|
|
const DefaultMap defaultIRCv3 {
|
|
{ "account-notify", "1" },
|
|
{ "extended-join", "1" },
|
|
{ "away-notify", "1" },
|
|
{ "invite-notify", "1" },
|
|
{ "multi-prefix", "1" },
|
|
{ "userhost-in-names", "1" },
|
|
{ "message-tags", "1" },
|
|
{ "server-time", "1" }
|
|
};
|
|
|
|
const std::string& getDefault(const DefaultMap& map, const std::string& key)
|
|
{
|
|
static const std::string empty;
|
|
try {
|
|
return map.at(key);
|
|
}
|
|
catch (const std::out_of_range&) {
|
|
return empty;
|
|
}
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
ConfigMgr& ConfigMgr::instance()
|
|
{
|
|
static ConfigMgr inst;
|
|
return inst;
|
|
}
|
|
|
|
// Constructor is private, use static instance()
|
|
ConfigMgr::ConfigMgr()
|
|
: ini( QString(LOCAL_PATH+"/iirc.ini").toStdString() )
|
|
{}
|
|
|
|
void ConfigMgr::save()
|
|
{
|
|
ini.flush();
|
|
emit saved();
|
|
}
|
|
|
|
QString ConfigMgr::geometry(const QString& key) const
|
|
{
|
|
const auto keystdstr = key.toStdString();
|
|
const auto& defaultValue = getDefault(defaultGeometry, keystdstr);
|
|
return QString::fromStdString( ini.read("Geometry", keystdstr, defaultValue) );
|
|
}
|
|
|
|
QString ConfigMgr::connection(const QString& key) const
|
|
{
|
|
const auto keystdstr = key.toStdString();
|
|
const auto& defaultValue = getDefault(defaultConnection, keystdstr);
|
|
return QString::fromStdString( ini.read("Connection", keystdstr, defaultValue) );
|
|
}
|
|
|
|
QString ConfigMgr::common(const QString& key) const
|
|
{
|
|
const auto keystdstr = key.toStdString();
|
|
const auto& defaultValue = getDefault(defaultCommon, keystdstr);
|
|
return QString::fromStdString( ini.read("Common", keystdstr, defaultValue) );
|
|
}
|
|
|
|
QString ConfigMgr::color(const QString& key) const
|
|
{
|
|
const auto keystdstr = key.toStdString();
|
|
const auto& defaultValue = getDefault(defaultColor, keystdstr);
|
|
return QString::fromStdString( ini.read("Color", keystdstr, defaultValue) );
|
|
}
|
|
|
|
QString ConfigMgr::window(const QString& key) const
|
|
{
|
|
const auto keystdstr = key.toStdString();
|
|
const auto& defaultValue = getDefault(defaultColor, keystdstr);
|
|
return QString::fromStdString( ini.read("Window", keystdstr, defaultValue) );
|
|
}
|
|
|
|
std::optional<QColor> ConfigMgr::prefixColor(const QChar& prefix) const
|
|
{
|
|
const std::string key = std::to_string(prefix.toLatin1());
|
|
if (!ini.exist("PrefixColor", key))
|
|
return {};
|
|
|
|
const auto colorStr = QString::fromStdString( ini.read("PrefixColor", key) );
|
|
return QColor(colorStr);
|
|
}
|
|
|
|
QHash<QString, QString> ConfigMgr::color() const
|
|
{
|
|
QHash<QString, QString> ret;
|
|
const int sectSize = ini.count("Color");
|
|
for (int i = 0; i < sectSize; ++i) {
|
|
const auto key = QString::fromStdString( ini.item("Color", i) );
|
|
const auto val = QString::fromStdString( ini.read("Color", i) );
|
|
ret.insert(key, val);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
QVector<std::pair<QChar, QColor> > ConfigMgr::prefixColor() const
|
|
{
|
|
QVector<std::pair<QChar, QColor>> ret;
|
|
const int sectSize = ini.count("PrefixColor");
|
|
for (int i = 0; i < sectSize; ++i) {
|
|
const auto code = ini.item("PrefixColor", i);
|
|
const auto first = std::stoi(code);
|
|
const auto second = QString::fromStdString( ini.read("PrefixColor", i) );
|
|
ret.push_back( std::make_pair(first, second) );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
QString ConfigMgr::logging(const QString& key) const
|
|
{
|
|
const auto keystdstr = key.toStdString();
|
|
const auto& defaultValue = getDefault(defaultLogging, keystdstr);
|
|
return QString::fromStdString( ini.read("Logging", keystdstr, defaultValue) );
|
|
}
|
|
|
|
QStringList ConfigMgr::scripts() const
|
|
{
|
|
QStringList ret;
|
|
const int sectSize = ini.count("Scripts");
|
|
for (int i = 0; i < sectSize; ++i) {
|
|
const auto path = ini.read("Scripts", i);
|
|
ret.push_back( QString::fromStdString(path) );
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
QString ConfigMgr::IRCv3(const QString& key) const
|
|
{
|
|
const auto keystdstr = key.toStdString();
|
|
const auto& defaultValue = getDefault(defaultColor, keystdstr);
|
|
return QString::fromStdString( ini.read("IRCv3", keystdstr, defaultValue) );
|
|
}
|
|
|
|
|
|
void ConfigMgr::setGeometry(const QString& key, const QString& value)
|
|
{
|
|
ini.write("Geometry", key.toStdString(), value.toStdString());
|
|
}
|
|
|
|
void ConfigMgr::setConnection(const QString& key, const QString& value)
|
|
{
|
|
ini.write("Connection", key.toStdString(), value.toStdString());
|
|
}
|
|
|
|
void ConfigMgr::setCommon(const QString& key, const QString& value)
|
|
{
|
|
ini.write("Common", key.toStdString(), value.toStdString());
|
|
}
|
|
|
|
void ConfigMgr::setWindow(const QString& key, const QString& value)
|
|
{
|
|
ini.write("Window", key.toStdString(), value.toStdString());
|
|
}
|
|
|
|
void ConfigMgr::setLogging(const QString& key, const QString& value)
|
|
{
|
|
ini.write("Logging", key.toStdString(), value.toStdString());
|
|
}
|
|
|
|
void ConfigMgr::setColorPalette(const QHash<QString, QString>& palette)
|
|
{
|
|
QHashIterator<QString,QString> it(palette);
|
|
while (it.hasNext()) {
|
|
it.next();
|
|
const auto& key = it.key();
|
|
const auto& val = it.value();
|
|
ini.write("Color", key.toStdString(), val.toStdString());
|
|
}
|
|
}
|
|
|
|
void ConfigMgr::setPrefixColorPalette(const QVector<std::pair<QChar, QColor>>& palette)
|
|
{
|
|
for (const auto& item : palette) {
|
|
const auto key = std::to_string(item.first.toLatin1());
|
|
const auto val = item.second.name();
|
|
ini.write("PrefixColor", key, val.toStdString());
|
|
}
|
|
}
|
|
|
|
void ConfigMgr::addScript(const QString& path)
|
|
{
|
|
/*
|
|
* Scripts are stored to ini file with a number for key.
|
|
* Find the highest available number and use that.
|
|
*/
|
|
QStringList scripts;
|
|
const int sectSize = ini.count("Scripts");
|
|
for (int i = 0; i < sectSize; ++i) {
|
|
scripts << QString::fromStdString( ini.read("Scripts", i) );
|
|
}
|
|
scripts << path;
|
|
|
|
ini.remove("Scripts");
|
|
|
|
int n = 1;
|
|
for (const auto& script : scripts) {
|
|
ini.write("Scripts", std::to_string(n), script.toStdString());
|
|
++n;
|
|
}
|
|
}
|
|
|
|
void ConfigMgr::delScript(const QString& path)
|
|
{
|
|
std::string n;
|
|
const int sectSize = ini.count("Scripts");
|
|
for (int i = 0; i < sectSize; ++i) {
|
|
n = ini.item("Scripts", i);
|
|
if (ini.read("Scripts", i) == path.toStdString())
|
|
break;
|
|
}
|
|
|
|
if (!n.empty())
|
|
ini.remove("Scripts", n);
|
|
}
|
|
|
|
void ConfigMgr::setIRCv3(const QString& key, const QString& value)
|
|
{
|
|
ini.write("IRCv3", key.toStdString(), value.toStdString());
|
|
}
|
|
|