diff --git a/Makefile.common b/Makefile.common index 48b1b3b1bc..90ce3fe265 100644 --- a/Makefile.common +++ b/Makefile.common @@ -352,7 +352,8 @@ OBJ += ui/drivers/ui_qt.o \ ui/drivers/qt/viewoptionsdialog.o \ ui/drivers/qt/playlist.o \ ui/drivers/qt/updateretroarch.o \ - ui/drivers/qt/thumbnaildownload.o + ui/drivers/qt/thumbnaildownload.o \ + ui/drivers/qt/thumbnailpackdownload.o MOC_HEADERS += ui/drivers/ui_qt.h \ ui/drivers/qt/ui_qt_load_core_window.h \ diff --git a/griffin/griffin_cpp.cpp b/griffin/griffin_cpp.cpp index 5c75dfefdb..47f25ab447 100644 --- a/griffin/griffin_cpp.cpp +++ b/griffin/griffin_cpp.cpp @@ -50,6 +50,7 @@ UI #include "../ui/drivers/qt/playlist.cpp" #include "../ui/drivers/qt/updateretroarch.cpp" #include "../ui/drivers/qt/thumbnaildownload.cpp" +#include "../ui/drivers/qt/thumbnailpackdownload.cpp" #endif /*============================================================ diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index ca2fca063d..d71ea6ff28 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -3794,3 +3794,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALREADY_IN_PROGRESS, "他のダウンロードが実行中です。") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST, "起動時に表示するプレイリスト:") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS, + "すべてのサムネイルをダウンロード") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY, + "サムネイルのダウンロードが成功しました。") diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index b88c1049c4..b0c9290fa0 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -7392,3 +7392,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALREADY_IN_PROGRESS, "A download is already in progress.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST, "Start on playlist:") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS, + "Download All Thumbnails") +MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY, + "Thumbnails downloaded successfully.") diff --git a/msg_hash.h b/msg_hash.h index 7e69b4e23c..3e1cd59d77 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -2007,6 +2007,8 @@ enum msg_hash_enums MENU_ENUM_LABEL_VALUE_QT_RESET_PARAMETER, MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_THUMBNAIL, MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALREADY_IN_PROGRESS, + MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS, + MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY, MENU_LABEL(MIDI_INPUT), MENU_LABEL(MIDI_OUTPUT), diff --git a/ui/drivers/qt/playlist.cpp b/ui/drivers/qt/playlist.cpp index 7113500f3d..af8bf6bc31 100644 --- a/ui/drivers/qt/playlist.cpp +++ b/ui/drivers/qt/playlist.cpp @@ -377,6 +377,7 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) QScopedPointer hideAction; QScopedPointer newPlaylistAction; QScopedPointer deletePlaylistAction; + QScopedPointer downloadAllThumbnailsAction; QPointer selectedAction; QPoint cursorPos = QCursor::pos(); QListWidgetItem *selectedItem = m_listWidget->itemAt(m_listWidget->viewport()->mapFromGlobal(cursorPos)); @@ -527,6 +528,13 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) menu->addMenu(associateMenu.data()); } + if (!specialPlaylist) + { + downloadAllThumbnailsAction.reset(new QAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS), this)); + + menu->addAction(downloadAllThumbnailsAction.data()); + } + selectedAction = menu->exec(cursorPos); if (!selectedAction) @@ -625,6 +633,13 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&) } } } + else if (selectedItem && !specialPlaylist && selectedAction == downloadAllThumbnailsAction.data()) + { + int row = m_listWidget->row(selectedItem); + + if (row >= 0) + downloadAllThumbnails(currentPlaylistFileInfo.completeBaseName()); + } setCoreActions(); diff --git a/ui/drivers/qt/thumbnailpackdownload.cpp b/ui/drivers/qt/thumbnailpackdownload.cpp new file mode 100644 index 0000000000..75de1a6016 --- /dev/null +++ b/ui/drivers/qt/thumbnailpackdownload.cpp @@ -0,0 +1,314 @@ +#include +#include +#include + +#include "../ui_qt.h" + +extern "C" { +#include +#include +#include +#include "../../../tasks/tasks_internal.h" +#include "../../../verbosity.h" +#include "../../../config.def.h" +#include "../../../configuration.h" +#include "../../../version.h" +} + +#define USER_AGENT "RetroArch-WIMP/" PACKAGE_VERSION +#define PARTIAL_EXTENSION ".partial" +#define TEMP_EXTENSION ".tmp" +#define THUMBNAILPACK_URL_HEADER "http://thumbnailpacks.libretro.com/" +#define THUMBNAILPACK_EXTENSION ".zip" + +static void extractCB(void *task_data, void *user_data, const char *err) +{ + decompress_task_data_t *dec = (decompress_task_data_t*)task_data; + MainWindow *mainwindow = (MainWindow*)user_data; + + if (err) + RARCH_ERR("%s", err); + + if (dec) + { + if (filestream_exists(dec->source_file)) + filestream_delete(dec->source_file); + + free(dec->source_file); + free(dec); + } + + mainwindow->onThumbnailPackExtractFinished(string_is_empty(err)); +} + +void MainWindow::onThumbnailPackDownloadNetworkError(QNetworkReply::NetworkError code) +{ + QNetworkReply *reply = m_thumbnailPackDownloadReply.data(); + QByteArray errorStringArray; + const char *errorStringData = NULL; + + m_thumbnailPackDownloadProgressDialog->cancel(); + + if (!reply) + return; + + errorStringArray = reply->errorString().toUtf8(); + errorStringData = errorStringArray.constData(); + + RARCH_ERR("[Qt]: Network error code %d received: %s\n", code, errorStringData); + + /* Deleting the reply here seems to cause a strange heap-use-after-free crash. */ + /* + reply->disconnect(); + reply->abort(); + reply->deleteLater(); + */ +} + +void MainWindow::onThumbnailPackDownloadNetworkSslErrors(const QList &errors) +{ + QNetworkReply *reply = m_thumbnailPackDownloadReply.data(); + int i; + + if (!reply) + return; + + for (i = 0; i < errors.count(); i++) + { + const QSslError &error = errors.at(i); + QString string = QString("Ignoring SSL error code ") + QString::number(error.error()) + ": " + error.errorString(); + QByteArray stringArray = string.toUtf8(); + const char *stringData = stringArray.constData(); + RARCH_ERR("[Qt]: %s\n", stringData); + } + + /* ignore all SSL errors for now, like self-signed, expired etc. */ + reply->ignoreSslErrors(); +} + +void MainWindow::onThumbnailPackDownloadCanceled() +{ + m_thumbnailPackDownloadProgressDialog->cancel(); +} + +void MainWindow::onThumbnailPackDownloadFinished() +{ + QString system; + QNetworkReply *reply = m_thumbnailPackDownloadReply.data(); + QNetworkReply::NetworkError error; + int code; + + m_thumbnailPackDownloadProgressDialog->cancel(); + + /* At least on Linux, the progress dialog will refuse to hide itself and will stay on screen in a corrupted way if we happen to show an error message in this function. processEvents() will sometimes fix it, other times not... seems random. */ + qApp->processEvents(); + + if (!reply) + return; + + system = reply->property("system").toString(); + + error = reply->error(); + code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + if (m_thumbnailPackDownloadFile.isOpen()) + m_thumbnailPackDownloadFile.close(); + + if (code != 200) + { + QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + + if (!redirectUrl.isEmpty()) + { + QByteArray redirectUrlArray = redirectUrl.toString().toUtf8(); + const char *redirectUrlData = redirectUrlArray.constData(); + + RARCH_LOG("[Qt]: Thumbnail pack download got redirect with HTTP code %d: %s\n", code, redirectUrlData); + + reply->disconnect(); + reply->abort(); + reply->deleteLater(); + + downloadAllThumbnails(system, redirectUrl); + + return; + } + else + { + emit showErrorMessageDeferred(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": HTTP Code " + QString::number(code)); + + m_thumbnailPackDownloadFile.remove(); + + RARCH_ERR("[Qt]: Thumbnail pack download failed with HTTP status code: %d\n", code); + + reply->disconnect(); + reply->abort(); + reply->deleteLater(); + + return; + } + } + + if (error == QNetworkReply::NoError) + { + int index = m_thumbnailPackDownloadFile.fileName().lastIndexOf(PARTIAL_EXTENSION); + QString newFileName = m_thumbnailPackDownloadFile.fileName().left(index); + QFile newFile(newFileName); + + /* rename() requires the old file to be deleted first if it exists */ + if (newFile.exists() && !newFile.remove()) + RARCH_ERR("[Qt]: Thumbnail pack download finished, but old file could not be deleted.\n"); + else + { + if (m_thumbnailPackDownloadFile.rename(newFileName)) + { + settings_t *settings = config_get_ptr(); + + if (settings) + { + RARCH_LOG("[Qt]: Thumbnail pack download finished successfully.\n"); + emit extractArchiveDeferred(newFileName, settings->paths.directory_thumbnails, TEMP_EXTENSION, extractCB); + } + } + else + { + RARCH_ERR("[Qt]: Thumbnail pack download finished, but temp file could not be renamed.\n"); + emit showErrorMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE)); + } + } + } + else + { + QByteArray errorArray = reply->errorString().toUtf8(); + const char *errorData = errorArray.constData(); + + m_thumbnailPackDownloadFile.remove(); + + RARCH_ERR("[Qt]: Thumbnail pack download ended prematurely: %s\n", errorData); + emit showErrorMessageDeferred(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": Code " + QString::number(code) + ": " + errorData); + } + + reply->disconnect(); + reply->close(); + reply->deleteLater(); +} + +void MainWindow::onThumbnailPackDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) +{ + QNetworkReply *reply = m_thumbnailPackDownloadReply.data(); + int progress = (bytesReceived / (float)bytesTotal) * 100.0f; + + if (!reply) + return; + + m_thumbnailPackDownloadProgressDialog->setValue(progress); +} + +void MainWindow::onThumbnailPackDownloadReadyRead() +{ + QNetworkReply *reply = m_thumbnailPackDownloadReply.data(); + + if (!reply) + return; + + m_thumbnailPackDownloadFile.write(reply->readAll()); +} + +void MainWindow::downloadAllThumbnails(QString system, QUrl url) +{ + QString urlString; + QNetworkReply *reply = NULL; + QNetworkRequest request; + QByteArray urlArray; + settings_t *settings = config_get_ptr(); + const char *urlData = NULL; + + if (!settings) + return; + + urlString = QString(THUMBNAILPACK_URL_HEADER) + system + THUMBNAILPACK_EXTENSION; + + if (url.isEmpty()) + url = urlString; + + request.setUrl(url); + + urlArray = url.toString().toUtf8(); + urlData = urlArray.constData(); + + if (m_thumbnailPackDownloadFile.isOpen()) + { + RARCH_ERR("[Qt]: File is already open.\n"); + return; + } + else + { + QString dirString = QString(settings->paths.directory_thumbnails); + QString fileName = dirString + "/" + system + THUMBNAILPACK_EXTENSION + PARTIAL_EXTENSION; + QDir dir; + QByteArray fileNameArray = fileName.toUtf8(); + const char *fileNameData = fileNameArray.constData(); + + dir.mkpath(dirString); + + m_thumbnailPackDownloadFile.setFileName(fileName); + + if (!m_thumbnailPackDownloadFile.open(QIODevice::WriteOnly)) + { + showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + RARCH_ERR("[Qt]: Could not open file for writing: %s\n", fileNameData); + return; + } + } + + RARCH_LOG("[Qt]: Starting thumbnail pack download...\n"); + RARCH_LOG("[Qt]: Downloading URL %s\n", urlData); + + request.setHeader(QNetworkRequest::UserAgentHeader, USER_AGENT); + + m_thumbnailPackDownloadProgressDialog->setWindowModality(Qt::NonModal); + m_thumbnailPackDownloadProgressDialog->setMinimumDuration(0); + m_thumbnailPackDownloadProgressDialog->setRange(0, 100); + m_thumbnailPackDownloadProgressDialog->setAutoClose(true); + m_thumbnailPackDownloadProgressDialog->setAutoReset(true); + m_thumbnailPackDownloadProgressDialog->setValue(0); + m_thumbnailPackDownloadProgressDialog->setLabelText(QString(msg_hash_to_str(MSG_DOWNLOADING)) + "..."); + m_thumbnailPackDownloadProgressDialog->setCancelButtonText(tr("Cancel")); + m_thumbnailPackDownloadProgressDialog->show(); + + m_thumbnailPackDownloadReply = m_networkManager->get(request); + + reply = m_thumbnailPackDownloadReply.data(); + reply->setProperty("system", system); + + /* make sure any previous connection is removed first */ + disconnect(m_thumbnailPackDownloadProgressDialog, SIGNAL(canceled()), reply, SLOT(abort())); + disconnect(m_thumbnailPackDownloadProgressDialog, SIGNAL(canceled()), m_thumbnailPackDownloadProgressDialog, SLOT(cancel())); + connect(m_thumbnailPackDownloadProgressDialog, SIGNAL(canceled()), reply, SLOT(abort())); + connect(m_thumbnailPackDownloadProgressDialog, SIGNAL(canceled()), m_thumbnailPackDownloadProgressDialog, SLOT(cancel())); + + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onThumbnailPackDownloadNetworkError(QNetworkReply::NetworkError))); + connect(reply, SIGNAL(sslErrors(const QList&)), this, SLOT(onThumbnailPackDownloadNetworkSslErrors(const QList&))); + connect(reply, SIGNAL(finished()), this, SLOT(onThumbnailPackDownloadFinished())); + connect(reply, SIGNAL(readyRead()), this, SLOT(onThumbnailPackDownloadReadyRead())); + connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(onThumbnailPackDownloadProgress(qint64, qint64))); +} + +void MainWindow::onThumbnailPackExtractFinished(bool success) +{ + m_updateProgressDialog->cancel(); + + if (!success) + { + RARCH_ERR("[Qt]: Thumbnail pack extraction failed.\n"); + emit showErrorMessageDeferred(msg_hash_to_str(MSG_DECOMPRESSION_FAILED)); + return; + } + + RARCH_LOG("[Qt]: Thumbnail pack extracted successfully.\n"); + + emit showInfoMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY)); + + /* reload thumbnail image */ + emit itemChanged(); +} diff --git a/ui/drivers/qt/ui_qt_window.cpp b/ui/drivers/qt/ui_qt_window.cpp index bf8ea5943e..c84ae8f878 100644 --- a/ui/drivers/qt/ui_qt_window.cpp +++ b/ui/drivers/qt/ui_qt_window.cpp @@ -321,8 +321,12 @@ MainWindow::MainWindow(QWidget *parent) : ,m_updateFile() ,m_updateReply() ,m_thumbnailDownloadProgressDialog(new QProgressDialog()) + ,m_thumbnailDownloadFile() ,m_thumbnailDownloadReply() ,m_pendingThumbnailDownloadTypes() + ,m_thumbnailPackDownloadProgressDialog(new QProgressDialog()) + ,m_thumbnailPackDownloadFile() + ,m_thumbnailPackDownloadReply() { settings_t *settings = config_get_ptr(); QDir playlistDir(settings->paths.directory_playlist); @@ -341,9 +345,12 @@ MainWindow::MainWindow(QWidget *parent) : int i = 0; qRegisterMetaType >("ThumbnailWidget"); + qRegisterMetaType("retro_task_callback_t"); + /* Cancel all progress dialogs immediately since they show as soon as they're constructed. */ m_updateProgressDialog->cancel(); m_thumbnailDownloadProgressDialog->cancel(); + m_thumbnailPackDownloadProgressDialog->cancel(); m_gridProgressWidget = new QWidget(); gridProgressLabel = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PROGRESS), m_gridProgressWidget); @@ -553,7 +560,7 @@ MainWindow::MainWindow(QWidget *parent) : /* these are always queued */ connect(this, SIGNAL(showErrorMessageDeferred(QString)), this, SLOT(onShowErrorMessage(QString)), Qt::QueuedConnection); connect(this, SIGNAL(showInfoMessageDeferred(QString)), this, SLOT(onShowInfoMessage(QString)), Qt::QueuedConnection); - connect(this, SIGNAL(extractArchiveDeferred(QString)), this, SLOT(onExtractArchive(QString)), Qt::QueuedConnection); + connect(this, SIGNAL(extractArchiveDeferred(QString,QString,QString,retro_task_callback_t)), this, SLOT(onExtractArchive(QString,QString,QString,retro_task_callback_t)), Qt::QueuedConnection); m_timer->start(TIMER_MSEC); @@ -3032,6 +3039,84 @@ void MainWindow::onShowInfoMessage(QString msg) showMessageBox(msg, MainWindow::MSGBOX_TYPE_INFO, Qt::ApplicationModal, false); } +int MainWindow::onExtractArchive(QString path, QString extractionDir, QString tempExtension, retro_task_callback_t cb) +{ + QByteArray pathArray = path.toUtf8(); + QByteArray dirArray = extractionDir.toUtf8(); + const char *file = pathArray.constData(); + const char *dir = dirArray.constData(); + file_archive_transfer_t state; + struct archive_extract_userdata userdata; + struct string_list *file_list = file_archive_get_file_list(file, NULL); + bool returnerr = true; + unsigned i; + + if (!file_list || file_list->size == 0) + { + showMessageBox("Error: Archive is empty.", MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + RARCH_ERR("[Qt]: Downloaded archive is empty?\n"); + return -1; + } + + for (i = 0; i < file_list->size; i++) + { + QFile fileObj(file_list->elems[i].data); + + if (fileObj.exists()) + { + if (!fileObj.remove()) + { + /* if we cannot delete the existing file to update it, rename it for now and delete later */ + QFile fileTemp(fileObj.fileName() + tempExtension); + + if (fileTemp.exists()) + { + if (!fileTemp.remove()) + { + showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + RARCH_ERR("[Qt]: Could not delete file: %s\n", file_list->elems[i].data); + return -1; + } + } + + if (!fileObj.rename(fileTemp.fileName())) + { + showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); + RARCH_ERR("[Qt]: Could not rename file: %s\n", file_list->elems[i].data); + return -1; + } + } + } + } + + string_list_free(file_list); + + memset(&state, 0, sizeof(state)); + memset(&userdata, 0, sizeof(userdata)); + + state.type = ARCHIVE_TRANSFER_INIT; + + m_updateProgressDialog->setWindowModality(Qt::NonModal); + m_updateProgressDialog->setMinimumDuration(0); + m_updateProgressDialog->setRange(0, 0); + m_updateProgressDialog->setAutoClose(true); + m_updateProgressDialog->setAutoReset(true); + m_updateProgressDialog->setValue(0); + m_updateProgressDialog->setLabelText(QString(msg_hash_to_str(MSG_EXTRACTING)) + "..."); + m_updateProgressDialog->setCancelButtonText(QString()); + m_updateProgressDialog->show(); + + if (!task_push_decompress(file, dir, + NULL, NULL, NULL, + cb, this)) + { + m_updateProgressDialog->cancel(); + return -1; + } + + return returnerr; +} + static void* ui_window_qt_init(void) { ui_window.qtWindow = new MainWindow(); diff --git a/ui/drivers/qt/updateretroarch.cpp b/ui/drivers/qt/updateretroarch.cpp index 1381345516..9f524abc9e 100644 --- a/ui/drivers/qt/updateretroarch.cpp +++ b/ui/drivers/qt/updateretroarch.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -157,7 +157,7 @@ void MainWindow::onRetroArchUpdateDownloadFinished() if (m_updateFile.rename(newFileName)) { RARCH_LOG("[Qt]: RetroArch update finished downloading successfully.\n"); - emit extractArchiveDeferred(newFileName); + emit extractArchiveDeferred(newFileName, ".", TEMP_EXTENSION, extractCB); } else { @@ -198,82 +198,6 @@ void MainWindow::onUpdateRetroArchFinished(bool success) emit showInfoMessageDeferred(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FINISHED)); } -int MainWindow::onExtractArchive(QString path) -{ - QByteArray pathArray = path.toUtf8(); - const char *file = pathArray.constData(); - file_archive_transfer_t state; - struct archive_extract_userdata userdata; - struct string_list *file_list = file_archive_get_file_list(file, NULL); - bool returnerr = true; - unsigned i; - - if (!file_list || file_list->size == 0) - { - showMessageBox("Error: Archive is empty.", MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - RARCH_ERR("[Qt]: Downloaded archive is empty?\n"); - return -1; - } - - for (i = 0; i < file_list->size; i++) - { - QFile fileObj(file_list->elems[i].data); - - if (fileObj.exists()) - { - if (!fileObj.remove()) - { - /* if we cannot delete the existing file to update it, rename it for now and delete later */ - QFile fileTemp(fileObj.fileName() + TEMP_EXTENSION); - - if (fileTemp.exists()) - { - if (!fileTemp.remove()) - { - showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - RARCH_ERR("[Qt]: Could not delete file: %s\n", file_list->elems[i].data); - return -1; - } - } - - if (!fileObj.rename(fileTemp.fileName())) - { - showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false); - RARCH_ERR("[Qt]: Could not rename file: %s\n", file_list->elems[i].data); - return -1; - } - } - } - } - - string_list_free(file_list); - - memset(&state, 0, sizeof(state)); - memset(&userdata, 0, sizeof(userdata)); - - state.type = ARCHIVE_TRANSFER_INIT; - - m_updateProgressDialog->setWindowModality(Qt::NonModal); - m_updateProgressDialog->setMinimumDuration(0); - m_updateProgressDialog->setRange(0, 0); - m_updateProgressDialog->setAutoClose(true); - m_updateProgressDialog->setAutoReset(true); - m_updateProgressDialog->setValue(0); - m_updateProgressDialog->setLabelText(QString(msg_hash_to_str(MSG_EXTRACTING)) + "..."); - m_updateProgressDialog->setCancelButtonText(QString()); - m_updateProgressDialog->show(); - - if (!task_push_decompress(file, ".", - NULL, NULL, NULL, - extractCB, this)) - { - m_updateProgressDialog->cancel(); - return -1; - } - - return returnerr; -} - void MainWindow::onUpdateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { QNetworkReply *reply = m_updateReply.data(); diff --git a/ui/drivers/ui_qt.h b/ui/drivers/ui_qt.h index d55f076f6e..656d5bd967 100644 --- a/ui/drivers/ui_qt.h +++ b/ui/drivers/ui_qt.h @@ -41,6 +41,7 @@ extern "C" { #include #include +#include #include "../ui_companion_driver.h" #include "../../gfx/video_driver.h" } @@ -297,7 +298,7 @@ signals: void gotReloadShaderParams(); void showErrorMessageDeferred(QString msg); void showInfoMessageDeferred(QString msg); - void extractArchiveDeferred(QString path); + void extractArchiveDeferred(QString path, QString extractionDir, QString tempExtension, retro_task_callback_t cb); void itemChanged(); void gotThumbnailDownload(QString system, QString title); @@ -337,8 +338,10 @@ public slots: void showDocs(); void updateRetroArchNightly(); void onUpdateRetroArchFinished(bool success); + void onThumbnailPackExtractFinished(bool success); void deferReloadShaderParams(); void downloadThumbnail(QString system, QString title, QUrl url = QUrl()); + void downloadAllThumbnails(QString system, QUrl url = QUrl()); private slots: void onLoadCoreClicked(const QStringList &extensionFilters = QStringList()); @@ -371,24 +374,33 @@ private slots: void onGridItemClicked(ThumbnailWidget *thumbnailWidget = NULL); void onPlaylistFilesDropped(QStringList files); void onShaderParamsClicked(); + void onShowErrorMessage(QString msg); + void onShowInfoMessage(QString msg); + void onContributorsClicked(); + void onItemChanged(); + int onExtractArchive(QString path, QString extractionDir, QString tempExtension, retro_task_callback_t cb); + void onUpdateNetworkError(QNetworkReply::NetworkError code); void onUpdateNetworkSslErrors(const QList &errors); void onRetroArchUpdateDownloadFinished(); void onUpdateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal); void onUpdateDownloadReadyRead(); void onUpdateDownloadCanceled(); - void onShowErrorMessage(QString msg); - void onShowInfoMessage(QString msg); - void onContributorsClicked(); + void onThumbnailDownloadNetworkError(QNetworkReply::NetworkError code); void onThumbnailDownloadNetworkSslErrors(const QList &errors); void onThumbnailDownloadFinished(); void onThumbnailDownloadProgress(qint64 bytesReceived, qint64 bytesTotal); void onThumbnailDownloadReadyRead(); void onThumbnailDownloadCanceled(); - void onItemChanged(); void onDownloadThumbnail(QString system, QString title); - int onExtractArchive(QString path); + + void onThumbnailPackDownloadNetworkError(QNetworkReply::NetworkError code); + void onThumbnailPackDownloadNetworkSslErrors(const QList &errors); + void onThumbnailPackDownloadFinished(); + void onThumbnailPackDownloadProgress(qint64 bytesReceived, qint64 bytesTotal); + void onThumbnailPackDownloadReadyRead(); + void onThumbnailPackDownloadCanceled(); private: void setCurrentCoreLabel(); @@ -463,14 +475,20 @@ private: QElapsedTimer m_statusMessageElapsedTimer; QPointer m_shaderParamsDialog; QNetworkAccessManager *m_networkManager; + QProgressDialog *m_updateProgressDialog; QFile m_updateFile; QPointer m_updateReply; + QProgressDialog *m_thumbnailDownloadProgressDialog; QFile m_thumbnailDownloadFile; QPointer m_thumbnailDownloadReply; QStringList m_pendingThumbnailDownloadTypes; + QProgressDialog *m_thumbnailPackDownloadProgressDialog; + QFile m_thumbnailPackDownloadFile; + QPointer m_thumbnailPackDownloadReply; + protected: void closeEvent(QCloseEvent *event); void keyPressEvent(QKeyEvent *event);