Initial commit
This commit is contained in:
@@ -0,0 +1,491 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user