chatgui: per-event sound settings with DB persistence

- Sound files loaded from filesystem (sound_dir in INI config, absolute or relative)
- Per-event enable/disable + volume stored in DB (ui_state table)
- SoundManager: setEvent(), effective volume = master * per-event
- SoundSettingsPage UI: 4 event rows (checkbox + slider)
- chat_core_save_ui_state() for async DB writes via uasync thread
- DbManager::getUiStateInt() for reading settings from GUI thread
- Default sounds copied to sounds/ dir next to DB, config entries written
This commit is contained in:
Evgeny committed 2026-07-19 15:17:52 +03:00
1 parent 1593079da8
commit 98bfb9dcd2
12 files changed
+267 -114

No files matched your search

+49 -8
View File
@@ -21,6 +21,7 @@
#include <QSettings>
#include <QFile>
#include <QTextStream>
#include <QDir>
extern "C" {
#include "../transport/chat_core.h"
@@ -85,25 +86,65 @@ MainWindow::MainWindow(QWidget *parent, DbManager* db, const QString& cfgPath,
SoundManager* sm = SoundManager::instance();
if (sm->init()) {
QString soundDir;
QString msgInFile, msgOutFile, connectFile, disconnectFile;
QFile cfgFile(m_cfgPath);
if (cfgFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
bool inGui = false; bool enabled = true; int volume = 80;
bool inGui = false;
QTextStream in(&cfgFile);
while (!in.atEnd()) {
QString line = in.readLine().trimmed();
if (line == "[gui]") { inGui = true; continue; }
if (line.startsWith("[") && line.endsWith("]")) inGui = false;
if (!inGui) continue;
if (line.startsWith("sound_enabled="))
enabled = line.mid(15).trimmed() != "0";
else if (line.startsWith("sound_volume="))
volume = line.mid(13).trimmed().toInt();
if (line.startsWith("sound_dir="))
soundDir = line.mid(10).trimmed();
else if (line.startsWith("sound_msg_incoming="))
msgInFile = line.mid(19).trimmed();
else if (line.startsWith("sound_msg_outgoing="))
msgOutFile = line.mid(19).trimmed();
else if (line.startsWith("sound_connect="))
connectFile = line.mid(14).trimmed();
else if (line.startsWith("sound_disconnect="))
disconnectFile = line.mid(17).trimmed();
}
cfgFile.close();
sm->setEnabled(enabled);
sm->setVolume(volume / 100.0f);
}
sm->loadSound("msg_incoming", ":/sounds/msg_incoming.mp3");
if (soundDir.isEmpty()) soundDir = "sounds";
QDir binDir(QApplication::applicationDirPath());
QString baseDir = QDir::isAbsolutePath(soundDir) ? soundDir
: binDir.absoluteFilePath(soundDir);
auto resolvePath = [&baseDir](const QString& file) -> QString {
if (file.isEmpty()) return {};
return QDir::cleanPath(baseDir + "/" + file);
};
struct { const char* name; QString file; } events[] = {
{"msg_incoming", msgInFile},
{"msg_outgoing", msgOutFile},
{"connect", connectFile},
{"disconnect", disconnectFile},
};
for (auto& e : events) {
if (!e.file.isEmpty()) {
QString path = resolvePath(e.file);
sm->loadSound(e.name, path);
}
}
if (m_db && m_db->isOpen()) {
sm->setEnabled(m_db->getUiStateInt("sound_enabled", 1));
sm->setVolume(m_db->getUiStateInt("sound_volume", 80) / 100.0f);
QString soundEvents[] = {"msg_incoming", "msg_outgoing", "connect", "disconnect"};
for (int i = 0; i < 4; i++) {
const QString& ek = soundEvents[i];
bool on = m_db->getUiStateInt(QStringLiteral("sound_%1_on").arg(ek), i == 0 ? 1 : 0);
float ev = m_db->getUiStateInt(QStringLiteral("sound_%1_vol").arg(ek), 80) / 100.0f;
sm->setEvent(ek, on, ev);
}
}
}
if (m_db) {