#include "udatabase.h" #include #include #include #include #include "qlistwidget.h" #include "webserverchat.h" uDataBase::uDataBase(const QString& dbFileName, QObject* parent) : QObject(parent) , m_dbFileName(dbFileName) { // Создаем уникальное имя подключения QString connectionName = QString("settings_connection_%1").arg((quintptr)this); // Открываем базу данных m_db = QSqlDatabase::addDatabase("QSQLITE", connectionName); m_db.setDatabaseName(m_dbFileName); if (!m_db.open()) { m_lastError = m_db.lastError().text(); qWarning() << "Failed to open database:" << m_lastError; return; } // Инициализируем базу данных if (!initializeDatabase()) { qWarning() << "Failed to initialize database"; } } uDataBase::~uDataBase() { if (m_db.isOpen()) { QString connectionName = m_db.connectionName(); m_db.close(); m_db = QSqlDatabase(); // сбрасываем объект базы данных QSqlDatabase::removeDatabase(connectionName); // удаляем соединение } } bool uDataBase::close() { if (!isConnected()) { return true; // Уже закрыто } // Сохраняем имя соединения перед закрытием QString connectionName = m_db.connectionName(); // Закрываем базу данных m_db.close(); // Очищаем объект базы данных m_db = QSqlDatabase(); // Удаляем соединение из пула Qt QSqlDatabase::removeDatabase(connectionName); return true; } bool uDataBase::initializeDatabase() { // Создаем таблицу настроек, если она не существует QString createTableQuery = "CREATE TABLE IF NOT EXISTS params (" "name TEXT PRIMARY KEY," "value TEXT" ")"; QSqlQuery query(m_db); if (!query.exec(createTableQuery)) { m_lastError = query.lastError().text(); qWarning() << "Failed to create table:" << m_lastError; return false; } // Создаем таблицу для чатов if (!createChatsTable()) { qWarning() << "Failed to create chats table"; // Продолжаем, даже если не удалось создать таблицу чатов } return true; } QString uDataBase::readSetting(const QString& aName, const QString& aDefault) { if (!m_db.isOpen()) { qWarning() << "Database is not open"; return aDefault; } QSqlQuery query(m_db); query.prepare("SELECT value FROM params WHERE name = :name"); query.bindValue(":name", aName); if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Failed to read setting" << aName << ":" << m_lastError; return aDefault; } if (query.next()) { return query.value(0).toString(); } // Если настройка не найдена, возвращаем значение по умолчанию return aDefault; } bool uDataBase::writeSetting(const QString& aName, const QString& aValue) { if (!m_db.isOpen()) { qWarning() << "Database is not open"; return false; } // Используем INSERT OR REPLACE для обновления существующей записи или создания новой QSqlQuery query(m_db); query.prepare( "INSERT OR REPLACE INTO params (name, value) " "VALUES (:name, :value)" ); query.bindValue(":name", aName); query.bindValue(":value", aValue); if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Failed to write setting" << aName << ":" << m_lastError; return false; } return true; } // В классе uDataBase добавьте эти методы: /** * @brief Специальная загрузка для таблицы таймеров с сохранением состояния * @param tableWidget Таблица для загрузки * @param timers Список таймеров для заполнения * @return true если успешно */ bool uDataBase::LoadTimers(QTableWidget *tableWidget, QList &timers) { if (!tableWidget) { m_lastError = "Table widget is null"; qWarning() << m_lastError; return false; } // Получаем имя таблицы из objectName виджета QString tableName = tableWidget->objectName(); if (tableName.isEmpty()) { m_lastError = "Table widget has no object name"; qWarning() << m_lastError; return false; } // Проверяем соединение с БД if (!m_db.isOpen()) { m_lastError = "Database is not open"; qWarning() << m_lastError; return false; } // Очищаем таблицу и список таймеров tableWidget->setRowCount(0); timers.clear(); // Выполняем SQL запрос QSqlQuery query(m_db); QString sql = QString("SELECT * FROM %1 ORDER BY id").arg(tableName); if (!query.exec(sql)) { m_lastError = query.lastError().text(); qWarning() << "Query failed:" << m_lastError; qWarning() << "SQL:" << sql; return false; } int rowCount = 0; while (query.next()) { // Создаем объект таймера TimerInfo timer; timer.id = query.value("id").toInt(); timer.message = query.value("message").toString(); timer.interval = query.value("interval").toInt(); timer.isActive = query.value("is_active").toBool(); timer.isAnnouncement = query.value("is_announcement").toBool(); timer.timer = nullptr; // Добавляем в список timers.append(timer); // Добавляем строку в таблицу int row = tableWidget->rowCount(); tableWidget->insertRow(row); // Чекбокс "Вкл" QTableWidgetItem* enabledItem = new QTableWidgetItem(); enabledItem->setCheckState(timer.isActive ? Qt::Checked : Qt::Unchecked); tableWidget->setItem(row, 0, enabledItem); // Сообщение QTableWidgetItem* messageItem = new QTableWidgetItem(timer.message); tableWidget->setItem(row, 1, messageItem); // Интервал QTableWidgetItem* intervalItem = new QTableWidgetItem(QString::number(timer.interval)); tableWidget->setItem(row, 2, intervalItem); // Чекбокс "О" QTableWidgetItem* announcementItem = new QTableWidgetItem(); announcementItem->setCheckState(timer.isAnnouncement ? Qt::Checked : Qt::Unchecked); tableWidget->setItem(row, 3, announcementItem); rowCount++; } return true; } /** * @brief Специальное сохранение для таблицы таймеров * @param tableWidget Таблица для сохранения * @param timers Список таймеров * @return true если успешно */ bool uDataBase::SaveTimers(QTableWidget *tableWidget, const QList &timers) { if (!tableWidget) { m_lastError = "Table widget is null"; qWarning() << m_lastError; return false; } // Получаем имя таблицы из objectName виджета QString tableName = tableWidget->objectName(); if (tableName.isEmpty()) { m_lastError = "Table widget has no object name"; qWarning() << m_lastError; return false; } // Проверяем соединение с БД if (!m_db.isOpen()) { m_lastError = "Database is not open"; qWarning() << m_lastError; return false; } // Создаем таблицу если не существует QString createTableQuery = QString( "CREATE TABLE IF NOT EXISTS %1 (" "id INTEGER PRIMARY KEY AUTOINCREMENT," "message TEXT NOT NULL," "interval INTEGER NOT NULL," "is_active BOOLEAN DEFAULT 1," "is_announcement BOOLEAN DEFAULT 0" ")" ).arg(tableName); QSqlQuery createQuery(m_db); if (!createQuery.exec(createTableQuery)) { m_lastError = createQuery.lastError().text(); qWarning() << "Failed to create table:" << m_lastError; return false; } // Начинаем транзакцию if (!m_db.transaction()) { m_lastError = m_db.lastError().text(); qWarning() << "Failed to start transaction:" << m_lastError; return false; } // Очищаем таблицу QSqlQuery clearQuery(m_db); QString clearSql = QString("DELETE FROM %1").arg(tableName); if (!clearQuery.exec(clearSql)) { m_lastError = clearQuery.lastError().text(); qWarning() << "Failed to clear table:" << m_lastError; m_db.rollback(); return false; } // Сохраняем таймеры QSqlQuery insertQuery(m_db); insertQuery.prepare(QString( "INSERT INTO %1 (message, interval, is_active, is_announcement) " "VALUES (:message, :interval, :is_active, :is_announcement)" ).arg(tableName)); int savedRows = 0; for (const TimerInfo &timer : timers) { insertQuery.bindValue(":message", timer.message); insertQuery.bindValue(":interval", timer.interval); insertQuery.bindValue(":is_active", timer.isActive); insertQuery.bindValue(":is_announcement", timer.isAnnouncement); if (!insertQuery.exec()) { m_lastError = insertQuery.lastError().text(); qWarning() << "Failed to insert timer:" << m_lastError; m_db.rollback(); return false; } savedRows++; } // Завершаем транзакцию if (!m_db.commit()) { m_lastError = m_db.lastError().text(); qWarning() << "Failed to commit transaction:" << m_lastError; m_db.rollback(); return false; } qDebug() << "Saved" << savedRows << "timers to database"; return true; } bool uDataBase::LoadTableWidget(QTableWidget *tableWidget) { if (!tableWidget) { m_lastError = "Table widget is null"; qWarning() << m_lastError; return false; } // Получаем имя таблицы из objectName виджета QString tableName = tableWidget->objectName(); if (tableName.isEmpty()) { m_lastError = "Table widget has no object name"; qWarning() << m_lastError; return false; } // Проверяем соединение с БД if (!m_db.isOpen()) { m_lastError = "Database is not open"; qWarning() << m_lastError; return false; } // Очищаем таблицу (но сохраняем заголовки) tableWidget->setRowCount(0); // Выполняем SQL запрос QSqlQuery query(m_db); QString sql = QString("SELECT * FROM %1 ORDER BY id").arg(tableName); if (!query.exec(sql)) { m_lastError = query.lastError().text(); qWarning() << "Query failed:" << m_lastError; qWarning() << "SQL:" << sql; return false; } // Получаем информацию о колонках в результате запроса QSqlRecord record = query.record(); int dbColumnCount = record.count(); // Определяем сколько колонок нам нужно в QTableWidget int widgetColumnCount = tableWidget->columnCount(); int columnsToLoad = qMin(dbColumnCount - 1, widgetColumnCount); // -1 потому что пропускаем id int rowCount = 0; while (query.next()) { // Добавляем новую строку int row = tableWidget->rowCount(); tableWidget->insertRow(row); // Заполняем ячейки (начиная с col0, пропускаем id) for (int col = 0; col < columnsToLoad; col++) { QString columnName = QString("col%1").arg(col); QVariant value = query.value(columnName); QTableWidgetItem *item = new QTableWidgetItem(); if (value.isNull()) { item->setText(""); } else { item->setText(value.toString()); } // Устанавливаем выравнивание по умолчанию item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); tableWidget->setItem(row, col, item); } rowCount++; } return true; } bool uDataBase::SaveTableWidget(QTableWidget *tableWidget) { if (!tableWidget) { m_lastError = "Table widget is null"; qWarning() << m_lastError; return false; } // Получаем имя таблицы из objectName виджета QString tableName = tableWidget->objectName(); if (tableName.isEmpty()) { m_lastError = "Table widget has no object name"; qWarning() << m_lastError; return false; } // Проверяем соединение с БД if (!m_db.isOpen()) { m_lastError = "Database is not open"; qWarning() << m_lastError; return false; } // Проверяем существует ли таблица if (!tableExists(tableName)) { // Создаем таблицу с нужным количеством колонок if (!createTableForWidget(tableName, tableWidget->columnCount())) { return false; } } else { // Очищаем существующую таблицу if (!clearTable(tableName)) { return false; } } // Сохраняем данные из таблицы QSqlQuery query(m_db); // Начинаем транзакцию для быстрой вставки if (!m_db.transaction()) { m_lastError = m_db.lastError().text(); qWarning() << "Failed to start transaction:" << m_lastError; return false; } int rowCount = tableWidget->rowCount(); int colCount = tableWidget->columnCount(); if (colCount == 0) { m_lastError = "Table widget has no columns"; qWarning() << m_lastError; m_db.rollback(); return false; } // Подготавливаем SQL запрос для вставки QStringList columnNames; QStringList valuePlaceholders; // Добавляем id (автоинкремент) columnNames << "id"; valuePlaceholders << "NULL"; // Добавляем col0, col1, col2 и т.д. for (int col = 0; col < colCount; col++) { columnNames << QString("col%1").arg(col); valuePlaceholders << QString(":col%1").arg(col); } QString sql = QString("INSERT INTO %1 (%2) VALUES (%3)") .arg(tableName) .arg(columnNames.join(", ")) .arg(valuePlaceholders.join(", ")); query.prepare(sql); int savedRows = 0; for (int row = 0; row < rowCount; row++) { // Пропускаем пустые строки (если все ячейки пустые) bool isEmptyRow = true; for (int col = 0; col < colCount; col++) { QTableWidgetItem *item = tableWidget->item(row, col); if (item && !item->text().trimmed().isEmpty()) { isEmptyRow = false; break; } } if (isEmptyRow) { continue; // Пропускаем полностью пустые строки } // Биндим значения для каждой колонки for (int col = 0; col < colCount; col++) { QString paramName = QString(":col%1").arg(col); QTableWidgetItem *item = tableWidget->item(row, col); if (item && !item->text().isEmpty()) { query.bindValue(paramName, item->text()); } else { query.bindValue(paramName, QVariant(QVariant::String)); } } if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Failed to insert row:" << m_lastError; qWarning() << "SQL:" << sql; m_db.rollback(); return false; } savedRows++; } // Завершаем транзакцию if (!m_db.commit()) { m_lastError = m_db.lastError().text(); qWarning() << "Failed to commit transaction:" << m_lastError; m_db.rollback(); return false; } return true; } // Вспомогательные методы bool uDataBase::tableExists(const QString &tableName) { QSqlQuery query(m_db); QString sql = QString("SELECT name FROM sqlite_master WHERE type='table' AND name='%1'") .arg(tableName); if (query.exec(sql) && query.next()) { return true; } return false; } bool uDataBase::createTableForWidget(const QString &tableName, int columnCount) { if (columnCount <= 0) { m_lastError = "Invalid column count"; return false; } QSqlQuery query(m_db); // Создаем SQL для создания таблицы QStringList columns; columns << "id INTEGER PRIMARY KEY AUTOINCREMENT"; for (int i = 0; i < columnCount; i++) { columns << QString("col%1 TEXT").arg(i); } QString sql = QString("CREATE TABLE %1 (%2)").arg(tableName).arg(columns.join(", ")); if (!query.exec(sql)) { m_lastError = query.lastError().text(); qWarning() << "Failed to create table:" << m_lastError; qWarning() << "SQL:" << sql; return false; } return true; } bool uDataBase::clearTable(const QString &tableName) { QSqlQuery query(m_db); QString sql = QString("DELETE FROM %1").arg(tableName); if (!query.exec(sql)) { m_lastError = query.lastError().text(); qWarning() << "Failed to clear table:" << m_lastError; return false; } // Сбрасываем автоинкремент sql = QString("DELETE FROM sqlite_sequence WHERE name='%1'").arg(tableName); query.exec(sql); // Игнорируем ошибки, т.к. может не быть sqlite_sequence return true; } bool uDataBase::LoadRandomGroups(QListWidget *listWidget) { if (!listWidget) { m_lastError = "List widget is null"; qWarning() << m_lastError; return false; } listWidget->clear(); m_lastError.clear(); // Проверяем соединение с БД if (!m_db.isOpen()) { m_lastError = "Database is not open"; qWarning() << m_lastError; return false; } // Проверяем существование таблицы if (!tableExists("GroupResponse")) { qWarning() << "Table GroupResponse doesn't exist"; // Можно создать таблицу автоматически if (!createGroupResponseTable()) { return false; } } // Выполняем SQL запрос для получения уникальных имен QSqlQuery query(m_db); QString sql = "SELECT DISTINCT Name FROM GroupResponse ORDER BY Name"; if (!query.exec(sql)) { m_lastError = query.lastError().text(); qWarning() << "Query failed:" << m_lastError; qWarning() << "SQL:" << sql; return false; } int count = 0; while (query.next()) { QString groupName = query.value(0).toString(); if (!groupName.isEmpty()) { listWidget->addItem(groupName); count++; } } return true; } // Метод для загрузки ответов конкретной группы bool uDataBase::LoadRandomResponses(const QString &groupName, QListWidget *listWidget) { if (!listWidget) { m_lastError = "List widget is null"; qWarning() << m_lastError; return false; } if (groupName.isEmpty()) { m_lastError = "Group name is empty"; qWarning() << m_lastError; return false; } listWidget->clear(); m_lastError.clear(); // Проверяем соединение с БД if (!m_db.isOpen()) { m_lastError = "Database is not open"; qWarning() << m_lastError; return false; } // Проверяем существование таблицы if (!tableExists("GroupResponse")) { m_lastError = "Table GroupResponse doesn't exist"; qWarning() << m_lastError; return false; } // Выполняем SQL запрос для получения ответов группы QSqlQuery query(m_db); query.prepare("SELECT Response FROM GroupResponse WHERE Name = :name ORDER BY id"); query.bindValue(":name", groupName); if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Query failed:" << m_lastError; return false; } int count = 0; while (query.next()) { QString response = query.value(0).toString(); listWidget->addItem(response); count++; } return true; } // Метод для получения случайного ответа из группы QString uDataBase::GetRandomResponse(const QString &groupName) { if (groupName.isEmpty()) { qWarning() << "Group name is empty"; return QString(); } if (!m_db.isOpen()) { qWarning() << "Database is not open"; return QString(); } if (!tableExists("GroupResponse")) { qWarning() << "Table GroupResponse doesn't exist"; return QString(); } QSqlQuery query(m_db); query.prepare("SELECT Response FROM GroupResponse WHERE Name = :name ORDER BY RANDOM() LIMIT 1"); query.bindValue(":name", groupName); if (!query.exec()) { qWarning() << "Query failed for group:" << groupName << "Error:" << query.lastError().text(); return QString(); } if (!query.next()) { qWarning() << "No responses found for group:" << groupName; return QString(); } return query.value(0).toString(); } // Метод для обработки текста с заменой {{grN}} QString uDataBase::ProcessResponseTemplate(const QString &templateText) { QRegularExpression re("\\{\\{(.+?)\\}\\}"); QRegularExpressionMatchIterator i = re.globalMatch(templateText); QString result = templateText; while (i.hasNext()) { QRegularExpressionMatch match = i.next(); QString fullMatch = match.captured(0); // {{ANY_GROUP_NAME}} QString groupName = match.captured(1).trimmed(); // ANY_GROUP_NAME if (groupName.isEmpty()) { continue; // Пропускаем пустые имена групп } QString replacement = GetRandomResponse(groupName); if (replacement.isEmpty()) { qWarning() << "No response found for group:" << groupName; // Можно оставить оригинальный текст или заменить на что-то другое replacement = QString("[Группа '%1' не найдена]").arg(groupName); } result.replace(fullMatch, replacement); } return result; } // Методы для добавления/удаления групп и ответов bool uDataBase::AddGroupResponse(const QString &groupName, const QString &response) { if (groupName.isEmpty() || response.isEmpty()) { m_lastError = "Group name or response is empty"; return false; } if (!m_db.isOpen()) { m_lastError = "Database is not open"; return false; } // Создаем таблицу если она не существует if (!tableExists("GroupResponse")) { if (!createGroupResponseTable()) { return false; } } QSqlQuery query(m_db); query.prepare("INSERT INTO GroupResponse (Name, Response) VALUES (:name, :response)"); query.bindValue(":name", groupName); query.bindValue(":response", response); if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Failed to add response:" << m_lastError; return false; } return true; } bool uDataBase::DeleteGroup(const QString &groupName) { if (groupName.isEmpty()) { m_lastError = "Group name is empty"; return false; } if (!m_db.isOpen()) { m_lastError = "Database is not open"; return false; } QSqlQuery query(m_db); query.prepare("DELETE FROM GroupResponse WHERE Name = :name"); query.bindValue(":name", groupName); if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Failed to delete group:" << m_lastError; return false; } return true; } bool uDataBase::DeleteResponse(const QString &groupName, const QString &ResponseName) { if (groupName.isEmpty()) { m_lastError = "Group name is empty"; return false; } if (!m_db.isOpen()) { m_lastError = "Database is not open"; return false; } // Получаем ID ответа по индексу в группе QSqlQuery query(m_db); // Удаляем ответ по ID query.prepare("DELETE FROM GroupResponse WHERE Name = :name and Response = :response"); query.bindValue(":name", groupName); query.bindValue(":response", ResponseName); if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Failed to delete response:" << m_lastError; return false; } return true; } // Вспомогательные методы bool uDataBase::createGroupResponseTable() { QSqlQuery query(m_db); QString sql = "CREATE TABLE IF NOT EXISTS GroupResponse (" " id INTEGER PRIMARY KEY AUTOINCREMENT," " Name TEXT NOT NULL," " Response TEXT NOT NULL" ")"; if (!query.exec(sql)) { m_lastError = query.lastError().text(); qWarning() << "Failed to create GroupResponse table:" << m_lastError; return false; } // Создаем индекс для быстрого поиска по имени группы sql = "CREATE INDEX IF NOT EXISTS idx_groupresponse_name ON GroupResponse (Name)"; query.exec(sql); // Игнорируем ошибки, если индекс уже существует return true; } // Метод для сохранения списка ответов группы (заменяет все существующие) bool uDataBase::SaveGroupResponses(const QString &groupName, const QStringList &responses) { if (groupName.isEmpty()) { m_lastError = "Group name is empty"; return false; } if (!m_db.isOpen()) { m_lastError = "Database is not open"; return false; } // Начинаем транзакцию if (!m_db.transaction()) { m_lastError = m_db.lastError().text(); return false; } // Удаляем старые ответы группы QSqlQuery query(m_db); query.prepare("DELETE FROM GroupResponse WHERE Name = :name"); query.bindValue(":name", groupName); if (!query.exec()) { m_lastError = query.lastError().text(); m_db.rollback(); return false; } // Добавляем новые ответы query.prepare("INSERT INTO GroupResponse (Name, Response) VALUES (:name, :response)"); foreach (const QString &response, responses) { if (!response.trimmed().isEmpty()) { query.bindValue(":name", groupName); query.bindValue(":response", response); if (!query.exec()) { m_lastError = query.lastError().text(); m_db.rollback(); return false; } } } if (!m_db.commit()) { m_lastError = m_db.lastError().text(); m_db.rollback(); return false; } return true; } bool uDataBase::isConnected() const { return m_db.isOpen(); } QString uDataBase::lastError() const { return m_lastError; } /** * @brief Создает таблицу для хранения настроек чатов */ bool uDataBase::createChatsTable() { QSqlQuery query(m_db); QString sql = "CREATE TABLE IF NOT EXISTS chats (" " id INTEGER PRIMARY KEY AUTOINCREMENT," " name TEXT NOT NULL," " type TEXT NOT NULL," // "chat" или "notification" " port INTEGER NOT NULL," " font_list TEXT," " background_color TEXT," " block_color TEXT," " border_color TEXT," " border_size INTEGER," " padding INTEGER," " transparency INTEGER," " font_family TEXT," " font_size INTEGER," " font_color TEXT," " freez BOOLEAN," " message_timeout INTEGER," " max_msg_count INTEGER," " delete_by_time BOOLEAN," " created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP" ")"; if (!query.exec(sql)) { m_lastError = query.lastError().text(); qWarning() << "Failed to create chats table:" << m_lastError; return false; } // Создаем индекс для быстрого поиска по порту sql = "CREATE INDEX IF NOT EXISTS idx_chats_port ON chats (port)"; query.exec(sql); return true; } /** * @brief Сохраняет настройки чата в базу данных */ bool uDataBase::saveChat(const QString &name, const QString &type, HttpServerChat *server, const QString &fontList) { if (!server) { m_lastError = "Server is null"; return false; } if (!m_db.isOpen()) { m_lastError = "Database is not open"; return false; } // Создаем таблицу если не существует if (!tableExists("chats")) { if (!createChatsTable()) { return false; } } QSqlQuery query(m_db); query.prepare( "INSERT OR REPLACE INTO chats (" " name, type, port, font_list, background_color, " " block_color, border_color, border_size, padding, " " transparency, font_family, font_size, font_color, " " freez, message_timeout, max_msg_count, delete_by_time" ") VALUES (" " :name, :type, :port, :font_list, :background_color, " " :block_color, :border_color, :border_size, :padding, " " :transparency, :font_family, :font_size, :font_color, " " :freez, :message_timeout, :max_msg_count, :delete_by_time" ")" ); query.bindValue(":name", name); query.bindValue(":type", type); query.bindValue(":port", server->port()); query.bindValue(":font_list", fontList); query.bindValue(":background_color", server->getBackgroundColor()); query.bindValue(":block_color", server->getBlockColor()); query.bindValue(":border_color", server->getBorderColor()); query.bindValue(":border_size", server->getBorderSize()); query.bindValue(":padding", server->getPadding()); query.bindValue(":transparency", server->getTransparency()); query.bindValue(":font_family", server->getFontFamily()); query.bindValue(":font_size", server->getFontSize()); query.bindValue(":font_color", server->getFontColor()); query.bindValue(":freez", server->isFreez()); query.bindValue(":message_timeout", server->getMessageTimeout()); query.bindValue(":max_msg_count", server->getMaxMsgCount()); query.bindValue(":delete_by_time", !server->isFreez()); // delete_by_time = !freez if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Failed to save chat:" << m_lastError; return false; } return true; } /** * @brief Загружает все сохраненные чаты из базы данных */ QList uDataBase::loadAllChats() { QList chats; if (!m_db.isOpen()) { m_lastError = "Database is not open"; return chats; } if (!tableExists("chats")) { // Если таблицы нет, ничего не загружаем return chats; } QSqlQuery query(m_db); QString sql = "SELECT * FROM chats ORDER BY created_at"; if (!query.exec(sql)) { m_lastError = query.lastError().text(); qWarning() << "Failed to load chats:" << m_lastError; return chats; } while (query.next()) { ChatSettings settings; settings.id = query.value("id").toInt(); settings.name = query.value("name").toString(); settings.type = query.value("type").toString(); settings.port = query.value("port").toInt(); settings.fontList = query.value("font_list").toString().split(',', Qt::SkipEmptyParts); settings.backgroundColor = query.value("background_color").toString(); settings.blockColor = query.value("block_color").toString(); settings.borderColor = query.value("border_color").toString(); settings.borderSize = query.value("border_size").toInt(); settings.padding = query.value("padding").toInt(); settings.transparency = query.value("transparency").toInt(); settings.fontFamily = query.value("font_family").toString(); settings.fontSize = query.value("font_size").toInt(); settings.fontColor = query.value("font_color").toString(); settings.freez = query.value("freez").toBool(); settings.messageTimeout = query.value("message_timeout").toInt(); settings.maxMsgCount = query.value("max_msg_count").toInt(); settings.deleteByTime = query.value("delete_by_time").toBool(); chats.append(settings); } return chats; } /** * @brief Удаляет чат из базы данных по порту */ bool uDataBase::deleteChat(int port) { if (!m_db.isOpen()) { m_lastError = "Database is not open"; return false; } QSqlQuery query(m_db); query.prepare("DELETE FROM chats WHERE port = :port"); query.bindValue(":port", port); if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Failed to delete chat:" << m_lastError; return false; } return true; } /** * @brief Обновляет настройки существующего чата */ bool uDataBase::updateChat(const QString &name, HttpServerChat *server, const QString &fontList, int oldPort) { if (!server) { m_lastError = "Server is null"; return false; } if (!m_db.isOpen()) { m_lastError = "Database is not open"; return false; } QSqlQuery query(m_db); query.prepare( "UPDATE chats SET " " name = :name, " " port = :port, " " font_list = :font_list, " " background_color = :background_color, " " block_color = :block_color, " " border_color = :border_color, " " border_size = :border_size, " " padding = :padding, " " transparency = :transparency, " " font_family = :font_family, " " font_size = :font_size, " " font_color = :font_color, " " freez = :freez, " " message_timeout = :message_timeout, " " max_msg_count = :max_msg_count, " " delete_by_time = :delete_by_time " "WHERE port = :old_port" ); query.bindValue(":name", name); query.bindValue(":port", server->port()); query.bindValue(":font_list", fontList); query.bindValue(":background_color", server->getBackgroundColor()); query.bindValue(":block_color", server->getBlockColor()); query.bindValue(":border_color", server->getBorderColor()); query.bindValue(":border_size", server->getBorderSize()); query.bindValue(":padding", server->getPadding()); query.bindValue(":transparency", server->getTransparency()); query.bindValue(":font_family", server->getFontFamily()); query.bindValue(":font_size", server->getFontSize()); query.bindValue(":font_color", server->getFontColor()); query.bindValue(":freez", server->isFreez()); query.bindValue(":message_timeout", server->getMessageTimeout()); query.bindValue(":max_msg_count", server->getMaxMsgCount()); query.bindValue(":delete_by_time", !server->isFreez()); query.bindValue(":old_port", oldPort); if (!query.exec()) { m_lastError = query.lastError().text(); qWarning() << "Failed to update chat:" << m_lastError; return false; } return true; }