From b1814e0e3f55fbec581e7c67c50f1e4a4f348882 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 21 Aug 2024 13:06:30 -0400 Subject: [PATCH] Initial wild pokemon summary chart --- forms/mainwindow.ui | 7 +++ forms/wildmonchart.ui | 43 +++++++++++++++ include/editor.h | 1 + include/mainwindow.h | 3 + include/ui/encountertablemodel.h | 1 + include/ui/wildmonchart.h | 28 ++++++++++ porymap.pro | 11 ++-- src/editor.cpp | 6 ++ src/mainwindow.cpp | 10 ++++ src/ui/wildmonchart.cpp | 94 ++++++++++++++++++++++++++++++++ 10 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 forms/wildmonchart.ui create mode 100644 include/ui/wildmonchart.h create mode 100644 src/ui/wildmonchart.cpp diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 8e586198..899c9376 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -3010,6 +3010,13 @@ + + + + Summary Chart... + + + diff --git a/forms/wildmonchart.ui b/forms/wildmonchart.ui new file mode 100644 index 00000000..035272c2 --- /dev/null +++ b/forms/wildmonchart.ui @@ -0,0 +1,43 @@ + + + WildMonChart + + + + 0 + 0 + 400 + 300 + + + + Wild Pokémon Summary + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + QChartView + QGraphicsView +
QtCharts
+
+
+ + +
diff --git a/include/editor.h b/include/editor.h index 8e30ae70..939f5a59 100644 --- a/include/editor.h +++ b/include/editor.h @@ -83,6 +83,7 @@ public: void removeCurrentConnection(); void addNewWildMonGroup(QWidget *window); void deleteWildMonGroup(); + QTableView* getCurrentWildMonTable(); void updateDiveMap(QString mapName); void updateEmergeMap(QString mapName); void setSelectedConnectionFromMap(QString mapName); diff --git a/include/mainwindow.h b/include/mainwindow.h index d58d11c0..4f35d551 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -27,6 +27,7 @@ #include "preferenceeditor.h" #include "projectsettingseditor.h" #include "customscriptseditor.h" +#include "wildmonchart.h" #include "updatepromoter.h" #include "aboutporymap.h" @@ -285,6 +286,7 @@ private slots: void on_horizontalSlider_CollisionZoom_valueChanged(int value); void on_pushButton_NewWildMonGroup_clicked(); void on_pushButton_DeleteWildMonGroup_clicked(); + void on_pushButton_SummaryChart_clicked(); void on_pushButton_ConfigureEncountersJSON_clicked(); void on_pushButton_CreatePrefab_clicked(); void on_spinBox_SelectedElevation_valueChanged(int elevation); @@ -314,6 +316,7 @@ private: QPointer updatePromoter = nullptr; QPointer networkAccessManager = nullptr; QPointer aboutWindow = nullptr; + QPointer wildMonChart = nullptr; FilterChildrenProxyModel *mapListProxyModel; QStandardItemModel *mapListModel; QList *mapGroupItemsList; diff --git a/include/ui/encountertablemodel.h b/include/ui/encountertablemodel.h index 6aacbf30..1a05476a 100644 --- a/include/ui/encountertablemodel.h +++ b/include/ui/encountertablemodel.h @@ -29,6 +29,7 @@ public: }; WildMonInfo encounterData(); + QList percentages() const { return slotPercentages; } void resize(int rows, int cols); private: diff --git a/include/ui/wildmonchart.h b/include/ui/wildmonchart.h new file mode 100644 index 00000000..62560207 --- /dev/null +++ b/include/ui/wildmonchart.h @@ -0,0 +1,28 @@ +#ifndef WILDMONCHART_H +#define WILDMONCHART_H + +#include "encountertablemodel.h" + +#include + +namespace Ui { +class WildMonChart; +} + +class WildMonChart : public QWidget +{ + Q_OBJECT +public: + explicit WildMonChart(QWidget *parent, EncounterTableModel *data); + ~WildMonChart(); + +public slots: + void setChartData(EncounterTableModel *data); + void updateChart(); + +private: + Ui::WildMonChart *ui; + EncounterTableModel *data; +}; + +#endif // WILDMONCHART_H diff --git a/porymap.pro b/porymap.pro index dfc3306e..b7a6f789 100644 --- a/porymap.pro +++ b/porymap.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui qml network +QT += core gui qml network charts greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -106,7 +106,8 @@ SOURCES += src/core/block.cpp \ src/settings.cpp \ src/log.cpp \ src/ui/uintspinbox.cpp \ - src/ui/updatepromoter.cpp + src/ui/updatepromoter.cpp \ + src/ui/wildmonchart.cpp HEADERS += include/core/block.h \ include/core/bitpacker.h \ @@ -202,7 +203,8 @@ HEADERS += include/core/block.h \ include/settings.h \ include/log.h \ include/ui/uintspinbox.h \ - include/ui/updatepromoter.h + include/ui/updatepromoter.h \ + include/ui/wildmonchart.h FORMS += forms/mainwindow.ui \ forms/prefabcreationdialog.ui \ @@ -221,7 +223,8 @@ FORMS += forms/mainwindow.ui \ forms/projectsettingseditor.ui \ forms/customscriptseditor.ui \ forms/customscriptslistitem.ui \ - forms/updatepromoter.ui + forms/updatepromoter.ui \ + forms/wildmonchart.ui RESOURCES += \ resources/images.qrc \ diff --git a/src/editor.cpp b/src/editor.cpp index 46aa0458..604df065 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -698,6 +698,12 @@ void Editor::saveEncounterTabData() { } } +QTableView* Editor::getCurrentWildMonTable() { + QStackedWidget *stack = ui->stackedWidget_WildMons; + auto tabWidget = static_cast(stack->widget(stack->currentIndex())); + return tabWidget->tableAt(tabWidget->currentIndex()); +} + void Editor::updateEncounterFields(EncounterFields newFields) { EncounterFields oldFields = project->wildMonFields; // Go through fields and determine whether we need to update a field. diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 39167597..f4557ac4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2572,6 +2572,16 @@ void MainWindow::on_pushButton_DeleteWildMonGroup_clicked() { editor->deleteWildMonGroup(); } +void MainWindow::on_pushButton_SummaryChart_clicked() { + if (!this->wildMonChart) { + // TODO: Move to editor, connect to signals for when the table data changes + QTableView *table = this->editor->getCurrentWildMonTable(); + EncounterTableModel *data = table ? static_cast(table->model()) : nullptr; + this->wildMonChart = new WildMonChart(this, data); + } + openSubWindow(this->wildMonChart); +} + void MainWindow::on_pushButton_ConfigureEncountersJSON_clicked() { editor->configureEncounterJSON(this); } diff --git a/src/ui/wildmonchart.cpp b/src/ui/wildmonchart.cpp new file mode 100644 index 00000000..1047e92b --- /dev/null +++ b/src/ui/wildmonchart.cpp @@ -0,0 +1,94 @@ +#include "wildmonchart.h" +#include "ui_wildmonchart.h" + +#include + +WildMonChart::WildMonChart(QWidget *parent, EncounterTableModel *data) : + QWidget(parent), + ui(new Ui::WildMonChart) +{ + ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + setWindowFlags(Qt::Window); + + ui->chartView->setRenderHint(QPainter::Antialiasing); + + setChartData(data); +}; + +WildMonChart::~WildMonChart() { + delete ui; +}; + +void WildMonChart::setChartData(EncounterTableModel *data) { + this->data = data; + updateChart(); +} + +void WildMonChart::updateChart() { + // TODO: Handle empty chart + if (!this->data) + return; + + const QList inputValues = data->percentages(); + const QVector inputPokemon = data->encounterData().wildPokemon; + + QList chartValues; + QList chartPokemon; + + // Combine data for duplicate species entries + QList seenSpecies; + for (int i = 0; i < qMin(inputValues.length(), inputPokemon.length()); i++) { + const double percent = inputValues.at(i); + const WildPokemon pokemon = inputPokemon.at(i); + + int existingIndex = seenSpecies.indexOf(pokemon.species); + if (existingIndex >= 0) { + // Duplicate species entry + chartValues[existingIndex] += percent; + if (pokemon.minLevel < chartPokemon.at(existingIndex).minLevel) + chartPokemon[existingIndex].minLevel = pokemon.minLevel; + if (pokemon.maxLevel > chartPokemon.at(existingIndex).maxLevel) + chartPokemon[existingIndex].maxLevel = pokemon.maxLevel; + } else { + // New species entry + chartValues.append(percent); + chartPokemon.append(pokemon); + seenSpecies.append(pokemon.species); + } + } + + // TODO: If pokemon < values, fill remainder with an "empty" slice + + // Populate chart + //const QString speciesPrefix = projectConfig.getIdentifier(ProjectIdentifier::regex_species); // TODO: Change regex to prefix + const QString speciesPrefix = "SPECIES_"; + QPieSeries *series = new QPieSeries(); + for (int i = 0; i < qMin(chartValues.length(), chartPokemon.length()); i++) { + const double percent = chartValues.at(i); + const WildPokemon pokemon = chartPokemon.at(i); + + // Strip 'SPECIES_' prefix + QString name = pokemon.species; + if (name.startsWith(speciesPrefix)) + name.remove(0, speciesPrefix.length()); + + QString label = QString("%1\nLv %2").arg(name).arg(pokemon.minLevel); + if (pokemon.minLevel != pokemon.maxLevel) + label.append(QString("-%1").arg(pokemon.maxLevel)); + label.append(QString(" (%1%)").arg(percent * 100)); + + QPieSlice *slice = new QPieSlice(label, percent); + //slice->setLabelPosition(QPieSlice::LabelInsideNormal); + slice->setLabelVisible(); + series->append(slice); + } + + QChart *chart = new QChart(); + chart->addSeries(series); + chart->legend()->hide(); + + ui->chartView->setChart(chart); // TODO: Leaking old chart + + // TODO: Draw icons onto slices +}