diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index 476f5457b7..2a8295228c 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -670,6 +670,8 @@
+
+
@@ -1159,6 +1161,21 @@
$(QTDIR)\bin\moc.exe;%(FullPath)
$(QTDIR)\bin\moc.exe;%(FullPath)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters
index 080136e8de..ff5977b1cf 100644
--- a/rpcs3/rpcs3.vcxproj.filters
+++ b/rpcs3/rpcs3.vcxproj.filters
@@ -151,6 +151,9 @@
{d60be100-0d7e-4076-a24a-d413d0e91532}
+
+ {9191ae51-8b80-4606-b5bc-966a9588f538}
+
@@ -951,6 +954,18 @@
Gui\game list
+
+ Gui\flow_layout
+
+
+ Gui\flow_layout
+
+
+ Generated Files\Debug
+
+
+ Generated Files\Release
+
@@ -1124,6 +1139,9 @@
Gui\game list
+
+ Gui\flow_layout
+
@@ -1402,6 +1420,9 @@
Gui\game list
+
+ Gui\flow_layout
+
diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt
index f6cb298511..6262889249 100644
--- a/rpcs3/rpcs3qt/CMakeLists.txt
+++ b/rpcs3/rpcs3qt/CMakeLists.txt
@@ -22,6 +22,8 @@ set(SRC_FILES
emu_settings.cpp
fatal_error_dialog.cpp
find_dialog.cpp
+ flow_layout.cpp
+ flow_widget.cpp
game_compatibility.cpp
game_list.cpp
game_list_delegate.cpp
diff --git a/rpcs3/rpcs3qt/flow_layout.cpp b/rpcs3/rpcs3qt/flow_layout.cpp
new file mode 100644
index 0000000000..698999dbed
--- /dev/null
+++ b/rpcs3/rpcs3qt/flow_layout.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include
+#include "flow_layout.h"
+
+flow_layout::flow_layout(QWidget* parent, int margin, int hSpacing, int vSpacing)
+ : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
+{
+ setContentsMargins(margin, margin, margin, margin);
+}
+
+flow_layout::flow_layout(int margin, int hSpacing, int vSpacing)
+ : m_hSpace(hSpacing), m_vSpace(vSpacing)
+{
+ setContentsMargins(margin, margin, margin, margin);
+}
+
+flow_layout::~flow_layout()
+{
+ clear();
+}
+
+void flow_layout::clear()
+{
+ while (QLayoutItem* item = takeAt(0))
+ {
+ delete item->widget();
+ delete item;
+ }
+ itemList.clear();
+}
+
+void flow_layout::addItem(QLayoutItem* item)
+{
+ itemList.append(item);
+}
+
+int flow_layout::horizontalSpacing() const
+{
+ if (m_hSpace >= 0)
+ {
+ return m_hSpace;
+ }
+
+ return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
+}
+
+int flow_layout::verticalSpacing() const
+{
+ if (m_vSpace >= 0)
+ {
+ return m_vSpace;
+ }
+
+ return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
+}
+
+int flow_layout::count() const
+{
+ return itemList.size();
+}
+
+QLayoutItem* flow_layout::itemAt(int index) const
+{
+ return itemList.value(index);
+}
+
+QLayoutItem* flow_layout::takeAt(int index)
+{
+ if (index >= 0 && index < itemList.size())
+ return itemList.takeAt(index);
+
+ return nullptr;
+}
+
+Qt::Orientations flow_layout::expandingDirections() const
+{
+ return {};
+}
+
+bool flow_layout::hasHeightForWidth() const
+{
+ return true;
+}
+
+int flow_layout::heightForWidth(int width) const
+{
+ return doLayout(QRect(0, 0, width, 0), true);
+}
+
+void flow_layout::setGeometry(const QRect& rect)
+{
+ QLayout::setGeometry(rect);
+ doLayout(rect, false);
+}
+
+QSize flow_layout::sizeHint() const
+{
+ return minimumSize();
+}
+
+QSize flow_layout::minimumSize() const
+{
+ QSize size;
+ for (const QLayoutItem* item : qAsConst(itemList))
+ {
+ if (item)
+ {
+ size = size.expandedTo(item->minimumSize());
+ }
+ }
+
+ const QMargins margins = contentsMargins();
+ size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
+ return size;
+}
+
+int flow_layout::doLayout(const QRect& rect, bool testOnly) const
+{
+ int left, top, right, bottom;
+ getContentsMargins(&left, &top, &right, &bottom);
+ QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
+ int x = effectiveRect.x();
+ int y = effectiveRect.y();
+ int lineHeight = 0;
+
+ for (QLayoutItem* item : qAsConst(itemList))
+ {
+ const QWidget* wid = item->widget();
+ if (!wid)
+ continue;
+
+ int spaceX = horizontalSpacing();
+ if (spaceX == -1)
+ spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
+
+ int spaceY = verticalSpacing();
+ if (spaceY == -1)
+ spaceY = wid->style()->layoutSpacing(QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
+
+ int nextX = x + item->sizeHint().width() + spaceX;
+ if (nextX - spaceX > effectiveRect.right() && lineHeight > 0)
+ {
+ x = effectiveRect.x();
+ y = y + lineHeight + spaceY;
+ nextX = x + item->sizeHint().width() + spaceX;
+ lineHeight = 0;
+ }
+
+ if (!testOnly)
+ item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
+
+ x = nextX;
+ lineHeight = qMax(lineHeight, item->sizeHint().height());
+ }
+ return y + lineHeight - rect.y() + bottom;
+}
+
+int flow_layout::smartSpacing(QStyle::PixelMetric pm) const
+{
+ QObject* parent = this->parent();
+ if (!parent)
+ {
+ return -1;
+ }
+
+ if (parent->isWidgetType())
+ {
+ QWidget* pw = static_cast(parent);
+ return pw->style()->pixelMetric(pm, nullptr, pw);
+ }
+
+ return static_cast(parent)->spacing();
+}
diff --git a/rpcs3/rpcs3qt/flow_layout.h b/rpcs3/rpcs3qt/flow_layout.h
new file mode 100644
index 0000000000..b395b2cbcc
--- /dev/null
+++ b/rpcs3/rpcs3qt/flow_layout.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#pragma once
+
+#include
+#include
+#include
+
+class flow_layout : public QLayout
+{
+public:
+ explicit flow_layout(QWidget* parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
+ explicit flow_layout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
+ ~flow_layout();
+
+ void clear();
+
+ void addItem(QLayoutItem* item) override;
+ int horizontalSpacing() const;
+ int verticalSpacing() const;
+ Qt::Orientations expandingDirections() const override;
+ bool hasHeightForWidth() const override;
+ int heightForWidth(int) const override;
+ int count() const override;
+ QLayoutItem* itemAt(int index) const override;
+ QSize minimumSize() const override;
+ void setGeometry(const QRect& rect) override;
+ QSize sizeHint() const override;
+ QLayoutItem* takeAt(int index) override;
+
+private:
+ int doLayout(const QRect& rect, bool testOnly) const;
+ int smartSpacing(QStyle::PixelMetric pm) const;
+
+ QList itemList;
+ int m_hSpace;
+ int m_vSpace;
+};
diff --git a/rpcs3/rpcs3qt/flow_widget.cpp b/rpcs3/rpcs3qt/flow_widget.cpp
new file mode 100644
index 0000000000..281b8e9ee7
--- /dev/null
+++ b/rpcs3/rpcs3qt/flow_widget.cpp
@@ -0,0 +1,64 @@
+#include "flow_widget.h"
+#include "flow_layout.h"
+
+#include
+#include
+
+flow_widget::flow_widget(QWidget* parent)
+ : QWidget(parent)
+{
+ m_flow_layout = new flow_layout();
+
+ QWidget* widget = new QWidget(this);
+ widget->setLayout(m_flow_layout);
+
+ QScrollArea* scrollArea = new QScrollArea(this);
+ scrollArea->setWidget(widget);
+ scrollArea->setWidgetResizable(true);
+
+ QVBoxLayout* layout = new QVBoxLayout(this);
+ layout->addWidget(scrollArea);
+ layout->setContentsMargins(0, 0, 0, 0);
+ setLayout(layout);
+}
+
+flow_widget::~flow_widget()
+{
+}
+
+void flow_widget::add_widget(flow_widget_item* widget)
+{
+ if (widget)
+ {
+ m_widgets << widget;
+ m_flow_layout->addWidget(widget);
+ }
+}
+
+void flow_widget::clear()
+{
+ m_widgets.clear();
+ m_flow_layout->clear();
+}
+
+QList& flow_widget::items()
+{
+ return m_widgets;
+}
+
+void flow_widget_item::paintEvent(QPaintEvent* event)
+{
+ QWidget::paintEvent(event);
+
+ if (!got_visible && cb_on_first_visibility)
+ {
+ if (QWidget* widget = static_cast(parent()))
+ {
+ if (widget->visibleRegion().intersects(geometry()))
+ {
+ got_visible = true;
+ cb_on_first_visibility();
+ }
+ }
+ }
+}
diff --git a/rpcs3/rpcs3qt/flow_widget.h b/rpcs3/rpcs3qt/flow_widget.h
new file mode 100644
index 0000000000..5389f6cfed
--- /dev/null
+++ b/rpcs3/rpcs3qt/flow_widget.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include
+
+class flow_layout;
+
+class flow_widget_item : public QWidget
+{
+public:
+ using QWidget::QWidget;
+ void paintEvent(QPaintEvent* event) override;
+
+ bool got_visible{};
+ std::function cb_on_first_visibility{};
+};
+
+class flow_widget : public QWidget
+{
+public:
+ flow_widget(QWidget* parent);
+ virtual ~flow_widget();
+
+ void add_widget(flow_widget_item* widget);
+ void clear();
+
+ QList& items();
+
+private:
+ flow_layout* m_flow_layout{};
+ QList m_widgets{};
+};
diff --git a/rpcs3/rpcs3qt/screenshot_manager_dialog.cpp b/rpcs3/rpcs3qt/screenshot_manager_dialog.cpp
index 61d18179bb..8d0f5acc5f 100644
--- a/rpcs3/rpcs3qt/screenshot_manager_dialog.cpp
+++ b/rpcs3/rpcs3qt/screenshot_manager_dialog.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "screenshot_manager_dialog.h"
#include "screenshot_preview.h"
+#include "flow_widget.h"
#include "qt_utils.h"
#include "Utilities/File.h"
#include "Emu/VFS.h"
@@ -9,9 +10,7 @@
#include
#include
#include
-#include
#include
-#include
#include
#include
@@ -23,57 +22,18 @@ screenshot_manager_dialog::screenshot_manager_dialog(QWidget* parent) : QDialog(
setAttribute(Qt::WA_DeleteOnClose);
m_icon_size = QSize(160, 90);
+ m_flow_widget = new flow_widget(this);
+ m_flow_widget->setObjectName("m_flow_widget");
- m_grid = new QListWidget(this);
- m_grid->setViewMode(QListWidget::IconMode);
- m_grid->setMovement(QListWidget::Static);
- m_grid->setResizeMode(QListWidget::Adjust);
- m_grid->setIconSize(m_icon_size);
- m_grid->setGridSize(m_icon_size + QSize(10, 10));
+ m_placeholder = QPixmap(m_icon_size);
+ m_placeholder.fill(Qt::gray);
- // Make sure the directory is mounted
- vfs::mount("/dev_hdd0", rpcs3::utils::get_hdd0_dir());
-
- const std::string screenshot_path_qt = fs::get_config_dir() + "screenshots/";
- const std::string screenshot_path_cell = vfs::get("/dev_hdd0/photo/");
- const QStringList filter{ QStringLiteral("*.png") };
-
- QPixmap placeholder(m_icon_size);
- placeholder.fill(Qt::gray);
- m_placeholder = QIcon(placeholder);
-
- for (const std::string& path : { screenshot_path_qt, screenshot_path_cell })
- {
- if (path.empty())
- {
- gui_log.error("Screenshot manager: Trying to load screenshots from empty path!");
- continue;
- }
-
- QDirIterator dir_iter(QString::fromStdString(path), filter, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
-
- while (dir_iter.hasNext())
- {
- const QString filepath = dir_iter.next();
-
- QListWidgetItem* item = new QListWidgetItem;
- item->setData(item_role::source, filepath);
- item->setData(item_role::loaded, false);
- item->setIcon(m_placeholder);
- item->setToolTip(filepath);
-
- m_grid->addItem(item);
- }
- }
-
- connect(&m_icon_loader, &QFutureWatcher::resultReadyAt, this, &screenshot_manager_dialog::update_icon);
-
- connect(m_grid, &QListWidget::itemDoubleClicked, this, &screenshot_manager_dialog::show_preview);
- connect(m_grid->verticalScrollBar(), &QScrollBar::valueChanged, this, &screenshot_manager_dialog::update_icons);
+ connect(this, &screenshot_manager_dialog::signal_icon_preview, this, &screenshot_manager_dialog::show_preview);
+ connect(this, &screenshot_manager_dialog::signal_entry_parsed, this, &screenshot_manager_dialog::add_entry);
QVBoxLayout* layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
- layout->addWidget(m_grid);
+ layout->addWidget(m_flow_widget);
setLayout(layout);
resize(QGuiApplication::primaryScreen()->availableSize() * 3 / 5);
@@ -81,80 +41,130 @@ screenshot_manager_dialog::screenshot_manager_dialog(QWidget* parent) : QDialog(
screenshot_manager_dialog::~screenshot_manager_dialog()
{
- gui::utils::stop_future_watcher(m_icon_loader, true);
+ m_abort_parsing = true;
+ gui::utils::stop_future_watcher(m_parsing_watcher, true);
}
-void screenshot_manager_dialog::show_preview(QListWidgetItem* item)
+void screenshot_manager_dialog::add_entry(const QString& path)
{
- if (!item)
- {
- return;
- }
+ screenshot_item* item = new screenshot_item(m_flow_widget);
+ ensure(item->label);
+ item->setToolTip(path);
+ item->installEventFilter(this);
+ item->label->setPixmap(m_placeholder);
+ item->icon_path = path;
+ item->icon_size = m_icon_size;
+ connect(item, &screenshot_item::signal_icon_update, this, &screenshot_manager_dialog::update_icon);
- const QString filepath = item->data(Qt::UserRole).toString();
+ m_flow_widget->add_widget(item);
+}
- screenshot_preview* preview = new screenshot_preview(filepath);
+void screenshot_manager_dialog::show_preview(const QString& path)
+{
+ screenshot_preview* preview = new screenshot_preview(path);
preview->show();
}
-void screenshot_manager_dialog::update_icon(int index) const
+void screenshot_manager_dialog::update_icon(const QPixmap& pixmap)
{
- const thumbnail tn = m_icon_loader.resultAt(index);
-
- if (QListWidgetItem* item = m_grid->item(tn.index))
+ if (screenshot_item* item = static_cast(QObject::sender()))
{
- item->setIcon(tn.icon);
- item->setData(item_role::loaded, true);
+ if (item->label)
+ {
+ item->label->setPixmap(pixmap);
+ }
}
}
-void screenshot_manager_dialog::update_icons(int value)
+void screenshot_manager_dialog::reload()
{
- const QRect visible_rect = rect();
+ m_abort_parsing = true;
+ gui::utils::stop_future_watcher(m_parsing_watcher, true);
- QList thumbnails_to_load;
+ // Make sure the directory is mounted
+ vfs::mount("/dev_hdd0", rpcs3::utils::get_hdd0_dir());
- const bool forward = value >= m_scrollbar_value;
- m_scrollbar_value = value;
+ const std::string screenshot_path_qt = fs::get_config_dir() + "screenshots/";
+ const std::string screenshot_path_cell = vfs::get("/dev_hdd0/photo/");
- const int first = forward ? 0 : (m_grid->count() - 1);
- const int last = forward ? (m_grid->count() - 1) : 0;
-
- for (int i = first; forward ? i <= last : i >= last; forward ? ++i : --i)
+ m_flow_widget->clear();
+ m_abort_parsing = false;
+ m_parsing_watcher.setFuture(QtConcurrent::map(m_parsing_threads, [this, screenshot_path_qt, screenshot_path_cell](int index)
{
- if (QListWidgetItem* item = m_grid->item(i))
+ if (index != 0)
{
- const bool is_loaded = item->data(item_role::loaded).toBool();
- const bool is_visible = visible_rect.intersects(m_grid->visualItemRect(item));
+ return;
+ }
- if (is_visible)
+ const QStringList filter{ QStringLiteral("*.png") };
+
+ for (const std::string& path : { screenshot_path_qt, screenshot_path_cell })
+ {
+ if (m_abort_parsing)
{
- if (!is_loaded)
- {
- thumbnails_to_load.push_back({ QIcon(), item->data(item_role::source).toString() , i });
- }
+ return;
}
- else if (is_loaded)
+
+ if (path.empty())
{
- item->setIcon(m_placeholder);
- item->setData(item_role::loaded, false);
+ gui_log.error("Screenshot manager: Trying to load screenshots from empty path!");
+ continue;
}
+
+ QDirIterator dir_iter(QString::fromStdString(path), filter, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
+
+ while (dir_iter.hasNext() && !m_abort_parsing)
+ {
+ Q_EMIT signal_entry_parsed(dir_iter.next());
+ }
+ }
+ }));
+}
+
+void screenshot_manager_dialog::showEvent(QShowEvent* event)
+{
+ QDialog::showEvent(event);
+ reload();
+}
+
+bool screenshot_manager_dialog::eventFilter(QObject* watched, QEvent* event)
+{
+ if (event && event->type() == QEvent::MouseButtonDblClick)
+ {
+ if (screenshot_item* item = static_cast(watched))
+ {
+ Q_EMIT signal_icon_preview(item->icon_path);
+ return true;
}
}
- gui::utils::stop_future_watcher(m_icon_loader, true);
+ return false;
+}
- const std::function load = [icon_size = m_icon_size](thumbnail tn) -> thumbnail
+screenshot_item::screenshot_item(QWidget* parent)
+ : flow_widget_item(parent)
+{
+ cb_on_first_visibility = [this]()
{
- tn.icon = QIcon(gui::utils::get_centered_pixmap(tn.path, icon_size, 0, 0, 1.0));
- return tn;
+ m_thread.reset(QThread::create([this]()
+ {
+ const QPixmap pixmap = gui::utils::get_centered_pixmap(icon_path, icon_size, 0, 0, 1.0);
+ Q_EMIT signal_icon_update(pixmap);
+ }));
+ m_thread->start();
};
- m_icon_loader.setFuture(QtConcurrent::mapped(thumbnails_to_load, load));
+ label = new QLabel(this);
+ QVBoxLayout* layout = new QVBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addWidget(label);
+ setLayout(layout);
}
-void screenshot_manager_dialog::resizeEvent(QResizeEvent* event)
+screenshot_item::~screenshot_item()
{
- QDialog::resizeEvent(event);
- update_icons(m_scrollbar_value);
+ if (m_thread && m_thread->isRunning())
+ {
+ m_thread->wait();
+ }
}
diff --git a/rpcs3/rpcs3qt/screenshot_manager_dialog.h b/rpcs3/rpcs3qt/screenshot_manager_dialog.h
index a67313f843..8eec1aa324 100644
--- a/rpcs3/rpcs3qt/screenshot_manager_dialog.h
+++ b/rpcs3/rpcs3qt/screenshot_manager_dialog.h
@@ -1,12 +1,15 @@
#pragma once
+#include "flow_widget.h";
+
#include
#include
-#include
+#include
#include
-
-class QListWidget;
-class QListWidgetItem;
+#include
+#include
+#include
+#include
class screenshot_manager_dialog : public QDialog
{
@@ -16,38 +19,49 @@ public:
screenshot_manager_dialog(QWidget* parent = nullptr);
~screenshot_manager_dialog();
-protected:
- void resizeEvent(QResizeEvent* event) override;
-
-private Q_SLOTS:
- void update_icon(int index) const;
+ bool eventFilter(QObject* watched, QEvent* event) override;
Q_SIGNALS:
- void signal_icon_change(int index, const QString& path);
+ void signal_entry_parsed(const QString& path);
+ void signal_icon_preview(const QString& path);
+
+public Q_SLOTS:
+ void update_icon(const QPixmap& pixmap);
+
+private Q_SLOTS:
+ void add_entry(const QString& path);
+ void show_preview(const QString& path);
+
+protected:
+ void showEvent(QShowEvent* event) override;
private:
- static void show_preview(QListWidgetItem* item);
- void update_icons(int value);
+ void reload();
- enum item_role
- {
- source = Qt::UserRole,
- loaded = Qt::UserRole + 1,
- };
-
- struct thumbnail
- {
- QIcon icon;
- QString path;
- int index = 0;
- };
-
- QListWidget* m_grid = nullptr;
-
- QFutureWatcher m_icon_loader;
+ bool m_abort_parsing = false;
+ const std::array m_parsing_threads{0};
+ QFutureWatcher m_parsing_watcher;
+ flow_widget* m_flow_widget = nullptr;
QSize m_icon_size;
- QIcon m_placeholder;
-
- int m_scrollbar_value = 0;
+ QPixmap m_placeholder;
+};
+
+class screenshot_item : public flow_widget_item
+{
+ Q_OBJECT
+
+public:
+ screenshot_item(QWidget* parent);
+ virtual ~screenshot_item();
+
+ QString icon_path;
+ QSize icon_size;
+ QLabel* label{};
+
+private:
+ std::unique_ptr m_thread;
+
+Q_SIGNALS:
+ void signal_icon_update(const QPixmap& pixmap);
};