Keep rename dialog open until the core confirms its write

This commit is contained in:
evgeny committed 2026-10-28 00:58:59 +01:00
1 parent 096e721faa
commit be11fbb8b6
2 files changed
+51 -28

No files matched your search

+36 -22
View File
@@ -1,6 +1,8 @@
#include <QCoreApplication>
#include "renamedialog.h"
#include "../db/db_manager.h"
#include "../transport/member_edit.h"
#include "debug_config.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
@@ -19,18 +21,22 @@ RenameDialog::RenameDialog(DbManager* db, const QString& channelId,
setModal(true);
QString curNick;
if (m_db->m_db) {
bool loaded = false;
if (m_db && m_db->m_db) {
QString tbl = m_db->peersTableName(channelId);
QByteArray sql = QString(
"SELECT local_nick FROM \"%1\" WHERE node_id=?"
).arg(tbl).toUtf8();
sqlite3_stmt* st = nullptr;
if (sqlite3_prepare_v2(m_db->m_db, sql.constData(), -1, &st, nullptr) == SQLITE_OK) {
sqlite3_bind_int64(st, 1, (sqlite3_int64)nodeId);
if (sqlite3_step(st) == SQLITE_ROW)
curNick = DbManager::colText(st, 0);
sqlite3_finalize(st);
}
int rc = sqlite3_prepare_v2(m_db->m_db, sql.constData(), -1, &st, nullptr);
if (rc == SQLITE_OK) rc = sqlite3_bind_int64(st, 1, (sqlite3_int64)nodeId);
if (rc == SQLITE_OK) rc = sqlite3_step(st);
if (rc == SQLITE_ROW) curNick = DbManager::colText(st, 0);
int finish = sqlite3_finalize(st); loaded = rc == SQLITE_ROW && finish == SQLITE_OK;
if (!loaded) DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "rename: read ch=%s node=%016llx rc=%d finalize=%d: %s",
qPrintable(channelId), (unsigned long long)nodeId, rc, finish, sqlite3_errmsg(m_db->m_db));
} else {
DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "rename: database unavailable at open");
}
auto* layout = new QVBoxLayout(this);
@@ -45,6 +51,9 @@ RenameDialog::RenameDialog(DbManager* db, const QString& channelId,
m_edit->setText(curNick);
m_edit->setPlaceholderText(displayName);
layout->addWidget(m_edit);
m_errorLabel = new QLabel(this); m_errorLabel->setWordWrap(true);
if (!loaded) m_errorLabel->setText(QCoreApplication::translate("ChatGui", "Could not load member details."));
layout->addWidget(m_errorLabel);
layout->addStretch();
@@ -61,6 +70,7 @@ RenameDialog::RenameDialog(DbManager* db, const QString& channelId,
btnLayout->addWidget(cancelBtn);
auto* saveBtn = new QPushButton(QCoreApplication::translate("ChatGui", "Save"), this);
m_saveBtn = saveBtn;
saveBtn->setMinimumWidth(90);
saveBtn->setDefault(true);
saveBtn->setStyleSheet(
@@ -72,22 +82,26 @@ RenameDialog::RenameDialog(DbManager* db, const QString& channelId,
btnLayout->addWidget(saveBtn);
layout->addLayout(btnLayout);
connect(this, &QDialog::finished, this, [this] {
delete m_saveContext; m_saveContext = nullptr;
m_edit->setEnabled(true); m_saveBtn->setEnabled(true);
});
}
/* Результат адресован context запроса; после закрытия/удаления формы мост его не вызовет. */
void RenameDialog::finishSave(int result) {
delete m_saveContext; m_saveContext = nullptr;
m_edit->setEnabled(true); m_saveBtn->setEnabled(true);
if (!result) { accept(); return; }
m_errorLabel->setText(QCoreApplication::translate("ChatGui", "Could not save member changes. Please try again."));
DEBUG_WARN(DEBUG_CATEGORY_CHAT_SYNC, "rename: save refused ch=%s node=%016llx result=%d",
qPrintable(m_channelId), (unsigned long long)m_nodeId, result);
}
void RenameDialog::onSave() {
if (!m_db->m_db) return;
QString tbl = m_db->peersTableName(m_channelId);
QString nick = m_edit->text().trimmed();
QByteArray sql = QString(
"UPDATE \"%1\" SET local_nick=? WHERE node_id=?"
).arg(tbl).toUtf8();
sqlite3_stmt* st = nullptr;
if (sqlite3_prepare_v2(m_db->m_db, sql.constData(), -1, &st, nullptr) == SQLITE_OK) {
sqlite3_bind_text(st, 1, nick.isEmpty() ? nullptr : nick.toUtf8().constData(),
-1, nick.isEmpty() ? SQLITE_STATIC : SQLITE_TRANSIENT);
sqlite3_bind_int64(st, 2, (sqlite3_int64)m_nodeId);
sqlite3_step(st);
sqlite3_finalize(st);
}
accept();
if (m_saveContext) return;
m_errorLabel->clear(); m_edit->setEnabled(false); m_saveBtn->setEnabled(false);
m_saveContext = new QObject(this);
if (!gui_bridge_save_member(m_db ? m_db->m_db : nullptr, m_channelId, m_nodeId, m_edit->text().trimmed(), {},
m_saveContext, [this](int result) { finishSave(result); })) finishSave(-1);
}
+15 -6
View File
@@ -1,25 +1,34 @@
/* Локальное переименование участника: сохраняет local_nick в таблице peers канала для этого UI. */
/* Локальный псевдоним участника: GUI только читает SQLite, запись подтверждает поток ядра.
* Отказ сохраняет форму и введённый текст; закрытие формы снимает callback, но не отменяет принятую запись. */
#pragma once
#include <QDialog>
#include <QLineEdit>
#include <QString>
#include <QPointer>
class DbManager;
class QLabel;
class QPushButton;
class RenameDialog : public QDialog {
Q_OBJECT
public:
/* db заимствован через QPointer; channelId/nodeId выбирают строку, displayName — заголовок/подсказка, parent владеет диалогом. */
explicit RenameDialog(DbManager* db, const QString& channelId,
quint64 nodeId, const QString& displayName,
QWidget* parent = nullptr);
private slots:
void onSave();
void onSave(); // Передать собственный снимок ника в uasync; повтор до результата игнорируется.
private:
DbManager* m_db;
QString m_channelId;
quint64 m_nodeId;
QLineEdit* m_edit;
void finishSave(int result); // GUI: 0 закрывает с Accepted, отказ возвращает редактирование и показывает ошибку.
QPointer<DbManager> m_db; // Заимствованная read-only проекция, может исчезнуть во время запроса.
QString m_channelId; // Собственный снимок канала.
quint64 m_nodeId; // Узел участника.
QLineEdit* m_edit; // Локальный черновик; пробелы по краям удаляются при сохранении.
QLabel* m_errorLabel; // Ошибка чтения/сохранения без технических подробностей.
QPushButton* m_saveBtn; // Отключена до результата.
QObject* m_saveContext = nullptr; // Собственный context одного запроса; удаляется при результате/закрытии.
};