RetroArch/ui/drivers/ui_qt.cpp

790 lines
29 KiB
C++
Raw Normal View History

/* RetroArch - A frontend for libretro.
2017-01-22 12:40:32 +00:00
* Copyright (C) 2011-2017 - Daniel De Matteis
2019-02-22 15:07:32 +00:00
* Copyright (C) 2016-2019 - Brad Parker
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
2019-01-14 05:56:16 +00:00
#ifndef CXX_BUILD
2018-04-30 18:33:05 +00:00
extern "C" {
2019-01-14 05:56:16 +00:00
#endif
#include <file/file_path.h>
#include <string/stdstring.h>
2016-09-11 12:54:34 +00:00
#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif
2016-05-16 18:21:53 +00:00
#include "../ui_companion_driver.h"
2016-09-05 16:33:22 +00:00
#include "../../configuration.h"
2018-04-30 18:33:05 +00:00
#include "../../verbosity.h"
#include "../../msg_hash.h"
2016-05-16 18:21:53 +00:00
#include "../../tasks/tasks_internal.h"
2019-01-14 05:56:16 +00:00
#ifndef CXX_BUILD
2018-04-30 18:33:05 +00:00
}
2019-01-14 05:56:16 +00:00
#endif
2018-04-30 18:33:05 +00:00
#include "ui_qt.h"
#include "qt/viewoptionsdialog.h"
2018-04-30 18:33:05 +00:00
#include <QApplication>
#include <QtWidgets>
#include <QDesktopWidget>
#include <QtGlobal>
#include <QStyle>
#define INITIAL_WIDTH 1280
#define INITIAL_HEIGHT 720
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
#define GROUPED_DRAGGING QMainWindow::GroupedDragging
#else
#define GROUPED_DRAGGING static_cast<QMainWindow::DockOption>(0)
2016-06-10 08:15:38 +00:00
#endif
typedef struct ui_companion_qt
{
2018-04-30 18:33:05 +00:00
ui_application_qt_t *app;
ui_window_qt_t *window;
} ui_companion_qt_t;
ThumbnailWidget::ThumbnailWidget(ThumbnailType type, QWidget *parent) :
2019-01-30 20:26:33 +00:00
QStackedWidget(parent)
,m_thumbnailType(type)
2019-01-30 20:26:33 +00:00
,m_thumbnailLabel(new ThumbnailLabel(this))
,m_dropIndicator(new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DROP_IMAGE_HERE), this))
{
2019-01-30 20:26:33 +00:00
m_dropIndicator->setObjectName("dropIndicator");
m_dropIndicator->setAlignment(Qt::AlignCenter);
addWidget(m_dropIndicator);
addWidget(m_thumbnailLabel);
2018-04-30 18:33:05 +00:00
}
2019-01-30 20:26:33 +00:00
void ThumbnailWidget::setPixmap(const QPixmap &pixmap, bool acceptDrops)
{
2019-01-30 20:26:33 +00:00
m_thumbnailLabel->setPixmap(pixmap);
2019-01-30 20:26:33 +00:00
if (acceptDrops && pixmap.isNull())
setCurrentWidget(m_dropIndicator);
else
setCurrentWidget(m_thumbnailLabel);
2018-04-30 18:33:05 +00:00
2019-01-30 20:26:33 +00:00
m_thumbnailLabel->update();
2019-01-30 20:26:33 +00:00
QWidget::setAcceptDrops(acceptDrops);
2018-04-30 18:33:05 +00:00
}
void ThumbnailWidget::dragEnterEvent(QDragEnterEvent *event)
{
const QMimeData *data = event->mimeData();
if (data->hasUrls())
event->acceptProposedAction();
}
2019-04-15 22:46:27 +00:00
/* Workaround for QTBUG-72844. Without it, you can't
* drop on this if you first drag over another
* widget that doesn't accept drops. */
void ThumbnailWidget::dragMoveEvent(QDragMoveEvent *event)
{
event->acceptProposedAction();
}
void ThumbnailWidget::dropEvent(QDropEvent *event)
{
const QMimeData *data = event->mimeData();
if (data->hasUrls())
{
const QString imageString = data->urls().at(0).toLocalFile();
const QImage image(imageString);
if (!image.isNull())
emit(filesDropped(image, m_thumbnailType));
else
{
2019-07-20 10:04:50 +00:00
const char *string_data = QDir::toNativeSeparators(imageString).toUtf8().constData();
RARCH_ERR("[Qt]: Could not read image: %s\n", string_data);
}
}
}
2018-04-30 18:33:05 +00:00
ThumbnailLabel::ThumbnailLabel(QWidget *parent) :
QWidget(parent)
,m_pixmap(NULL)
,m_pixmapWidth(0)
,m_pixmapHeight(0)
{
}
ThumbnailLabel::~ThumbnailLabel()
{
if (m_pixmap)
delete m_pixmap;
}
void ThumbnailLabel::setPixmap(const QPixmap &pixmap)
{
m_pixmapWidth = pixmap.width();
m_pixmapHeight = pixmap.height();
if (m_pixmap)
delete m_pixmap;
m_pixmap = new QPixmap(pixmap);
}
QSize ThumbnailLabel::sizeHint() const
{
return QSize(256, 256);
}
void ThumbnailLabel::paintEvent(QPaintEvent *event)
{
QStyleOption o;
QPainter p;
2019-04-15 22:46:27 +00:00
int w = width();
int h = height();
2018-04-30 18:33:05 +00:00
event->accept();
o.initFrom(this);
p.begin(this);
style()->drawPrimitive(
QStyle::PE_Widget, &o, &p, this);
p.end();
if (!m_pixmap || m_pixmap->isNull())
{
2019-02-22 14:38:59 +00:00
if (m_pixmap)
delete m_pixmap;
2018-04-30 18:33:05 +00:00
m_pixmap = new QPixmap(sizeHint());
m_pixmap->fill(QColor(0, 0, 0, 0));
}
2018-04-30 18:33:05 +00:00
if (w > 0 && h > 0 && m_pixmap && !m_pixmap->isNull())
{
int newHeight = (m_pixmap->height() / static_cast<float>(m_pixmap->width())) * width();
QPixmap pixmapScaled = *m_pixmap;
QPixmap pixmap;
QPainter pScale;
int pw = 0;
int ph = 0;
unsigned *buf = new unsigned[w * h];
if (newHeight > h)
pixmapScaled = pixmapScaled.scaledToHeight(h, Qt::SmoothTransformation);
else
pixmapScaled = pixmapScaled.scaledToWidth(w, Qt::SmoothTransformation);
pw = pixmapScaled.width();
ph = pixmapScaled.height();
pixmap = QPixmap(w, h);
pixmap.fill(QColor(0, 0, 0, 0));
pScale.begin(&pixmap);
pScale.drawPixmap(QRect((w - pw) / 2, (h - ph) / 2, pw, ph), pixmapScaled, pixmapScaled.rect());
pScale.end();
if (!pixmap.isNull())
{
p.begin(this);
p.drawPixmap(rect(), pixmap, pixmap.rect());
p.end();
}
delete []buf;
}
else
QWidget::paintEvent(event);
}
void ThumbnailLabel::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event);
}
static void ui_companion_qt_deinit(void *data)
{
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
if (!handle)
return;
2018-04-30 18:33:05 +00:00
/* why won't deleteLater() here call the destructor? */
delete handle->window->qtWindow;
free(handle);
}
2018-04-30 18:33:05 +00:00
static void* ui_companion_qt_init(void)
{
2019-04-15 22:46:27 +00:00
int i = 0;
QString initialPlaylist;
QRect desktopRect;
ui_companion_qt_t *handle = (ui_companion_qt_t*)
calloc(1, sizeof(*handle));
MainWindow *mainwindow = NULL;
QHBoxLayout *browserButtonsHBoxLayout = NULL;
QVBoxLayout *layout = NULL;
QVBoxLayout *launchWithWidgetLayout = NULL;
QHBoxLayout *coreComboBoxLayout = NULL;
QMenuBar *menu = NULL;
QDesktopWidget *desktop = NULL;
QMenu *fileMenu = NULL;
QMenu *editMenu = NULL;
QMenu *viewMenu = NULL;
QMenu *viewClosedDocksMenu = NULL;
#ifdef Q_OS_WIN
#ifdef HAVE_ONLINE_UPDATER
2019-04-15 22:46:27 +00:00
QMenu *toolsMenu = NULL;
QMenu *updaterMenu = NULL;
#endif
#endif
2019-04-15 22:46:27 +00:00
QMenu *helpMenu = NULL;
QDockWidget *thumbnailDock = NULL;
QDockWidget *thumbnail2Dock = NULL;
QDockWidget *thumbnail3Dock = NULL;
QDockWidget *browserAndPlaylistTabDock = NULL;
QDockWidget *coreSelectionDock = NULL;
2018-04-30 18:33:05 +00:00
QTabWidget *browserAndPlaylistTabWidget = NULL;
2019-04-15 22:46:27 +00:00
QStackedWidget *centralWidget = NULL;
QStackedWidget *widget = NULL;
QFrame *browserWidget = NULL;
QFrame *playlistWidget = NULL;
QWidget *coreSelectionWidget = NULL;
QWidget *launchWithWidget = NULL;
ThumbnailWidget *thumbnailWidget = NULL;
ThumbnailWidget *thumbnail2Widget = NULL;
ThumbnailWidget *thumbnail3Widget = NULL;
QPushButton *browserDownloadsButton = NULL;
QPushButton *browserUpButton = NULL;
QPushButton *browserStartButton = NULL;
ThumbnailLabel *thumbnail = NULL;
ThumbnailLabel *thumbnail2 = NULL;
ThumbnailLabel *thumbnail3 = NULL;
QAction *editSearchAction = NULL;
QAction *loadCoreAction = NULL;
QAction *unloadCoreAction = NULL;
QAction *exitAction = NULL;
QComboBox *launchWithComboBox = NULL;
QSettings *qsettings = NULL;
QListWidget *listWidget = NULL;
bool foundPlaylist = false;
2018-04-30 18:33:05 +00:00
if (!handle)
return NULL;
2019-04-15 22:46:27 +00:00
handle->app = static_cast<ui_application_qt_t*>
(ui_application_qt.initialize());
handle->window = static_cast<ui_window_qt_t*>(ui_window_qt.init());
2018-04-30 18:33:05 +00:00
2019-04-15 22:46:27 +00:00
desktop = qApp->desktop();
desktopRect = desktop->availableGeometry();
2018-04-30 18:33:05 +00:00
2019-04-15 22:46:27 +00:00
mainwindow = handle->window->qtWindow;
2018-04-30 18:33:05 +00:00
2019-04-15 22:46:27 +00:00
qsettings = mainwindow->settings();
2018-04-30 18:33:05 +00:00
initialPlaylist = qsettings->value("initial_playlist", mainwindow->getSpecialPlaylistPath(SPECIAL_PLAYLIST_HISTORY)).toString();
2018-04-30 18:33:05 +00:00
mainwindow->resize(qMin(desktopRect.width(), INITIAL_WIDTH), qMin(desktopRect.height(), INITIAL_HEIGHT));
mainwindow->setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, mainwindow->size(), desktopRect));
mainwindow->setWindowTitle("RetroArch");
mainwindow->setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks | GROUPED_DRAGGING);
2019-04-15 22:46:27 +00:00
listWidget = mainwindow->playlistListWidget();
2019-04-15 22:46:27 +00:00
widget = mainwindow->playlistViews();
widget->setContextMenuPolicy(Qt::CustomContextMenu);
2018-04-30 18:33:05 +00:00
QObject::connect(widget, SIGNAL(filesDropped(QStringList)), mainwindow, SLOT(onPlaylistFilesDropped(QStringList)));
QObject::connect(widget, SIGNAL(enterPressed()), mainwindow, SLOT(onDropWidgetEnterPressed()));
QObject::connect(widget, SIGNAL(deletePressed()), mainwindow, SLOT(deleteCurrentPlaylistItem()));
QObject::connect(widget, SIGNAL(customContextMenuRequested(const QPoint&)), mainwindow, SLOT(onFileDropWidgetContextMenuRequested(const QPoint&)));
centralWidget = mainwindow->centralWidget();
2018-05-03 03:04:10 +00:00
centralWidget->addWidget(mainwindow->playlistViewsAndFooter());
centralWidget->addWidget(mainwindow->fileTableView());
2018-04-30 18:33:05 +00:00
mainwindow->setCentralWidget(centralWidget);
2018-04-30 18:33:05 +00:00
menu = mainwindow->menuBar();
fileMenu = menu->addMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_FILE));
loadCoreAction = fileMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_FILE_LOAD_CORE), mainwindow, SLOT(onLoadCoreClicked()));
loadCoreAction->setShortcut(QKeySequence("Ctrl+L"));
unloadCoreAction = fileMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_FILE_UNLOAD_CORE), mainwindow, SLOT(onUnloadCoreMenuAction()));
unloadCoreAction->setObjectName("unloadCoreAction");
unloadCoreAction->setEnabled(false);
unloadCoreAction->setShortcut(QKeySequence("Ctrl+U"));
exitAction = fileMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_FILE_EXIT), mainwindow, SLOT(close()));
exitAction->setShortcut(QKeySequence::Quit);
editMenu = menu->addMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_EDIT));
editSearchAction = editMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_EDIT_SEARCH), mainwindow->searchLineEdit(), SLOT(setFocus()));
editSearchAction->setShortcut(QKeySequence::Find);
viewMenu = menu->addMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW));
viewClosedDocksMenu = viewMenu->addMenu(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_CLOSED_DOCKS));
viewClosedDocksMenu->setObjectName("viewClosedDocksMenu");
QObject::connect(viewClosedDocksMenu, SIGNAL(aboutToShow()), mainwindow, SLOT(onViewClosedDocksAboutToShow()));
2018-08-29 15:34:36 +00:00
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS), mainwindow, SLOT(onCoreOptionsClicked()));
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
2018-08-18 04:33:52 +00:00
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS), mainwindow, SLOT(onShaderParamsClicked()));
#endif
2018-08-14 04:47:10 +00:00
viewMenu->addSeparator();
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_ICONS), mainwindow, SLOT(onIconViewClicked()));
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_LIST), mainwindow, SLOT(onListViewClicked()));
viewMenu->addSeparator();
2018-04-30 18:33:05 +00:00
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS), mainwindow->viewOptionsDialog(), SLOT(showDialog()));
#ifdef Q_OS_WIN
#ifdef HAVE_ONLINE_UPDATER
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));
updaterMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_UPDATE_RETROARCH_NIGHTLY), mainwindow, SLOT(updateRetroArchNightly()));
#endif
#endif
2018-08-03 03:21:39 +00:00
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()));
2018-08-03 03:21:39 +00:00
helpMenu->addAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_ABOUT)) + "...", mainwindow, SLOT(showAbout()));
helpMenu->addAction("About Qt...", qApp, SLOT(aboutQt()));
2019-01-14 19:06:07 +00:00
playlistWidget = new QFrame();
2018-04-30 18:33:05 +00:00
playlistWidget->setLayout(new QVBoxLayout());
playlistWidget->setObjectName("playlistWidget");
2019-01-14 19:06:07 +00:00
playlistWidget->layout()->setContentsMargins(0, 0, 0, 0);
2018-04-30 18:33:05 +00:00
playlistWidget->layout()->addWidget(mainwindow->playlistListWidget());
2019-01-14 19:06:07 +00:00
browserWidget = new QFrame();
2018-04-30 18:33:05 +00:00
browserWidget->setLayout(new QVBoxLayout());
browserWidget->setObjectName("browserWidget");
2019-01-14 19:06:07 +00:00
browserWidget->layout()->setContentsMargins(0, 0, 0, 0);
2018-04-30 18:33:05 +00:00
browserDownloadsButton = new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_ASSETS_DIRECTORY));
browserUpButton = new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_TAB_FILE_BROWSER_UP));
browserStartButton = new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FAVORITES));
QObject::connect(browserDownloadsButton, SIGNAL(clicked()), mainwindow, SLOT(onBrowserDownloadsClicked()));
QObject::connect(browserUpButton, SIGNAL(clicked()), mainwindow, SLOT(onBrowserUpClicked()));
QObject::connect(browserStartButton, SIGNAL(clicked()), mainwindow, SLOT(onBrowserStartClicked()));
browserButtonsHBoxLayout = new QHBoxLayout();
browserButtonsHBoxLayout->addWidget(browserUpButton);
browserButtonsHBoxLayout->addWidget(browserStartButton);
browserButtonsHBoxLayout->addWidget(browserDownloadsButton);
qobject_cast<QVBoxLayout*>(browserWidget->layout())->addLayout(browserButtonsHBoxLayout);
browserWidget->layout()->addWidget(mainwindow->dirTreeView());
browserAndPlaylistTabWidget = mainwindow->browserAndPlaylistTabWidget();
browserAndPlaylistTabWidget->setObjectName("browserAndPlaylistTabWidget");
/* Several functions depend on the same tab title strings here, so if you change these, make sure to change those too
* setCoreActions()
* onTabWidgetIndexChanged()
* onCurrentListItemChanged()
*/
browserAndPlaylistTabWidget->addTab(playlistWidget, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_TAB_PLAYLISTS));
browserAndPlaylistTabWidget->addTab(browserWidget, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_TAB_FILE_BROWSER));
browserAndPlaylistTabDock = new QDockWidget(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_DOCK_CONTENT_BROWSER), mainwindow);
browserAndPlaylistTabDock->setObjectName("browserAndPlaylistTabDock");
browserAndPlaylistTabDock->setProperty("default_area", Qt::LeftDockWidgetArea);
browserAndPlaylistTabDock->setProperty("menu_text", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_DOCK_CONTENT_BROWSER));
browserAndPlaylistTabDock->setWidget(browserAndPlaylistTabWidget);
mainwindow->addDockWidget(static_cast<Qt::DockWidgetArea>(browserAndPlaylistTabDock->property("default_area").toInt()), browserAndPlaylistTabDock);
browserButtonsHBoxLayout->addItem(new QSpacerItem(browserAndPlaylistTabWidget->tabBar()->width(), 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
thumbnailWidget = new ThumbnailWidget(THUMBNAIL_TYPE_BOXART);
2019-01-30 20:26:33 +00:00
thumbnailWidget->setObjectName("thumbnail");
thumbnail2Widget = new ThumbnailWidget(THUMBNAIL_TYPE_TITLE_SCREEN);
2019-01-30 20:26:33 +00:00
thumbnail2Widget->setObjectName("thumbnail2");
thumbnail3Widget = new ThumbnailWidget(THUMBNAIL_TYPE_SCREENSHOT);
2019-01-30 20:26:33 +00:00
thumbnail3Widget->setObjectName("thumbnail3");
2018-04-30 18:33:05 +00:00
QObject::connect(thumbnailWidget, SIGNAL(filesDropped(const QImage&, ThumbnailType)), mainwindow, SLOT(onThumbnailDropped(const QImage&, ThumbnailType)));
QObject::connect(thumbnail2Widget, SIGNAL(filesDropped(const QImage&, ThumbnailType)), mainwindow, SLOT(onThumbnailDropped(const QImage&, ThumbnailType)));
QObject::connect(thumbnail3Widget, SIGNAL(filesDropped(const QImage&, ThumbnailType)), mainwindow, SLOT(onThumbnailDropped(const QImage&, ThumbnailType)));
2018-04-30 18:33:05 +00:00
thumbnailDock = new QDockWidget(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_BOXART), mainwindow);
thumbnailDock->setObjectName("thumbnailDock");
thumbnailDock->setProperty("default_area", Qt::RightDockWidgetArea);
thumbnailDock->setProperty("menu_text", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_BOXART));
thumbnailDock->setWidget(thumbnailWidget);
mainwindow->addDockWidget(static_cast<Qt::DockWidgetArea>(thumbnailDock->property("default_area").toInt()), thumbnailDock);
thumbnail2Dock = new QDockWidget(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_TITLE_SCREEN), mainwindow);
thumbnail2Dock->setObjectName("thumbnail2Dock");
thumbnail2Dock->setProperty("default_area", Qt::RightDockWidgetArea);
thumbnail2Dock->setProperty("menu_text", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_TITLE_SCREEN));
thumbnail2Dock->setWidget(thumbnail2Widget);
mainwindow->addDockWidget(static_cast<Qt::DockWidgetArea>(thumbnail2Dock->property("default_area").toInt()), thumbnail2Dock);
thumbnail3Dock = new QDockWidget(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_SCREENSHOT), mainwindow);
thumbnail3Dock->setObjectName("thumbnail3Dock");
thumbnail3Dock->setProperty("default_area", Qt::RightDockWidgetArea);
thumbnail3Dock->setProperty("menu_text", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_SCREENSHOT));
thumbnail3Dock->setWidget(thumbnail3Widget);
mainwindow->addDockWidget(static_cast<Qt::DockWidgetArea>(thumbnail3Dock->property("default_area").toInt()), thumbnail3Dock);
mainwindow->tabifyDockWidget(thumbnailDock, thumbnail2Dock);
mainwindow->tabifyDockWidget(thumbnailDock, thumbnail3Dock);
/* when tabifying the dock widgets, the last tab added is selected by default, so we need to re-select the first tab */
thumbnailDock->raise();
coreSelectionWidget = new QWidget();
coreSelectionWidget->setLayout(new QVBoxLayout());
launchWithComboBox = mainwindow->launchWithComboBox();
launchWithWidgetLayout = new QVBoxLayout();
launchWithWidget = new QWidget();
launchWithWidget->setLayout(launchWithWidgetLayout);
coreComboBoxLayout = new QHBoxLayout();
mainwindow->runPushButton()->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
mainwindow->stopPushButton()->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
mainwindow->startCorePushButton()->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
coreComboBoxLayout->addWidget(launchWithComboBox);
coreComboBoxLayout->addWidget(mainwindow->startCorePushButton());
coreComboBoxLayout->addWidget(mainwindow->coreInfoPushButton());
coreComboBoxLayout->addWidget(mainwindow->runPushButton());
coreComboBoxLayout->addWidget(mainwindow->stopPushButton());
mainwindow->stopPushButton()->hide();
coreComboBoxLayout->setStretchFactor(launchWithComboBox, 1);
launchWithWidgetLayout->addLayout(coreComboBoxLayout);
coreSelectionWidget->layout()->addWidget(launchWithWidget);
coreSelectionWidget->layout()->addItem(new QSpacerItem(20, browserAndPlaylistTabWidget->height(), QSizePolicy::Minimum, QSizePolicy::Expanding));
coreSelectionDock = new QDockWidget(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CORE), mainwindow);
coreSelectionDock->setObjectName("coreSelectionDock");
coreSelectionDock->setProperty("default_area", Qt::LeftDockWidgetArea);
coreSelectionDock->setProperty("menu_text", msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CORE));
coreSelectionDock->setWidget(coreSelectionWidget);
coreSelectionDock->setFixedHeight(coreSelectionDock->minimumSizeHint().height());
2018-04-30 18:33:05 +00:00
mainwindow->addDockWidget(static_cast<Qt::DockWidgetArea>(coreSelectionDock->property("default_area").toInt()), coreSelectionDock);
mainwindow->splitDockWidget(browserAndPlaylistTabDock, coreSelectionDock, Qt::Vertical);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
mainwindow->resizeDocks(QList<QDockWidget*>() << coreSelectionDock, QList<int>() << 1, Qt::Vertical);
#endif
if (qsettings->contains("all_playlists_list_max_count"))
mainwindow->setAllPlaylistsListMaxCount(qsettings->value("all_playlists_list_max_count", 0).toInt());
if (qsettings->contains("all_playlists_grid_max_count"))
mainwindow->setAllPlaylistsGridMaxCount(qsettings->value("all_playlists_grid_max_count", 5000).toInt());
if (qsettings->contains("thumbnail_cache_limit"))
mainwindow->setThumbnailCacheLimit(qsettings->value("thumbnail_cache_limit", 500).toInt());
else
mainwindow->setThumbnailCacheLimit(500);
2018-04-30 18:33:05 +00:00
if (qsettings->contains("geometry"))
if (qsettings->contains("save_geometry"))
mainwindow->restoreGeometry(qsettings->value("geometry").toByteArray());
2019-04-15 20:29:16 +00:00
if (qsettings->contains("options_dialog_geometry"))
mainwindow->viewOptionsDialog()->restoreGeometry(qsettings->value("options_dialog_geometry").toByteArray());
2018-05-03 11:42:25 +00:00
if (qsettings->contains("save_dock_positions"))
2018-04-30 18:33:05 +00:00
if (qsettings->contains("dock_positions"))
mainwindow->restoreState(qsettings->value("dock_positions").toByteArray());
if (qsettings->contains("file_browser_table_headers"))
mainwindow->fileTableView()->horizontalHeader()->restoreState(qsettings->value("file_browser_table_headers").toByteArray());
else
mainwindow->fileTableView()->horizontalHeader()->resizeSection(0, 300);
if (qsettings->contains("icon_view_zoom"))
mainwindow->setIconViewZoom(qsettings->value("icon_view_zoom", 50).toInt());
2018-04-30 18:33:05 +00:00
if (qsettings->contains("theme"))
{
QString themeStr = qsettings->value("theme").toString();
MainWindow::Theme theme = mainwindow->getThemeFromString(themeStr);
if (qsettings->contains("custom_theme") && theme == MainWindow::THEME_CUSTOM)
{
QString customThemeFilePath = qsettings->value("custom_theme").toString();
mainwindow->setCustomThemeFile(customThemeFilePath);
}
mainwindow->setTheme(theme);
}
else
mainwindow->setTheme();
if (qsettings->contains("view_type"))
{
QString viewType = qsettings->value("view_type", "list").toString();
if (viewType == "list")
mainwindow->setCurrentViewType(MainWindow::VIEW_TYPE_LIST);
else if (viewType == "icons")
mainwindow->setCurrentViewType(MainWindow::VIEW_TYPE_ICONS);
else
mainwindow->setCurrentViewType(MainWindow::VIEW_TYPE_LIST);
}
else
mainwindow->setCurrentViewType(MainWindow::VIEW_TYPE_LIST);
if (qsettings->contains("icon_view_thumbnail_type"))
{
QString thumbnailType = qsettings->value("icon_view_thumbnail_type", "boxart").toString();
if (thumbnailType == "boxart")
mainwindow->setCurrentThumbnailType(THUMBNAIL_TYPE_BOXART);
else if (thumbnailType == "screenshot")
mainwindow->setCurrentThumbnailType(THUMBNAIL_TYPE_SCREENSHOT);
else if (thumbnailType == "title")
mainwindow->setCurrentThumbnailType(THUMBNAIL_TYPE_TITLE_SCREEN);
else
mainwindow->setCurrentThumbnailType(THUMBNAIL_TYPE_BOXART);
}
/* We make sure to hook up the tab widget callback only after the tabs themselves have been added,
* but before changing to a specific one, to avoid the callback firing before the view type is set.
*/
QObject::connect(browserAndPlaylistTabWidget, SIGNAL(currentChanged(int)), mainwindow, SLOT(onTabWidgetIndexChanged(int)));
/* setting the last tab must come after setting the view type */
if (qsettings->contains("save_last_tab"))
{
int lastTabIndex = qsettings->value("last_tab", 0).toInt();
if (lastTabIndex >= 0 && browserAndPlaylistTabWidget->count() > lastTabIndex)
{
browserAndPlaylistTabWidget->setCurrentIndex(lastTabIndex);
mainwindow->onTabWidgetIndexChanged(lastTabIndex);
}
}
else
{
browserAndPlaylistTabWidget->setCurrentIndex(0);
mainwindow->onTabWidgetIndexChanged(0);
}
/* the initial playlist that is selected is based on the user's setting (initialPlaylist) */
for (i = 0; listWidget->count() && i < listWidget->count(); i++)
{
QString path;
2020-02-19 19:57:02 +00:00
QListWidgetItem *item = listWidget->item(i);
if (!item)
continue;
path = item->data(Qt::UserRole).toString();
if (path == initialPlaylist)
{
foundPlaylist = true;
listWidget->setRowHidden(i, false);
listWidget->setCurrentRow(i);
break;
}
}
/* couldn't find the user's initial playlist, just find anything */
if (!foundPlaylist)
{
for (i = 0; listWidget->count() && i < listWidget->count(); i++)
{
/* select the first non-hidden row */
if (!listWidget->isRowHidden(i))
{
listWidget->setCurrentRow(i);
break;
}
}
}
mainwindow->initContentTableWidget();
return handle;
}
2020-02-19 19:57:02 +00:00
static void ui_companion_qt_notify_content_loaded(void *data) { }
2018-04-30 18:33:05 +00:00
static void ui_companion_qt_toggle(void *data, bool force)
{
2020-06-04 12:41:28 +00:00
static bool already_started = false;
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
ui_window_qt_t *win_handle = (ui_window_qt_t*)handle->window;
settings_t *settings = config_get_ptr();
bool ui_companion_toggle = settings->bools.ui_companion_toggle;
bool video_fullscreen = settings->bools.video_fullscreen;
2018-04-30 18:33:05 +00:00
2020-02-19 19:57:02 +00:00
if (ui_companion_toggle || force)
{
2020-02-19 19:57:02 +00:00
if (video_fullscreen)
command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL);
win_handle->qtWindow->activateWindow();
win_handle->qtWindow->raise();
video_driver_show_mouse();
win_handle->qtWindow->show();
2018-04-30 18:33:05 +00:00
if (video_driver_started_fullscreen())
win_handle->qtWindow->lower();
2018-04-30 18:33:05 +00:00
if (!already_started)
{
already_started = true;
2018-04-30 18:33:05 +00:00
2020-02-19 19:57:02 +00:00
if (win_handle->qtWindow->settings()->value(
"show_welcome_screen", true).toBool())
win_handle->qtWindow->showWelcomeScreen();
2018-04-30 18:33:05 +00:00
}
}
}
static void ui_companion_qt_event_command(void *data, enum event_command cmd)
2015-04-13 11:46:48 +00:00
{
2019-07-20 10:04:50 +00:00
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
ui_window_qt_t *win_handle = (ui_window_qt_t*)handle->window;
2018-04-30 18:33:05 +00:00
2015-04-13 11:46:48 +00:00
if (!handle)
return;
switch (cmd)
{
case CMD_EVENT_SHADERS_APPLY_CHANGES:
case CMD_EVENT_SHADER_PRESET_LOADED:
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
RARCH_LOG("[Qt]: Reloading shader parameters.\n");
win_handle->qtWindow->deferReloadShaderParams();
#endif
break;
default:
break;
}
2015-04-13 11:46:48 +00:00
}
static void ui_companion_qt_notify_list_pushed(void *data, file_list_t *list,
2020-02-19 19:57:02 +00:00
file_list_t *menu_list) { }
2018-04-30 18:33:05 +00:00
static void ui_companion_qt_notify_refresh(void *data)
{
2019-07-20 10:04:50 +00:00
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
2018-04-30 18:33:05 +00:00
ui_window_qt_t *win_handle = (ui_window_qt_t*)handle->window;
win_handle->qtWindow->deferReloadPlaylists();
}
static void ui_companion_qt_log_msg(void *data, const char *msg)
{
2019-07-20 10:04:50 +00:00
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
2018-04-30 18:33:05 +00:00
ui_window_qt_t *win_handle = (ui_window_qt_t*)handle->window;
win_handle->qtWindow->appendLogMessage(msg);
}
static bool ui_companion_qt_is_active(void *data)
{
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
ui_window_qt_t *win_handle = (ui_window_qt_t*)handle->window;
return win_handle->qtWindow->isVisible();
}
2020-02-19 19:57:02 +00:00
void ui_companion_qt_msg_queue_push(void *data,
const char *msg, unsigned priority, unsigned duration, bool flush)
2018-04-30 18:33:05 +00:00
{
2019-07-20 10:04:50 +00:00
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
2018-04-30 18:33:05 +00:00
ui_window_qt_t *win_handle = NULL;
if (!handle)
return;
2020-02-19 19:57:02 +00:00
win_handle = (ui_window_qt_t*)handle->window;
2018-04-30 18:33:05 +00:00
if (win_handle)
win_handle->qtWindow->showStatusMessage(msg, priority, duration, flush);
}
ui_companion_driver_t ui_companion_qt = {
ui_companion_qt_init,
ui_companion_qt_deinit,
ui_companion_qt_toggle,
2015-04-13 11:46:48 +00:00
ui_companion_qt_event_command,
ui_companion_qt_notify_content_loaded,
ui_companion_qt_notify_list_pushed,
2018-04-30 18:33:05 +00:00
ui_companion_qt_notify_refresh,
ui_companion_qt_msg_queue_push,
NULL,
NULL,
2018-04-30 18:33:05 +00:00
ui_companion_qt_log_msg,
ui_companion_qt_is_active,
&ui_browser_window_qt,
&ui_msg_window_qt,
2016-06-09 18:11:26 +00:00
&ui_window_qt,
2016-06-09 18:18:08 +00:00
&ui_application_qt,
"qt",
};
QStringList string_split_to_qt(QString str, char delim)
{
int at;
QStringList list = QStringList();
for (at = 0;;)
{
/* Find next split */
int spl = str.indexOf(delim, at);
/* Store split into list of extensions */
list << str.mid(at, (spl < 0 ? str.length() : spl));
/* No more splits */
if (spl < 0)
break;
at = spl + 1;
}
return list;
}