diff --git a/forms/newmapdialog.ui b/forms/newmapdialog.ui
index dcf4f052..3ddba1dc 100644
--- a/forms/newmapdialog.ui
+++ b/forms/newmapdialog.ui
@@ -25,7 +25,7 @@
0
0
427
- 526
+ 520
@@ -39,24 +39,23 @@
- -
-
+
-
+
+
+ false
+
+
+ color: rgb(255, 0, 0)
+
- ID
+
-
-
- -
-
-
- <html><head/><body><p>The name of the new map. The name cannot be the same as any other existing map.</p></body></html>
-
-
+
true
- -
+
-
false
@@ -72,7 +71,7 @@
- -
+
-
Border Dimensions
@@ -127,115 +126,14 @@
- -
-
+
-
+
- Group
+ ID
- -
-
-
- Qt::Orientation::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- false
-
-
- color: rgb(255, 0, 0)
-
-
-
-
-
- true
-
-
-
- -
-
-
- Can Fly To
-
-
-
- -
-
-
- Tilesets
-
-
-
-
-
-
- Primary
-
-
-
- -
-
-
- <html><head/><body><p>The primary tileset for the new map.</p></body></html>
-
-
- true
-
-
- QComboBox::InsertPolicy::NoInsert
-
-
-
- -
-
-
- Secondary
-
-
-
- -
-
-
- <html><head/><body><p>The secondary tileset for the new map.</p></body></html>
-
-
- true
-
-
- QComboBox::InsertPolicy::NoInsert
-
-
-
- -
-
-
- false
-
-
- color: rgb(255, 0, 0)
-
-
-
-
-
- true
-
-
-
-
-
-
- -
+
-
Map Dimensions
@@ -306,14 +204,102 @@
- -
+
-
+
+
+ <html><head/><body><p>The name of the group this map will be added to.</p></body></html>
+
+
+ true
+
+
+ QComboBox::InsertPolicy::NoInsert
+
+
+
+ -
<html><head/><body><p>The constant that will be used to refer to this map. It cannot be the same as any other existing map, and it must start with the specified prefix.</p></body></html>
- -
+
-
+
+
+ <html><head/><body><p>The name of the new map. The name cannot be the same as any other existing map.</p></body></html>
+
+
+ true
+
+
+
+ -
+
+
+ Tilesets
+
+
+
-
+
+
+ Primary
+
+
+
+ -
+
+
+ <html><head/><body><p>The primary tileset for the new map.</p></body></html>
+
+
+ true
+
+
+ QComboBox::InsertPolicy::NoInsert
+
+
+
+ -
+
+
+ Secondary
+
+
+
+ -
+
+
+ <html><head/><body><p>The secondary tileset for the new map.</p></body></html>
+
+
+ true
+
+
+ QComboBox::InsertPolicy::NoInsert
+
+
+
+ -
+
+
+ false
+
+
+ color: rgb(255, 0, 0)
+
+
+
+
+
+ true
+
+
+
+
+
+
+ -
false
@@ -329,28 +315,45 @@
- -
-
-
- Header Data
+
-
+
+
+ Qt::Orientation::Vertical
-
-
+
+
+ 20
+ 40
+
+
+
- -
-
-
- <html><head/><body><p>The name of the group this map will be added to.</p></body></html>
-
-
- true
-
-
- QComboBox::InsertPolicy::NoInsert
+
-
+
+
+ Group
- -
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+ -
<html><head/><body><p>If checked, a Heal Location will be added to this map automatically.</p></body></html>
@@ -360,6 +363,13 @@
+ -
+
+
+ Can Fly To
+
+
+
diff --git a/include/config.h b/include/config.h
index 2a93a793..0dcbfe66 100644
--- a/include/config.h
+++ b/include/config.h
@@ -70,6 +70,7 @@ public:
this->showTilesetEditorLayerGrid = true;
this->monitorFiles = true;
this->tilesetCheckerboardFill = true;
+ this->newMapHeaderSectionExpanded = false;
this->theme = "default";
this->wildMonChartTheme = "";
this->textEditorOpenFolder = "";
@@ -121,6 +122,7 @@ public:
bool showTilesetEditorLayerGrid;
bool monitorFiles;
bool tilesetCheckerboardFill;
+ bool newMapHeaderSectionExpanded;
QString theme;
QString wildMonChartTheme;
QString textEditorOpenFolder;
diff --git a/include/lib/collapsiblesection.h b/include/lib/collapsiblesection.h
index 3a1b3023..584e44cb 100644
--- a/include/lib/collapsiblesection.h
+++ b/include/lib/collapsiblesection.h
@@ -16,6 +16,10 @@
You should have received a copy of the GNU General Public License
along with Elypson/qt-collapsible-section. If not, see .
+
+
+ PORYMAP NOTE: Modified to support having the section expanded by default, to stop the contents
+ squashing during the collapse animation, and to add some guard rails against crashes.
*/
#ifndef COLLAPSIBLESECTION_H
@@ -24,6 +28,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -31,32 +36,33 @@
class CollapsibleSection : public QWidget
{
Q_OBJECT
+
+public:
+ explicit CollapsibleSection(const QString& title = "", const bool expanded = false, const int animationDuration = 0, QWidget* parent = 0);
+
+ void setContentLayout(QLayout* contentLayout);
+ void setTitle(QString title);
+ bool isExpanded() const { return this->expanded; }
+
+public slots:
+ void toggle(bool collapsed);
private:
QGridLayout* mainLayout;
QToolButton* toggleButton;
QFrame* headerLine;
QParallelAnimationGroup* toggleAnimation;
+ QSet sectionAnimations;
+ QPropertyAnimation* contentAnimation;
QScrollArea* contentArea;
int animationDuration;
int collapsedHeight;
- bool isExpanded = false;
-
-public slots:
- void toggle(bool collapsed);
+ bool expanded;
-public:
- // initialize section
- explicit CollapsibleSection(const QString& title = "", const int animationDuration = 0, QWidget* parent = 0);
+ void updateToggleButton();
+ void updateAnimationTargets();
+ int getContentHeight() const;
- // set layout of content
- void setContentLayout(QLayout& contentLayout);
-
- // set title
- void setTitle(QString title);
-
- // update animations and their heights
- void updateHeights();
};
#endif // COLLAPSIBLESECTION_H
diff --git a/include/ui/newmapdialog.h b/include/ui/newmapdialog.h
index 090fcb96..72b0b5de 100644
--- a/include/ui/newmapdialog.h
+++ b/include/ui/newmapdialog.h
@@ -7,6 +7,7 @@
#include "project.h"
#include "map.h"
#include "mapheaderform.h"
+#include "lib/collapsiblesection.h"
namespace Ui {
class NewMapDialog;
@@ -24,7 +25,7 @@ public:
bool importedMap;
QString layoutId;
void init();
- //void initUi();
+ //void initUi();//TODO
void init(int tabIndex, QString data);
void init(Layout *);
static void setDefaultSettings(Project *project);
@@ -35,6 +36,7 @@ signals:
private:
Ui::NewMapDialog *ui;
Project *project;
+ CollapsibleSection *headerSection;
MapHeaderForm *headerData;
bool validateMapDimensions();
diff --git a/src/config.cpp b/src/config.cpp
index a1987203..316c9ea3 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -371,6 +371,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
this->monitorFiles = getConfigBool(key, value);
} else if (key == "tileset_checkerboard_fill") {
this->tilesetCheckerboardFill = getConfigBool(key, value);
+ } else if (key == "new_map_header_section_expanded") {
+ this->newMapHeaderSectionExpanded = getConfigBool(key, value);
} else if (key == "theme") {
this->theme = value;
} else if (key == "wild_mon_chart_theme") {
@@ -453,6 +455,7 @@ QMap PorymapConfig::getKeyValueMap() {
map.insert("show_tileset_editor_layer_grid", this->showTilesetEditorLayerGrid ? "1" : "0");
map.insert("monitor_files", this->monitorFiles ? "1" : "0");
map.insert("tileset_checkerboard_fill", this->tilesetCheckerboardFill ? "1" : "0");
+ map.insert("new_map_header_section_expanded", this->newMapHeaderSectionExpanded ? "1" : "0");
map.insert("theme", this->theme);
map.insert("wild_mon_chart_theme", this->wildMonChartTheme);
map.insert("text_editor_open_directory", this->textEditorOpenFolder);
diff --git a/src/lib/collapsiblesection.cpp b/src/lib/collapsiblesection.cpp
index 000e822e..34dfb780 100644
--- a/src/lib/collapsiblesection.cpp
+++ b/src/lib/collapsiblesection.cpp
@@ -16,13 +16,15 @@
You should have received a copy of the GNU General Public License
along with Elypson/qt-collapsible-section. If not, see .
+
+
+ PORYMAP NOTE: Modified to support having the section expanded by default, to stop the contents
+ squashing during the collapse animation, and to add some guard rails against crashes.
*/
-#include
-
#include "collapsiblesection.h"
-CollapsibleSection::CollapsibleSection(const QString& title, const int animationDuration, QWidget* parent)
- : QWidget(parent), animationDuration(animationDuration)
+CollapsibleSection::CollapsibleSection(const QString& title, const bool expanded, const int animationDuration, QWidget* parent)
+ : QWidget(parent), animationDuration(animationDuration), expanded(expanded)
{
toggleButton = new QToolButton(this);
headerLine = new QFrame(this);
@@ -32,25 +34,24 @@ CollapsibleSection::CollapsibleSection(const QString& title, const int animation
toggleButton->setStyleSheet("QToolButton {border: none;}");
toggleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- toggleButton->setArrowType(Qt::ArrowType::RightArrow);
toggleButton->setText(title);
toggleButton->setCheckable(true);
- toggleButton->setChecked(false);
+ updateToggleButton();
headerLine->setFrameShape(QFrame::HLine);
headerLine->setFrameShadow(QFrame::Sunken);
headerLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
contentArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-
- // start out collapsed
contentArea->setMaximumHeight(0);
contentArea->setMinimumHeight(0);
- // let the entire widget grow and shrink with its content
- toggleAnimation->addAnimation(new QPropertyAnimation(this, "maximumHeight"));
- toggleAnimation->addAnimation(new QPropertyAnimation(this, "minimumHeight"));
- toggleAnimation->addAnimation(new QPropertyAnimation(contentArea, "maximumHeight"));
+ sectionAnimations.insert(new QPropertyAnimation(this, "minimumHeight"));
+ sectionAnimations.insert(new QPropertyAnimation(this, "maximumHeight"));
+ for (const auto &anim : sectionAnimations)
+ toggleAnimation->addAnimation(anim);
+ contentAnimation = new QPropertyAnimation(contentArea, "maximumHeight");
+ toggleAnimation->addAnimation(contentAnimation);
mainLayout->setVerticalSpacing(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
@@ -64,22 +65,58 @@ CollapsibleSection::CollapsibleSection(const QString& title, const int animation
connect(toggleButton, &QToolButton::toggled, this, &CollapsibleSection::toggle);
}
-void CollapsibleSection::toggle(bool expanded)
+void CollapsibleSection::updateToggleButton()
{
- toggleButton->setArrowType(expanded ? Qt::ArrowType::DownArrow : Qt::ArrowType::RightArrow);
- toggleAnimation->setDirection(expanded ? QAbstractAnimation::Forward : QAbstractAnimation::Backward);
- toggleAnimation->start();
-
- this->isExpanded = expanded;
+ toggleButton->setChecked(this->expanded);
+ toggleButton->setArrowType(this->expanded ? Qt::ArrowType::DownArrow : Qt::ArrowType::RightArrow);
}
-void CollapsibleSection::setContentLayout(QLayout& contentLayout)
+void CollapsibleSection::toggle(bool expand)
{
+ if (toggleAnimation->state() != QAbstractAnimation::Stopped)
+ return;
+ if (this->expanded == expand)
+ return;
+ this->expanded = expand;
+
+ updateToggleButton();
+
+ if (expand) {
+ // Opening animation. Set the contents to their maximum size immediately,
+ // and they will be revealed slowly by the section animation.
+ int contentHeight = getContentHeight();
+ contentArea->setMinimumHeight(contentHeight);
+ contentArea->setMaximumHeight(contentHeight);
+ toggleAnimation->setDirection(QAbstractAnimation::Forward);
+ } else {
+ // Closing animation. Keep the contents at their current size, allowing
+ // them to be hidden slowly by the section animation, then change their size
+ // once the animation is complete so they aren't visible just below the title.
+ auto ctx = new QObject();
+ connect(toggleAnimation, &QAbstractAnimation::finished, ctx, [this, ctx]() {
+ // This is a single-shot connection. Qt6 has built-in support for this kind of thing.
+ contentArea->setMinimumHeight(0);
+ contentArea->setMaximumHeight(0);
+ ctx->deleteLater();
+ });
+ toggleAnimation->setDirection(QAbstractAnimation::Backward);
+ }
+ toggleAnimation->start();
+}
+
+void CollapsibleSection::setContentLayout(QLayout* contentLayout)
+{
+ if (contentArea->layout() == contentLayout)
+ return;
delete contentArea->layout();
- contentArea->setLayout(&contentLayout);
+ contentArea->setLayout(contentLayout);
collapsedHeight = sizeHint().height() - contentArea->maximumHeight();
-
- updateHeights();
+
+ int contentHeight = this->expanded ? getContentHeight() : 0;
+ contentArea->setMinimumHeight(contentHeight);
+ contentArea->setMaximumHeight(contentHeight);
+
+ updateAnimationTargets();
}
void CollapsibleSection::setTitle(QString title)
@@ -87,23 +124,20 @@ void CollapsibleSection::setTitle(QString title)
toggleButton->setText(std::move(title));
}
-void CollapsibleSection::updateHeights()
+int CollapsibleSection::getContentHeight() const
{
- int contentHeight = contentArea->layout()->sizeHint().height();
+ return contentArea->layout() ? contentArea->layout()->sizeHint().height() : 0;
+}
- for (int i = 0; i < toggleAnimation->animationCount() - 1; ++i)
- {
- QPropertyAnimation* SectionAnimation = static_cast(toggleAnimation->animationAt(i));
- SectionAnimation->setDuration(animationDuration);
- SectionAnimation->setStartValue(collapsedHeight);
- SectionAnimation->setEndValue(collapsedHeight + contentHeight);
+void CollapsibleSection::updateAnimationTargets()
+{
+ const int contentHeight = getContentHeight();
+ for (auto anim : sectionAnimations) {
+ anim->setDuration(animationDuration);
+ anim->setStartValue(collapsedHeight);
+ anim->setEndValue(collapsedHeight + contentHeight);
}
-
- QPropertyAnimation* contentAnimation = static_cast(toggleAnimation->animationAt(toggleAnimation->animationCount() - 1));
contentAnimation->setDuration(animationDuration);
contentAnimation->setStartValue(0);
contentAnimation->setEndValue(contentHeight);
-
- toggleAnimation->setDirection(isExpanded ? QAbstractAnimation::Forward : QAbstractAnimation::Backward);
- toggleAnimation->start();
}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index d47dfef2..50c4b4d8 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -86,11 +86,27 @@ MainWindow::MainWindow(QWidget *parent) :
MainWindow::~MainWindow()
{
+ // Some config settings are updated as subwindows are destroyed (e.g. their geometry),
+ // so we need to ensure that the configs are saved after this happens.
+ saveGlobalConfigs();
+
delete label_MapRulerStatus;
delete editor;
delete ui;
}
+void MainWindow::saveGlobalConfigs() {
+ porymapConfig.setMainGeometry(
+ this->saveGeometry(),
+ this->saveState(),
+ this->ui->splitter_map->saveState(),
+ this->ui->splitter_main->saveState(),
+ this->ui->splitter_Metatiles->saveState()
+ );
+ porymapConfig.save();
+ shortcutsConfig.save();
+}
+
void MainWindow::setWindowDisabled(bool disabled) {
for (auto action : findChildren())
action->setDisabled(disabled);
@@ -1739,12 +1755,14 @@ void MainWindow::on_action_Save_Project_triggered() {
editor->saveProject();
updateWindowTitle();
updateMapList();
+ saveGlobalConfigs();
}
void MainWindow::on_action_Save_triggered() {
editor->save();
updateWindowTitle();
updateMapList();
+ saveGlobalConfigs();
}
void MainWindow::duplicate() {
@@ -3282,24 +3300,9 @@ bool MainWindow::closeProject() {
return true;
}
-void MainWindow::saveGlobalConfigs() {
- porymapConfig.setMainGeometry(
- this->saveGeometry(),
- this->saveState(),
- this->ui->splitter_map->saveState(),
- this->ui->splitter_main->saveState(),
- this->ui->splitter_Metatiles->saveState()
- );
- porymapConfig.save();
- shortcutsConfig.save();
-}
-
void MainWindow::on_action_Exit_triggered() {
if (!closeProject())
return;
-
- saveGlobalConfigs();
-
QApplication::quit();
}
@@ -3308,8 +3311,5 @@ void MainWindow::closeEvent(QCloseEvent *event) {
event->ignore();
return;
}
-
- saveGlobalConfigs();
-
QMainWindow::closeEvent(event);
}
diff --git a/src/ui/newmapdialog.cpp b/src/ui/newmapdialog.cpp
index d3096a86..ff4cb209 100644
--- a/src/ui/newmapdialog.cpp
+++ b/src/ui/newmapdialog.cpp
@@ -8,8 +8,6 @@
#include
#include
-// TODO: Make ui->groupBox_HeaderData collapsible
-
const QString lineEdit_ErrorStylesheet = "QLineEdit { background-color: rgba(255, 0, 0, 25%) }";
struct NewMapDialog::Settings NewMapDialog::settings = {};
@@ -31,8 +29,15 @@ NewMapDialog::NewMapDialog(QWidget *parent, Project *project) :
ui->lineEdit_Name->setValidator(validator);
ui->lineEdit_ID->setValidator(validator);
+ // Create a collapsible section that has all the map header data.
this->headerData = new MapHeaderForm();
- ui->layout_HeaderData->addWidget(this->headerData);
+ auto sectionLayout = new QVBoxLayout();
+ sectionLayout->addWidget(this->headerData);
+
+ this->headerSection = new CollapsibleSection("Header Data", porymapConfig.newMapHeaderSectionExpanded, 150, this);
+ this->headerSection->setContentLayout(sectionLayout);
+ ui->layout_HeaderData->addWidget(this->headerSection);
+ ui->layout_HeaderData->addItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::Expanding));
connect(ui->spinBox_MapWidth, QOverload::of(&QSpinBox::valueChanged), [=](int){validateMapDimensions();});
connect(ui->spinBox_MapHeight, QOverload::of(&QSpinBox::valueChanged), [=](int){validateMapDimensions();});
@@ -162,6 +167,7 @@ void NewMapDialog::saveSettings() {
settings.allowEscaping = this->headerData->ui->checkBox_AllowEscaping->isChecked();
settings.floorNumber = this->headerData->ui->spinBox_FloorNumber->value();
settings.canFlyTo = ui->checkBox_CanFlyTo->isChecked();
+ porymapConfig.newMapHeaderSectionExpanded = this->headerSection->isExpanded();
}
void NewMapDialog::useLayoutSettings(Layout *layout) {