diff --git a/src/qt/animated_pixmap.cpp b/src/qt/animated_pixmap.cpp
new file mode 100644
index 0000000..9003e7c
--- /dev/null
+++ b/src/qt/animated_pixmap.cpp
@@ -0,0 +1,56 @@
+/* Copyright 2020, Michele Santullo
+ * This file is part of memoserv.
+ *
+ * Memoserv is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Memoserv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Memoserv. If not, see .
+ */
+
+#include "animated_pixmap.hpp"
+#include
+
+namespace duck {
+AnimatedPixmap::AnimatedPixmap (bool loop) :
+ m_frame(0),
+ m_loop(loop)
+{
+}
+
+AnimatedPixmap::~AnimatedPixmap() noexcept = default;
+
+void AnimatedPixmap::push_back (QPixmap&& frame) {
+ m_frames.push_back(std::move(frame));
+}
+
+std::size_t AnimatedPixmap::frame_count() const {
+ return m_frames.size();
+}
+
+QSize AnimatedPixmap::size() const {
+ return {
+ (m_frames.empty() ? EmptyPixmapWidth : m_frames.front().width()),
+ (m_frames.empty() ? EmptyPixmapHeight : m_frames.front().height())
+ };
+}
+
+void AnimatedPixmap::advance_frame() {
+ ++m_frame;
+ if (m_loop)
+ m_frame = (not m_frames.empty() ? m_frame % m_frames.size() : 0);
+ else
+ m_frame = std::min(m_frame, m_frames.size());
+}
+
+const QPixmap& AnimatedPixmap::current_frame() const {
+ return m_frames[m_frame];
+}
+} //namespace duck
diff --git a/src/qt/widgets/animated_icon.hpp b/src/qt/animated_pixmap.hpp
similarity index 54%
rename from src/qt/widgets/animated_icon.hpp
rename to src/qt/animated_pixmap.hpp
index ec54a28..4c206a1 100644
--- a/src/qt/widgets/animated_icon.hpp
+++ b/src/qt/animated_pixmap.hpp
@@ -17,43 +17,32 @@
#pragma once
-#include
#include
#include
-namespace duck::widget {
-class AnimatedIcon : public QWidget {
- Q_OBJECT
+namespace duck {
+class AnimatedPixmap {
public:
- static const constexpr unsigned int EmptyIconWidth = 50;
- static const constexpr unsigned int EmptyIconHeight = EmptyIconWidth;
+ static const constexpr int EmptyPixmapWidth = -1;
+ static const constexpr int EmptyPixmapHeight = EmptyPixmapWidth;
- AnimatedIcon (AnimatedIcon&&) = default;
- AnimatedIcon (const AnimatedIcon&) = delete;
- explicit AnimatedIcon (QWidget* parent=nullptr, float fps=24.0f, bool loop=true);
- ~AnimatedIcon() noexcept;
+ AnimatedPixmap (AnimatedPixmap&&) = default;
+ AnimatedPixmap (const AnimatedPixmap&) = delete;
+ AnimatedPixmap (bool loop);
+ ~AnimatedPixmap() noexcept;
- AnimatedIcon& operator= (AnimatedIcon&&) = default;
-
- QSize minimumSizeHint() const override;
- QSize sizeHint() const override;
+ AnimatedPixmap& operator= (AnimatedPixmap&&) = default;
void push_back (QPixmap&& frame);
- std::size_t size() const;
+ std::size_t frame_count() const;
+ QSize size() const;
- unsigned int width() const;
- unsigned int height() const;
-
-public slots:
void advance_frame();
-
-protected:
- void paintEvent (QPaintEvent* event) override;
+ const QPixmap& current_frame() const;
private:
std::vector m_frames;
std::size_t m_frame;
- float m_fps;
bool m_loop;
};
-} //namespace duck::widget
+} //namespace duck
diff --git a/src/qt/make_qt_animation.cpp b/src/qt/make_qt_animation.cpp
index 8250908..a45376d 100644
--- a/src/qt/make_qt_animation.cpp
+++ b/src/qt/make_qt_animation.cpp
@@ -21,15 +21,15 @@
#include
namespace duck {
- std::unique_ptr make_qt_animation (const mc::psx::ConstBlock& block, int width, int height, float fps) {
+ AnimatedPixmap make_qt_animation (const mc::psx::ConstBlock& block, int width, int height) {
using mc::icon_fetch;
- auto retval = std::make_unique();
+ AnimatedPixmap retval(true);
for (const auto& frame : icon_fetch(block, width, height)) {
QPixmap pix(width, height);
pix.loadFromData(reinterpret_cast(frame.data()), frame.size(), "BMP");
- retval->push_back(std::move(pix));
+ retval.push_back(std::move(pix));
}
return retval;
diff --git a/src/qt/make_qt_animation.hpp b/src/qt/make_qt_animation.hpp
index d2e0c89..4e495b6 100644
--- a/src/qt/make_qt_animation.hpp
+++ b/src/qt/make_qt_animation.hpp
@@ -17,8 +17,7 @@
#pragma once
-#include "widgets/animated_icon.hpp"
-#include
+#include "animated_pixmap.hpp"
namespace mc::psx {
template class BasicBlock;
@@ -26,10 +25,9 @@ using ConstBlock = BasicBlock;
} //namespace mc::psx
namespace duck {
- std::unique_ptr make_qt_animation (
+ AnimatedPixmap make_qt_animation (
const mc::psx::ConstBlock& block,
int width,
- int height,
- float fps
+ int height
);
} //namespace duck
diff --git a/src/qt/meson.build b/src/qt/meson.build
index a4cb59e..8fa4df4 100644
--- a/src/qt/meson.build
+++ b/src/qt/meson.build
@@ -9,7 +9,6 @@ moc_files = qt5.preprocess(
'memoserv_win.hpp',
'version_info_win.hpp',
'widgets/block_grid.hpp',
- 'widgets/animated_icon.hpp',
],
#ui_files: 'main_window.ui',
moc_extra_arguments: ['-DMAKES_MY_MOC_HEADER_COMPILE'],
@@ -36,8 +35,8 @@ executable(app_name,
project_config_file,
gitrev_config_file,
'widgets/block_grid.cpp',
- 'widgets/animated_icon.cpp',
'make_qt_animation.cpp',
+ 'animated_pixmap.cpp',
include_directories: inc,
dependencies: [qt5_dep, fslib_dep, memcard_dep],
install: true,
diff --git a/src/qt/widgets/animated_icon.cpp b/src/qt/widgets/animated_icon.cpp
deleted file mode 100644
index d374a1e..0000000
--- a/src/qt/widgets/animated_icon.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright 2020, Michele Santullo
- * This file is part of memoserv.
- *
- * Memoserv is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Memoserv is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Memoserv. If not, see .
- */
-
-#include "animated_icon.hpp"
-#include
-#include
-#include
-
-namespace duck::widget {
-namespace {
-} //unnamed namespace
-
-AnimatedIcon::AnimatedIcon (QWidget* parent, float fps, bool loop) :
- QWidget(parent),
- m_frame(0),
- m_fps(fps),
- m_loop(loop)
-{
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-}
-
-AnimatedIcon::~AnimatedIcon() noexcept = default;
-
-QSize AnimatedIcon::minimumSizeHint() const {
- return {static_cast(width()), static_cast(height())};
-}
-
-QSize AnimatedIcon::sizeHint() const {
- return {static_cast(width()), static_cast(height())};
-}
-
-void AnimatedIcon::push_back (QPixmap&& frame) {
- m_frames.push_back(std::move(frame));
-}
-
-std::size_t AnimatedIcon::size() const {
- return m_frames.size();
-}
-
-unsigned int AnimatedIcon::width() const {
- return (m_frames.empty() ? EmptyIconWidth : m_frames.front().width());
-}
-
-unsigned int AnimatedIcon::height() const {
- return (m_frames.empty() ? EmptyIconHeight : m_frames.front().height());
-}
-
-void AnimatedIcon::advance_frame() {
- ++m_frame;
- if (m_loop)
- m_frame = (not m_frames.empty() ? m_frame % m_frames.size() : 0);
- else
- m_frame = std::min(m_frame, m_frames.size());
- update();
-}
-
-void AnimatedIcon::paintEvent (QPaintEvent* event) {
- if (m_frame < m_frames.size()) {
- QPainter painter(this);
- painter.drawPixmap(0, 0, m_frames[m_frame]);
- }
-}
-
-} //namespace duck::widget
diff --git a/src/qt/widgets/block_grid.cpp b/src/qt/widgets/block_grid.cpp
index db89d6d..8d08d07 100644
--- a/src/qt/widgets/block_grid.cpp
+++ b/src/qt/widgets/block_grid.cpp
@@ -17,28 +17,19 @@
#include "block_grid.hpp"
#include
-#include
+#include
+#include
+#include
namespace duck::widget {
namespace {
const constexpr int g_icon_spacing = 3;
} //unnamed namespace
-BlockGrid::BlockGrid (QWidget* parent) :
- BlockGrid(parent, 3)
-{
-}
-
BlockGrid::BlockGrid (QWidget* parent, unsigned int columns) :
QWidget(parent),
- m_columns(columns),
- m_block_lay(nullptr)
+ m_columns(columns)
{
- auto block_lay = std::make_unique();
- block_lay->setSpacing(g_icon_spacing);
- m_block_lay = block_lay.get();
- m_block_lay->setColumnStretch(m_columns, 1);
- this->setLayout(block_lay.release());
}
BlockGrid::~BlockGrid() noexcept = default;
@@ -48,39 +39,61 @@ QSize BlockGrid::minimumSizeHint() const {
}
QSize BlockGrid::sizeHint() const {
- const auto w = icon_width() * m_columns + g_icon_spacing * (1 + m_columns);
- const unsigned int rows = size() / m_columns;
- const auto h = icon_height() * rows + g_icon_spacing * (rows + 1);
+ if (m_columns) {
+ const auto w = icon_width() * m_columns + g_icon_spacing * (1 + m_columns);
+ const unsigned int rows = size() / m_columns;
+ const auto h = icon_height() * rows + g_icon_spacing * (rows + 1);
- return {static_cast(w), static_cast(h)};
+ return {static_cast(w), static_cast(h)};
+ }
+ else {
+ return {-1, -1};
+ }
}
unsigned int BlockGrid::icon_width() const {
- return m_icons.empty() ? AnimatedIcon::EmptyIconWidth : m_icons.front()->width();
+ return m_icons.empty() ? static_cast(g_icon_spacing) : m_icons.front().size().width();
}
unsigned int BlockGrid::icon_height() const {
- return m_icons.empty() ? AnimatedIcon::EmptyIconHeight : m_icons.front()->height();
+ return m_icons.empty() ? static_cast(g_icon_spacing) : m_icons.front().size().height();
}
-void BlockGrid::emplace_back (std::unique_ptr&& anim) {
- const auto& columns = m_columns;
- const auto count = this->size();
-
- const int x = count % columns;
- const int y = count / columns;
-
- {
- const auto raw_ptr = anim.release();
- m_block_lay->addWidget(raw_ptr, y, x);
- m_icons.push_back(raw_ptr);
- }
-
- m_block_lay->setRowStretch(y, 0);
- m_block_lay->setRowStretch(y + 1, 1);
+void BlockGrid::push_back (AnimatedPixmap&& anim) {
+ m_icons.push_back(std::move(anim));
}
std::size_t BlockGrid::size() const {
return m_icons.size();
}
+
+unsigned int BlockGrid::columns() const {
+ if (m_columns) {
+ return m_columns;
+ }
+ else {
+ const auto widget_w = static_cast(std::max(this->width(), g_icon_spacing));
+ const auto ico_spacing_uns = static_cast(g_icon_spacing);
+
+ return (widget_w - ico_spacing_uns) / (icon_width() + ico_spacing_uns);
+ }
+}
+
+void BlockGrid::paintEvent (QPaintEvent* event) {
+ QPainter painter(this);
+ const int max_col = static_cast(this->columns());
+ int x = 0;
+ int y = 0;
+ int count = 0;
+
+ for (auto& ico : m_icons) {
+ x = g_icon_spacing + (count % max_col) * (g_icon_spacing + ico.size().width());
+ y = g_icon_spacing + (count / max_col) * (g_icon_spacing + ico.size().height());
+ if (ico.frame_count()) {
+ painter.drawPixmap(x, y, ico.current_frame());
+ }
+
+ ++count;
+ }
+}
} //namespace duck::widget
diff --git a/src/qt/widgets/block_grid.hpp b/src/qt/widgets/block_grid.hpp
index ebf25ee..09e156f 100644
--- a/src/qt/widgets/block_grid.hpp
+++ b/src/qt/widgets/block_grid.hpp
@@ -17,7 +17,7 @@
#pragma once
-#include "animated_icon.hpp"
+#include "../animated_pixmap.hpp"
#include
#include
#include
@@ -28,8 +28,7 @@ namespace duck::widget {
class BlockGrid : public QWidget {
Q_OBJECT
public:
- explicit BlockGrid (QWidget* parent=nullptr);
- BlockGrid (QWidget* parent, unsigned int columns);
+ explicit BlockGrid (QWidget* parent=nullptr, unsigned int columns=0);
~BlockGrid() noexcept;
QSize minimumSizeHint() const override;
@@ -38,12 +37,16 @@ public:
unsigned int icon_width() const;
unsigned int icon_height() const;
- void emplace_back (std::unique_ptr&& anim);
+ void push_back (AnimatedPixmap&& anim);
std::size_t size() const;
+protected:
+ void paintEvent (QPaintEvent* event) override;
+
private:
- std::vector m_icons;
+ unsigned int columns() const;
+
+ std::vector m_icons;
unsigned int m_columns;
- QGridLayout* m_block_lay;
};
} //namespace duck::widget