Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 49 additions & 20 deletions launcher/minecraft/ScreenshotsWatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,78 @@
*/

#include <QClipboard>
#include <QFileSystemWatcher>
#include <QImage>
#include <QThread>

#include "Application.h"
#include "FileSystem.h"
#include "MinecraftInstance.h"

#include "ScreenshotsWatcher.h"

ScreenshotsWatcher::ScreenshotsWatcher(const QString& path) : QObject(), m_path(path)
ScreenshotsWatcher::ScreenshotsWatcher(const QString& path) : m_watcher(QStringList{ path })
{
auto watcher = new QFileSystemWatcher({ path });

connect(watcher, &QFileSystemWatcher::directoryChanged, this, &ScreenshotsWatcher::dirUpdated);

m_watcher = std::make_unique<QFileSystemWatcher>(watcher);
m_retryTimer.setSingleShot(true);
m_retryTimer.setInterval(200);
connect(&m_retryTimer, &QTimer::timeout, this, &ScreenshotsWatcher::tryCopy);
connect(&m_watcher, &QFileSystemWatcher::directoryChanged, this, &ScreenshotsWatcher::dirUpdated);
}

void ScreenshotsWatcher::dirUpdated()
void ScreenshotsWatcher::dirUpdated(const QString& path)
{
QDir d(m_path, "*.png", QDir::Time, QDir::Files);
QDir d(path, "*.png", QDir::Time, QDir::Files);
if (!d.exists() || !d.count()) {
qDebug() << "Invalid screenshots dir";
return;
}
QString path = m_path + '/' + d[0];

auto clipboard = Application::clipboard();
if (clipboard == nullptr) {
qDebug() << "Clipboard ptr is null, aborting copying";
QString file = FS::PathCombine(path, d[0]);
if (file == m_pendingPath)
return;

m_pendingPath = file;
m_attempt = 0;
m_lastSize = QFileInfo(m_pendingPath).size();

scheduleRetry();
}

void ScreenshotsWatcher::tryCopy()
{
const QFileInfo fileInfo(m_pendingPath);
if (!fileInfo.exists())
return;

if (m_lastSize == 0 || m_lastSize != fileInfo.size()) {
m_lastSize = fileInfo.size();
scheduleRetry();
return;
}
m_lastSize = fileInfo.size();

QImage img;
bool loaded = img.load(path);
for (int i = 0; i < 5 && !loaded; i++) {
QThread::msleep(200);
loaded = img.load(path);
}
bool loaded = img.load(m_pendingPath);

if (!loaded) {
qDebug() << "Image wasn't loaded in 1 sec, aborting copying";
scheduleRetry();
return;
}

const auto clipboard = QApplication::clipboard();
if (clipboard == nullptr) {
qDebug() << "Clipboard is null";
return;
}

clipboard->setImage(img);
}

void ScreenshotsWatcher::scheduleRetry()
{
++m_attempt;
if (m_attempt > 5) {
qDebug() << "Image wasn't loaded after 5 retries";
return;
}

m_retryTimer.start();
}
22 changes: 13 additions & 9 deletions launcher/minecraft/ScreenshotsWatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,27 @@

#pragma once

#include <QFileSystemWatcher>
#include <QObject>
#include <memory>

class QFileSystemWatcher;
class QString;
class QObject;
class MinecraftInstance;
#include <QString>
#include <QTimer>
#include <cstddef>

class ScreenshotsWatcher : public QObject {
Q_OBJECT
public:
explicit ScreenshotsWatcher(const QString& path);

private slots:
void dirUpdated();
void dirUpdated(const QString& path);
void tryCopy();

private:
std::unique_ptr<QFileSystemWatcher> m_watcher;
const QString m_path;
void scheduleRetry();

QFileSystemWatcher m_watcher;
QString m_pendingPath;
std::size_t m_attempt{};
std::size_t m_lastSize{};
QTimer m_retryTimer;
};
Loading