From cb5cfe724208beb7d506868fc4e50d9f13e28a53 Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Tue, 25 Feb 2014 00:51:24 +0100 Subject: Reorganize all the screenshot files --- logic/screenshots/ImgurAlbumCreation.cpp | 90 +++++++++++++++++++++++++ logic/screenshots/ImgurAlbumCreation.h | 42 ++++++++++++ logic/screenshots/ImgurUpload.cpp | 106 +++++++++++++++++++++++++++++ logic/screenshots/ImgurUpload.h | 30 +++++++++ logic/screenshots/Screenshot.h | 15 +++++ logic/screenshots/ScreenshotList.cpp | 112 +++++++++++++++++++++++++++++++ logic/screenshots/ScreenshotList.h | 70 +++++++++++++++++++ 7 files changed, 465 insertions(+) create mode 100644 logic/screenshots/ImgurAlbumCreation.cpp create mode 100644 logic/screenshots/ImgurAlbumCreation.h create mode 100644 logic/screenshots/ImgurUpload.cpp create mode 100644 logic/screenshots/ImgurUpload.h create mode 100644 logic/screenshots/Screenshot.h create mode 100644 logic/screenshots/ScreenshotList.cpp create mode 100644 logic/screenshots/ScreenshotList.h (limited to 'logic/screenshots') diff --git a/logic/screenshots/ImgurAlbumCreation.cpp b/logic/screenshots/ImgurAlbumCreation.cpp new file mode 100644 index 00000000..e473952e --- /dev/null +++ b/logic/screenshots/ImgurAlbumCreation.cpp @@ -0,0 +1,90 @@ +#include "ImgurAlbumCreation.h" + +#include +#include +#include +#include + +#include "logic/screenshots//ScreenshotList.h" +#include "logic/net/URLConstants.h" +#include "MultiMC.h" +#include "logger/QsLog.h" + +ImgurAlbumCreation::ImgurAlbumCreation(QList screenshots) : NetAction(), m_screenshots(screenshots) +{ + m_url = URLConstants::IMGUR_BASE_URL + "album.json"; + m_status = Job_NotStarted; +} + +void ImgurAlbumCreation::start() +{ + m_status = Job_InProgress; + QNetworkRequest request(m_url); + request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)"); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + request.setRawHeader("Authorization", "Client-ID 5b97b0713fba4a3"); + request.setRawHeader("Accept", "application/json"); + + QStringList ids; + for (auto shot : m_screenshots) + { + ids.append(shot->imgurId); + } + + const QByteArray data = "ids=" + ids.join(',').toUtf8() + "&title=Minecraft%20Screenshots&privacy=hidden"; + + auto worker = MMC->qnam(); + QNetworkReply *rep = worker->post(request, data); + + m_reply = std::shared_ptr(rep); + connect(rep, &QNetworkReply::uploadProgress, this, &ImgurAlbumCreation::downloadProgress); + connect(rep, &QNetworkReply::finished, this, &ImgurAlbumCreation::downloadFinished); + connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), + SLOT(downloadError(QNetworkReply::NetworkError))); +} +void ImgurAlbumCreation::downloadError(QNetworkReply::NetworkError error) +{ + QLOG_DEBUG() << m_reply->errorString(); + m_status = Job_Failed; +} +void ImgurAlbumCreation::downloadFinished() +{ + if (m_status != Job_Failed) + { + QByteArray data = m_reply->readAll(); + m_reply.reset(); + QJsonParseError jsonError; + QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); + if (jsonError.error != QJsonParseError::NoError) + { + QLOG_DEBUG() << jsonError.errorString(); + emit failed(m_index_within_job); + return; + } + auto object = doc.object(); + if (!object.value("success").toBool()) + { + QLOG_DEBUG() << doc.toJson(); + emit failed(m_index_within_job); + return; + } + m_deleteHash = object.value("data").toObject().value("deletehash").toString(); + m_id = object.value("data").toObject().value("id").toString(); + m_status = Job_Finished; + emit succeeded(m_index_within_job); + return; + } + else + { + QLOG_DEBUG() << m_reply->readAll(); + m_reply.reset(); + emit failed(m_index_within_job); + return; + } +} +void ImgurAlbumCreation::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + m_total_progress = bytesTotal; + m_progress = bytesReceived; + emit progress(m_index_within_job, bytesReceived, bytesTotal); +} diff --git a/logic/screenshots/ImgurAlbumCreation.h b/logic/screenshots/ImgurAlbumCreation.h new file mode 100644 index 00000000..6e8fbe94 --- /dev/null +++ b/logic/screenshots/ImgurAlbumCreation.h @@ -0,0 +1,42 @@ +#pragma once +#include "logic/net/NetAction.h" +#include "Screenshot.h" + +typedef std::shared_ptr ImgurAlbumCreationPtr; +class ImgurAlbumCreation : public NetAction +{ +public: + explicit ImgurAlbumCreation(QList screenshots); + static ImgurAlbumCreationPtr make(QList screenshots) + { + return ImgurAlbumCreationPtr(new ImgurAlbumCreation(screenshots)); + } + + QString deleteHash() const + { + return m_deleteHash; + } + QString id() const + { + return m_id; + } + +protected +slots: + virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + virtual void downloadError(QNetworkReply::NetworkError error); + virtual void downloadFinished(); + virtual void downloadReadyRead() + { + } + +public +slots: + virtual void start(); + +private: + QList m_screenshots; + + QString m_deleteHash; + QString m_id; +}; diff --git a/logic/screenshots/ImgurUpload.cpp b/logic/screenshots/ImgurUpload.cpp new file mode 100644 index 00000000..62033ef5 --- /dev/null +++ b/logic/screenshots/ImgurUpload.cpp @@ -0,0 +1,106 @@ +#include "ImgurUpload.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "logic/screenshots/ScreenshotList.h" +#include "logic/net/URLConstants.h" +#include "MultiMC.h" +#include "logger/QsLog.h" + +ImgurUpload::ImgurUpload(ScreenshotPtr shot) : NetAction(), m_shot(shot) +{ + m_url = URLConstants::IMGUR_BASE_URL + "upload.json"; + m_status = Job_NotStarted; +} + +void ImgurUpload::start() +{ + m_status = Job_InProgress; + QNetworkRequest request(m_url); + request.setHeader(QNetworkRequest::UserAgentHeader, "MultiMC/5.0 (Uncached)"); + request.setRawHeader("Authorization", "Client-ID 5b97b0713fba4a3"); + request.setRawHeader("Accept", "application/json"); + + QFile f(m_shot->file); + if (!f.open(QFile::ReadOnly)) + { + emit failed(m_index_within_job); + return; + } + + QHttpMultiPart *multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType); + QHttpPart filePart; + filePart.setBody(f.readAll().toBase64()); + filePart.setHeader(QNetworkRequest::ContentTypeHeader, "image/png"); + filePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"image\""); + multipart->append(filePart); + QHttpPart typePart; + typePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"type\""); + typePart.setBody("base64"); + multipart->append(typePart); + QHttpPart namePart; + namePart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data; name=\"name\""); + namePart.setBody(m_shot->timestamp.toString(Qt::ISODate).toUtf8()); + multipart->append(namePart); + + auto worker = MMC->qnam(); + QNetworkReply *rep = worker->post(request, multipart); + + m_reply = std::shared_ptr(rep); + connect(rep, &QNetworkReply::uploadProgress, this, &ImgurUpload::downloadProgress); + connect(rep, &QNetworkReply::finished, this, &ImgurUpload::downloadFinished); + connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), + SLOT(downloadError(QNetworkReply::NetworkError))); +} +void ImgurUpload::downloadError(QNetworkReply::NetworkError error) +{ + QLOG_DEBUG() << m_reply->errorString(); + m_status = Job_Failed; +} +void ImgurUpload::downloadFinished() +{ + if (m_status != Job_Failed) + { + QByteArray data = m_reply->readAll(); + m_reply.reset(); + QJsonParseError jsonError; + QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); + if (jsonError.error != QJsonParseError::NoError) + { + QLOG_DEBUG() << jsonError.errorString(); + emit failed(m_index_within_job); + return; + } + auto object = doc.object(); + if (!object.value("success").toBool()) + { + QLOG_DEBUG() << doc.toJson(); + emit failed(m_index_within_job); + return; + } + m_shot->imgurId = object.value("data").toObject().value("id").toString(); + m_shot->url = object.value("data").toObject().value("link").toString(); + m_status = Job_Finished; + emit succeeded(m_index_within_job); + return; + } + else + { + QLOG_DEBUG() << m_reply->readAll(); + m_reply.reset(); + emit failed(m_index_within_job); + return; + } +} +void ImgurUpload::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + m_total_progress = bytesTotal; + m_progress = bytesReceived; + emit progress(m_index_within_job, bytesReceived, bytesTotal); +} diff --git a/logic/screenshots/ImgurUpload.h b/logic/screenshots/ImgurUpload.h new file mode 100644 index 00000000..1111a8d0 --- /dev/null +++ b/logic/screenshots/ImgurUpload.h @@ -0,0 +1,30 @@ +#pragma once +#include "logic/net/NetAction.h" +#include "Screenshot.h" + +typedef std::shared_ptr ImgurUploadPtr; +class ImgurUpload : public NetAction +{ +public: + explicit ImgurUpload(ScreenshotPtr shot); + static ImgurUploadPtr make(ScreenshotPtr shot) + { + return ImgurUploadPtr(new ImgurUpload(shot)); + } + +protected +slots: + virtual void downloadProgress(qint64 bytesReceived, qint64 bytesTotal); + virtual void downloadError(QNetworkReply::NetworkError error); + virtual void downloadFinished(); + virtual void downloadReadyRead() + { + } + +public +slots: + virtual void start(); + +private: + ScreenshotPtr m_shot; +}; diff --git a/logic/screenshots/Screenshot.h b/logic/screenshots/Screenshot.h new file mode 100644 index 00000000..194e70e5 --- /dev/null +++ b/logic/screenshots/Screenshot.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include + +struct ScreenShot +{ + QDateTime timestamp; + QString file; + QString url; + QString imgurId; +}; + +typedef std::shared_ptr ScreenshotPtr; diff --git a/logic/screenshots/ScreenshotList.cpp b/logic/screenshots/ScreenshotList.cpp new file mode 100644 index 00000000..def1bdf7 --- /dev/null +++ b/logic/screenshots/ScreenshotList.cpp @@ -0,0 +1,112 @@ +#include "ScreenshotList.h" +#include "gui/dialogs/ScreenshotDialog.h" + +#include +#include +#include +#include "gui/dialogs/ProgressDialog.h" +#include "gui/dialogs/CustomMessageBox.h" + +ScreenshotList::ScreenshotList(BaseInstance *instance, QObject *parent) + : QAbstractListModel(parent), m_instance(instance) +{ +} + +int ScreenshotList::rowCount(const QModelIndex &) const +{ + return m_screenshots.size(); +} + +QVariant ScreenshotList::data(const QModelIndex &index, int role) const +{ + if (index.row() >= m_screenshots.size() || index.row() < 0) + return QVariant(); + + switch (role) + { + case Qt::DecorationRole: + return QIcon(m_screenshots.at(index.row())->file); + case Qt::DisplayRole: + return m_screenshots.at(index.row())->timestamp.toString("yyyy-MM-dd HH:mm:ss"); + case Qt::ToolTipRole: + return m_screenshots.at(index.row())->timestamp.toString("yyyy-MM-dd HH:mm:ss"); + case Qt::TextAlignmentRole: + return (int)(Qt::AlignHCenter | Qt::AlignVCenter); + default: + return QVariant(); + } +} + +QVariant ScreenshotList::headerData(int section, Qt::Orientation orientation, int role) const +{ + return QVariant(); +} + +Qt::ItemFlags ScreenshotList::flags(const QModelIndex &index) const +{ + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; +} + +Task *ScreenshotList::load() +{ + return new ScreenshotLoadTask(this); +} + +ScreenshotLoadTask::ScreenshotLoadTask(ScreenshotList *list) : m_list(list) +{ +} + +ScreenshotLoadTask::~ScreenshotLoadTask() +{ +} + +void ScreenshotLoadTask::executeTask() +{ + auto dir = QDir(m_list->instance()->minecraftRoot()); + if (!dir.cd("screenshots")) + { + emitFailed("Selected instance does not have any screenshots!"); + return; + } + dir.setNameFilters(QStringList() << "*.png"); + this->m_results.clear(); + for (auto file : dir.entryList()) + { + ScreenShot *shot = new ScreenShot(); + shot->timestamp = QDateTime::fromString(file, "yyyy-MM-dd_HH.mm.ss.png"); + shot->file = dir.absoluteFilePath(file); + m_results.append(ScreenshotPtr(shot)); + } + m_list->loadShots(m_results); + emitSucceeded(); +} +void ScreenshotList::deleteSelected(ScreenshotDialog *dialog) +{ + auto screens = dialog->selected(); + if (screens.isEmpty()) + { + return; + } + beginResetModel(); + QList>::const_iterator it; + for (it = screens.cbegin(); it != screens.cend(); it++) + { + auto shot = *it; + if (!QFile(shot->file).remove()) + { + CustomMessageBox::selectable(dialog, tr("Error!"), + tr("Failed to delete screenshots!"), + QMessageBox::Warning)->exec(); + break; + } + } + ProgressDialog refresh(dialog); + Task *t = load(); + if (refresh.exec(t) != QDialog::Accepted) + { + CustomMessageBox::selectable(dialog, tr("Error!"), + tr("Unable to refresh list: %1").arg(t->failReason()), + QMessageBox::Warning)->exec(); + } + endResetModel(); +} diff --git a/logic/screenshots/ScreenshotList.h b/logic/screenshots/ScreenshotList.h new file mode 100644 index 00000000..ca6314e9 --- /dev/null +++ b/logic/screenshots/ScreenshotList.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include "logic/BaseInstance.h" +#include "logic/tasks/Task.h" + +#include "Screenshot.h" + +class ScreenshotList : public QAbstractListModel +{ + Q_OBJECT +public: + ScreenshotList(BaseInstance *instance, QObject *parent = 0); + + QVariant data(const QModelIndex &index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + + int rowCount(const QModelIndex &parent) const; + + Qt::ItemFlags flags(const QModelIndex &index) const; + + Task *load(); + + void loadShots(QList shots) + { + m_screenshots = shots; + } + + QList screenshots() const + { + return m_screenshots; + } + + BaseInstance *instance() const + { + return m_instance; + } + + void deleteSelected(class ScreenshotDialog *dialog); + +signals: + +public +slots: + +private: + QList m_screenshots; + BaseInstance *m_instance; +}; + +class ScreenshotLoadTask : public Task +{ + Q_OBJECT + +public: + explicit ScreenshotLoadTask(ScreenshotList *list); + ~ScreenshotLoadTask(); + + QList screenShots() const + { + return m_results; + } + +protected: + virtual void executeTask(); + +private: + ScreenshotList *m_list; + QList m_results; +}; -- cgit From 9d4e840a6e1a7169a2863fa1ff1812f8fe19e615 Mon Sep 17 00:00:00 2001 From: Petr Mrázek Date: Tue, 25 Feb 2014 01:21:46 +0100 Subject: Screenshots: Optimize image loading and memory use, fix list and button layout. --- CMakeLists.txt | 1 + gui/dialogs/ScreenshotDialog.ui | 31 +++++++++++++++++-------------- logic/screenshots/Screenshot.cpp | 14 ++++++++++++++ logic/screenshots/Screenshot.h | 4 ++++ logic/screenshots/ScreenshotList.cpp | 3 ++- 5 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 logic/screenshots/Screenshot.cpp (limited to 'logic/screenshots') diff --git a/CMakeLists.txt b/CMakeLists.txt index da7b0e0b..ee836cd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -465,6 +465,7 @@ logic/lists/JavaVersionList.cpp # the screenshots feature logic/screenshots/Screenshot.h +logic/screenshots/Screenshot.cpp logic/screenshots/ScreenshotList.h logic/screenshots/ScreenshotList.cpp logic/screenshots/ImgurUpload.h diff --git a/gui/dialogs/ScreenshotDialog.ui b/gui/dialogs/ScreenshotDialog.ui index 4e42a548..eb3dafba 100644 --- a/gui/dialogs/ScreenshotDialog.ui +++ b/gui/dialogs/ScreenshotDialog.ui @@ -38,6 +38,9 @@ true + + QListView::Adjust + QListView::IconMode @@ -45,6 +48,20 @@ + + + + Upload + + + + + + + Delete + + + @@ -65,20 +82,6 @@ - - - - Upload - - - - - - - Delete - - - diff --git a/logic/screenshots/Screenshot.cpp b/logic/screenshots/Screenshot.cpp new file mode 100644 index 00000000..882e491f --- /dev/null +++ b/logic/screenshots/Screenshot.cpp @@ -0,0 +1,14 @@ +#include "Screenshot.h" +#include +#include +QIcon ScreenShot::getImage() +{ + if(!imageloaded) + { + QImage image(file); + QImage thumbnail = image.scaledToWidth(256, Qt::SmoothTransformation); + m_image = QIcon(QPixmap::fromImage(thumbnail)); + imageloaded = true; + } + return m_image; +} diff --git a/logic/screenshots/Screenshot.h b/logic/screenshots/Screenshot.h index 194e70e5..815c0d47 100644 --- a/logic/screenshots/Screenshot.h +++ b/logic/screenshots/Screenshot.h @@ -3,9 +3,13 @@ #include #include #include +#include struct ScreenShot { + QIcon getImage(); + QIcon m_image; + bool imageloaded = false; QDateTime timestamp; QString file; QString url; diff --git a/logic/screenshots/ScreenshotList.cpp b/logic/screenshots/ScreenshotList.cpp index def1bdf7..8a64dc36 100644 --- a/logic/screenshots/ScreenshotList.cpp +++ b/logic/screenshots/ScreenshotList.cpp @@ -25,7 +25,7 @@ QVariant ScreenshotList::data(const QModelIndex &index, int role) const switch (role) { case Qt::DecorationRole: - return QIcon(m_screenshots.at(index.row())->file); + return m_screenshots.at(index.row())->getImage(); case Qt::DisplayRole: return m_screenshots.at(index.row())->timestamp.toString("yyyy-MM-dd HH:mm:ss"); case Qt::ToolTipRole: @@ -80,6 +80,7 @@ void ScreenshotLoadTask::executeTask() m_list->loadShots(m_results); emitSucceeded(); } + void ScreenshotList::deleteSelected(ScreenshotDialog *dialog) { auto screens = dialog->selected(); -- cgit