diff --git a/source/d1formats/d1trn.cpp b/source/d1formats/d1trn.cpp index 2aa0d6594..301c92341 100644 --- a/source/d1formats/d1trn.cpp +++ b/source/d1formats/d1trn.cpp @@ -1,13 +1,13 @@ #include "d1trn.h" D1Trn::D1Trn(D1Pal *pal) - : palette(QPointer(pal)) + : palette(pal) { } bool D1Trn::load(QString filePath) { - if (this->palette.isNull()) + if (this->palette == nullptr) return false; QFile file = QFile(filePath); @@ -73,6 +73,16 @@ QString D1Trn::getFilePath() return this->trnFilePath; } +QString D1Trn::getDefaultPath() const +{ + return IDENTITY_PATH; +} + +QString D1Trn::getDefaultName() const +{ + return IDENTITY_NAME; +} + quint8 D1Trn::getTranslation(quint8 index) { return this->translations[index]; diff --git a/source/d1formats/d1trn.h b/source/d1formats/d1trn.h index e5783bc0f..0da144164 100644 --- a/source/d1formats/d1trn.h +++ b/source/d1formats/d1trn.h @@ -6,7 +6,7 @@ #define D1TRN_TRANSLATIONS 256 -class D1Trn : public QObject { +class D1Trn final : public D1Pal { Q_OBJECT public: @@ -17,15 +17,19 @@ class D1Trn : public QObject { D1Trn(D1Pal *pal); ~D1Trn() = default; - bool load(QString); - bool save(QString); + bool load(QString filepath) override; + bool save(QString filepath) override; - bool isModified() const; + [[nodiscard]] bool isModified() const override; void refreshResultingPalette(); QColor getResultingColor(quint8); - QString getFilePath(); + QString getFilePath() override; + + [[nodiscard]] QString getDefaultPath() const override; + [[nodiscard]] QString getDefaultName() const override; + quint8 getTranslation(quint8); void setTranslation(quint8, quint8); void setPalette(D1Pal *pal); @@ -35,6 +39,6 @@ class D1Trn : public QObject { QString trnFilePath; bool modified; quint8 translations[D1TRN_TRANSLATIONS]; - QPointer palette; + D1Pal *palette = nullptr; D1Pal resultingPalette; }; diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index e1c1de0a5..0dc13f94f 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -26,6 +26,7 @@ #include "d1formats/d1celtileset.h" #include "d1formats/d1cl2.h" #include "ui_mainwindow.h" +#include "widgets/palettewidget.h" MainWindow::MainWindow() : QMainWindow(nullptr) @@ -116,36 +117,28 @@ MainWindow::~MainWindow() delete this->redoAction; } -void MainWindow::setPal(QString path) +void MainWindow::setPal(const QString &path) { - this->pal = this->pals[path]; - this->trnUnique->setPalette(this->pal); - this->trnUnique->refreshResultingPalette(); - this->trn->refreshResultingPalette(); - - this->palWidget->setPal(this->pal); + this->m_palWidget->setPal(path); + this->m_trnUniqueWidget->setTrnPalette(m_palWidget->pal()); + this->m_trnWidget->refresh(); } -void MainWindow::setTrnUnique(QString path) +void MainWindow::setTrnUnique(const QString &path) { - this->trnUnique = this->trnsUnique[path]; - this->trnUnique->setPalette(this->pal); - this->trnUnique->refreshResultingPalette(); - this->trn->setPalette(this->trnUnique->getResultingPalette()); - this->trn->refreshResultingPalette(); - - this->trnUniqueWidget->setTrn(this->trnUnique); + this->m_trnUniqueWidget->setTrn(path); + this->m_trnUniqueWidget->setTrnPalette(m_palWidget->pal()); + this->m_trnWidget->setTrnPalette(this->m_trnUniqueWidget->trn()->getResultingPalette()); + this->m_trnWidget->refresh(); } -void MainWindow::setTrn(QString path) +void MainWindow::setTrn(const QString &path) { - this->trn = this->trns[path]; - this->trn->setPalette(this->trnUnique->getResultingPalette()); - this->trn->refreshResultingPalette(); + this->m_trnWidget->setTrn(path); + this->m_trnWidget->setTrnPalette(this->m_trnUniqueWidget->trn()->getResultingPalette()); + this->m_trnWidget->refresh(); - this->gfx->setPalette(this->trn->getResultingPalette()); - - this->trnWidget->setTrn(this->trn); + this->gfx->setPalette(this->m_trnWidget->trn()->getResultingPalette()); } QString MainWindow::getLastFilePath() @@ -157,7 +150,7 @@ void MainWindow::updateWindow() { // rebuild palette hits this->palHits->update(); - this->palWidget->refresh(); + this->m_palWidget->refresh(); this->undoAction->setEnabled(this->undoStack->canUndo()); this->redoAction->setEnabled(this->undoStack->canRedo()); @@ -176,138 +169,37 @@ void MainWindow::updateWindow() } } -bool MainWindow::loadPal(QString palFilePath) -{ - QFileInfo palFileInfo(palFilePath); - // QString path = palFileInfo.absoluteFilePath(); - QString &path = palFilePath; - QString name = palFileInfo.fileName(); - - D1Pal *newPal = new D1Pal(); - if (!newPal->load(path)) { - delete newPal; - QMessageBox::critical(this, "Error", "Could not load PAL file."); - return false; - } - - if (this->pals.contains(path)) - delete this->pals[path]; - this->pals[path] = newPal; - this->palWidget->addPath(path, name); - return true; -} - -bool MainWindow::loadTrnUnique(QString trnFilePath) -{ - QFileInfo trnFileInfo(trnFilePath); - // QString path = trnFileInfo.absoluteFilePath(); - QString &path = trnFilePath; - QString name = trnFileInfo.fileName(); - - D1Trn *newTrn = new D1Trn(this->pal); - if (!newTrn->load(path)) { - delete newTrn; - QMessageBox::critical(this, "Error", "Could not load TRN file."); - return false; - } - - if (this->trnsUnique.contains(path)) - delete this->trnsUnique[path]; - this->trnsUnique[path] = newTrn; - this->trnUniqueWidget->addPath(path, name); - return true; -} - -bool MainWindow::loadTrn(QString trnFilePath) -{ - QFileInfo trnFileInfo(trnFilePath); - // QString path = trnFileInfo.absoluteFilePath(); - QString &path = trnFilePath; - QString name = trnFileInfo.fileName(); - - D1Trn *newTrn = new D1Trn(this->pal); - if (!newTrn->load(path)) { - delete newTrn; - QMessageBox::critical(this, "Error", "Could not load TRN file."); - return false; - } - - if (this->trns.contains(path)) - delete this->trns[path]; - this->trns[path] = newTrn; - this->trnWidget->addPath(path, name); - return true; -} - void MainWindow::paletteWidget_callback(PaletteWidget *widget, PWIDGET_CALLBACK_TYPE type) { - if (widget == this->palWidget) { - switch (type) { - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_NEW: - this->on_actionNew_PAL_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_OPEN: - this->on_actionOpen_PAL_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVE: - this->on_actionSave_PAL_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVEAS: - this->on_actionSave_PAL_as_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_CLOSE: - this->on_actionClose_PAL_triggered(); - break; - } - } else if (widget == this->trnUniqueWidget) { - switch (type) { - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_NEW: - this->on_actionNew_Unique_Translation_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_OPEN: - this->on_actionOpen_Unique_Translation_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVE: - this->on_actionSave_Unique_Translation_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVEAS: - this->on_actionSave_Unique_Translation_as_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_CLOSE: - this->on_actionClose_Unique_Translation_triggered(); - break; - } - } else if (widget == this->trnWidget) { - switch (type) { - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_NEW: - this->on_actionNew_Translation_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_OPEN: - this->on_actionOpen_Translation_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVE: - this->on_actionSave_Translation_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVEAS: - this->on_actionSave_Translation_as_triggered(); - break; - case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_CLOSE: - this->on_actionClose_Translation_triggered(); - break; - } + switch (type) { + case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_NEW: + widget->newOrSaveAsFile(PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_NEW); + break; + case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_OPEN: + widget->openPalette(); + break; + case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVE: + widget->save(); + break; + case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVEAS: + widget->newOrSaveAsFile(PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVEAS); + break; + case PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_CLOSE: + widget->closePalette(); + break; } } void MainWindow::resetPaletteCycle() { - this->pal->resetColors(); - this->palWidget->modify(); + // this->pal->resetColors(); + this->m_palWidget->modify(); } void MainWindow::nextPaletteCycle(D1PAL_CYCLE_TYPE type) { - this->pal->cycleColors(type); - this->palWidget->modify(); + // this->pal->cycleColors(type); + this->m_palWidget->modify(); } static QString prepareFilePath(QString filePath, const char *filter) @@ -499,18 +391,13 @@ void MainWindow::openFile(const OpenAsParam ¶ms) // Loading default.pal D1Pal *newPal = new D1Pal(); newPal->load(D1Pal::DEFAULT_PATH); - this->pals[D1Pal::DEFAULT_PATH] = newPal; - this->pal = newPal; // Loading default null.trn - D1Trn *newTrn = new D1Trn(this->pal); - newTrn->load(D1Trn::IDENTITY_PATH); - this->trnsUnique[D1Trn::IDENTITY_PATH] = newTrn; - this->trnUnique = newTrn; - newTrn = new D1Trn(this->trnUnique->getResultingPalette()); + D1Trn *newUniqTrn = new D1Trn(newPal); + newUniqTrn->load(D1Trn::IDENTITY_PATH); + + D1Trn *newTrn = new D1Trn(newUniqTrn->getResultingPalette()); newTrn->load(D1Trn::IDENTITY_PATH); - this->trns[D1Trn::IDENTITY_PATH] = newTrn; - this->trn = newTrn; QFileInfo celFileInfo = QFileInfo(openFilePath); @@ -535,7 +422,7 @@ void MainWindow::openFile(const OpenAsParam ¶ms) } this->gfx = new D1Gfx(); - this->gfx->setPalette(this->trn->getResultingPalette()); + this->gfx->setPalette(newTrn->getResultingPalette()); if (isTileset) { // Loading SOL this->sol = new D1Sol(); @@ -593,65 +480,65 @@ void MainWindow::openFile(const OpenAsParam ¶ms) } // Add palette widgets for PAL and TRNs - this->palWidget = new PaletteWidget(this->undoStack, "Palette"); - this->trnWidget = new PaletteWidget(this->undoStack, "Translation"); - this->trnUniqueWidget = new PaletteWidget(this->undoStack, "Unique translation"); - this->ui->palFrame->layout()->addWidget(this->palWidget); - this->ui->palFrame->layout()->addWidget(this->trnWidget); - this->ui->palFrame->layout()->addWidget(this->trnUniqueWidget); + this->m_palWidget = new PaletteWidget(this->undoStack, "Palette"); + this->m_trnWidget = new PaletteWidget(this->undoStack, "Translation"); + this->m_trnUniqueWidget = new PaletteWidget(this->undoStack, "Unique translation"); + this->ui->palFrame->layout()->addWidget(this->m_palWidget); + this->ui->palFrame->layout()->addWidget(this->m_trnWidget); + this->ui->palFrame->layout()->addWidget(this->m_trnUniqueWidget); // Configuration update triggers refresh of the palette widgets - QObject::connect(&this->settingsDialog, &SettingsDialog::configurationSaved, this->palWidget, &PaletteWidget::reloadConfig); - QObject::connect(&this->settingsDialog, &SettingsDialog::configurationSaved, this->trnUniqueWidget, &PaletteWidget::reloadConfig); - QObject::connect(&this->settingsDialog, &SettingsDialog::configurationSaved, this->trnWidget, &PaletteWidget::reloadConfig); - QObject::connect(&this->settingsDialog, &SettingsDialog::configurationSaved, this->palWidget, &PaletteWidget::refresh); + QObject::connect(&this->settingsDialog, &SettingsDialog::configurationSaved, this->m_palWidget, &PaletteWidget::reloadConfig); + QObject::connect(&this->settingsDialog, &SettingsDialog::configurationSaved, this->m_trnUniqueWidget, &PaletteWidget::reloadConfig); + QObject::connect(&this->settingsDialog, &SettingsDialog::configurationSaved, this->m_trnWidget, &PaletteWidget::reloadConfig); + QObject::connect(&this->settingsDialog, &SettingsDialog::configurationSaved, this->m_palWidget, &PaletteWidget::refresh); // Palette and translation file selection // When a .pal or .trn file is selected in the PaletteWidget update the pal or trn - QObject::connect(this->palWidget, &PaletteWidget::pathSelected, this, &MainWindow::setPal); - QObject::connect(this->trnUniqueWidget, &PaletteWidget::pathSelected, this, &MainWindow::setTrnUnique); - QObject::connect(this->trnWidget, &PaletteWidget::pathSelected, this, &MainWindow::setTrn); + QObject::connect(this->m_palWidget, &PaletteWidget::pathSelected, this, &MainWindow::setPal); + QObject::connect(this->m_trnUniqueWidget, &PaletteWidget::pathSelected, this, &MainWindow::setTrnUnique); + QObject::connect(this->m_trnWidget, &PaletteWidget::pathSelected, this, &MainWindow::setTrn); // Refresh PAL/TRN view chain - QObject::connect(this->palWidget, &PaletteWidget::refreshed, this->trnUniqueWidget, &PaletteWidget::refresh); - QObject::connect(this->trnUniqueWidget, &PaletteWidget::refreshed, this->trnWidget, &PaletteWidget::refresh); + QObject::connect(this->m_palWidget, &PaletteWidget::refreshed, this->m_trnUniqueWidget, &PaletteWidget::refresh); + QObject::connect(this->m_trnUniqueWidget, &PaletteWidget::refreshed, this->m_trnWidget, &PaletteWidget::refresh); // Translation color selection - QObject::connect(this->palWidget, &PaletteWidget::colorsSelected, this->trnWidget, &PaletteWidget::checkTranslationsSelection); - QObject::connect(this->trnWidget, &PaletteWidget::colorsSelected, this->trnUniqueWidget, &PaletteWidget::checkTranslationsSelection); - QObject::connect(this->trnWidget, &PaletteWidget::displayAllRootColors, this->palWidget, &PaletteWidget::temporarilyDisplayAllColors); - QObject::connect(this->trnUniqueWidget, &PaletteWidget::displayAllRootColors, this->trnWidget, &PaletteWidget::temporarilyDisplayAllColors); - QObject::connect(this->trnWidget, &PaletteWidget::displayRootInformation, this->palWidget, &PaletteWidget::displayInfo); - QObject::connect(this->trnUniqueWidget, &PaletteWidget::displayRootInformation, this->trnWidget, &PaletteWidget::displayInfo); - QObject::connect(this->trnWidget, &PaletteWidget::displayRootBorder, this->palWidget, &PaletteWidget::displayBorder); - QObject::connect(this->trnUniqueWidget, &PaletteWidget::displayRootBorder, this->trnWidget, &PaletteWidget::displayBorder); - QObject::connect(this->trnWidget, &PaletteWidget::clearRootInformation, this->palWidget, &PaletteWidget::clearInfo); - QObject::connect(this->trnUniqueWidget, &PaletteWidget::clearRootInformation, this->trnWidget, &PaletteWidget::clearInfo); - QObject::connect(this->trnWidget, &PaletteWidget::clearRootBorder, this->palWidget, &PaletteWidget::clearBorder); - QObject::connect(this->trnUniqueWidget, &PaletteWidget::clearRootBorder, this->trnWidget, &PaletteWidget::clearBorder); + QObject::connect(this->m_palWidget, &PaletteWidget::colorsSelected, this->m_trnWidget, &PaletteWidget::checkTranslationsSelection); + QObject::connect(this->m_trnWidget, &PaletteWidget::colorsSelected, this->m_trnUniqueWidget, &PaletteWidget::checkTranslationsSelection); + QObject::connect(this->m_trnWidget, &PaletteWidget::displayAllRootColors, this->m_palWidget, &PaletteWidget::temporarilyDisplayAllColors); + QObject::connect(this->m_trnUniqueWidget, &PaletteWidget::displayAllRootColors, this->m_trnWidget, &PaletteWidget::temporarilyDisplayAllColors); + QObject::connect(this->m_trnWidget, &PaletteWidget::displayRootInformation, this->m_palWidget, &PaletteWidget::displayInfo); + QObject::connect(this->m_trnUniqueWidget, &PaletteWidget::displayRootInformation, this->m_trnWidget, &PaletteWidget::displayInfo); + QObject::connect(this->m_trnWidget, &PaletteWidget::displayRootBorder, this->m_palWidget, &PaletteWidget::displayBorder); + QObject::connect(this->m_trnUniqueWidget, &PaletteWidget::displayRootBorder, this->m_trnWidget, &PaletteWidget::displayBorder); + QObject::connect(this->m_trnWidget, &PaletteWidget::clearRootInformation, this->m_palWidget, &PaletteWidget::clearInfo); + QObject::connect(this->m_trnUniqueWidget, &PaletteWidget::clearRootInformation, this->m_trnWidget, &PaletteWidget::clearInfo); + QObject::connect(this->m_trnWidget, &PaletteWidget::clearRootBorder, this->m_palWidget, &PaletteWidget::clearBorder); + QObject::connect(this->m_trnUniqueWidget, &PaletteWidget::clearRootBorder, this->m_trnWidget, &PaletteWidget::clearBorder); if (isTileset) { this->levelCelView = new LevelCelView(this->undoStack, this); this->levelCelView->initialize(this->gfx, this->min, this->til, this->sol, this->amp); // Refresh CEL view if a PAL or TRN is modified - QObject::connect(this->palWidget, &PaletteWidget::modified, this->levelCelView, &LevelCelView::displayFrame); - QObject::connect(this->trnUniqueWidget, &PaletteWidget::modified, this->levelCelView, &LevelCelView::displayFrame); - QObject::connect(this->trnWidget, &PaletteWidget::modified, this->levelCelView, &LevelCelView::displayFrame); + QObject::connect(this->m_palWidget, &PaletteWidget::modified, this->levelCelView, &LevelCelView::displayFrame); + QObject::connect(this->m_trnUniqueWidget, &PaletteWidget::modified, this->levelCelView, &LevelCelView::displayFrame); + QObject::connect(this->m_trnWidget, &PaletteWidget::modified, this->levelCelView, &LevelCelView::displayFrame); // Select color when level CEL view clicked - QObject::connect(this->levelCelView, &LevelCelView::colorIndexClicked, this->palWidget, &PaletteWidget::selectColor); - QObject::connect(this->levelCelView, &LevelCelView::colorIndexClicked, this->trnUniqueWidget, &PaletteWidget::selectColor); - QObject::connect(this->levelCelView, &LevelCelView::colorIndexClicked, this->trnWidget, &PaletteWidget::selectColor); + QObject::connect(this->levelCelView, &LevelCelView::colorIndexClicked, this->m_palWidget, &PaletteWidget::selectColor); + QObject::connect(this->levelCelView, &LevelCelView::colorIndexClicked, this->m_trnUniqueWidget, &PaletteWidget::selectColor); + QObject::connect(this->levelCelView, &LevelCelView::colorIndexClicked, this->m_trnWidget, &PaletteWidget::selectColor); // Refresh palette widgets when frame, subtile of tile is changed - QObject::connect(this->levelCelView, &LevelCelView::frameRefreshed, this->palWidget, &PaletteWidget::refresh); + QObject::connect(this->levelCelView, &LevelCelView::frameRefreshed, this->m_palWidget, &PaletteWidget::refresh); // Initialize palette widgets this->palHits = new D1PalHits(this->gfx, this->min, this->til); - this->palWidget->initialize(this->pal, this->levelCelView, this->palHits); - this->trnUniqueWidget->initialize(this->pal, this->trnUnique, this->levelCelView, this->palHits); - this->trnWidget->initialize(this->trnUnique->getResultingPalette(), this->trn, this->levelCelView, this->palHits); + this->m_palWidget->initialize(newPal, this->levelCelView, this->palHits, PaletteType::Palette); + this->m_trnUniqueWidget->initialize(newPal, newUniqTrn, this->levelCelView, this->palHits, PaletteType::UniqTranslation); + this->m_trnWidget->initialize(newUniqTrn->getResultingPalette(), newTrn, this->levelCelView, this->palHits, PaletteType::Translation); this->levelCelView->displayFrame(); } @@ -661,23 +548,23 @@ void MainWindow::openFile(const OpenAsParam ¶ms) this->celView->initialize(this->gfx); // Refresh CEL view if a PAL or TRN is modified - QObject::connect(this->palWidget, &PaletteWidget::modified, this->celView, &CelView::displayFrame); - QObject::connect(this->trnUniqueWidget, &PaletteWidget::modified, this->celView, &CelView::displayFrame); - QObject::connect(this->trnWidget, &PaletteWidget::modified, this->celView, &CelView::displayFrame); + QObject::connect(this->m_palWidget, &PaletteWidget::modified, this->celView, &CelView::displayFrame); + QObject::connect(this->m_trnUniqueWidget, &PaletteWidget::modified, this->celView, &CelView::displayFrame); + QObject::connect(this->m_trnWidget, &PaletteWidget::modified, this->celView, &CelView::displayFrame); // Select color when CEL view clicked - QObject::connect(this->celView, &CelView::colorIndexClicked, this->palWidget, &PaletteWidget::selectColor); - QObject::connect(this->celView, &CelView::colorIndexClicked, this->trnUniqueWidget, &PaletteWidget::selectColor); - QObject::connect(this->celView, &CelView::colorIndexClicked, this->trnWidget, &PaletteWidget::selectColor); + QObject::connect(this->celView, &CelView::colorIndexClicked, this->m_palWidget, &PaletteWidget::selectColor); + QObject::connect(this->celView, &CelView::colorIndexClicked, this->m_trnUniqueWidget, &PaletteWidget::selectColor); + QObject::connect(this->celView, &CelView::colorIndexClicked, this->m_trnWidget, &PaletteWidget::selectColor); // Refresh palette widgets when frame - QObject::connect(this->celView, &CelView::frameRefreshed, this->palWidget, &PaletteWidget::refresh); + QObject::connect(this->celView, &CelView::frameRefreshed, this->m_palWidget, &PaletteWidget::refresh); // Initialize palette widgets this->palHits = new D1PalHits(this->gfx); - this->palWidget->initialize(this->pal, this->celView, this->palHits); - this->trnUniqueWidget->initialize(this->pal, this->trnUnique, this->celView, this->palHits); - this->trnWidget->initialize(this->trnUnique->getResultingPalette(), this->trn, this->celView, this->palHits); + this->m_palWidget->initialize(newPal, this->celView, this->palHits, PaletteType::Palette); + this->m_trnUniqueWidget->initialize(newPal, newUniqTrn, this->celView, this->palHits, PaletteType::UniqTranslation); + this->m_trnWidget->initialize(newUniqTrn->getResultingPalette(), newTrn, this->celView, this->palHits, PaletteType::Translation); this->celView->displayFrame(); } @@ -688,13 +575,13 @@ void MainWindow::openFile(const OpenAsParam ¶ms) while (it.hasNext()) { QString sPath = it.next(); - if (this->loadPal(sPath) && firstPaletteFound.isEmpty()) { + if (m_palWidget->loadPalette(sPath) && firstPaletteFound.isEmpty()) { firstPaletteFound = sPath; } } // Select the first palette found in the same folder as the CEL/CL2 if it exists if (!firstPaletteFound.isEmpty()) - this->palWidget->selectPath(firstPaletteFound); + this->m_palWidget->selectPath(firstPaletteFound); // Adding the CelView to the main frame this->ui->mainFrame->layout()->addWidget(isTileset ? (QWidget *)this->levelCelView : this->celView); @@ -744,42 +631,23 @@ void MainWindow::openImageFiles(IMAGE_FILE_MODE mode, QStringList filePaths, boo this->ui->statusBar->clearMessage(); } -void MainWindow::openPalFiles(QStringList filePaths, PaletteWidget *widget) +void MainWindow::openPalFiles(const QStringList &filePaths, PaletteWidget *widget) const { QString firstFound; this->ui->statusBar->showMessage("Reading..."); this->ui->statusBar->repaint(); - if (widget == this->palWidget) { - for (QString path : filePaths) { - if (this->loadPal(path) && firstFound.isEmpty()) { - firstFound = path; - } - } - if (!firstFound.isEmpty()) { - this->palWidget->selectPath(firstFound); - } - } else if (widget == this->trnUniqueWidget) { - for (const QString &path : filePaths) { - if (this->loadTrnUnique(path) && firstFound.isEmpty()) { - firstFound = path; - } - } - if (!firstFound.isEmpty()) { - this->trnUniqueWidget->selectPath(firstFound); - } - } else if (widget == this->trnWidget) { - for (QString path : filePaths) { - if (this->loadTrn(path) && firstFound.isEmpty()) { - firstFound = path; - } - } - if (!firstFound.isEmpty()) { - this->trnWidget->selectPath(firstFound); + for (const QString &path : filePaths) { + if (widget->loadPalette(path) && firstFound.isEmpty()) { + firstFound = path; } } + if (!firstFound.isEmpty()) { + widget->selectPath(firstFound); + } + // Clear loading message from status bar this->ui->statusBar->clearMessage(); } @@ -994,7 +862,7 @@ void MainWindow::on_actionSaveAs_triggered() this->saveFile(filePath); } -namespace { +namespace mw { // TODO: move that function in some better place later on, as both PaletteWidget and MW use it bool QuestionDiscardChanges(bool isModified, QString filePath) { @@ -1013,41 +881,28 @@ bool QuestionDiscardChanges(bool isModified, QString filePath) return true; } -} // namespace +} // namespace mw bool MainWindow::isOkToQuit() { - for (D1Pal *pallete : this->pals) { - if (!QuestionDiscardChanges(pallete->isModified(), pallete->getFilePath())) { - return false; - } - } - - for (D1Trn *translation : this->trnsUnique) { - if (!QuestionDiscardChanges(translation->isModified(), translation->getFilePath())) { + if ((m_palWidget != nullptr) && (m_trnWidget != nullptr) && (m_trnUniqueWidget != nullptr)) { + if (!m_palWidget->isOkToQuit() || !m_trnWidget->isOkToQuit() || !m_trnUniqueWidget->isOkToQuit()) return false; - } } - for (D1Trn *translation : this->trns) { - if (!QuestionDiscardChanges(translation->isModified(), translation->getFilePath())) { - return false; - } - } - - if (this->min != nullptr && !QuestionDiscardChanges(this->min->isModified(), this->min->getFilePath())) { + if (this->min != nullptr && !mw::QuestionDiscardChanges(this->min->isModified(), this->min->getFilePath())) { return false; } - if (this->til != nullptr && !QuestionDiscardChanges(this->til->isModified(), this->til->getFilePath())) { + if (this->til != nullptr && !mw::QuestionDiscardChanges(this->til->isModified(), this->til->getFilePath())) { return false; } - if (this->sol != nullptr && !QuestionDiscardChanges(this->sol->isModified(), this->sol->getFilePath())) { + if (this->sol != nullptr && !mw::QuestionDiscardChanges(this->sol->isModified(), this->sol->getFilePath())) { return false; } - if (this->amp != nullptr && !QuestionDiscardChanges(this->amp->isModified(), this->amp->getFilePath())) { + if (this->amp != nullptr && !mw::QuestionDiscardChanges(this->amp->isModified(), this->amp->getFilePath())) { return false; } - if (this->gfx != nullptr && !QuestionDiscardChanges(this->gfx->isModified(), this->gfx->getFilePath())) { + if (this->gfx != nullptr && !mw::QuestionDiscardChanges(this->gfx->isModified(), this->gfx->getFilePath())) { return false; } @@ -1069,19 +924,15 @@ void MainWindow::closeAllElements() delete this->celView; delete this->levelCelView; - delete this->palWidget; - delete this->trnUniqueWidget; - delete this->trnWidget; - delete this->gfx; - - qDeleteAll(this->pals); - this->pals.clear(); + delete this->m_palWidget; + delete this->m_trnUniqueWidget; + delete this->m_trnWidget; - qDeleteAll(this->trnsUnique); - this->trnsUnique.clear(); + this->m_palWidget = nullptr; + this->m_trnUniqueWidget = nullptr; + this->m_trnWidget = nullptr; - qDeleteAll(this->trns); - this->trns.clear(); + delete this->gfx; delete this->min; delete this->til; @@ -1398,351 +1249,6 @@ void MainWindow::on_actionSortSubtiles_Tileset_triggered() this->ui->statusBar->clearMessage(); } -void MainWindow::on_actionNew_PAL_triggered() -{ - QString palFilePath = this->fileDialog(FILE_DIALOG_MODE::SAVE_CONF, "New Palette File", "PAL Files (*.pal *.PAL)"); - - if (palFilePath.isEmpty()) { - return; - } - - QFileInfo palFileInfo(palFilePath); - QString path = palFileInfo.absoluteFilePath(); - QString name = palFileInfo.fileName(); - - if (palFileInfo.suffix().isEmpty()) { - path += ".pal"; - name += ".pal"; - } else if (palFileInfo.suffix() != "pal") { - QMessageBox::critical(nullptr, "Error", "Only .pal is supported for palettes."); - return; - } - - D1Pal *newPal = new D1Pal(); - if (!newPal->load(D1Pal::DEFAULT_PATH)) { - delete newPal; - QMessageBox::critical(this, "Error", "Could not load PAL file."); - return; - } - if (!newPal->save(path)) { - delete newPal; - QMessageBox::critical(this, "Error", "Could not save PAL file."); - return; - } - - if (this->pals.contains(path)) - delete this->pals[path]; - this->pals[path] = newPal; - this->palWidget->addPath(path, name); - this->palWidget->selectPath(path); -} - -void MainWindow::on_actionOpen_PAL_triggered() -{ - QString palFilePath = this->fileDialog(FILE_DIALOG_MODE::OPEN, "Load Palette File", "PAL Files (*.pal *.PAL)"); - - if (!palFilePath.isEmpty() && this->loadPal(palFilePath)) { - this->palWidget->selectPath(palFilePath); - } -} - -void MainWindow::on_actionSave_PAL_triggered() -{ - QString selectedPath = this->palWidget->getSelectedPath(); - if (selectedPath == D1Pal::DEFAULT_PATH) { - this->on_actionSave_PAL_as_triggered(); - } else { - if (!this->pal->save(selectedPath)) { - QMessageBox::critical(this, "Error", "Could not save PAL file."); - return; - } - } -} - -void MainWindow::on_actionSave_PAL_as_triggered() -{ - QString palFilePath = this->fileDialog(FILE_DIALOG_MODE::SAVE_CONF, "Save Palette File as...", "PAL Files (*.pal *.PAL)"); - - if (palFilePath.isEmpty()) { - return; - } - - QFileInfo palFileInfo(palFilePath); - QString path = palFileInfo.absoluteFilePath(); - QString name = palFileInfo.fileName(); - - if (palFileInfo.suffix().isEmpty()) { - path += ".pal"; - name += ".pal"; - } else if (palFileInfo.suffix() != "pal") { - QMessageBox::critical(nullptr, "Error", "Only .pal is supported for palettes."); - return; - } - - if (!this->pal->save(palFilePath)) { - QMessageBox::critical(this, "Error", "Could not save PAL file."); - return; - } - - D1Pal *newPal = new D1Pal(); - if (!newPal->load(path)) { - delete newPal; - QMessageBox::critical(this, "Error", "Could not load PAL file."); - return; - } - - if (this->pals.contains(path)) - delete this->pals[path]; - this->pals[path] = newPal; - this->palWidget->addPath(path, name); - this->palWidget->selectPath(path); -} - -void MainWindow::on_actionClose_PAL_triggered() -{ - QString selectedPath = this->palWidget->getSelectedPath(); - if (selectedPath == D1Pal::DEFAULT_PATH) - return; - - if (this->pals.contains(selectedPath)) { - delete this->pals[selectedPath]; - this->pals.remove(selectedPath); - } - - this->palWidget->removePath(selectedPath); - this->palWidget->selectPath(D1Pal::DEFAULT_PATH); -} - -void MainWindow::on_actionNew_Unique_Translation_triggered() -{ - QString trnFilePath = this->fileDialog(FILE_DIALOG_MODE::SAVE_CONF, "New Translation File", "TRN Files (*.trn *.TRN)"); - - if (trnFilePath.isEmpty()) { - return; - } - - QFileInfo trnFileInfo(trnFilePath); - QString path = trnFileInfo.absoluteFilePath(); - QString name = trnFileInfo.fileName(); - - if (trnFileInfo.suffix().isEmpty()) { - path += ".trn"; - name += ".trn"; - } else if (trnFileInfo.suffix() != "trn") { - QMessageBox::critical(nullptr, "Error", "Only .trn is supported for translations."); - return; - } - - D1Trn *newTrn = new D1Trn(this->pal); - if (!newTrn->load(D1Trn::IDENTITY_PATH)) { - delete newTrn; - QMessageBox::critical(this, "Error", "Could not load TRN file."); - return; - } - if (!newTrn->save(path)) { - delete newTrn; - QMessageBox::critical(this, "Error", "Could not save TRN file."); - return; - } - - if (this->trnsUnique.contains(path)) - delete this->trnsUnique[path]; - this->trnsUnique[path] = newTrn; - this->trnUniqueWidget->addPath(path, name); - this->trnUniqueWidget->selectPath(path); -} - -void MainWindow::on_actionOpen_Unique_Translation_triggered() -{ - QString trnFilePath = this->fileDialog(FILE_DIALOG_MODE::OPEN, "Load Translation File", "TRN Files (*.trn *.TRN)"); - - if (!trnFilePath.isEmpty() && this->loadTrnUnique(trnFilePath)) { - this->trnUniqueWidget->selectPath(trnFilePath); - } -} - -void MainWindow::on_actionSave_Unique_Translation_triggered() -{ - QString selectedPath = this->trnUniqueWidget->getSelectedPath(); - if (selectedPath == D1Trn::IDENTITY_PATH) { - this->on_actionSave_Unique_Translation_as_triggered(); - } else { - if (!this->trnUnique->save(selectedPath)) { - QMessageBox::critical(this, "Error", "Could not save TRN file."); - return; - } - } -} - -void MainWindow::on_actionSave_Unique_Translation_as_triggered() -{ - QString trnFilePath = this->fileDialog(FILE_DIALOG_MODE::SAVE_CONF, "Save Translation File as...", "TRN Files (*.trn *.TRN)"); - - if (trnFilePath.isEmpty()) { - return; - } - - QFileInfo trnFileInfo(trnFilePath); - QString path = trnFileInfo.absoluteFilePath(); - QString name = trnFileInfo.fileName(); - - if (trnFileInfo.suffix().isEmpty()) { - path += ".trn"; - name += ".trn"; - } else if (trnFileInfo.suffix() != "trn") { - QMessageBox::critical(nullptr, "Error", "Only .trn is supported for translations."); - return; - } - - if (!this->trnUnique->save(trnFilePath)) { - QMessageBox::critical(this, "Error", "Could not save TRN file."); - return; - } - - D1Trn *newTrn = new D1Trn(this->pal); - if (!newTrn->load(path)) { - delete newTrn; - QMessageBox::critical(this, "Error", "Could not load TRN file."); - return; - } - - if (this->trnsUnique.contains(path)) - delete this->trnsUnique[path]; - this->trnsUnique[path] = newTrn; - this->trnUniqueWidget->addPath(path, name); - this->trnUniqueWidget->selectPath(path); -} - -void MainWindow::on_actionClose_Unique_Translation_triggered() -{ - QString selectedPath = this->trnUniqueWidget->getSelectedPath(); - if (selectedPath == D1Trn::IDENTITY_PATH) - return; - - if (this->trnsUnique.contains(selectedPath)) { - delete this->trnsUnique[selectedPath]; - this->trnsUnique.remove(selectedPath); - } - - this->trnUniqueWidget->removePath(selectedPath); - this->trnUniqueWidget->selectPath(D1Trn::IDENTITY_PATH); -} - -void MainWindow::on_actionNew_Translation_triggered() -{ - QString trnFilePath = this->fileDialog(FILE_DIALOG_MODE::SAVE_CONF, "New Translation File", "TRN Files (*.trn *.TRN)"); - - if (trnFilePath.isEmpty()) { - return; - } - - QFileInfo trnFileInfo(trnFilePath); - QString path = trnFileInfo.absoluteFilePath(); - QString name = trnFileInfo.fileName(); - - if (trnFileInfo.suffix().isEmpty()) { - path += ".trn"; - name += ".trn"; - } else if (trnFileInfo.suffix() != "trn") { - QMessageBox::critical(nullptr, "Error", "Only .trn is supported for translations."); - return; - } - - D1Trn *newTrn = new D1Trn(this->trnUnique->getResultingPalette()); - if (!newTrn->load(D1Trn::IDENTITY_PATH)) { - delete newTrn; - QMessageBox::critical(this, "Error", "Could not load TRN file."); - return; - } - if (!newTrn->save(path)) { - delete newTrn; - QMessageBox::critical(this, "Error", "Could not save TRN file."); - return; - } - - if (this->trns.contains(path)) - delete this->trns[path]; - this->trns[path] = newTrn; - this->trnWidget->addPath(path, name); - this->trnWidget->selectPath(path); -} - -void MainWindow::on_actionOpen_Translation_triggered() -{ - QString trnFilePath = this->fileDialog(FILE_DIALOG_MODE::OPEN, "Load Translation File", "TRN Files (*.trn *.TRN)"); - - if (!trnFilePath.isEmpty() && this->loadTrn(trnFilePath)) { - this->trnWidget->selectPath(trnFilePath); - } -} - -void MainWindow::on_actionSave_Translation_triggered() -{ - QString selectedPath = this->trnWidget->getSelectedPath(); - if (selectedPath == D1Trn::IDENTITY_PATH) { - this->on_actionSave_Translation_as_triggered(); - } else { - if (!this->trn->save(selectedPath)) { - QMessageBox::critical(this, "Error", "Could not save TRN file."); - return; - } - } -} - -void MainWindow::on_actionSave_Translation_as_triggered() -{ - QString trnFilePath = this->fileDialog(FILE_DIALOG_MODE::SAVE_CONF, "Save Translation File as...", "TRN Files (*.trn *.TRN)"); - - if (trnFilePath.isEmpty()) { - return; - } - - QFileInfo trnFileInfo(trnFilePath); - QString path = trnFileInfo.absoluteFilePath(); - QString name = trnFileInfo.fileName(); - - if (trnFileInfo.suffix().isEmpty()) { - path += ".trn"; - name += ".trn"; - } else if (trnFileInfo.suffix() != "trn") { - QMessageBox::critical(nullptr, "Error", "Only .trn is supported for translations."); - return; - } - - if (!this->trn->save(trnFilePath)) { - QMessageBox::critical(this, "Error", "Could not save TRN file."); - return; - } - - D1Trn *newTrn = new D1Trn(this->trnUnique->getResultingPalette()); - if (!newTrn->load(path)) { - delete newTrn; - QMessageBox::critical(this, "Error", "Could not load TRN file."); - return; - } - - if (this->trns.contains(path)) - delete this->trns[path]; - this->trns[path] = newTrn; - this->trnWidget->addPath(path, name); - this->trnWidget->selectPath(path); -} - -void MainWindow::on_actionClose_Translation_triggered() -{ - QString selectedPath = this->trnWidget->getSelectedPath(); - if (selectedPath == D1Trn::IDENTITY_PATH) - return; - - if (this->trns.contains(selectedPath)) { - delete this->trns[selectedPath]; - this->trns.remove(selectedPath); - } - - this->trnWidget->removePath(selectedPath); - this->trnWidget->selectPath(D1Trn::IDENTITY_PATH); -} - void MainWindow::setupUndoMacroWidget(std::unique_ptr &userData, enum OperationType opType) { this->m_currMacroOpType = opType; diff --git a/source/mainwindow.h b/source/mainwindow.h index 53451e516..9f29dd467 100644 --- a/source/mainwindow.h +++ b/source/mainwindow.h @@ -44,6 +44,10 @@ namespace Ui { class MainWindow; } +namespace mw { +bool QuestionDiscardChanges(bool isModified, QString filePath); +} // namespace mw + class MainWindow : public QMainWindow { Q_OBJECT @@ -51,13 +55,13 @@ class MainWindow : public QMainWindow { explicit MainWindow(); ~MainWindow(); - void setPal(QString); - void setTrn(QString); - void setTrnUnique(QString); + void setPal(const QString &); + void setTrn(const QString &); + void setTrnUnique(const QString &); void openFile(const OpenAsParam ¶ms); void openImageFiles(IMAGE_FILE_MODE mode, QStringList filePaths, bool append); - void openPalFiles(QStringList filePaths, PaletteWidget *widget); + void openPalFiles(const QStringList &filePaths, PaletteWidget *widget) const; void openFontFile(QString filePath, QColor renderColor, int pointSize, uint symbolPrefix); void saveFile(const QString &gfxPath); @@ -70,6 +74,18 @@ class MainWindow : public QMainWindow { QString getLastFilePath(); QString fileDialog(FILE_DIALOG_MODE mode, const char *title, const char *filter); QStringList filesDialog(const char *title, const char *filter); + PaletteWidget *trnWidget() + { + return m_trnWidget; + } + PaletteWidget *uniqTrnWidget() + { + return m_trnUniqueWidget; + } + PaletteWidget *paletteWidget() + { + return m_palWidget; + } static bool hasImageUrl(const QMimeData *mimeData); @@ -78,9 +94,6 @@ class MainWindow : public QMainWindow { private: void updateWindow(); - bool loadPal(QString palFilePath); - bool loadTrn(QString trnfilePath); - bool loadTrnUnique(QString trnfilePath); void addFrames(bool append); void addSubtiles(bool append); @@ -143,24 +156,6 @@ private slots: void on_actionSortFrames_Tileset_triggered(); void on_actionSortSubtiles_Tileset_triggered(); - void on_actionNew_PAL_triggered(); - void on_actionOpen_PAL_triggered(); - void on_actionSave_PAL_triggered(); - void on_actionSave_PAL_as_triggered(); - void on_actionClose_PAL_triggered(); - - void on_actionNew_Unique_Translation_triggered(); - void on_actionOpen_Unique_Translation_triggered(); - void on_actionSave_Unique_Translation_triggered(); - void on_actionSave_Unique_Translation_as_triggered(); - void on_actionClose_Unique_Translation_triggered(); - - void on_actionNew_Translation_triggered(); - void on_actionOpen_Translation_triggered(); - void on_actionSave_Translation_triggered(); - void on_actionSave_Translation_as_triggered(); - void on_actionClose_Translation_triggered(); - void on_actionAbout_triggered(); void on_actionAbout_Qt_triggered(); @@ -184,28 +179,21 @@ private slots: QPointer celView; QPointer levelCelView; - QPointer palWidget; - QPointer trnWidget; - QPointer trnUniqueWidget; + PaletteWidget *m_palWidget = nullptr; + PaletteWidget *m_trnWidget = nullptr; + PaletteWidget *m_trnUniqueWidget = nullptr; OpenAsDialog openAsDialog = OpenAsDialog(this); SettingsDialog settingsDialog = SettingsDialog(this); ImportDialog importDialog = ImportDialog(this); ExportDialog exportDialog = ExportDialog(this); - QPointer pal; - QPointer trn; - QPointer trnUnique; QPointer gfx; QPointer min; QPointer til; QPointer sol; QPointer amp; - QMap pals; // key: path, value: pointer to palette - QMap trns; // key: path, value: pointer to translation - QMap trnsUnique; // key: path, value: pointer to translation - std::unique_ptr m_progressDialog; // Palette hits are instantiated in main window to make them available to the three PaletteWidgets diff --git a/source/palette/d1pal.cpp b/source/palette/d1pal.cpp index 03236dea3..d044143ea 100644 --- a/source/palette/d1pal.cpp +++ b/source/palette/d1pal.cpp @@ -120,6 +120,16 @@ QString D1Pal::getFilePath() return this->palFilePath; } +QString D1Pal::getDefaultPath() const +{ + return DEFAULT_PATH; +} + +QString D1Pal::getDefaultName() const +{ + return DEFAULT_NAME; +} + QColor D1Pal::getColor(quint8 index) { return this->colors[index]; diff --git a/source/palette/d1pal.h b/source/palette/d1pal.h index 3329712f7..2ac2d9777 100644 --- a/source/palette/d1pal.h +++ b/source/palette/d1pal.h @@ -29,14 +29,17 @@ class D1Pal : public QObject { static constexpr const char *DEFAULT_NAME = "_default.pal"; D1Pal() = default; - ~D1Pal() = default; + ~D1Pal() override = default; - bool load(QString); - bool save(QString); + virtual bool load(QString); + virtual bool save(QString); - bool isModified() const; + [[nodiscard]] virtual bool isModified() const; - QString getFilePath(); + virtual QString getFilePath(); + + [[nodiscard]] virtual QString getDefaultPath() const; + [[nodiscard]] virtual QString getDefaultName() const; QColor getColor(quint8); void setColor(quint8, QColor); diff --git a/source/widgets/palettewidget.cpp b/source/widgets/palettewidget.cpp index 24154d6b0..923e6b3df 100644 --- a/source/widgets/palettewidget.cpp +++ b/source/widgets/palettewidget.cpp @@ -293,32 +293,36 @@ PaletteWidget::~PaletteWidget() { delete ui; delete scene; + + for (auto &pair : m_palettes_map) { + delete pair.second.second; + } } -void PaletteWidget::setPal(D1Pal *p) +void PaletteWidget::setPal(const QString &path) { - this->pal = p; + m_pal = m_palettes_map[path].second; emit this->modified(); } -void PaletteWidget::setTrn(D1Trn *t) +void PaletteWidget::setTrn(const QString &path) { - this->trn = t; + this->m_trn = dynamic_cast(m_palettes_map[path].second); emit this->modified(); } bool PaletteWidget::isTrnWidget() { - return this->isTrn; + return (m_paletteType == PaletteType::Translation || m_paletteType == PaletteType::UniqTranslation); } -void PaletteWidget::initialize(D1Pal *p, CelView *c, D1PalHits *ph) +void PaletteWidget::initialize(D1Pal *p, CelView *c, D1PalHits *ph, PaletteType palType) { - this->isTrn = false; - this->pal = p; - this->trn = nullptr; + this->m_paletteType = palType; + this->m_pal = p; + this->m_trn = nullptr; this->celView = c; this->levelCelView = nullptr; this->palHits = ph; @@ -326,11 +330,11 @@ void PaletteWidget::initialize(D1Pal *p, CelView *c, D1PalHits *ph) this->initializeUi(); } -void PaletteWidget::initialize(D1Pal *p, LevelCelView *lc, D1PalHits *ph) +void PaletteWidget::initialize(D1Pal *p, LevelCelView *lc, D1PalHits *ph, PaletteType palType) { - this->isTrn = false; - this->pal = p; - this->trn = nullptr; + this->m_paletteType = palType; + this->m_pal = p; + this->m_trn = nullptr; this->celView = nullptr; this->levelCelView = lc; this->palHits = ph; @@ -338,11 +342,11 @@ void PaletteWidget::initialize(D1Pal *p, LevelCelView *lc, D1PalHits *ph) this->initializeUi(); } -void PaletteWidget::initialize(D1Pal *p, D1Trn *t, CelView *c, D1PalHits *ph) +void PaletteWidget::initialize(D1Pal *p, D1Trn *t, CelView *c, D1PalHits *ph, PaletteType palType) { - this->isTrn = true; - this->pal = p; - this->trn = t; + this->m_paletteType = palType; + this->m_pal = p; + this->m_trn = t; this->celView = c; this->levelCelView = nullptr; this->palHits = ph; @@ -350,11 +354,11 @@ void PaletteWidget::initialize(D1Pal *p, D1Trn *t, CelView *c, D1PalHits *ph) this->initializeUi(); } -void PaletteWidget::initialize(D1Pal *p, D1Trn *t, LevelCelView *lc, D1PalHits *ph) +void PaletteWidget::initialize(D1Pal *p, D1Trn *t, LevelCelView *lc, D1PalHits *ph, PaletteType palType) { - this->isTrn = true; - this->pal = p; - this->trn = t; + this->m_paletteType = palType; + this->m_pal = p; + this->m_trn = t; this->celView = nullptr; this->levelCelView = lc; this->palHits = ph; @@ -364,7 +368,7 @@ void PaletteWidget::initialize(D1Pal *p, D1Trn *t, LevelCelView *lc, D1PalHits * void PaletteWidget::initializeUi() { - bool trnMode = this->isTrn; + bool trnMode = this->m_paletteType == PaletteType::Translation || this->m_paletteType == PaletteType::UniqTranslation; this->ui->monsterTrnPushButton->setVisible(trnMode); this->ui->translationClearPushButton->setVisible(trnMode); @@ -389,10 +393,12 @@ void PaletteWidget::initializeUi() void PaletteWidget::initializePathComboBox() { - if (!this->isTrn) { - this->paths[D1Pal::DEFAULT_PATH] = D1Pal::DEFAULT_NAME; + if (m_paletteType == PaletteType::Palette) { + this->m_palettes_map[D1Pal::DEFAULT_PATH].first = D1Pal::DEFAULT_NAME; + this->m_palettes_map[D1Pal::DEFAULT_PATH].second = m_pal; } else { - this->paths[D1Trn::IDENTITY_PATH] = D1Trn::IDENTITY_NAME; + this->m_palettes_map[D1Trn::IDENTITY_PATH].first = D1Trn::IDENTITY_NAME; + this->m_palettes_map[D1Trn::IDENTITY_PATH].second = m_trn; } this->refreshPathComboBox(); @@ -402,7 +408,7 @@ void PaletteWidget::initializeDisplayComboBox() { ui->displayComboBox->addItem("Show all colors", QVariant((int)COLORFILTER_TYPE::NONE)); - if (!this->isTrn) { + if (m_paletteType == PaletteType::Palette) { ui->displayComboBox->addItem("Show all frames hits", QVariant((int)COLORFILTER_TYPE::USED)); if (this->levelCelView != nullptr) { ui->displayComboBox->addItem("Show current tile hits", QVariant((int)COLORFILTER_TYPE::TILE)); @@ -447,7 +453,7 @@ void PaletteWidget::checkTranslationsSelection(QList indexes) // Build color editing command and connect it to the current palette widget // to update the PAL/TRN and CEL views when undo/redo is performed std::unique_ptr command = std::make_unique( - this->trn, this->selectedFirstColorIndex, this->selectedLastColorIndex, indexes); + this->m_trn, this->selectedFirstColorIndex, this->selectedLastColorIndex, indexes); QObject::connect(command.get(), &EditTranslationsCommand::modified, this, &PaletteWidget::modify); this->undoStack->push(std::move(command)); @@ -459,18 +465,18 @@ void PaletteWidget::checkTranslationsSelection(QList indexes) emit this->clearRootBorder(); } -void PaletteWidget::addPath(QString path, QString name) +void PaletteWidget::addPath(const QString &path, const QString &name, D1Pal *pal) { - this->paths[path] = name; + this->m_palettes_map[path] = std::make_pair(name, pal); } -void PaletteWidget::removePath(QString path) +void PaletteWidget::removePath(const QString &path) { - if (this->paths.contains(path)) - this->paths.remove(path); + if (this->m_palettes_map.contains(path)) + this->m_palettes_map.erase(path); } -void PaletteWidget::selectPath(QString path) +void PaletteWidget::selectPath(const QString &path) { this->ui->pathComboBox->setCurrentIndex(this->ui->pathComboBox->findData(path)); this->ui->pathComboBox->setToolTip(path); @@ -479,9 +485,22 @@ void PaletteWidget::selectPath(QString path) emit this->modified(); } -QString PaletteWidget::getSelectedPath() +QString PaletteWidget::getWidgetsDefaultPath() const +{ + if (m_paletteType == PaletteType::Palette) { + return D1Pal::DEFAULT_PATH; + } + + return D1Trn::IDENTITY_PATH; +} + +QString PaletteWidget::getSelectedPath() const { - return this->paths.key(this->ui->pathComboBox->currentText()); + QString path = this->ui->pathComboBox->currentText(); + for (const auto &[key, valuePair] : m_palettes_map) { + if (valuePair.first == this->ui->pathComboBox->currentText()) + return key; + } } static QRectF getColorCoordinates(quint8 index) @@ -537,19 +556,17 @@ void PaletteWidget::finishColorSelection() std::swap(this->selectedFirstColorIndex, this->selectedLastColorIndex); } - if (this->isTrn) { - if (this->pickingTranslationColor) { - this->clearInfo(); - emit this->clearRootInformation(); - emit this->clearRootBorder(); - this->pickingTranslationColor = false; - } + if (m_paletteType != PaletteType::Palette && this->pickingTranslationColor) { + this->clearInfo(); + emit this->clearRootInformation(); + emit this->clearRootBorder(); + this->pickingTranslationColor = false; } this->temporarilyDisplayingAllColors = false; // emit selected colors - // if ((!this->isTrn && !this->pal.isNull()) || (this->isTrn && !this->trn.isNull())) { + // if ((!this->isTrn && !this->pal.isNull()) || (this->isTrn && !this->m_trn.isNull())) { QList indexes; for (int i = this->selectedFirstColorIndex; i <= this->selectedLastColorIndex; i++) indexes.append(i); @@ -559,6 +576,202 @@ void PaletteWidget::finishColorSelection() this->refresh(); } +void PaletteWidget::setTrnPalette(D1Pal *pal) +{ + this->m_trn->setPalette(pal); + refresh(); +} + +void PaletteWidget::save() +{ + PaletteFileInfo fileInfo = paletteFileInfo(); + + QString selectedPath = getSelectedPath(); + if (selectedPath == getWidgetsDefaultPath()) { + newOrSaveAsFile(PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVEAS); + } else { + if (!(m_paletteType != PaletteType::Palette ? m_trn->save(selectedPath) : m_pal->save(selectedPath))) { + QMessageBox::critical(this, "Error", QString("Could not save %1 file.").arg(fileInfo.suffix.toUpper())); + } + } +} + +PaletteFileInfo PaletteWidget::paletteFileInfo() const +{ + if (m_paletteType != PaletteType::Palette) { + return { "translation", "trn" }; + } + + return { "palette", "pal" }; +} + +void PaletteWidget::performSave(const QString &palFilePath, const PaletteFileInfo &fileInfo) +{ + bool opResult = false; + if (m_paletteType == PaletteType::Palette) { + opResult = this->m_pal->save(palFilePath); + } else { + opResult = this->m_trn->save(palFilePath); + } + + if (!opResult) { + QMessageBox::critical(this, "Error", QString("Could not save %1 file.").arg(fileInfo.suffix.toUpper())); + } +} + +void PaletteWidget::newOrSaveAsFile(const PWIDGET_CALLBACK_TYPE action) +{ + PaletteFileInfo fileInfo = paletteFileInfo(); + + QString actionStr; + if (action == PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVEAS) { + actionStr = QString("Save %1 File as...").arg(fileInfo.name); + } else { + actionStr = QString("New %1 File").arg(fileInfo.name); + } + + auto *mw = dynamic_cast(this->window()); + QString palFilePath = mw->fileDialog(FILE_DIALOG_MODE::SAVE_CONF, + actionStr.toStdString().c_str(), + (QString("%2 Files (*.%1 *.%2)").arg(fileInfo.suffix, fileInfo.suffix.toUpper())).toStdString().c_str()); + + if (palFilePath.isEmpty()) { + return; + } + + QFileInfo palFileInfo(palFilePath); + QString path = palFileInfo.absoluteFilePath(); + QString name = palFileInfo.fileName(); + + if (palFileInfo.suffix().isEmpty()) { + path += "." + fileInfo.suffix; + name += "." + fileInfo.suffix; + } else if (palFileInfo.suffix() != fileInfo.suffix) { + QMessageBox::critical(nullptr, "Error", QString("Only %1 is supported for %2").arg(fileInfo.suffix, fileInfo.name)); + return; + } + + // For save operation we need to save first and then load, but for new file op + // we need to propagate `newPal` with default information first by loading and + // then save + if (action == PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_SAVEAS) { + performSave(palFilePath, fileInfo); + } + + D1Pal *newPal; + switch (m_paletteType) { + case PaletteType::Palette: + newPal = new D1Pal(); + break; + case PaletteType::Translation: + newPal = new D1Trn(mw->uniqTrnWidget()->trn()->getResultingPalette()); + break; + case PaletteType::UniqTranslation: + newPal = new D1Trn(mw->paletteWidget()->pal()); + break; + } + + QString loadedFilePath; + if (action == PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_NEW) { + loadedFilePath = newPal->getDefaultPath(); + } else { + loadedFilePath = path; + } + + if (!newPal->load(loadedFilePath)) { + delete newPal; + QMessageBox::critical(this, "Error", QString("Could not load %1 file.").arg(fileInfo.suffix.toUpper())); + return; + } + + // For new operation we need to load first and then save, as the file has to be + // propagated with default information first + if (action == PWIDGET_CALLBACK_TYPE::PWIDGET_CALLBACK_NEW) { + performSave(path, fileInfo); + } + + if (this->m_palettes_map.contains(name)) + delete this->m_palettes_map[name].second; + addPath(path, name, newPal); + selectPath(path); +} + +bool PaletteWidget::loadPalette(const QString &filepath) +{ + PaletteFileInfo fileInfo = paletteFileInfo(); + + auto *mw = dynamic_cast(this->window()); + QFileInfo palFileInfo(filepath); + // QString path = trnFileInfo.absoluteFilePath(); + const QString &path = filepath; + QString name = palFileInfo.fileName(); + + D1Pal *newPal; + switch (m_paletteType) { + case PaletteType::Palette: + newPal = new D1Pal(); + break; + case PaletteType::Translation: + newPal = new D1Trn(mw->uniqTrnWidget()->trn()->getResultingPalette()); + break; + case PaletteType::UniqTranslation: + newPal = new D1Trn(mw->paletteWidget()->pal()); + break; + } + + if (!newPal->load(path)) { + delete newPal; + QMessageBox::critical(this, "Error", QString("Could not load %1 file.").arg(fileInfo.suffix.toUpper())); + return false; + } + + if (this->m_palettes_map.contains(name)) + delete this->m_palettes_map[name].second; + addPath(path, name, newPal); + return true; +} + +void PaletteWidget::openPalette() +{ + PaletteFileInfo fileInfo = paletteFileInfo(); + + auto *mw = dynamic_cast(this->window()); + QString paletteFilePath = mw->fileDialog(FILE_DIALOG_MODE::OPEN, + QString("Load %1 File").arg(fileInfo.name).toStdString().c_str(), + QString("%2 Files (*.%1 *.%2)").arg(fileInfo.suffix, fileInfo.suffix.toUpper()).toStdString().c_str()); + + if (!paletteFilePath.isEmpty() && loadPalette(paletteFilePath)) { + selectPath(paletteFilePath); + } +} + +bool PaletteWidget::isOkToQuit() +{ + for (const auto &pair : m_palettes_map) { + D1Pal *pal = pair.second.second; + if (!mw::QuestionDiscardChanges(pal->isModified(), pal->getFilePath())) { + return false; + } + } + + return true; +} + +void PaletteWidget::closePalette() +{ + QString selectedPath = getSelectedPath(); + if (selectedPath == getWidgetsDefaultPath()) + return; + + if (this->m_palettes_map.contains(selectedPath)) { + delete this->m_palettes_map[selectedPath].second; + this->m_palettes_map.erase(selectedPath); + } + + removePath(selectedPath); + selectPath(getWidgetsDefaultPath()); +} + bool PaletteWidget::displayColor(int colorIndex) { quint32 itemIndex; @@ -604,14 +817,14 @@ void PaletteWidget::displayColors() continue; // Check translation display filter - if (this->isTrn && ui->displayComboBox->currentData().value() == COLORFILTER_TYPE::TRANSLATED // "Show translated colors" - && this->trn->getTranslation(i) == i) + if (m_paletteType != PaletteType::Palette && ui->displayComboBox->currentData().value() == COLORFILTER_TYPE::TRANSLATED // "Show translated colors" + && this->m_trn->getTranslation(i) == i) continue; int x = i % PALETTE_COLORS_PER_LINE; int y = i / PALETTE_COLORS_PER_LINE; - QBrush brush = QBrush(this->isTrn ? this->trn->getResultingPalette()->getColor(i) : this->pal->getColor(i)); + QBrush brush = QBrush(m_paletteType != PaletteType::Palette ? this->m_trn->getResultingPalette()->getColor(i) : this->m_pal->getColor(i)); this->scene->addRect(x * dx + bsw, y * dy + bsw, w, w, pen, brush); } } @@ -700,15 +913,15 @@ void PaletteWidget::refreshPathComboBox() this->ui->pathComboBox->clear(); // Go through the hits of the CEL frame and add them to the subtile hits - for (auto iter = this->paths.cbegin(); iter != this->paths.cend(); iter++) { - this->ui->pathComboBox->addItem(iter.value(), iter.key()); + for (const auto &[key, pair] : m_palettes_map) { + this->ui->pathComboBox->addItem(pair.first, key); } QString selectedPath; - if (!this->isTrn) { - selectedPath = this->pal->getFilePath(); + if (m_paletteType == PaletteType::Palette) { + selectedPath = this->m_pal->getFilePath(); } else { - selectedPath = this->trn->getFilePath(); + selectedPath = this->m_trn->getFilePath(); } this->ui->pathComboBox->setCurrentIndex(this->ui->pathComboBox->findData(selectedPath)); this->ui->pathComboBox->setToolTip(selectedPath); @@ -717,7 +930,7 @@ void PaletteWidget::refreshPathComboBox() void PaletteWidget::refreshColorLineEdit() { if (this->selectedFirstColorIndex == this->selectedLastColorIndex) { - QColor selectedColor = this->pal->getColor(this->selectedFirstColorIndex); + QColor selectedColor = this->m_pal->getColor(this->selectedFirstColorIndex); this->ui->colorLineEdit->setText(selectedColor.name()); } else { this->ui->colorLineEdit->setText("*"); @@ -741,12 +954,12 @@ void PaletteWidget::refreshIndexLineEdit() void PaletteWidget::refreshTranslationIndexLineEdit() { - if (this->trn.isNull()) + if (this->m_trn == nullptr) return; if (this->selectedFirstColorIndex == this->selectedLastColorIndex) { this->ui->translationIndexLineEdit->setText( - QString::number(this->trn->getTranslation(this->selectedFirstColorIndex))); + QString::number(this->m_trn->getTranslation(this->selectedFirstColorIndex))); } else { this->ui->translationIndexLineEdit->setText("*"); } @@ -759,15 +972,15 @@ void PaletteWidget::modify() void PaletteWidget::refresh() { - if (this->isTrn) - this->trn->refreshResultingPalette(); + if (m_paletteType != PaletteType::Palette) + this->m_trn->refreshResultingPalette(); this->displayColors(); this->displaySelection(); this->refreshPathComboBox(); this->refreshColorLineEdit(); this->refreshIndexLineEdit(); - if (this->isTrn) + if (m_paletteType != PaletteType::Palette) this->refreshTranslationIndexLineEdit(); emit refreshed(); @@ -818,7 +1031,7 @@ void PaletteWidget::on_pathComboBox_activated(int index) void PaletteWidget::on_displayComboBox_activated(int index) { - if (!this->isTrn) { + if (m_paletteType == PaletteType::Palette) { D1PALHITS_MODE mode = D1PALHITS_MODE::ALL_COLORS; switch (this->ui->displayComboBox->currentData().value()) { case COLORFILTER_TYPE::NONE: @@ -850,7 +1063,7 @@ void PaletteWidget::on_colorLineEdit_returnPressed() // Build color editing command and connect it to the current palette widget // to update the PAL/TRN and CEL views when undo/redo is performed std::unique_ptr command = std::make_unique( - this->pal, this->selectedFirstColorIndex, this->selectedLastColorIndex, color, color); + this->m_pal, this->selectedFirstColorIndex, this->selectedLastColorIndex, color, color); QObject::connect(command.get(), &EditColorsCommand::modified, this, &PaletteWidget::modify); this->undoStack->push(std::move(command)); @@ -861,7 +1074,7 @@ void PaletteWidget::on_colorLineEdit_returnPressed() void PaletteWidget::on_colorPickPushButton_clicked() { - QColor color = this->pal->getColor(this->selectedFirstColorIndex); + QColor color = this->m_pal->getColor(this->selectedFirstColorIndex); color = QColorDialog::getColor(color); if (!color.isValid()) return; @@ -870,7 +1083,7 @@ void PaletteWidget::on_colorPickPushButton_clicked() if (this->selectedFirstColorIndex == this->selectedLastColorIndex) { colorEnd = color; } else { - colorEnd = this->pal->getColor(this->selectedLastColorIndex); + colorEnd = this->m_pal->getColor(this->selectedLastColorIndex); colorEnd = QColorDialog::getColor(colorEnd); if (!colorEnd.isValid()) return; @@ -879,7 +1092,7 @@ void PaletteWidget::on_colorPickPushButton_clicked() // Build color editing command and connect it to the current palette widget // to update the PAL/TRN and CEL views when undo/redo is performed std::unique_ptr command = std::make_unique( - this->pal, this->selectedFirstColorIndex, this->selectedLastColorIndex, color, colorEnd); + this->m_pal, this->selectedFirstColorIndex, this->selectedLastColorIndex, color, colorEnd); QObject::connect(command.get(), &EditColorsCommand::modified, this, &PaletteWidget::modify); this->undoStack->push(std::move(command)); @@ -890,7 +1103,7 @@ void PaletteWidget::on_colorClearPushButton_clicked() // Build color editing command and connect it to the current palette widget // to update the PAL/TRN and CEL views when undo/redo is performed std::unique_ptr command = std::make_unique( - this->pal, this->selectedFirstColorIndex, this->selectedLastColorIndex, this->paletteDefaultColor, this->paletteDefaultColor); + this->m_pal, this->selectedFirstColorIndex, this->selectedLastColorIndex, this->paletteDefaultColor, this->paletteDefaultColor); QObject::connect(command.get(), &EditColorsCommand::modified, this, &PaletteWidget::modify); this->undoStack->push(std::move(command)); @@ -908,7 +1121,7 @@ void PaletteWidget::on_translationIndexLineEdit_returnPressed() // Build translation editing command and connect it to the current palette widget // to update the PAL/TRN and CEL views when undo/redo is performed std::unique_ptr command = std::make_unique( - this->trn, this->selectedFirstColorIndex, this->selectedLastColorIndex, newTranslations); + this->m_trn, this->selectedFirstColorIndex, this->selectedLastColorIndex, newTranslations); QObject::connect(command.get(), &EditTranslationsCommand::modified, this, &PaletteWidget::modify); this->undoStack->push(std::move(command)); @@ -931,7 +1144,7 @@ void PaletteWidget::on_translationClearPushButton_clicked() // Build translation clearing command and connect it to the current palette widget // to update the PAL/TRN and CEL views when undo/redo is performed std::unique_ptr command = std::make_unique( - this->trn, this->selectedFirstColorIndex, this->selectedLastColorIndex); + this->m_trn, this->selectedFirstColorIndex, this->selectedLastColorIndex); QObject::connect(command.get(), &ClearTranslationsCommand::modified, this, &PaletteWidget::modify); this->undoStack->push(std::move(command)); @@ -942,8 +1155,8 @@ void PaletteWidget::on_monsterTrnPushButton_clicked() bool trnModified = false; for (int i = 0; i < D1PAL_COLORS; i++) { - if (this->trn->getTranslation(i) == 0xFF) { - this->trn->setTranslation(i, 0); + if (this->m_trn->getTranslation(i) == 0xFF) { + this->m_trn->setTranslation(i, 0); trnModified = true; } } diff --git a/source/widgets/palettewidget.h b/source/widgets/palettewidget.h index 2969260fa..e572b4ef7 100644 --- a/source/widgets/palettewidget.h +++ b/source/widgets/palettewidget.h @@ -120,6 +120,17 @@ private slots: QWidget *view; }; +using PaletteFileInfo = struct PaletteFileInfo { + QString name; // e.g., "palette" or "translation" + QString suffix; // e.g., ".pal" or ".trn" +}; + +enum class PaletteType : std::uint8_t { + Palette = 0, + Translation = 1, + UniqTranslation = 2 +}; + class PaletteWidget : public QWidget { Q_OBJECT @@ -127,15 +138,15 @@ class PaletteWidget : public QWidget { explicit PaletteWidget(std::shared_ptr undoStack, QString title); ~PaletteWidget(); - void setPal(D1Pal *p); - void setTrn(D1Trn *t); + void setPal(const QString &path); + void setTrn(const QString &path); bool isTrnWidget(); - void initialize(D1Pal *p, CelView *c, D1PalHits *ph); - void initialize(D1Pal *p, LevelCelView *lc, D1PalHits *ph); + void initialize(D1Pal *p, CelView *c, D1PalHits *ph, PaletteType palType); + void initialize(D1Pal *p, LevelCelView *lc, D1PalHits *ph, PaletteType palType); - void initialize(D1Pal *p, D1Trn *t, CelView *c, D1PalHits *ph); - void initialize(D1Pal *p, D1Trn *t, LevelCelView *lc, D1PalHits *ph); + void initialize(D1Pal *p, D1Trn *t, CelView *c, D1PalHits *ph, PaletteType palType); + void initialize(D1Pal *p, D1Trn *t, LevelCelView *lc, D1PalHits *ph, PaletteType palType); void initializeUi(); void initializePathComboBox(); @@ -145,16 +156,37 @@ class PaletteWidget : public QWidget { void selectColor(quint8); void checkTranslationsSelection(QList); - void addPath(QString, QString); - void removePath(QString); - void selectPath(QString); - QString getSelectedPath(); + void addPath(const QString &, const QString &, D1Pal *pal); + void removePath(const QString &); + void selectPath(const QString &); + + QString getWidgetsDefaultPath() const; + QString getSelectedPath() const; // color selection handlers void startColorSelection(int colorIndex); void changeColorSelection(int colorIndex); void finishColorSelection(); + [[nodiscard]] D1Pal *pal() const + { + return m_pal; + }; + [[nodiscard]] D1Trn *trn() const + { + return m_trn; + }; + + void save(); + void newOrSaveAsFile(PWIDGET_CALLBACK_TYPE action); + bool loadPalette(const QString &filepath); + void openPalette(); + + bool isOkToQuit(); + + void closePalette(); + + void setTrnPalette(D1Pal *pal); // Display functions bool displayColor(int index); void displayColors(); @@ -187,6 +219,8 @@ class PaletteWidget : public QWidget { void refreshed(); private: + [[nodiscard]] PaletteFileInfo paletteFileInfo() const; + void performSave(const QString &palFilePath, const PaletteFileInfo &fileInfo); QPushButton *addButton(QStyle::StandardPixmap type, QString tooltip, void (PaletteWidget::*callback)(void)); public slots: @@ -217,7 +251,6 @@ private slots: private: std::shared_ptr undoStack; Ui::PaletteWidget *ui; - bool isTrn; CelView *celView; LevelCelView *levelCelView; @@ -233,10 +266,12 @@ private slots: bool pickingTranslationColor = false; bool temporarilyDisplayingAllColors = false; - QPointer pal; - QPointer trn; + D1Pal *m_pal; + D1Trn *m_trn; + + PaletteType m_paletteType; D1PalHits *palHits; - QMap paths; + std::map> m_palettes_map; };