Skip to content

Commit 8a789d8

Browse files
committed
fixed macOS file dialog and build
1 parent f428ca9 commit 8a789d8

File tree

11 files changed

+328
-29
lines changed

11 files changed

+328
-29
lines changed

app/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(APP_NAME "PPUC-Serum-Colorizer")
2+
set(APP_BUNDLE_ID "org.ppuc.serum-colorizer")
23
add_executable(${APP_NAME})
34

45
set(APP_ICON_PNG ${CMAKE_SOURCE_DIR}/icons/app-icon.png)
@@ -7,9 +8,11 @@ set(APP_ICON_ICO ${CMAKE_SOURCE_DIR}/icons/app-icon.ico)
78

89
set(HANDBOOK_MD ${CMAKE_SOURCE_DIR}/handbook.md)
910
set(HANDBOOK_QRC ${CMAKE_CURRENT_BINARY_DIR}/handbook.qrc)
11+
set(APP_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
1012

1113
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/handbook.qrc.in ${HANDBOOK_QRC} @ONLY)
1214
set_source_files_properties(${HANDBOOK_QRC} PROPERTIES GENERATED TRUE)
15+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in ${APP_INFO_PLIST} @ONLY)
1316

1417
target_sources(${APP_NAME} PRIVATE
1518
main.cpp
@@ -38,6 +41,7 @@ if (APPLE)
3841
set_target_properties(${APP_NAME} PROPERTIES
3942
MACOSX_BUNDLE TRUE
4043
MACOSX_BUNDLE_ICON_FILE "app-icon"
44+
MACOSX_BUNDLE_INFO_PLIST ${APP_INFO_PLIST}
4145
)
4246
if (EXISTS ${APP_ICON_ICNS})
4347
set_source_files_properties(${APP_ICON_ICNS} PROPERTIES

app/Info.plist.in

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>en</string>
7+
<key>CFBundleExecutable</key>
8+
<string>@APP_NAME@</string>
9+
<key>CFBundleIconFile</key>
10+
<string>app-icon</string>
11+
<key>CFBundleIdentifier</key>
12+
<string>@APP_BUNDLE_ID@</string>
13+
<key>CFBundleName</key>
14+
<string>@APP_NAME@</string>
15+
<key>CFBundleShortVersionString</key>
16+
<string>@PROJECT_VERSION@</string>
17+
<key>CFBundleVersion</key>
18+
<string>@PROJECT_VERSION@</string>
19+
<key>LSMinimumSystemVersion</key>
20+
<string>12.0</string>
21+
<key>NSHighResolutionCapable</key>
22+
<true/>
23+
</dict>
24+
</plist>

app/MainWindow.cpp

Lines changed: 114 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,10 @@ MainWindow::MainWindow(QWidget* parent)
945945
auto* openAction = new QAction(QIcon(":/icons/open.png"), "&Open...", this);
946946
auto* saveAction = new QAction(QIcon(":/icons/save.png"), "&Save", this);
947947
auto* saveAsAction = new QAction("Save &As...", this);
948+
saveAction->setShortcut(QKeySequence::Save);
949+
saveAction->setShortcutContext(Qt::ApplicationShortcut);
950+
saveAsAction->setShortcut(QKeySequence::SaveAs);
951+
saveAsAction->setShortcutContext(Qt::ApplicationShortcut);
948952
auto* importImageAction = new QAction(QIcon(":/icons/import.png"), "Import &Image...", this);
949953
auto* exitAction = new QAction("E&xit", this);
950954
auto* addFrameAction = new QAction(QIcon(":/icons/add.png"), "Add &Frame", this);
@@ -1165,10 +1169,16 @@ MainWindow::MainWindow(QWidget* parent)
11651169
updateMetadataForFrame(-1);
11661170
updateMetadataForSprite(-1);
11671171
populateBookmarks({}, {});
1172+
m_hasLegacyRoundTrip = false;
1173+
m_legacyRoundTrip = LegacyRoundTripData{};
11681174
statusBar()->showMessage("New project (stub)", 3000);
11691175
});
11701176
connect(openAction, &QAction::triggered, this, [this]() {
1171-
const QString filename = QFileDialog::getOpenFileName(this, "Open Project", QString(), "Serum Projects (*.crom *.cROM *.crp *.cRP);;All Files (*.*)");
1177+
const QString filename = QFileDialog::getOpenFileName(
1178+
this,
1179+
"Open Project",
1180+
QString(),
1181+
"Serum Projects (*.crom *.cROM *.crp *.cRP);;All Files (*.*)");
11721182
if (!filename.isEmpty()) {
11731183
openProjectFile(filename);
11741184
}
@@ -1188,12 +1198,21 @@ MainWindow::MainWindow(QWidget* parent)
11881198
}
11891199
});
11901200
connect(saveAsAction, &QAction::triggered, this, [this]() {
1191-
const QString filename = QFileDialog::getSaveFileName(this, "Save Project As", QString(), "Serum Projects (*.crom *.cROM *.crp *.cRP)");
1201+
const QString filename = QFileDialog::getSaveFileName(
1202+
this,
1203+
"Save Project As",
1204+
QString(),
1205+
"Serum Projects (*.crom *.cROM *.crp *.cRP)");
1206+
if (filename.isEmpty()) {
1207+
return;
1208+
}
11921209
if (filename.isEmpty()) {
11931210
return;
11941211
}
11951212
if (saveProjectToPath(filename)) {
1196-
statusBar()->showMessage(QString("Save As: %1").arg(m_state->projectPath()), 5000);
1213+
updateWindowTitle();
1214+
persistRecentFiles();
1215+
statusBar()->showMessage(QString("Save As: %1").arg(filename), 5000);
11971216
} else {
11981217
statusBar()->showMessage("Save failed", 5000);
11991218
}
@@ -4420,6 +4439,8 @@ void MainWindow::openProjectFile(const QString& filename)
44204439
updateMetadataForFrame(-1);
44214440
updateMetadataForSprite(-1);
44224441
populateBookmarks({}, {});
4442+
m_hasLegacyRoundTrip = false;
4443+
m_legacyRoundTrip = LegacyRoundTripData{};
44234444
if (LoadProjectJson(*m_state, filename, &error)) {
44244445
resetUndoStacks();
44254446
resetNavigationHistory();
@@ -4459,6 +4480,33 @@ void MainWindow::openProjectFile(const QString& filename)
44594480
statusBar()->showMessage(QString("Open failed: %1").arg(QString::fromStdString(error)), 5000);
44604481
return;
44614482
}
4483+
m_hasLegacyRoundTrip = true;
4484+
m_legacyRoundTrip = LegacyRoundTripData{};
4485+
m_legacyRoundTrip.name = legacy.name;
4486+
m_legacyRoundTrip.frame_width_x = legacy.frame_width_x;
4487+
m_legacyRoundTrip.frame_height_x = legacy.frame_height_x;
4488+
m_legacyRoundTrip.hash_codes = legacy.hash_codes;
4489+
m_legacyRoundTrip.active_frames = legacy.active_frames;
4490+
m_legacyRoundTrip.trigger_ids = legacy.trigger_ids;
4491+
m_legacyRoundTrip.dynashadow_dir = legacy.dynashadow_dir;
4492+
m_legacyRoundTrip.dynashadow_col = legacy.dynashadow_col;
4493+
m_legacyRoundTrip.dynashadow_dir_x = legacy.dynashadow_dir_x;
4494+
m_legacyRoundTrip.dynashadow_col_x = legacy.dynashadow_col_x;
4495+
m_legacyRoundTrip.active_col_sets = legacy.active_col_sets;
4496+
m_legacyRoundTrip.mask_names = legacy.mask_names;
4497+
m_legacyRoundTrip.draw_col_mode = legacy.draw_col_mode;
4498+
m_legacyRoundTrip.draw_mode = legacy.draw_mode;
4499+
m_legacyRoundTrip.mask_sel_mode = legacy.mask_sel_mode;
4500+
m_legacyRoundTrip.fill_mode = legacy.fill_mode;
4501+
m_legacyRoundTrip.edit_colors = legacy.edit_colors;
4502+
m_legacyRoundTrip.n_image_pos_saves = legacy.n_image_pos_saves;
4503+
m_legacyRoundTrip.image_pos_names = legacy.image_pos_names;
4504+
m_legacyRoundTrip.image_pos_data = legacy.image_pos_data;
4505+
m_legacyRoundTrip.is_imported = legacy.is_imported;
4506+
m_legacyRoundTrip.time_elapsed = legacy.time_elapsed;
4507+
m_legacyRoundTrip.is_pup_pack = legacy.is_pup_pack;
4508+
m_legacyRoundTrip.pup_pack = legacy.pup_pack;
4509+
m_legacyRoundTrip.preview_reduced_palette = legacy.preview_reduced_palette;
44624510

44634511
m_imageStore->clear();
44644512
m_frameStore->clear();
@@ -4640,6 +4688,8 @@ void MainWindow::openProjectFile(const QString& filename)
46404688
updateMetadataForFrame(-1);
46414689
updateMetadataForSprite(-1);
46424690
populateBookmarks({}, {});
4691+
m_hasLegacyRoundTrip = false;
4692+
m_legacyRoundTrip = LegacyRoundTripData{};
46434693
if (LoadProjectJson(*m_state, filename, &error)) {
46444694
statusBar()->showMessage(QString("Open: %1").arg(filename), 5000);
46454695
persistRecentFiles();
@@ -4703,8 +4753,42 @@ LegacyProject MainWindow::buildLegacyProject(const QString& baseName) const
47034753
{
47044754
LegacyProject project;
47054755
project.name = baseName.toStdString();
4756+
if (m_hasLegacyRoundTrip) {
4757+
if (!m_legacyRoundTrip.name.empty()) {
4758+
project.name = m_legacyRoundTrip.name;
4759+
}
4760+
project.frame_width_x = m_legacyRoundTrip.frame_width_x;
4761+
project.frame_height_x = m_legacyRoundTrip.frame_height_x;
4762+
project.hash_codes = m_legacyRoundTrip.hash_codes;
4763+
project.active_frames = m_legacyRoundTrip.active_frames;
4764+
project.trigger_ids = m_legacyRoundTrip.trigger_ids;
4765+
project.dynashadow_dir = m_legacyRoundTrip.dynashadow_dir;
4766+
project.dynashadow_col = m_legacyRoundTrip.dynashadow_col;
4767+
project.dynashadow_dir_x = m_legacyRoundTrip.dynashadow_dir_x;
4768+
project.dynashadow_col_x = m_legacyRoundTrip.dynashadow_col_x;
4769+
project.active_col_sets = m_legacyRoundTrip.active_col_sets;
4770+
project.mask_names = m_legacyRoundTrip.mask_names;
4771+
project.draw_col_mode = m_legacyRoundTrip.draw_col_mode;
4772+
project.draw_mode = m_legacyRoundTrip.draw_mode;
4773+
project.mask_sel_mode = m_legacyRoundTrip.mask_sel_mode;
4774+
project.fill_mode = m_legacyRoundTrip.fill_mode;
4775+
project.edit_colors = m_legacyRoundTrip.edit_colors;
4776+
project.n_image_pos_saves = m_legacyRoundTrip.n_image_pos_saves;
4777+
project.image_pos_names = m_legacyRoundTrip.image_pos_names;
4778+
project.image_pos_data = m_legacyRoundTrip.image_pos_data;
4779+
project.is_imported = m_legacyRoundTrip.is_imported;
4780+
project.time_elapsed = m_legacyRoundTrip.time_elapsed;
4781+
project.is_pup_pack = m_legacyRoundTrip.is_pup_pack;
4782+
project.pup_pack = m_legacyRoundTrip.pup_pack;
4783+
project.preview_reduced_palette = m_legacyRoundTrip.preview_reduced_palette;
4784+
}
47064785

47074786
const int frameCount = m_frameStore->count();
4787+
if (m_hasLegacyRoundTrip) {
4788+
project.hash_codes.resize(static_cast<std::size_t>(frameCount), 0);
4789+
project.active_frames.resize(static_cast<std::size_t>(frameCount), 0);
4790+
project.trigger_ids.resize(static_cast<std::size_t>(frameCount), 0xffffffffu);
4791+
}
47084792
project.frames.reserve(static_cast<std::size_t>(frameCount));
47094793
for (int i = 0; i < frameCount; ++i) {
47104794
if (const cv::Mat* frame = m_frameStore->at(i)) {
@@ -4783,7 +4867,11 @@ LegacyProject MainWindow::buildLegacyProject(const QString& baseName) const
47834867
project.background_masks = m_frameBackgroundMasks;
47844868
project.background_masks_x = m_frameBackgroundMasksX;
47854869
project.active_reduced_palette = static_cast<uint8_t>(std::max(0, std::min(m_reducedPaletteIndex, kReducedPaletteCount - 1)));
4786-
project.preview_reduced_palette = project.active_reduced_palette;
4870+
if (!m_hasLegacyRoundTrip) {
4871+
project.preview_reduced_palette = project.active_reduced_palette;
4872+
} else if (project.preview_reduced_palette >= kReducedPaletteCount) {
4873+
project.preview_reduced_palette = project.active_reduced_palette;
4874+
}
47874875
project.reduced_palettes = m_reducedPaletteIndices;
47884876
project.reduced_palette_names = m_reducedPaletteNames;
47894877
project.palettes.clear();
@@ -12438,7 +12526,28 @@ bool MainWindow::eventFilter(QObject* obj, QEvent* event)
1243812526
pos = m_framePreviewList->viewport()->mapFrom(m_framePreviewList, pos);
1243912527
}
1244012528
QListWidgetItem* hit = m_framePreviewList->itemAt(pos);
12441-
if (!hit) {
12529+
bool hitContent = false;
12530+
if (hit) {
12531+
const QRect itemRect = m_framePreviewList->visualItemRect(hit);
12532+
const QFontMetrics metrics(m_framePreviewList->font());
12533+
const int padding = 6;
12534+
const int textHeight = metrics.height() + 4;
12535+
QRect contentRect = itemRect.adjusted(padding, padding, -padding, -padding);
12536+
const QVariant sizeData = hit->data(kPreviewIconSizeRole);
12537+
const QSize iconSize = sizeData.isValid() && sizeData.toSize().isValid()
12538+
? sizeData.toSize()
12539+
: m_framePreviewList->iconSize().isValid()
12540+
? m_framePreviewList->iconSize()
12541+
: QSize(kPreviewIconWidth, kPreviewIconHeight);
12542+
const int iconX = contentRect.left() + (contentRect.width() - iconSize.width()) / 2;
12543+
QRect iconRect(iconX,
12544+
contentRect.top() + textHeight + 2,
12545+
iconSize.width(),
12546+
contentRect.height() - textHeight - 2);
12547+
QRect textRect(iconRect.left(), contentRect.top(), iconRect.width(), textHeight);
12548+
hitContent = iconRect.contains(pos) || textRect.contains(pos);
12549+
}
12550+
if (!hit || !hitContent) {
1244212551
clearPreviewSelection();
1244312552
return true;
1244412553
}

app/MainWindow.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,34 @@ class MainWindow : public QMainWindow
305305
void cancelPaletteSetSlot();
306306
void keyPressEvent(QKeyEvent* event) override;
307307

308+
struct LegacyRoundTripData {
309+
std::string name;
310+
uint32_t frame_width_x = 0;
311+
uint32_t frame_height_x = 0;
312+
std::vector<uint32_t> hash_codes;
313+
std::vector<uint8_t> active_frames;
314+
std::vector<uint32_t> trigger_ids;
315+
std::vector<uint8_t> dynashadow_dir;
316+
std::vector<uint16_t> dynashadow_col;
317+
std::vector<uint8_t> dynashadow_dir_x;
318+
std::vector<uint16_t> dynashadow_col_x;
319+
std::vector<uint32_t> active_col_sets;
320+
std::vector<char> mask_names;
321+
uint32_t draw_col_mode = 0;
322+
uint8_t draw_mode = 0;
323+
int32_t mask_sel_mode = 0;
324+
uint32_t fill_mode = 0;
325+
std::vector<uint16_t> edit_colors;
326+
uint32_t n_image_pos_saves = 0;
327+
std::vector<char> image_pos_names;
328+
std::vector<int32_t> image_pos_data;
329+
uint32_t is_imported = 0;
330+
uint32_t time_elapsed = 0;
331+
uint32_t is_pup_pack = 0;
332+
std::vector<char> pup_pack;
333+
uint8_t preview_reduced_palette = 0;
334+
};
335+
308336
class CanvasWidget* m_framesCanvas;
309337
class CanvasWidget* m_spritesCanvas;
310338
class CanvasWidget* m_imagesCanvas;
@@ -378,6 +406,8 @@ class MainWindow : public QMainWindow
378406
class QLabel* m_selectionLabel;
379407
class QLabel* m_frameMetaLabel;
380408
class QLabel* m_spriteMetaLabel;
409+
bool m_hasLegacyRoundTrip = false;
410+
LegacyRoundTripData m_legacyRoundTrip;
381411
class QLabel* m_coordLabel;
382412
class QToolButton* m_currentColorButton;
383413
class QLabel* m_colorInfoLabel;

0 commit comments

Comments
 (0)