diff --git a/CHANGES b/CHANGES index bb3d134c2..68620d659 100644 --- a/CHANGES +++ b/CHANGES @@ -78,6 +78,7 @@ Misc: - Qt: Remove What's This icon from dialogs - CMake: Don't use libzip on embedded platforms (fixes mgba.io/i/1527) - Qt: Printer quality of life improvements (fixes mgba.io/i/1540) + - Qt: Add copy and QoL improvements to graphic views (closes mgba.io/i/1541) 0.7.3: (2019-09-15) Emulation fixes: diff --git a/src/platform/qt/AssetTile.cpp b/src/platform/qt/AssetTile.cpp index 0f87f7654..23ff4ff56 100644 --- a/src/platform/qt/AssetTile.cpp +++ b/src/platform/qt/AssetTile.cpp @@ -116,6 +116,9 @@ void AssetTile::selectIndex(int index) { m_ui.preview->setColor(i ^ flip, data[i]); } m_ui.preview->update(); + + QImage tile(reinterpret_cast(data), 8, 8, QImage::Format_ARGB32); + m_activeTile = tile.rgbSwapped(); } void AssetTile::setFlip(bool h, bool v) { diff --git a/src/platform/qt/AssetTile.h b/src/platform/qt/AssetTile.h index 676582387..d90572018 100644 --- a/src/platform/qt/AssetTile.h +++ b/src/platform/qt/AssetTile.h @@ -21,6 +21,7 @@ Q_OBJECT public: AssetTile(QWidget* parent = nullptr); void setController(std::shared_ptr); + QImage activeTile() const { return m_activeTile; } public slots: void setPalette(int); @@ -48,6 +49,7 @@ private: bool m_flipV = false; QMap m_customProperties; + QImage m_activeTile; }; } diff --git a/src/platform/qt/MapView.cpp b/src/platform/qt/MapView.cpp index 0fe80c2c3..f71baf0fe 100644 --- a/src/platform/qt/MapView.cpp +++ b/src/platform/qt/MapView.cpp @@ -22,7 +22,9 @@ #include #endif +#include #include +#include #include #include #include @@ -88,11 +90,19 @@ MapView::MapView(std::shared_ptr controller, QWidget* parent) }); group->addButton(button); } -#ifdef USE_PNG connect(m_ui.exportButton, &QAbstractButton::clicked, this, &MapView::exportMap); -#else - m_ui.exportButton->setVisible(false); -#endif + connect(m_ui.copyButton, &QAbstractButton::clicked, this, &MapView::copyMap); + + QAction* exportAction = new QAction(this); + exportAction->setShortcut(QKeySequence::Save); + connect(exportAction, &QAction::triggered, this, &MapView::exportMap); + addAction(exportAction); + + QAction* copyAction = new QAction(this); + copyAction->setShortcut(QKeySequence::Copy); + connect(copyAction, &QAction::triggered, this, &MapView::copyMap); + addAction(copyAction); + m_ui.map->installEventFilter(this); m_ui.tile->addCustomProperty("mapAddr", tr("Map Addr.")); m_ui.tile->addCustomProperty("flip", tr("Mirror")); @@ -211,7 +221,7 @@ void MapView::updateTilesGBA(bool force) { mBitmapCacheCleanRow(bitmapCache, m_bitmapStatus, j); memcpy(static_cast(&bgBits[width * j * 4]), mBitmapCacheGetRow(bitmapCache, j), width * 4); } - m_rawMap = m_rawMap.rgbSwapped(); + m_rawMap = m_rawMap.convertToFormat(QImage::Format_RGB32).rgbSwapped(); } else { mMapCache* mapCache = mMapCacheSetGetPointer(&m_cacheSet->maps, m_map); int tilesW = 1 << mMapCacheSystemInfoGetTilesWide(mapCache->sysConfig); @@ -242,23 +252,18 @@ void MapView::updateTilesGB(bool force) { } #endif -#ifdef USE_PNG void MapView::exportMap() { QString filename = GBAApp::app()->getSaveFileName(this, tr("Export map"), tr("Portable Network Graphics (*.png)")); - VFile* vf = VFileDevice::open(filename, O_WRONLY | O_CREAT | O_TRUNC); - if (!vf) { - LOG(QT, ERROR) << tr("Failed to open output PNG file: %1").arg(filename); + if (filename.isNull()) { return; } CoreController::Interrupter interrupter(m_controller); - png_structp png = PNGWriteOpen(vf); - png_infop info = PNGWriteHeaderA(png, m_rawMap.width(), m_rawMap.height()); - - QImage map = m_rawMap.rgbSwapped(); - PNGWritePixelsA(png, map.width(), map.height(), map.bytesPerLine() / 4, static_cast(map.constBits())); - PNGWriteClose(png, info); - vf->close(vf); + m_rawMap.save(filename, "PNG"); } -#endif + +void MapView::copyMap() { + CoreController::Interrupter interrupter(m_controller); + GBAApp::app()->clipboard()->setImage(m_rawMap); +} \ No newline at end of file diff --git a/src/platform/qt/MapView.h b/src/platform/qt/MapView.h index 4b39dcd7a..89c09259b 100644 --- a/src/platform/qt/MapView.h +++ b/src/platform/qt/MapView.h @@ -21,10 +21,9 @@ Q_OBJECT public: MapView(std::shared_ptr controller, QWidget* parent = nullptr); -#ifdef USE_PNG public slots: void exportMap(); -#endif + void copyMap(); private slots: void selectMap(int); diff --git a/src/platform/qt/MapView.ui b/src/platform/qt/MapView.ui index d21cce841..2d733c934 100644 --- a/src/platform/qt/MapView.ui +++ b/src/platform/qt/MapView.ui @@ -13,38 +13,7 @@ Maps - - - - - - - - - - - - - - - - Export - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - + @@ -79,7 +48,7 @@ - + true @@ -133,21 +102,59 @@ + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + Export + + + + + + + + + + + + + + + Copy + + + - - QGBA::AssetInfo - QGroupBox -
AssetInfo.h
- 1 -
QGBA::AssetTile QGroupBox
AssetTile.h
1
+ + QGBA::AssetInfo + QGroupBox +
AssetInfo.h
+ 1 +
diff --git a/src/platform/qt/ObjView.cpp b/src/platform/qt/ObjView.cpp index e482f023b..373e0ef16 100644 --- a/src/platform/qt/ObjView.cpp +++ b/src/platform/qt/ObjView.cpp @@ -8,6 +8,8 @@ #include "CoreController.h" #include "GBAApp.h" +#include +#include #include #include @@ -52,6 +54,17 @@ ObjView::ObjView(std::shared_ptr controller, QWidget* parent) updateTiles(true); }); connect(m_ui.exportButton, &QAbstractButton::clicked, this, &ObjView::exportObj); + connect(m_ui.copyButton, &QAbstractButton::clicked, this, &ObjView::copyObj); + + QAction* exportAction = new QAction(this); + exportAction->setShortcut(QKeySequence::Save); + connect(exportAction, &QAction::triggered, this, &ObjView::exportObj); + addAction(exportAction); + + QAction* copyAction = new QAction(this); + copyAction->setShortcut(QKeySequence::Copy); + connect(copyAction, &QAction::triggered, this, &ObjView::copyObj); + addAction(copyAction); } void ObjView::selectObj(int obj) { @@ -203,7 +216,15 @@ void ObjView::updateTilesGB(bool force) { void ObjView::exportObj() { QString filename = GBAApp::app()->getSaveFileName(this, tr("Export sprite"), tr("Portable Network Graphics (*.png)")); + if (filename.isNull()) { + return; + } CoreController::Interrupter interrupter(m_controller); QImage obj = compositeObj(m_objInfo); obj.save(filename, "PNG"); } + +void ObjView::copyObj() { + CoreController::Interrupter interrupter(m_controller); + GBAApp::app()->clipboard()->setImage(compositeObj(m_objInfo)); +} diff --git a/src/platform/qt/ObjView.h b/src/platform/qt/ObjView.h index 42cd3f65e..1ceef7417 100644 --- a/src/platform/qt/ObjView.h +++ b/src/platform/qt/ObjView.h @@ -23,6 +23,7 @@ public: public slots: void exportObj(); + void copyObj(); private slots: void selectObj(int); diff --git a/src/platform/qt/ObjView.ui b/src/platform/qt/ObjView.ui index df0a003a9..5585b6393 100644 --- a/src/platform/qt/ObjView.ui +++ b/src/platform/qt/ObjView.ui @@ -6,80 +6,170 @@ 0 0 - 454 - 385 + 641 + 470 Sprites - - - - - QFrame::StyledPanel + + + + + Geometry - - - 0 - - - - - - 0 - 0 - - - - - 8 - 8 - - - + + + + + + + Position + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + 20 + 0 + + + + 0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + , + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 20 + 0 + + + + 0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Dimensions + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + 20 + 0 + + + + 8 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + × + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 20 + 0 + + + + 8 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + - - - - - - - 0 - 0 - - - - × - - - 1 - - - 8 - - - - - - - Magnification - - - - - - - Export - - - - + + + + Tile + + - + + + + Export + + + + Attributes @@ -383,154 +473,6 @@ - - - - Tile - - - - - - - Geometry - - - - - - - - Position - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - - 20 - 0 - - - - 0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - , - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 20 - 0 - - - - 0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - - Dimensions - - - - - - - Qt::Horizontal - - - - 0 - 20 - - - - - - - - - 20 - 0 - - - - 8 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - × - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 20 - 0 - - - - 8 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - @@ -568,6 +510,80 @@ + + + + + + + 0 + 0 + + + + × + + + 1 + + + 8 + + + + + + + Magnification + + + + + + + + + Copy + + + + + + + QFrame::StyledPanel + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 8 + 8 + + + + + + + diff --git a/src/platform/qt/PrinterView.cpp b/src/platform/qt/PrinterView.cpp index 9386e0994..816d29566 100644 --- a/src/platform/qt/PrinterView.cpp +++ b/src/platform/qt/PrinterView.cpp @@ -36,6 +36,11 @@ PrinterView::PrinterView(std::shared_ptr controller, QWidget* pa m_ui.image->setFixedHeight(m_ui.image->size().height() / oldMag * mag); }); + QAction* save = new QAction(this); + save->setShortcut(QKeySequence::Save); + connect(save, &QAction::triggered, this, &MapView::save); + addAction(save); + clear(); } diff --git a/src/platform/qt/TileView.cpp b/src/platform/qt/TileView.cpp index 972d5f419..166114a1d 100644 --- a/src/platform/qt/TileView.cpp +++ b/src/platform/qt/TileView.cpp @@ -8,6 +8,8 @@ #include "CoreController.h" #include "GBAApp.h" +#include +#include #include #include @@ -87,7 +89,20 @@ TileView::TileView(std::shared_ptr controller, QWidget* parent) updateTiles(true); }); - connect(m_ui.exportButton, &QAbstractButton::clicked, this, &TileView::exportTiles); + connect(m_ui.exportAll, &QAbstractButton::clicked, this, &TileView::exportTiles); + connect(m_ui.exportOne, &QAbstractButton::clicked, this, &TileView::exportTile); + connect(m_ui.copyAll, &QAbstractButton::clicked, this, &TileView::copyTiles); + connect(m_ui.copyOne, &QAbstractButton::clicked, this, &TileView::copyTile); + + QAction* exportAll = new QAction(this); + exportAll->setShortcut(QKeySequence::Save); + connect(exportAll, &QAction::triggered, this, &TileView::exportTiles); + addAction(exportAll); + + QAction* copyOne = new QAction(this); + copyOne->setShortcut(QKeySequence::Copy); + connect(copyOne, &QAction::triggered, this, &TileView::copyTile); + addAction(copyOne); } #ifdef M_CORE_GBA @@ -162,8 +177,36 @@ void TileView::updatePalette(int palette) { void TileView::exportTiles() { QString filename = GBAApp::app()->getSaveFileName(this, tr("Export tiles"), tr("Portable Network Graphics (*.png)")); + if (filename.isNull()) { + return; + } CoreController::Interrupter interrupter(m_controller); updateTiles(false); QPixmap pixmap(m_ui.tiles->backing()); pixmap.save(filename, "PNG"); } + +void TileView::exportTile() { + QString filename = GBAApp::app()->getSaveFileName(this, tr("Export tile"), + tr("Portable Network Graphics (*.png)")); + if (filename.isNull()) { + return; + } + CoreController::Interrupter interrupter(m_controller); + updateTiles(false); + QImage image(m_ui.tile->activeTile()); + image.save(filename, "PNG"); +} + +void TileView::copyTiles() { + CoreController::Interrupter interrupter(m_controller); + updateTiles(false); + QPixmap pixmap(); + GBAApp::app()->clipboard()->setPixmap(m_ui.tiles->backing()); +} + +void TileView::copyTile() { + CoreController::Interrupter interrupter(m_controller); + updateTiles(false); + GBAApp::app()->clipboard()->setImage(m_ui.tile->activeTile()); +} diff --git a/src/platform/qt/TileView.h b/src/platform/qt/TileView.h index bf89f5645..0f6e0017b 100644 --- a/src/platform/qt/TileView.h +++ b/src/platform/qt/TileView.h @@ -24,6 +24,9 @@ public: public slots: void updatePalette(int); void exportTiles(); + void exportTile(); + void copyTiles(); + void copyTile(); private: #ifdef M_CORE_GBA diff --git a/src/platform/qt/TileView.ui b/src/platform/qt/TileView.ui index 521ad27b0..d979459fc 100644 --- a/src/platform/qt/TileView.ui +++ b/src/platform/qt/TileView.ui @@ -6,14 +6,28 @@ 0 0 - 693 - 467 + 748 + 823 Tiles - + + + + + Export Selected + + + + + + + Export All + + + @@ -104,17 +118,7 @@ - - - - - - - Export - - - - + @@ -133,7 +137,7 @@ 0 0 - 405 + 480 768 @@ -179,6 +183,23 @@ + + + + + + + Copy Selected + + + + + + + Copy All + + +