mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-25 00:49:47 +00:00
Merge pull request #7049 from bparker06/wimp_update
Qt: add option to update RetroArch (Windows only for now)
This commit is contained in:
commit
d4ab18c188
@ -16,10 +16,11 @@
|
||||
- LOCALIZATION: Update Spanish translation.
|
||||
- MIDI: Add MIDI support to the libretro API. Dosbox is the first proof of concept core implementing libretro MIDI.
|
||||
- MIDI: Add a Windows driver for MIDI, based on winmm.
|
||||
- MENU/QT/WIMP: QT QSlider styling for Dark Theme.
|
||||
- MENU/QT/WIMP: Qt QSlider styling for Dark Theme.
|
||||
- MENU/QT/WIMP: Remove button ghostly inside highlighting.
|
||||
- MENU/QT/WIMP: Initial grid view.
|
||||
- MENU/QT/WIMP: Drag&drop to add new playlist items, add option to add/edit/delete playlists.
|
||||
- MENU/QT/WIMP: Add menu option to update RetroArch (Windows only for now).
|
||||
- METAL: Initial work-in-progress video driver for Metal. macOS-only right now, and currently requires macOS 10.13.
|
||||
- METAL: Supports XMB/MaterialUI, has a menu display driver. Has a font rendering driver.
|
||||
- METAL/SLANG: Slang shaders should be compatible with Metal video driver.
|
||||
|
@ -345,9 +345,9 @@ MOC_HEADERS += ui/drivers/ui_qt.h \
|
||||
ui/drivers/qt/ui_qt_load_core_window.h \
|
||||
ui/drivers/qt/flowlayout.h
|
||||
|
||||
DEFINES += $(QT5CORE_CFLAGS) $(QT5GUI_CFLAGS) $(QT5WIDGETS_CFLAGS) $(QT5CONCURRENT_CFLAGS) -DHAVE_MAIN
|
||||
DEFINES += $(QT5CORE_CFLAGS) $(QT5GUI_CFLAGS) $(QT5WIDGETS_CFLAGS) $(QT5CONCURRENT_CFLAGS) $(QT5NETWORK_CFLAGS) -DHAVE_MAIN
|
||||
#DEFINES += $(QT5WEBENGINE_CFLAGS)
|
||||
LIBS += $(QT5CORE_LIBS) $(QT5GUI_LIBS) $(QT5WIDGETS_LIBS) $(QT5CONCURRENT_LIBS)
|
||||
LIBS += $(QT5CORE_LIBS) $(QT5GUI_LIBS) $(QT5WIDGETS_LIBS) $(QT5CONCURRENT_LIBS) $(QT5NETWORK_LIBS)
|
||||
#LIBS += $(QT5WEBENGINE_LIBS)
|
||||
NEED_CXX_LINKER = 1
|
||||
|
||||
|
@ -3488,6 +3488,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_CUSTOM,
|
||||
"カスタム...")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_TITLE,
|
||||
"設定")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_TOOLS,
|
||||
"ツール(&T)")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP,
|
||||
"ヘルプ(&H)")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_ABOUT,
|
||||
@ -3534,6 +3536,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_WARNING,
|
||||
"警告")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ERROR,
|
||||
"エラー")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR,
|
||||
"ネットワークエラー")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_RESTART_TO_TAKE_EFFECT,
|
||||
"変更はRetroArchを再起動した後に反映されます。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_LOG,
|
||||
@ -3564,6 +3568,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_IS_EMPTY,
|
||||
"ファイルは空きです。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_READ_OPEN_FAILED,
|
||||
"ファイルを読み込みのために開けません。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED,
|
||||
"ファイルを書き込みのために開けません。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_DOES_NOT_EXIST,
|
||||
"ファイルは存在しません。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SUGGEST_LOADED_CORE_FIRST,
|
||||
@ -3656,6 +3662,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_QUESTION,
|
||||
"質問")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE,
|
||||
"ファイル削除に失敗しました。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE,
|
||||
"ファイルの名前変更に失敗しました。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES,
|
||||
"ファイルの一覧を構築しています...")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST,
|
||||
@ -3696,3 +3704,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_UPDATE_PLAYLIST_ENTRY,
|
||||
"プレイリストエントリーを更新するに失敗しました。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLEASE_FILL_OUT_REQUIRED_FIELDS,
|
||||
"必須フィールドがすべて入力されていることを確認してください。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_NIGHTLY,
|
||||
"RetroArchをアップデート (nightly)")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FINISHED,
|
||||
"更新に成功しました。変更を適用にするには、RetroArchを再起動する必要があります。")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FAILED,
|
||||
"更新に失敗しました。")
|
||||
|
@ -3764,6 +3764,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_CUSTOM,
|
||||
"Custom...")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_TITLE,
|
||||
"Options")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_TOOLS,
|
||||
"&Tools")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP,
|
||||
"&Help")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_ABOUT,
|
||||
@ -3810,6 +3812,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_WARNING,
|
||||
"Warning")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ERROR,
|
||||
"Error")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR,
|
||||
"Network Error")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_RESTART_TO_TAKE_EFFECT,
|
||||
"Please restart the program for the changes to take effect.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_LOG,
|
||||
@ -3848,6 +3852,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_IS_EMPTY,
|
||||
"File is empty.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_READ_OPEN_FAILED,
|
||||
"Could not open file for reading.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED,
|
||||
"Could not open file for writing.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_DOES_NOT_EXIST,
|
||||
"File does not exist.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SUGGEST_LOADED_CORE_FIRST,
|
||||
@ -4186,6 +4192,8 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_QUESTION,
|
||||
"Question")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE,
|
||||
"Could not delete file.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE,
|
||||
"Could not rename file.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES,
|
||||
"Gathering list of files...")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST,
|
||||
@ -4226,3 +4234,9 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_UPDATE_PLAYLIST_ENTRY,
|
||||
"Error updating playlist entry.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLEASE_FILL_OUT_REQUIRED_FIELDS,
|
||||
"Please fill out all required fields.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_NIGHTLY,
|
||||
"Update RetroArch (nightly)")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FINISHED,
|
||||
"RetroArch updated successfully. Please restart the application for the changes to take effect.")
|
||||
MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FAILED,
|
||||
"Update failed.")
|
||||
|
@ -1898,6 +1898,7 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SHOW_HIDDEN_FILES,
|
||||
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_LIST_MAX_COUNT,
|
||||
MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT,
|
||||
MENU_ENUM_LABEL_VALUE_QT_MENU_TOOLS,
|
||||
MENU_ENUM_LABEL_VALUE_QT_MENU_HELP,
|
||||
MENU_ENUM_LABEL_VALUE_QT_MENU_DOCK_CONTENT_BROWSER,
|
||||
MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_BOXART,
|
||||
@ -1934,6 +1935,7 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_VALUE_QT_FILE_PATH_IS_BLANK,
|
||||
MENU_ENUM_LABEL_VALUE_QT_FILE_IS_EMPTY,
|
||||
MENU_ENUM_LABEL_VALUE_QT_FILE_READ_OPEN_FAILED,
|
||||
MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED,
|
||||
MENU_ENUM_LABEL_VALUE_QT_FILE_DOES_NOT_EXIST,
|
||||
MENU_ENUM_LABEL_VALUE_QT_ZOOM,
|
||||
MENU_ENUM_LABEL_VALUE_QT_VIEW,
|
||||
@ -1947,6 +1949,7 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM,
|
||||
MENU_ENUM_LABEL_VALUE_QT_QUESTION,
|
||||
MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE,
|
||||
MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE,
|
||||
MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES,
|
||||
MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST,
|
||||
MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY,
|
||||
@ -1968,6 +1971,10 @@ enum msg_hash_enums
|
||||
MENU_ENUM_LABEL_VALUE_QT_PLEASE_FILL_OUT_REQUIRED_FIELDS,
|
||||
MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_ABOUT,
|
||||
MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_DOCUMENTATION,
|
||||
MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR,
|
||||
MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_NIGHTLY,
|
||||
MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FINISHED,
|
||||
MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FAILED,
|
||||
|
||||
MENU_LABEL(MIDI_INPUT),
|
||||
MENU_LABEL(MIDI_OUTPUT),
|
||||
@ -2045,6 +2052,7 @@ enum msg_hash_enums
|
||||
MSG_CHEAT_SEARCH_ADD_MATCH_SUCCESS,
|
||||
MSG_CHEAT_SEARCH_ADD_MATCH_FAIL,
|
||||
MSG_CHEAT_SEARCH_DELETE_MATCH_SUCCESS,
|
||||
|
||||
MSG_LAST
|
||||
};
|
||||
|
||||
|
@ -279,15 +279,17 @@ if [ "$HAVE_QT" != 'no' ] && [ "$MOC_PATH" != 'none' ]; then
|
||||
check_pkgconf QT5GUI Qt5Gui 5.2
|
||||
check_pkgconf QT5WIDGETS Qt5Widgets 5.2
|
||||
check_pkgconf QT5CONCURRENT Qt5Concurrent 5.2
|
||||
check_pkgconf QT5NETWORK Qt5Network 5.2
|
||||
#check_pkgconf QT5WEBENGINE Qt5WebEngine 5.4
|
||||
|
||||
check_val '' QT5CORE -lQt5Core QT5CORE
|
||||
check_val '' QT5GUI -lQt5Gui QT5GUI
|
||||
check_val '' QT5WIDGETS -lQt5Widgets QT5WIDGETS
|
||||
check_val '' QT5CONCURRENT -lQt5Widgets QT5CONCURRENT
|
||||
check_val '' QT5CONCURRENT -lQt5Concurrent QT5CONCURRENT
|
||||
check_val '' QT5NETWORK -lQt5Network QT5NETWORK
|
||||
#check_val '' QT5WEBENGINE -lQt5WebEngine QT5WEBENGINE
|
||||
|
||||
if [ "$HAVE_QT5CORE" = "no" ] || [ "$HAVE_QT5GUI" = "no" ] || [ "$HAVE_QT5WIDGETS" = "no" ] || [ "$HAVE_QT5CONCURRENT" = "no" ]; then
|
||||
if [ "$HAVE_QT5CORE" = "no" ] || [ "$HAVE_QT5GUI" = "no" ] || [ "$HAVE_QT5WIDGETS" = "no" ] || [ "$HAVE_QT5CONCURRENT" = "no" ] || [ "$HAVE_QT5NETWORK" = "no" ]; then
|
||||
die : 'Notice: Not building Qt support, required libraries were not found.'
|
||||
HAVE_QT=no
|
||||
else
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <QDragEnterEvent>
|
||||
#include <QDropEvent>
|
||||
#include <QtConcurrentRun>
|
||||
#include <QtNetwork>
|
||||
|
||||
#include "../ui_qt.h"
|
||||
#include "ui_qt_load_core_window.h"
|
||||
@ -56,10 +57,12 @@ extern "C" {
|
||||
#include "../../../content.h"
|
||||
#include "../../../menu/menu_driver.h"
|
||||
#include "../../../tasks/tasks_internal.h"
|
||||
#include "../../../config.def.h"
|
||||
#include <string/stdstring.h>
|
||||
#include <encodings/utf.h>
|
||||
#include <file/file_path.h>
|
||||
#include <file/archive_file.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <math.h>
|
||||
}
|
||||
|
||||
@ -81,6 +84,10 @@ extern "C" {
|
||||
#define KATAKANA_START 0x30A1U
|
||||
#define KATAKANA_END 0x30F6U
|
||||
#define HIRA_KATA_OFFSET (KATAKANA_START - HIRAGANA_START)
|
||||
#define USER_AGENT "RetroArch-WIMP/1.0"
|
||||
#define DOCS_URL "http://docs.libretro.com/"
|
||||
#define PARTIAL_EXTENSION ".partial"
|
||||
#define TEMP_EXTENSION ".update_tmp"
|
||||
|
||||
static ui_window_qt_t ui_window = {0};
|
||||
|
||||
@ -908,6 +915,10 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
,m_allPlaylistsGridMaxCount(0)
|
||||
,m_playlistEntryDialog(NULL)
|
||||
,m_statusMessageElapsedTimer()
|
||||
,m_networkManager(new QNetworkAccessManager(this))
|
||||
,m_updateProgressDialog(new QProgressDialog())
|
||||
,m_updateFile()
|
||||
,m_updateReply()
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
QDir playlistDir(settings->paths.directory_playlist);
|
||||
@ -927,6 +938,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
|
||||
qRegisterMetaType<QPointer<ThumbnailWidget> >("ThumbnailWidget");
|
||||
|
||||
m_updateProgressDialog->cancel();
|
||||
|
||||
m_gridProgressWidget = new QWidget();
|
||||
gridProgressLabel = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PROGRESS), m_gridProgressWidget);
|
||||
|
||||
@ -1146,6 +1159,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
resizeDocks(QList<QDockWidget*>() << m_searchDock, QList<int>() << 1, Qt::Vertical);
|
||||
#endif
|
||||
|
||||
removeUpdateTempFiles();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@ -1160,6 +1175,31 @@ MainWindow::~MainWindow()
|
||||
removeGridItems();
|
||||
}
|
||||
|
||||
void MainWindow::removeUpdateTempFiles()
|
||||
{
|
||||
/* a QDir with no path means the current working directory */
|
||||
QDir dir;
|
||||
QStringList dirList = dir.entryList(QStringList(), QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System, QDir::Name);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dirList.count(); i++)
|
||||
{
|
||||
QString path(dir.path() + "/" + dirList.at(i));
|
||||
QFile file(path);
|
||||
|
||||
if (path.endsWith(TEMP_EXTENSION))
|
||||
{
|
||||
QByteArray pathArray = path.toUtf8();
|
||||
const char *pathData = pathArray.constData();
|
||||
|
||||
if (file.remove())
|
||||
RARCH_LOG("[Qt]: removed temporary update file %s\n", pathData);
|
||||
else
|
||||
RARCH_LOG("[Qt]: could not remove temporary update file %s\n", pathData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onPlaylistFilesDropped(QStringList files)
|
||||
{
|
||||
addFilesToPlaylist(files);
|
||||
@ -1215,7 +1255,7 @@ void MainWindow::addFilesToPlaylist(QStringList files)
|
||||
|
||||
if (currentPlaylistPath == ALL_PLAYLISTS_TOKEN)
|
||||
{
|
||||
ui_window.qtWindow->showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CANNOT_ADD_TO_ALL_PLAYLISTS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CANNOT_ADD_TO_ALL_PLAYLISTS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1239,7 +1279,7 @@ void MainWindow::addFilesToPlaylist(QStringList files)
|
||||
if (selectedName.isEmpty() || selectedPath.isEmpty() ||
|
||||
selectedDatabase.isEmpty())
|
||||
{
|
||||
ui_window.qtWindow->showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLEASE_FILL_OUT_REQUIRED_FIELDS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_PLEASE_FILL_OUT_REQUIRED_FIELDS), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1269,7 +1309,7 @@ void MainWindow::addFilesToPlaylist(QStringList files)
|
||||
else if (files.count() == 1)
|
||||
{
|
||||
/* If adding a single file, tell user that it doesn't exist. */
|
||||
ui_window.qtWindow->showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_DOES_NOT_EXIST), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_FILE_DOES_NOT_EXIST), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1469,11 +1509,11 @@ void MainWindow::showWelcomeScreen()
|
||||
"Documentation for RetroArch, libretro and cores:<br>\n"
|
||||
"<a href=\"https://docs.libretro.com/\">https://docs.libretro.com/</a>");
|
||||
|
||||
if (!ui_window.qtWindow->settings()->value("show_welcome_screen", true).toBool())
|
||||
if (!m_settings->value("show_welcome_screen", true).toBool())
|
||||
return;
|
||||
|
||||
if (!ui_window.qtWindow->showMessageBox(welcomeText, MainWindow::MSGBOX_TYPE_INFO, Qt::ApplicationModal))
|
||||
ui_window.qtWindow->settings()->setValue("show_welcome_screen", false);
|
||||
if (!showMessageBox(welcomeText, MainWindow::MSGBOX_TYPE_INFO, Qt::ApplicationModal))
|
||||
m_settings->setValue("show_welcome_screen", false);
|
||||
|
||||
}
|
||||
|
||||
@ -1784,7 +1824,7 @@ void MainWindow::onFileDropWidgetContextMenuRequested(const QPoint &pos)
|
||||
|
||||
if (!updateCurrentPlaylistEntry(contentHash))
|
||||
{
|
||||
ui_window.qtWindow->showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_UPDATE_PLAYLIST_ENTRY), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_UPDATE_PLAYLIST_ENTRY), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1966,12 +2006,12 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&)
|
||||
{
|
||||
if (currentPlaylistFile.exists())
|
||||
{
|
||||
if (ui_window.qtWindow->showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST)).arg(selectedItem->text()), MainWindow::MSGBOX_TYPE_QUESTION, Qt::ApplicationModal, false))
|
||||
if (showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST)).arg(selectedItem->text()), MainWindow::MSGBOX_TYPE_QUESTION, Qt::ApplicationModal, false))
|
||||
{
|
||||
if (currentPlaylistFile.remove())
|
||||
reloadPlaylists();
|
||||
else
|
||||
ui_window.qtWindow->showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2823,7 +2863,7 @@ void MainWindow::deleteCurrentPlaylistItem()
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
if (!ui_window.qtWindow->showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM)).arg(contentHash["label"]), MainWindow::MSGBOX_TYPE_QUESTION, Qt::ApplicationModal, false))
|
||||
if (!showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST_ITEM)).arg(contentHash["label"]), MainWindow::MSGBOX_TYPE_QUESTION, Qt::ApplicationModal, false))
|
||||
return;
|
||||
|
||||
playlist = playlist_init(playlistData, COLLECTION_SIZE);
|
||||
@ -4587,7 +4627,313 @@ void MainWindow::showAbout()
|
||||
|
||||
void MainWindow::showDocs()
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("http://docs.libretro.com/"));
|
||||
QDesktopServices::openUrl(QUrl(DOCS_URL));
|
||||
}
|
||||
|
||||
void MainWindow::onUpdateNetworkError(QNetworkReply::NetworkError code)
|
||||
{
|
||||
QNetworkReply *reply = m_updateReply.data();
|
||||
QByteArray errorStringArray;
|
||||
const char *errorStringData = NULL;
|
||||
|
||||
m_updateProgressDialog->reset();
|
||||
|
||||
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::onUpdateNetworkSslErrors(const QList<QSslError> &errors)
|
||||
{
|
||||
QNetworkReply *reply = m_updateReply.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::onUpdateDownloadCanceled()
|
||||
{
|
||||
m_updateProgressDialog->reset();
|
||||
}
|
||||
|
||||
void MainWindow::onRetroArchUpdateDownloadFinished()
|
||||
{
|
||||
QNetworkReply *reply = m_updateReply.data();
|
||||
QNetworkReply::NetworkError error;
|
||||
int code;
|
||||
|
||||
m_updateProgressDialog->reset();
|
||||
|
||||
if (!reply)
|
||||
return;
|
||||
|
||||
error = reply->error();
|
||||
code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
|
||||
if (m_updateFile.isOpen())
|
||||
m_updateFile.close();
|
||||
|
||||
if (code != 200)
|
||||
{
|
||||
showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": HTTP Code " + QString::number(code), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
RARCH_ERR("[Qt]: RetroArch update failed with HTTP status code: %d\n", code);
|
||||
reply->disconnect();
|
||||
reply->abort();
|
||||
reply->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
if (error == QNetworkReply::NoError)
|
||||
{
|
||||
int index = m_updateFile.fileName().lastIndexOf(PARTIAL_EXTENSION);
|
||||
QString newFileName = m_updateFile.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]: RetroArch update finished, but old file could not be deleted.\n");
|
||||
else
|
||||
{
|
||||
if (!m_updateFile.rename(newFileName))
|
||||
RARCH_ERR("[Qt]: RetroArch update finished, but temp file could not be renamed.\n");
|
||||
else
|
||||
{
|
||||
RARCH_LOG("[Qt]: RetroArch update finished downloading successfully.\n");
|
||||
|
||||
extractArchive(newFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray errorArray = reply->errorString().toUtf8();
|
||||
const char *errorData = errorArray.constData();
|
||||
|
||||
RARCH_ERR("[Qt]: RetroArch update ended prematurely: %s\n", errorData);
|
||||
showMessageBox(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR)) + ": Code " + QString::number(code) + ": " + errorData, MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
}
|
||||
|
||||
reply->disconnect();
|
||||
reply->close();
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
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->onUpdateRetroArchFinished(string_is_empty(err));
|
||||
}
|
||||
|
||||
void MainWindow::onUpdateRetroArchFinished(bool success)
|
||||
{
|
||||
m_updateProgressDialog->reset();
|
||||
|
||||
if (!success)
|
||||
{
|
||||
RARCH_ERR("[Qt]: RetroArch update failed.\n");
|
||||
showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FAILED), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||
return;
|
||||
}
|
||||
|
||||
RARCH_LOG("[Qt]: RetroArch update finished successfully.\n");
|
||||
|
||||
showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_FINISHED), MainWindow::MSGBOX_TYPE_INFO, Qt::ApplicationModal, false);
|
||||
}
|
||||
|
||||
int MainWindow::extractArchive(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->reset();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return returnerr;
|
||||
}
|
||||
|
||||
void MainWindow::onUpdateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
QNetworkReply *reply = m_updateReply.data();
|
||||
int progress = (bytesReceived / (float)bytesTotal) * 100.0f;
|
||||
|
||||
if (!reply)
|
||||
return;
|
||||
|
||||
m_updateProgressDialog->setValue(progress);
|
||||
}
|
||||
|
||||
void MainWindow::onUpdateDownloadReadyRead()
|
||||
{
|
||||
QNetworkReply *reply = m_updateReply.data();
|
||||
|
||||
if (!reply)
|
||||
return;
|
||||
|
||||
m_updateFile.write(reply->readAll());
|
||||
}
|
||||
|
||||
void MainWindow::updateRetroArchNightly()
|
||||
{
|
||||
QUrl url(QUrl(buildbot_server_url).resolved(QUrl("../RetroArch_update.zip")));
|
||||
QNetworkRequest request(url);
|
||||
QNetworkReply *reply = NULL;
|
||||
QByteArray urlArray = url.toString().toUtf8();
|
||||
const char *urlData = urlArray.constData();
|
||||
|
||||
if (m_updateFile.isOpen())
|
||||
{
|
||||
RARCH_ERR("[Qt]: File is already open.\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
QString fileName = QFileInfo(url.toString()).fileName() + PARTIAL_EXTENSION;
|
||||
QByteArray fileNameArray = fileName.toUtf8();
|
||||
const char *fileNameData = fileNameArray.constData();
|
||||
|
||||
m_updateFile.setFileName(fileName);
|
||||
|
||||
if (!m_updateFile.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 update of RetroArch...\n");
|
||||
RARCH_LOG("[Qt]: Downloading URL %s\n", urlData);
|
||||
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, USER_AGENT);
|
||||
|
||||
m_updateProgressDialog->setWindowModality(Qt::NonModal);
|
||||
m_updateProgressDialog->setMinimumDuration(0);
|
||||
m_updateProgressDialog->setRange(0, 100);
|
||||
m_updateProgressDialog->setAutoClose(true);
|
||||
m_updateProgressDialog->setAutoReset(true);
|
||||
m_updateProgressDialog->setValue(0);
|
||||
m_updateProgressDialog->setLabelText(QString(msg_hash_to_str(MSG_DOWNLOADING)) + "...");
|
||||
m_updateProgressDialog->setCancelButtonText(tr("Cancel"));
|
||||
m_updateProgressDialog->show();
|
||||
|
||||
m_updateReply = m_networkManager->get(request);
|
||||
reply = m_updateReply.data();
|
||||
|
||||
/* make sure any previous connection is removed first */
|
||||
disconnect(m_updateProgressDialog, SIGNAL(canceled()), reply, SLOT(abort()));
|
||||
disconnect(m_updateProgressDialog, SIGNAL(canceled()), m_updateProgressDialog, SLOT(reset()));
|
||||
connect(m_updateProgressDialog, SIGNAL(canceled()), reply, SLOT(abort()));
|
||||
connect(m_updateProgressDialog, SIGNAL(canceled()), m_updateProgressDialog, SLOT(reset()));
|
||||
|
||||
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onUpdateNetworkError(QNetworkReply::NetworkError)));
|
||||
connect(reply, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(onUpdateNetworkSslErrors(const QList<QSslError>&)));
|
||||
connect(reply, SIGNAL(finished()), this, SLOT(onRetroArchUpdateDownloadFinished()));
|
||||
connect(reply, SIGNAL(readyRead()), this, SLOT(onUpdateDownloadReadyRead()));
|
||||
connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(onUpdateDownloadProgress(qint64, qint64)));
|
||||
|
||||
}
|
||||
|
||||
const QPixmap getInvader()
|
||||
|
@ -224,6 +224,8 @@ static void* ui_companion_qt_init(void)
|
||||
QMenu *editMenu = NULL;
|
||||
QMenu *viewMenu = NULL;
|
||||
QMenu *viewClosedDocksMenu = NULL;
|
||||
QMenu *toolsMenu = NULL;
|
||||
QMenu *updaterMenu = NULL;
|
||||
QMenu *helpMenu = NULL;
|
||||
QRect desktopRect;
|
||||
QDockWidget *thumbnailDock = NULL;
|
||||
@ -323,6 +325,11 @@ static void* ui_companion_qt_init(void)
|
||||
viewMenu->addSeparator();
|
||||
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS), mainwindow->viewOptionsDialog(), SLOT(showDialog()));
|
||||
|
||||
toolsMenu = menu->addMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_TOOLS));
|
||||
updaterMenu = toolsMenu->addMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ONLINE_UPDATER));
|
||||
#ifdef Q_OS_WIN
|
||||
updaterMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_NIGHTLY), mainwindow, SLOT(updateRetroArchNightly()));
|
||||
#endif
|
||||
helpMenu = menu->addMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP));
|
||||
helpMenu->addAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_DOCUMENTATION)), mainwindow, SLOT(showDocs()));
|
||||
helpMenu->addAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_ABOUT)) + "...", mainwindow, SLOT(showAbout()));
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include <QPointer>
|
||||
#include <QProgressBar>
|
||||
#include <QElapsedTimer>
|
||||
#include <QSslError>
|
||||
#include <QNetworkReply>
|
||||
|
||||
extern "C" {
|
||||
#include <retro_assert.h>
|
||||
@ -67,6 +69,9 @@ class QScrollArea;
|
||||
class QSlider;
|
||||
class QDragEnterEvent;
|
||||
class QDropEvent;
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QProgressDialog;
|
||||
class LoadCoreWindow;
|
||||
class MainWindow;
|
||||
class ThumbnailWidget;
|
||||
@ -392,6 +397,8 @@ public slots:
|
||||
void onFileDropWidgetContextMenuRequested(const QPoint &pos);
|
||||
void showAbout();
|
||||
void showDocs();
|
||||
void updateRetroArchNightly();
|
||||
void onUpdateRetroArchFinished(bool success);
|
||||
|
||||
private slots:
|
||||
void onLoadCoreClicked(const QStringList &extensionFilters = QStringList());
|
||||
@ -423,6 +430,12 @@ private slots:
|
||||
void onGridItemDoubleClicked();
|
||||
void onGridItemClicked();
|
||||
void onPlaylistFilesDropped(QStringList files);
|
||||
void onUpdateNetworkError(QNetworkReply::NetworkError code);
|
||||
void onUpdateNetworkSslErrors(const QList<QSslError> &errors);
|
||||
void onRetroArchUpdateDownloadFinished();
|
||||
void onUpdateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void onUpdateDownloadReadyRead();
|
||||
void onUpdateDownloadCanceled();
|
||||
|
||||
private:
|
||||
void setCurrentCoreLabel();
|
||||
@ -433,6 +446,8 @@ private:
|
||||
void loadImageDeferred(GridItem *item, QString path);
|
||||
void calcGridItemSize(GridItem *item, int zoomValue);
|
||||
bool updateCurrentPlaylistEntry(const QHash<QString, QString> &contentHash);
|
||||
int extractArchive(QString path);
|
||||
void removeUpdateTempFiles();
|
||||
QVector<QHash<QString, QString> > getPlaylistItems(QString pathString);
|
||||
|
||||
LoadCoreWindow *m_loadCoreWindow;
|
||||
@ -493,6 +508,10 @@ private:
|
||||
int m_allPlaylistsGridMaxCount;
|
||||
PlaylistEntryDialog *m_playlistEntryDialog;
|
||||
QElapsedTimer m_statusMessageElapsedTimer;
|
||||
QNetworkAccessManager *m_networkManager;
|
||||
QProgressDialog *m_updateProgressDialog;
|
||||
QFile m_updateFile;
|
||||
QPointer<QNetworkReply> m_updateReply;
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
Loading…
Reference in New Issue
Block a user