Files
cinema-ticket-management-sy…/ui/widgets/entity_updater_widget.cpp
T
2026-07-12 14:34:52 +04:00

492 lines
16 KiB
C++

#include "entity_updater_widget.h"
#include "genres_repository_interface.h"
#include "halls_repository_interface.h"
#include "movies_repository_interface.h"
#include "refunds_repository_interface.h"
#include "sessions_repository_interface.h"
#include "tickets_repository_interface.h"
#include "update_genre_request.h"
#include "update_hall_request.h"
#include "update_movie_request.h"
#include "update_refund_request.h"
#include "update_session_request.h"
#include "update_ticket_request.h"
#include "error_dialog.h"
#include "model_manager.h"
#include "base_sql_table_model.h"
#include <QMessageBox>
#include <qsqlrelationaltablemodel.h>
namespace DatabaseTableNames {
static constexpr char Genres[] = "genres";
static constexpr char Halls[] = "halls";
static constexpr char Movies[] = "movies";
static constexpr char Refunds[] = "refunds";
static constexpr char Sessions[] = "sessions";
static constexpr char Tickets[] = "tickets";
} // namespace DatabaseTableNames
EntityUpdaterWidget::EntityUpdaterWidget(QWidget *parent)
: QWidget(parent), primaryKey_(-1) {
setupUi(this);
setupConnections();
setupComboBoxCurrentTable(); // After setup connections
setupParentEntityFinderWidget();
setupChildEntityFinderWidget();
}
void EntityUpdaterWidget::setupComboBoxCurrentTable() {
SchemaMetadata metadata = SchemaMetadata::defaultSchema();
QList<QString> databaseTableNames = {
DatabaseTableNames::Genres, DatabaseTableNames::Halls,
DatabaseTableNames::Movies, DatabaseTableNames::Refunds,
DatabaseTableNames::Sessions, DatabaseTableNames::Tickets};
for (const QString &tableName : databaseTableNames) {
comboBoxCurrentTable->addItem(metadata.translatedTableName(tableName),
tableName);
}
}
void EntityUpdaterWidget::setupConnections() {
connect(foreignKeyFinder, &EntityFinderWidget::fieldRetrieved, this,
&EntityUpdaterWidget::onForeignFieldRetrieved);
connect(primaryKeyFinder, &EntityFinderWidget::fieldRetrieved, this,
&EntityUpdaterWidget::onPrimaryFieldRetrieved);
connect(primaryKeyFinder, &EntityFinderWidget::recordRetrieved, this,
&EntityUpdaterWidget::onPrimaryEntityRetrieved);
connect(comboBoxCurrentTable, &QComboBox::currentIndexChanged, this,
&EntityUpdaterWidget::onTableSelected);
connect(comboBoxCurrentColumn, &QComboBox::currentIndexChanged, this,
&EntityUpdaterWidget::onColumnSelected);
connect(pushButtonUpdate, &QPushButton::clicked, this,
&EntityUpdaterWidget::onPushButtonUpdateClicked);
}
void EntityUpdaterWidget::setupChildEntityFinderWidget() {
foreignKeyFinder->setLabelText(
EntityFinderWidget::tr("Select entity for replacement"));
foreignKeyFinder->setLineEditPlaceholder(
EntityFinderWidget::tr("Here will be information about selected entity"));
foreignKeyFinder->setHiddenFrame(true);
}
void EntityUpdaterWidget::setupParentEntityFinderWidget() {
primaryKeyFinder->setLabelText(
EntityFinderWidget::tr("Select entity for updating"));
primaryKeyFinder->setLineEditPlaceholder(
EntityFinderWidget::tr("Here will be information about selected entry"));
}
void EntityUpdaterWidget::configureForeignKeyFinder(
const QString &columnName, const QString &databaseTableName) {
TableInfoSQLite tableInfo(databaseTableName);
if (tableInfo.isPrimaryKey(columnName)) {
// NOTE: Change Primary Key is prohibited
// configurePrimaryKeyFinder(databaseTableName);
return;
}
QString foreignKeyDatabaseTableName = tableInfo.foreignKeyTable(columnName);
if (foreignKeyDatabaseTableName.isEmpty()) {
qCritical()
<< "Could not find the database table name for the key column, which "
"contains \"_id\":"
<< columnName;
return;
}
configureForeignKeyFinder(foreignKeyDatabaseTableName);
}
void EntityUpdaterWidget::configureForeignKeyFinder(
const QString &databaseTableName) {
foreignKeyFinder->resetToDefault();
foreignKeyFinder->setDefaultRelation(databaseTableName);
}
void EntityUpdaterWidget::configurePrimaryKeyFinder(
const QString &databaseTableName) {
primaryKeyFinder->resetToDefault();
primaryKeyFinder->setDefaultRelation(databaseTableName);
}
void EntityUpdaterWidget::onPrimaryFieldRetrieved(const QSqlField &field) {
qInfo() << "Selected primary field: Name:" << field.name()
<< "Value:" << field.value();
primaryKey_ = field.value().toInt();
}
void EntityUpdaterWidget::onForeignFieldRetrieved(const QSqlField &field) {
qInfo() << "Selected foreign field: Name:" << field.name()
<< "Value:" << field.value();
selectedForeignField_ = field;
}
void EntityUpdaterWidget::onPrimaryEntityRetrieved(const QSqlRecord &entity) {
qInfo() << "Retrieved foreign entity:" << entity;
selectedPrimaryEntity_ = entity;
}
template <>
QString EntityUpdaterWidget::actualColumnValue(const QString &columnName) {
QString value = isColumnsEqual(columnName)
? lineEdit->text()
: selectedPrimaryEntity_.value(columnName).toString();
qInfo() << "Actual column QString value:" << value;
return value;
}
template <>
QDateTime EntityUpdaterWidget::actualColumnValue(const QString &columnName) {
QDateTime value = isColumnsEqual(columnName)
? dateTimeEdit->dateTime()
: selectedPrimaryEntity_.value(columnName).toDateTime();
qInfo() << "Actual column QDateTime value:" << value;
return value;
}
template <>
int EntityUpdaterWidget::actualColumnValue(const QString &columnName) {
int value = isColumnsEqual(columnName)
? spinBox->value()
: selectedPrimaryEntity_.value(columnName).toInt();
qInfo() << "Actual column int value:" << value;
return value;
}
template <>
double EntityUpdaterWidget::actualColumnValue(const QString &columnName) {
double value = isColumnsEqual(columnName)
? doubleSpinBox->value()
: selectedPrimaryEntity_.value(columnName).toDouble();
qInfo() << "Actual column double value:" << value;
return value;
}
qint32 EntityUpdaterWidget::actualForeignKey(const QString &columnName) {
qint32 value = isColumnsEqual(columnName)
? selectedForeignField_.value().toInt()
: selectedPrimaryEntity_.value(columnName).toInt();
qInfo() << "Actual foreign key:" << value;
return value;
}
template <>
RepositoryResult
EntityUpdaterWidget::updateEntity<GenresRepositoryInterface>() {
UpdateGenreRequest request;
request.setGenreId(primaryKey_);
request.setGenreName(actualColumnValue<QString>("genre_name"));
return currentRepository<GenresRepositoryInterface>()->updateGenre(request);
}
template <>
RepositoryResult EntityUpdaterWidget::updateEntity<HallsRepositoryInterface>() {
UpdateHallRequest request;
request.setHallId(primaryKey_);
request.setCapacity(actualColumnValue<int>("capacity"));
request.setHallName(actualColumnValue<QString>("hall_name"));
return currentRepository<HallsRepositoryInterface>()->updateHall(request);
}
template <>
RepositoryResult
EntityUpdaterWidget::updateEntity<MoviesRepositoryInterface>() {
UpdateMovieRequest request;
request.setMovieId(primaryKey_);
request.setDuration(actualColumnValue<int>("duration"));
request.setGenreId(actualForeignKey("genre_id"));
request.setTitle(actualColumnValue<QString>("title"));
return currentRepository<MoviesRepositoryInterface>()->updateMovie(request);
}
template <>
RepositoryResult
EntityUpdaterWidget::updateEntity<RefundsRepositoryInterface>() {
UpdateRefundRequest request;
request.setRefundId(primaryKey_);
request.setRefundAmount(actualColumnValue<double>("refund_amount"));
request.setRefundAt(actualColumnValue<QDateTime>("refund_at"));
request.setTicketId(actualForeignKey("ticket_id"));
return currentRepository<RefundsRepositoryInterface>()->updateRefund(request);
}
template <>
RepositoryResult
EntityUpdaterWidget::updateEntity<SessionsRepositoryInterface>() {
UpdateSessionRequest request;
request.setSessionId(primaryKey_);
request.setHallId(actualForeignKey("hall_id"));
request.setMovieId(actualForeignKey("movie_id"));
request.setBeginAt(actualColumnValue<QDateTime>("begin_at"));
request.setTicketPrice(actualColumnValue<double>("ticket_price"));
return currentRepository<SessionsRepositoryInterface>()->updateSession(
request);
}
template <>
RepositoryResult
EntityUpdaterWidget::updateEntity<TicketsRepositoryInterface>() {
UpdateTicketRequest request;
request.setTicketId(primaryKey_);
request.setSeatNumber(actualColumnValue<int>("seat_number"));
request.setSessionId(actualForeignKey("session_id"));
request.setSoldAt(actualColumnValue<QDateTime>("sold_at"));
return currentRepository<TicketsRepositoryInterface>()->updateTicket(request);
}
template <>
void EntityUpdaterWidget::processEntityUpdate<DatabaseTableNames::Genres>(
RepositoryResult &resultOut) {
resultOut = updateEntity<GenresRepositoryInterface>();
if (!resultOut.success) {
ErrorDialog::displayError(this, resultOut.errorMessage);
return;
}
showMessageDialog(resultOut,
EntityUpdaterWidget::tr("Genre updated successfully"));
}
template <>
void EntityUpdaterWidget::processEntityUpdate<DatabaseTableNames::Halls>(
RepositoryResult &resultOut) {
resultOut = updateEntity<HallsRepositoryInterface>();
if (!resultOut.success) {
ErrorDialog::displayError(this, resultOut.errorMessage);
return;
}
showMessageDialog(resultOut,
EntityUpdaterWidget::tr("Hall updated successfully"));
}
template <>
void EntityUpdaterWidget::processEntityUpdate<DatabaseTableNames::Movies>(
RepositoryResult &resultOut) {
resultOut = updateEntity<MoviesRepositoryInterface>();
if (!resultOut.success) {
ErrorDialog::displayError(this, resultOut.errorMessage);
return;
}
showMessageDialog(resultOut,
EntityUpdaterWidget::tr("Movie updated successfully"));
}
template <>
void EntityUpdaterWidget::processEntityUpdate<DatabaseTableNames::Refunds>(
RepositoryResult &resultOut) {
resultOut = updateEntity<RefundsRepositoryInterface>();
if (!resultOut.success) {
ErrorDialog::displayError(this, resultOut.errorMessage);
return;
}
showMessageDialog(resultOut,
EntityUpdaterWidget::tr("Refund updated successfully"));
}
template <>
void EntityUpdaterWidget::processEntityUpdate<DatabaseTableNames::Sessions>(
RepositoryResult &resultOut) {
resultOut = updateEntity<SessionsRepositoryInterface>();
if (!resultOut.success) {
ErrorDialog::displayError(this, resultOut.errorMessage);
return;
}
showMessageDialog(resultOut,
EntityUpdaterWidget::tr("Session updated successfully"));
}
template <>
void EntityUpdaterWidget::processEntityUpdate<DatabaseTableNames::Tickets>(
RepositoryResult &resultOut) {
resultOut = updateEntity<TicketsRepositoryInterface>();
if (!resultOut.success) {
ErrorDialog::displayError(this, resultOut.errorMessage);
return;
}
showMessageDialog(resultOut,
EntityUpdaterWidget::tr("Ticket updated successfully"));
}
void EntityUpdaterWidget::onPushButtonUpdateClicked() {
const QString &databaseTableName =
comboBoxCurrentTable->currentData().toString();
RepositoryResult result;
if (databaseTableName == DatabaseTableNames::Genres) {
processEntityUpdate<DatabaseTableNames::Genres>(result);
} else if (databaseTableName == DatabaseTableNames::Halls) {
processEntityUpdate<DatabaseTableNames::Halls>(result);
} else if (databaseTableName == DatabaseTableNames::Movies) {
processEntityUpdate<DatabaseTableNames::Movies>(result);
} else if (databaseTableName == DatabaseTableNames::Refunds) {
processEntityUpdate<DatabaseTableNames::Refunds>(result);
} else if (databaseTableName == DatabaseTableNames::Sessions) {
processEntityUpdate<DatabaseTableNames::Sessions>(result);
} else if (databaseTableName == DatabaseTableNames::Tickets) {
processEntityUpdate<DatabaseTableNames::Tickets>(result);
} else {
qFatal() << "EntityDeleterWidget::onPressPushButtonDeleteEntity: "
"Unknown database table name:"
<< databaseTableName;
}
processUpdateResult(result);
}
void EntityUpdaterWidget::onTableSelected(int tableIndex) {
SchemaMetadata metadata = SchemaMetadata::defaultSchema();
const QString &databaseTableName =
comboBoxCurrentTable->itemData(tableIndex).toString();
ModelManager &modelManager = ModelManager::instance();
BaseSqlTableModel *model = modelManager.getModelAs<BaseSqlTableModel>(
metadata.modelTableName(databaseTableName));
comboBoxCurrentColumn->clear();
for (const auto &columnName : model->columnNames()) {
if (metadata.primaryIdColumnName(databaseTableName) == columnName) {
// NOTE: Change Primary Key is prohibited
continue;
}
int headerIndex = model->columnIndex(columnName);
QString displayName =
model->headerData(headerIndex, Qt::Horizontal).toString();
comboBoxCurrentColumn->addItem(displayName, columnName);
}
configurePrimaryKeyFinder(databaseTableName);
}
void EntityUpdaterWidget::onColumnSelected(int columnIndex) {
Q_UNUSED(columnIndex);
const QString &databaseTableName =
comboBoxCurrentTable->currentData().toString();
TableInfoSQLite tableInfoSQLite(databaseTableName);
QString columnName = comboBoxCurrentColumn->currentData().toString();
bool isKey = columnName.contains("_id", Qt::CaseInsensitive);
QWidget *page;
switch (tableInfoSQLite.columnMetaType(columnName)) {
case QMetaType::Int: {
page =
findChild<QWidget *>(isKey ? "pageChildFinderWidget" : "pageSpinBox");
} break;
case QMetaType::Double:
page = findChild<QWidget *>("pageDoubleSpinBox");
break;
case QMetaType::QString:
page = findChild<QWidget *>("pageLineEdit");
break;
case QMetaType::QDateTime:
page = findChild<QWidget *>("pageDateTimeEdit");
break;
default:
qCritical() << "Unknown column selected";
return;
}
stackedWidget->setCurrentWidget(page);
if (isKey) {
configureForeignKeyFinder(columnName, databaseTableName);
}
}
QModelIndex EntityUpdaterWidget::findIndexByColumn(QAbstractItemModel *model,
int column,
const QVariant &value) {
if (!model || column < 0 || column >= model->columnCount())
return QModelIndex();
for (int row = 0; row < model->rowCount(); ++row) {
QModelIndex index = model->index(row, column);
if (model->data(index) == value) {
return index;
}
}
return QModelIndex();
}
bool EntityUpdaterWidget::isColumnsEqual(const QString &other) {
TableInfoSQLite tableInfo(comboBoxCurrentTable->currentData().toString());
QString current = comboBoxCurrentColumn->currentData().toString();
bool isEqual = tableInfo.columnIndex(current) == tableInfo.columnIndex(other);
const static QString billet("Column \"%1\" and column \"%2\": %3");
qInfo().noquote() << billet.arg(current).arg(other).arg(
isEqual ? "Equal" : "Not equal");
return isEqual;
};
void EntityUpdaterWidget::processUpdateResult(const RepositoryResult &result) {
if (!result.success) {
return;
}
const QString &databaseTableName =
comboBoxCurrentTable->currentData().toString();
SchemaMetadata metadata = SchemaMetadata::defaultSchema();
ModelManager &modelManager = ModelManager::instance();
QSqlTableModel *model =
modelManager.getModel(metadata.modelTableName(databaseTableName));
QString primaryKeyColumnName =
metadata.primaryIdColumnName(databaseTableName);
int columnIndex = selectedPrimaryEntity_.indexOf(primaryKeyColumnName);
QModelIndex rowIndex = findIndexByColumn(model, columnIndex, primaryKey_);
selectedPrimaryEntity_ = model->record(rowIndex.row());
primaryKeyFinder->refreshLineEditText(selectedPrimaryEntity_);
foreignKeyFinder->resetToDefault();
}
void EntityUpdaterWidget::showMessageDialog(const RepositoryResult &result,
const QString &successMessage) {
if (!result.success) {
ErrorDialog::displayError(this, result.errorMessage);
} else {
QMessageBox::information(this, QMessageBox::tr("Success"), successMessage);
}
}