Добавил привязку действий к событиям

за баллы канала и за донаты можено можно выполнять списки действий, за каждое событие свой набор
This commit is contained in:
2026-02-22 10:20:04 +03:00
parent eb494ae8fa
commit 5094834ea1
7 changed files with 371 additions and 5 deletions
+10
View File
@@ -37,6 +37,8 @@ bool ActionManager::deleteAction(int id)
{
if (!m_db) return false;
if (!m_db->deleteAction(id)) return false;
// Удаляем все связи с этим действием
m_db->deleteLinksByActionId(id);
for (int i = 0; i < m_actions.size(); ++i) {
if (m_actions[i].id == id) {
@@ -60,3 +62,11 @@ bool ActionManager::loadFromDatabase()
emit dataChanged();
return true;
}
ActionData ActionManager::getAction(int id) const
{
for (const ActionData &a : m_actions) {
if (a.id == id) return a;
}
return ActionData(); // с id = -1
}
+2
View File
@@ -15,6 +15,8 @@ public:
bool deleteAction(int id);
QList<ActionData> getAllActions() const;
bool loadFromDatabase();
ActionData getAction(int id) const;
signals:
void actionAdded(const ActionData &action);
+136
View File
@@ -1664,3 +1664,139 @@ QList<DonationTrigger> uDataBase::loadAllDonationTriggers()
}
return list;
}
bool uDataBase::saveEventActionLink(const QString &eventType, const QString &eventName, int actionId)
{
if (!m_db.isOpen()) {
m_lastError = "Database is not open";
return false;
}
QString et = eventType.trimmed();
QString en = eventName.trimmed();
// Создаём таблицу, если её нет
if (!tableExists("event_action_links")) {
QSqlQuery query(m_db);
QString sql = "CREATE TABLE IF NOT EXISTS event_action_links ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"event_type TEXT NOT NULL,"
"event_name TEXT NOT NULL,"
"action_id INTEGER NOT NULL,"
"created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP"
")";
if (!query.exec(sql)) {
m_lastError = query.lastError().text();
qWarning() << "Failed to create event_action_links table:" << m_lastError;
return false;
}
}
qDebug()<<"Я ТУТ НАХУЙ";
// Проверяем, нет ли уже такой связи
QSqlQuery checkQuery(m_db);
checkQuery.prepare("SELECT id FROM event_action_links WHERE event_type=:et AND event_name=:en AND action_id=:aid");
checkQuery.bindValue(":et", et);
checkQuery.bindValue(":en", en);
checkQuery.bindValue(":aid", actionId);
if (checkQuery.exec() && checkQuery.next()) {
m_lastError = "Такая связь уже существует";
return false;
}
QSqlQuery query(m_db);
query.prepare("INSERT INTO event_action_links (event_type, event_name, action_id) VALUES (:et, :en, :aid)");
query.bindValue(":et", eventType);
query.bindValue(":en", eventName);
query.bindValue(":aid", actionId);
if (!query.exec()) {
m_lastError = query.lastError().text();
qWarning() << "Failed to save event-action link:" << m_lastError;
return false;
}
return true;
}
bool uDataBase::deleteEventActionLink(int id)
{
if (!m_db.isOpen()) {
m_lastError = "Database is not open";
return false;
}
QSqlQuery query(m_db);
query.prepare("DELETE FROM event_action_links WHERE id = :id");
query.bindValue(":id", id);
if (!query.exec()) {
m_lastError = query.lastError().text();
qWarning() << "Failed to delete event-action link:" << m_lastError;
return false;
}
if (query.numRowsAffected() == 0) {
m_lastError = "Связь с указанным ID не найдена";
return false;
}
return true;
}
QList<EventActionLink> uDataBase::getLinksForEvent(const QString &eventType, const QString &eventName)
{
QList<EventActionLink> links;
if (!m_db.isOpen()) {
m_lastError = "Database is not open";
return links;
}
if (!tableExists("event_action_links")) {
return links;
}
QSqlQuery query(m_db);
query.prepare("SELECT id, event_type, event_name, action_id FROM event_action_links WHERE event_type=:et AND event_name=:en");
query.bindValue(":et", eventType);
query.bindValue(":en", eventName);
if (!query.exec()) {
m_lastError = query.lastError().text();
qWarning() << "Failed to get links for event:" << m_lastError;
return links;
}
while (query.next()) {
EventActionLink link;
link.id = query.value(0).toInt();
link.eventType = query.value(1).toString();
link.eventName = query.value(2).toString();
link.actionId = query.value(3).toInt();
links.append(link);
}
return links;
}
bool uDataBase::deleteLinksForEvent(const QString &eventType, const QString &eventName)
{
if (!m_db.isOpen()) {
m_lastError = "Database is not open";
return false;
}
QSqlQuery query(m_db);
query.prepare("DELETE FROM event_action_links WHERE event_type=:et AND event_name=:en");
query.bindValue(":et", eventType);
query.bindValue(":en", eventName);
if (!query.exec()) {
m_lastError = query.lastError().text();
qWarning() << "Failed to delete links for event:" << m_lastError;
return false;
}
return true;
}
bool uDataBase::deleteLinksByActionId(int actionId)
{
if (!m_db.isOpen()) {
m_lastError = "Database is not open";
return false;
}
QSqlQuery query(m_db);
query.prepare("DELETE FROM event_action_links WHERE action_id = :aid");
query.bindValue(":aid", actionId);
if (!query.exec()) {
m_lastError = query.lastError().text();
qWarning() << "Failed to delete links by action id:" << m_lastError;
return false;
}
return true;
}
+13
View File
@@ -68,6 +68,13 @@ struct ActionData {
QString notificationSound;
};
struct EventActionLink {
int id;
QString eventType;
QString eventName;
int actionId;
};
class uDataBase : public QObject
{
Q_OBJECT
@@ -142,6 +149,12 @@ public:
int saveDonationTrigger(const DonationTrigger &trigger);
bool deleteDonationTrigger(int id);
QList<DonationTrigger> loadAllDonationTriggers();
bool saveEventActionLink(const QString &eventType, const QString &eventName, int actionId);
bool deleteEventActionLink(int id);
QList<EventActionLink> getLinksForEvent(const QString &eventType, const QString &eventName);
bool deleteLinksForEvent(const QString &eventType, const QString &eventName);
bool deleteLinksByActionId(int actionId);
private:
+140 -1
View File
@@ -169,6 +169,11 @@ uGeneral::uGeneral(QWidget *parent)
m_createChatDialog = new FCreateChat(db, this);
initializeNotificationSounds();
// connect(ui->cbDonateList, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &uGeneral::on_cbDonateList_currentIndexChanged);
// connect(ui->btnLinksAdd, &QPushButton::clicked, this, &uGeneral::on_btnLinksAdd_clicked);
// connect(ui->btnLinksDel, &QPushButton::clicked, this, &uGeneral::on_btnLinksDel_clicked);
updateLinksList();
}
// ============================================================================
@@ -3294,6 +3299,7 @@ void uGeneral::on_btnCRGet_clicked()
ui->sbCRCost->setValue(0);
ui->btnCREdit->setEnabled(false);
ui->btnCRDelete->setEnabled(false);
updateDonateList();
}
@@ -3492,7 +3498,9 @@ void uGeneral::on_btnCRDelete_clicked()
QMessageBox::critical(this, "Ошибка", "Не удалось удалить награду. Проверьте подключение к Twitch и права токена.");
return;
}
db->deleteLinksForEvent("reward", title);
updateDonateList();
updateLinksList();
// 7. Уведомляем об успехе
QMessageBox::information(this, "Успех", "Награда успешно удалена.");
@@ -3721,6 +3729,7 @@ void uGeneral::updateActionsTable()
ui->sgActions->setItem(row, 0, typeItem);
ui->sgActions->setItem(row, 1, new QTableWidgetItem(paramStr));
}
updateActionsList();
}
void uGeneral::clearActionInputs()
@@ -3745,6 +3754,7 @@ void uGeneral::updateDonationTriggersTable()
// Сохраним id в UserRole первого столбца для удаления
ui->sgDotateTriggers->item(row, 0)->setData(Qt::UserRole, t.id);
}
updateDonateList();
}
void uGeneral::on_btnDonateAdd_clicked()
@@ -3773,11 +3783,17 @@ void uGeneral::on_btnDonateDel_clicked()
}
int id = ui->sgDotateTriggers->item(row, 0)->data(Qt::UserRole).toInt();
QString name = ui->sgDotateTriggers->item(row, 0)->text(); // ← добавляем эту строку
if (QMessageBox::question(this, "Подтверждение", "Удалить выбранный триггер?") == QMessageBox::Yes) {
m_donationManager->deleteTrigger(id);
db->deleteLinksForEvent("donation", name);
updateDonateList(); // обновляем список событий
updateLinksList(); // обновляем список связей для текущего события
}
}
void uGeneral::on_sgDotateTriggers_cellDoubleClicked(int row, int column)
{
Q_UNUSED(column);
@@ -3786,3 +3802,126 @@ void uGeneral::on_sgDotateTriggers_cellDoubleClicked(int row, int column)
ui->lineEdit->setText(name);
ui->lineEdit_2->setText(rule);
}
void uGeneral::updateDonateList()
{
ui->cbDonateList->clear();
// Награды
for (int row = 0; row < ui->sgCustomRewards->rowCount(); ++row) {
QString name = ui->sgCustomRewards->item(row, 0)->text();
QVariantMap data;
data["type"] = "reward";
data["name"] = name;
ui->cbDonateList->addItem("Награды: " + name, data);
}
// Триггеры донатов
for (int row = 0; row < ui->sgDotateTriggers->rowCount(); ++row) {
QString name = ui->sgDotateTriggers->item(row, 0)->text();
QVariantMap data;
data["type"] = "donation";
data["name"] = name;
ui->cbDonateList->addItem("Донаты: " + name, data);
}
}
void uGeneral::updateActionsList()
{
ui->cbActionsList->clear();
auto actions = m_actionManager->getAllActions(); // предполагается, что такой метод есть
for (const ActionData &a : actions) {
QString typeStr;
switch (a.type) {
case 0: typeStr = "Нажатие"; break;
case 1: typeStr = "Звук"; break;
case 2: typeStr = "Уведомление"; break;
default: typeStr = "Неизвестно";
}
QString param = (a.type == 0) ? a.keyCombination :
(a.type == 1) ? QFileInfo(a.audioFile).fileName() : a.notificationTitle;
ui->cbActionsList->addItem(typeStr + ": " + param, a.id);
}
}
void uGeneral::updateLinksList()
{
ui->lvLinks->clear();
int idx = ui->cbDonateList->currentIndex();
if (idx < 0) return;
QVariant data = ui->cbDonateList->itemData(idx);
if (!data.isValid()) return;
QVariantMap map = data.toMap();
QString eventType = map["type"].toString();
QString eventName = map["name"].toString();
QList<EventActionLink> links = db->getLinksForEvent(eventType, eventName);
for (const EventActionLink &link : links) {
ActionData action = m_actionManager->getAction(link.actionId);
if (action.id < 0) continue;
QString typeStr;
switch (action.type) {
case 0: typeStr = "Нажатие"; break;
case 1: typeStr = "Звук"; break;
case 2: typeStr = "Уведомление"; break;
}
QString param = (action.type == 0) ? action.keyCombination :
(action.type == 1) ? QFileInfo(action.audioFile).fileName() : action.notificationTitle;
QListWidgetItem *item = new QListWidgetItem(typeStr + ": " + param);
item->setData(Qt::UserRole, link.id); // храним ID связи для удаления
ui->lvLinks->addItem(item);
}
}
void uGeneral::on_cbDonateList_currentIndexChanged(int index)
{
Q_UNUSED(index);
updateLinksList();
}
void uGeneral::on_btnLinksAdd_clicked()
{
int eventIdx = ui->cbDonateList->currentIndex();
int actionIdx = ui->cbActionsList->currentIndex();
if (eventIdx < 0 || actionIdx < 0) {
QMessageBox::warning(this, "Ошибка", "Выберите событие и действие");
return;
}
QVariant eventData = ui->cbDonateList->itemData(eventIdx);
if (!eventData.isValid()) return;
QVariantMap map = eventData.toMap();
QString eventType = map["type"].toString();
QString eventName = map["name"].toString();
int actionId = ui->cbActionsList->itemData(actionIdx).toInt();
qDebug() << "НАЖАЛ КНОПКУ";
if (!db->saveEventActionLink(eventType, eventName, actionId)) {
QMessageBox::critical(this, "Ошибка", "Не удалось добавить связь:\n" + db->lastError());
} else {
updateLinksList();
}
}
void uGeneral::on_btnLinksDel_clicked()
{
int row = ui->lvLinks->currentRow();
if (row < 0) {
QMessageBox::warning(this, "Ошибка", "Выберите связь для удаления");
return;
}
QListWidgetItem *item = ui->lvLinks->item(row);
int linkId = item->data(Qt::UserRole).toInt();
if (QMessageBox::question(this, "Подтверждение", "Удалить выбранную связь?") == QMessageBox::Yes) {
if (!db->deleteEventActionLink(linkId)) {
QMessageBox::critical(this, "Ошибка", "Не удалось удалить связь:\n" + db->lastError());
} else {
updateLinksList(); // ← перезагружаем список
}
}
}
+9 -2
View File
@@ -387,6 +387,12 @@ private slots:
void on_sgDotateTriggers_cellDoubleClicked(int row, int column);
void updateDonationTriggersTable();
void on_cbDonateList_currentIndexChanged(int index);
void on_btnLinksAdd_clicked();
void on_btnLinksDel_clicked();
public slots:
// Установка статуса подключения к Twitch
void setTwitchConnected(bool connected);
@@ -530,8 +536,9 @@ private:
void sendChatResponse(const QString &response);
QString cleanMessageFromAllEmotes(const QString& message) const;
void updateDonateList();
void updateActionsList();
void updateLinksList();
};
#endif // UGENERAL_H
+61 -2
View File
@@ -1492,7 +1492,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_30">
<property name="topMargin">
<number>10</number>
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="btnDonateAdd">
@@ -1533,7 +1533,66 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_34">
<item>
<widget class="QTableWidget" name="tableWidget_2"/>
<layout class="QHBoxLayout" name="horizontalLayout_31">
<item>
<widget class="QLabel" name="label_38">
<property name="text">
<string>Событие:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbDonateList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QListWidget" name="lvLinks"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_32">
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_39">
<property name="text">
<string>Действие:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbActionsList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnLinksAdd">
<property name="text">
<string>Добавить</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnLinksDel">
<property name="text">
<string>Удалить</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>