Files
TTW_Bot/udatabase.cpp
T
2026-02-07 08:28:56 +03:00

1404 lines
44 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "udatabase.h"
#include <QMetaProperty>
#include <QSqlRecord>
#include <QDateTime>
#include <QTableWidget>
#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<TimerInfo> &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<TimerInfo> &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<ChatSettings> uDataBase::loadAllChats()
{
QList<ChatSettings> 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;
}
bool uDataBase::createNotificationsTable()
{
QSqlQuery query(m_db);
QString sql =
"CREATE TABLE IF NOT EXISTS notifications ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" name TEXT NOT NULL,"
" type TEXT NOT NULL," // "notification"
" port INTEGER NOT NULL,"
" block_color TEXT,"
" border_color TEXT,"
" border_size INTEGER,"
" transparency INTEGER,"
" page_background_color TEXT,"
" title_family TEXT,"
" title_size INTEGER,"
" title_color TEXT,"
" content_family TEXT,"
" content_size INTEGER,"
" content_color TEXT,"
" duration INTEGER,"
" created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
")";
if (!query.exec(sql)) {
m_lastError = query.lastError().text();
qWarning() << "Failed to create notifications table:" << m_lastError;
return false;
}
// Создаем индекс для быстрого поиска по порту
sql = "CREATE INDEX IF NOT EXISTS idx_notifications_port ON notifications (port)";
query.exec(sql);
return true;
}
bool uDataBase::saveNotification(const QString &name, HttpServer *server)
{
if (!server) {
m_lastError = "Server is null";
return false;
}
if (!m_db.isOpen()) {
m_lastError = "Database is not open";
return false;
}
// Создаем таблицу если не существует
if (!tableExists("notifications")) {
if (!createNotificationsTable()) {
return false;
}
}
QSqlQuery query(m_db);
query.prepare(
"INSERT INTO notifications ("
" name, type, port, block_color, border_color, border_size,"
" transparency, page_background_color, title_family, title_size,"
" title_color, content_family, content_size, content_color, duration"
") VALUES ("
" :name, :type, :port, :block_color, :border_color, :border_size,"
" :transparency, :page_background_color, :title_family, :title_size,"
" :title_color, :content_family, :content_size, :content_color, :duration"
")"
);
// Используем реальные значения из сервера
query.bindValue(":name", name);
query.bindValue(":type", "notification");
query.bindValue(":port", server->port());
query.bindValue(":block_color", server->getBlockColor());
query.bindValue(":border_color", server->getBorderColor());
query.bindValue(":border_size", server->getBorderSize());
query.bindValue(":transparency", server->getTransparency());
query.bindValue(":page_background_color", server->getPageBackgroundColor());
query.bindValue(":title_family", server->getTitleFamily());
query.bindValue(":title_size", server->getTitleSize());
query.bindValue(":title_color", server->getTitleColor());
query.bindValue(":content_family", server->getContentFamily());
query.bindValue(":content_size", server->getContentSize());
query.bindValue(":content_color", server->getContentColor());
query.bindValue(":duration", server->getDuration());
if (!query.exec()) {
m_lastError = query.lastError().text();
qWarning() << "Failed to save notification:" << m_lastError;
return false;
}
return true;
}
bool uDataBase::updateNotification(const QString &name, HttpServer *server, 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 notifications SET "
" name = :name, "
" port = :port, "
" block_color = :block_color, "
" border_color = :border_color, "
" border_size = :border_size, "
" transparency = :transparency, "
" page_background_color = :page_background_color, "
" title_family = :title_family, "
" title_size = :title_size, "
" title_color = :title_color, "
" content_family = :content_family, "
" content_size = :content_size, "
" content_color = :content_color, "
" duration = :duration "
"WHERE port = :old_port"
);
query.bindValue(":name", name);
query.bindValue(":port", server->port());
query.bindValue(":block_color", server->getBlockColor());
query.bindValue(":border_color", server->getBorderColor());
query.bindValue(":border_size", server->getBorderSize());
query.bindValue(":transparency", server->getTransparency());
query.bindValue(":page_background_color", server->getPageBackgroundColor());
query.bindValue(":title_family", server->getTitleFamily());
query.bindValue(":title_size", server->getTitleSize());
query.bindValue(":title_color", server->getTitleColor());
query.bindValue(":content_family", server->getContentFamily());
query.bindValue(":content_size", server->getContentSize());
query.bindValue(":content_color", server->getContentColor());
query.bindValue(":duration", server->getDuration());
query.bindValue(":old_port", oldPort);
if (!query.exec()) {
m_lastError = query.lastError().text();
qWarning() << "Failed to update notification:" << m_lastError;
return false;
}
return true;
}
QList<NotificationSettings> uDataBase::loadAllNotifications()
{
QList<NotificationSettings> notifications;
if (!m_db.isOpen()) {
m_lastError = "Database is not open";
return notifications;
}
if (!tableExists("notifications")) {
// Если таблицы нет, ничего не загружаем
return notifications;
}
QSqlQuery query(m_db);
QString sql = "SELECT * FROM notifications ORDER BY created_at";
if (!query.exec(sql)) {
m_lastError = query.lastError().text();
qWarning() << "Failed to load notifications:" << m_lastError;
return notifications;
}
while (query.next()) {
NotificationSettings 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.blockColor = query.value("block_color").toString();
settings.borderColor = query.value("border_color").toString();
settings.borderSize = query.value("border_size").toInt();
settings.transparency = query.value("transparency").toInt();
settings.pageBackgroundColor = query.value("page_background_color").toString();
settings.titleFamily = query.value("title_family").toString();
settings.titleSize = query.value("title_size").toInt();
settings.titleColor = query.value("title_color").toString();
settings.contentFamily = query.value("content_family").toString();
settings.contentSize = query.value("content_size").toInt();
settings.contentColor = query.value("content_color").toString();
settings.duration = query.value("duration").toInt();
settings.createdAt = query.value("created_at").toDateTime();
notifications.append(settings);
}
return notifications;
}
bool uDataBase::deleteNotification(int port)
{
if (!m_db.isOpen()) {
m_lastError = "Database is not open";
return false;
}
QSqlQuery query(m_db);
query.prepare("DELETE FROM notifications WHERE port = :port");
query.bindValue(":port", port);
if (!query.exec()) {
m_lastError = query.lastError().text();
qWarning() << "Failed to delete notification:" << m_lastError;
return false;
}
return true;
}