#include "soundsettingspage.h" #include "sound_manager.h" #include "../db/db_manager.h" #include "../transport/gui_bridge.h" #include "../../lib/mem.h" extern "C" { #include "../transport/chat_core.h" } #include #include #include #include #include #include #include SoundSettingsPage::SoundSettingsPage(DbManager* db, QWidget* parent) : QWidget(parent) , m_db(db) { auto* layout = new QVBoxLayout(this); layout->setContentsMargins(0, 12, 0, 0); layout->setSpacing(14); m_enabledCheck = new QCheckBox("Enable sounds", this); m_enabledCheck->setStyleSheet("font-size: 13px;"); layout->addWidget(m_enabledCheck); auto* volLayout = new QHBoxLayout(); auto* volLabel = new QLabel("Volume:", this); volLabel->setStyleSheet("font-size: 13px;"); volLayout->addWidget(volLabel); m_volumeSlider = new QSlider(Qt::Horizontal, this); m_volumeSlider->setRange(0, 100); m_volumeSlider->setFixedWidth(200); m_volumeSlider->setStyleSheet( "QSlider::groove:horizontal { height: 6px; border-radius: 3px; background: palette(mid); }" "QSlider::handle:horizontal { width: 14px; height: 14px; margin: -4px 0; border-radius: 7px; background: #3390EC; }"); volLayout->addWidget(m_volumeSlider); m_volumeLabel = new QLabel("80%", this); m_volumeLabel->setFixedWidth(36); m_volumeLabel->setStyleSheet("font-size: 13px;"); volLayout->addWidget(m_volumeLabel); volLayout->addStretch(); layout->addLayout(volLayout); auto* sep = new QFrame(this); sep->setFrameShape(QFrame::HLine); sep->setStyleSheet("QFrame { color: palette(mid); }"); layout->addWidget(sep); auto* header = new QLabel("Events", this); header->setStyleSheet("font-size: 13px; font-weight: bold;"); layout->addWidget(header); m_events[0] = {"msg_incoming", "Incoming message", nullptr, nullptr, nullptr}; m_events[1] = {"msg_outgoing", "Outgoing message", nullptr, nullptr, nullptr}; m_events[2] = {"connect", "Peer connected", nullptr, nullptr, nullptr}; m_events[3] = {"disconnect", "Peer disconnected", nullptr, nullptr, nullptr}; for (int i = 0; i < 4; i++) { auto& e = m_events[i]; auto* row = new QHBoxLayout(); row->setSpacing(8); auto* lbl = new QLabel(e.label, this); lbl->setFixedWidth(140); lbl->setStyleSheet("font-size: 13px;"); row->addWidget(lbl); e.check = new QCheckBox(this); row->addWidget(e.check); e.slider = new QSlider(Qt::Horizontal, this); e.slider->setRange(0, 100); e.slider->setFixedWidth(100); e.slider->setStyleSheet( "QSlider::groove:horizontal { height: 4px; border-radius: 2px; background: palette(mid); }" "QSlider::handle:horizontal { width: 10px; height: 10px; margin: -3px 0; border-radius: 5px; background: #3390EC; }"); row->addWidget(e.slider); e.volLabel = new QLabel("80%", this); e.volLabel->setFixedWidth(30); e.volLabel->setStyleSheet("font-size: 12px;"); row->addWidget(e.volLabel); row->addStretch(); layout->addLayout(row); connect(e.slider, &QSlider::valueChanged, this, [this, i](int val) { m_events[i].volLabel->setText(QString::number(val) + "%"); }); } layout->addStretch(); connect(m_enabledCheck, &QCheckBox::stateChanged, this, [this](int state) { bool on = (state == Qt::Checked); m_volumeSlider->setEnabled(on); m_volumeLabel->setEnabled(on); }); connect(m_volumeSlider, &QSlider::valueChanged, this, [this](int val) { m_volumeLabel->setText(QString::number(val) + "%"); }); } void SoundSettingsPage::loadFromDb() { if (!m_db) return; bool enabled = m_db->getUiStateInt("sound_enabled", 1); m_enabledCheck->setChecked(enabled); int vol = m_db->getUiStateInt("sound_volume", 80); m_volumeSlider->setValue(vol); m_volumeSlider->setEnabled(enabled); m_volumeLabel->setEnabled(enabled); m_volumeLabel->setText(QString::number(vol) + "%"); for (int i = 0; i < 4; i++) { auto& e = m_events[i]; QString onKey = QStringLiteral("sound_%1_on").arg(e.key); QString volKey = QStringLiteral("sound_%1_vol").arg(e.key); bool on = m_db->getUiStateInt(onKey, i == 0 ? 1 : 0); // only msg_incoming on by default int ev = m_db->getUiStateInt(volKey, 80); e.check->setChecked(on); e.slider->setValue(ev); e.volLabel->setText(QString::number(ev) + "%"); } } void SoundSettingsPage::applyAndSave() { SoundManager* sm = SoundManager::instance(); bool enabled = m_enabledCheck->isChecked(); float masterVol = m_volumeSlider->value() / 100.0f; sm->setEnabled(enabled); sm->setVolume(masterVol); for (int i = 0; i < 4; i++) { auto& e = m_events[i]; bool on = e.check->isChecked(); float ev = e.slider->value() / 100.0f; sm->setEvent(e.key, on, ev); /* async DB persist — key\0value\0 */ QString onKey = QStringLiteral("sound_%1_on").arg(e.key); QString volKey = QStringLiteral("sound_%1_vol").arg(e.key); QByteArray onVal = on ? QByteArray("1") : QByteArray("0"); QByteArray volVal = QByteArray::number(e.slider->value()); for (int j = 0; j < 2; j++) { const char* k = j == 0 ? onKey.toUtf8().constData() : volKey.toUtf8().constData(); const char* v = j == 0 ? onVal.constData() : volVal.constData(); size_t klen = strlen(k), vlen = strlen(v); size_t total = klen + 1 + vlen + 1; if (total > 256) continue; void* arg = u_malloc(total); memcpy(arg, k, klen + 1); memcpy((char*)arg + klen + 1, v, vlen + 1); gui_bridge_post_uasync_fn(chat_core_save_ui_state_trampoline, arg); } } /* save global settings */ { const char* keys[] = {"sound_enabled", "sound_volume"}; QByteArray vals[] = {enabled ? QByteArray("1") : QByteArray("0"), QByteArray::number(m_volumeSlider->value())}; for (int j = 0; j < 2; j++) { size_t klen = strlen(keys[j]), vlen = vals[j].size(); size_t total = klen + 1 + vlen + 1; if (total > 256) continue; void* arg = u_malloc(total); memcpy(arg, keys[j], klen + 1); memcpy((char*)arg + klen + 1, vals[j].constData(), vlen + 1); gui_bridge_post_uasync_fn(chat_core_save_ui_state_trampoline, arg); } } }