dialog(new QDialog());
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
QTextEdit *textEdit = new QTextEdit(dialog.data());
connect(buttonBox, SIGNAL(accepted()), dialog.data(), SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), dialog.data(), SLOT(reject()));
dialog->setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_ABOUT_CONTRIBUTORS));
dialog->setLayout(new QVBoxLayout());
dialog->layout()->addWidget(textEdit);
dialog->layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Minimum));
dialog->layout()->addWidget(buttonBox);
textEdit->setReadOnly(true);
textEdit->setHtml(QString("") + retroarch_contributors_list + "
");
dialog->resize(480, 640);
dialog->exec();
}
void MainWindow::showAbout()
{
QScopedPointer dialog(new QDialog());
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
QString text = QString("RetroArch ") + PACKAGE_VERSION +
"
" + "www.libretro.com"
"
" + "www.retroarch.com"
#ifdef HAVE_GIT_VERSION
"
" + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_GIT_VERSION) + ": " + retroarch_git_version +
#endif
"
" + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_BUILD_DATE) + ": " + __DATE__;
QLabel *label = new QLabel(text, dialog.data());
QPixmap pix = getInvader();
QLabel *pixLabel = new QLabel(dialog.data());
QPushButton *contributorsPushButton = new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_ABOUT_CONTRIBUTORS), dialog.data());
connect(contributorsPushButton, SIGNAL(clicked()), this, SLOT(onContributorsClicked()));
connect(buttonBox, SIGNAL(accepted()), dialog.data(), SLOT(accept()));
connect(buttonBox, SIGNAL(rejected()), dialog.data(), SLOT(reject()));
label->setTextFormat(Qt::RichText);
label->setAlignment(Qt::AlignCenter);
label->setTextInteractionFlags(Qt::TextBrowserInteraction);
label->setOpenExternalLinks(true);
pixLabel->setAlignment(Qt::AlignCenter);
pixLabel->setPixmap(pix);
dialog->setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_ABOUT));
dialog->setLayout(new QVBoxLayout());
dialog->layout()->addWidget(pixLabel);
dialog->layout()->addWidget(label);
dialog->layout()->addWidget(contributorsPushButton);
dialog->layout()->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
dialog->layout()->addWidget(buttonBox);
dialog->exec();
}
void MainWindow::showDocs()
{
QDesktopServices::openUrl(QUrl(DOCS_URL));
}
void MainWindow::onShowErrorMessage(QString msg)
{
showMessageBox(msg, MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
}
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)
{
unsigned i;
file_archive_transfer_t state;
struct archive_extract_userdata userdata;
QByteArray pathArray = path.toUtf8();
QByteArray dirArray = extractionDir.toUtf8();
const char *file = pathArray.constData();
const char *dir = dirArray.constData();
struct string_list *file_list = file_archive_get_file_list(file, NULL);
bool returnerr = true;
retro_task_t *decompress_task = NULL;
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();
decompress_task = (retro_task_t*)task_push_decompress(
file, dir,
NULL, NULL, NULL,
cb, this, NULL, false);
if (!decompress_task)
{
m_updateProgressDialog->cancel();
return -1;
}
return returnerr;
}
QString MainWindow::getScrubbedString(QString str)
{
const QString chars("&*/:`\"<>?\\|");
int i;
for (i = 0; i < chars.count(); i++)
str.replace(chars.at(i), '_');
return str;
}
static void* ui_window_qt_init(void)
{
ui_window.qtWindow = new MainWindow();
return &ui_window;
}
static void ui_window_qt_destroy(void *data)
{
#if 0
ui_window_qt_t *window = (ui_window_qt_t*)data;
delete window->qtWindow;
#endif
}
static void ui_window_qt_set_focused(void *data)
{
#if 0
ui_window_qt_t *window = (ui_window_qt_t*)data;
window->qtWindow->raise();
window->qtWindow->activateWindow();
#endif
}
static void ui_window_qt_set_visible(void *data,
bool set_visible)
{
(void)data;
(void)set_visible;
/* TODO/FIXME */
}
static void ui_window_qt_set_title(void *data, char *buf)
{
#if 0
ui_window_qt_t *window = (ui_window_qt_t*)data;
window->qtWindow->setWindowTitle(QString::fromUtf8(buf));
#endif
}
static void ui_window_qt_set_droppable(void *data, bool droppable)
{
#if 0
ui_window_qt_t *window = (ui_window_qt_t*)data;
window->qtWindow->setAcceptDrops(droppable);
#endif
}
static bool ui_window_qt_focused(void *data)
{
#if 0
ui_window_qt_t *window = (ui_window_qt_t*)data;
return window->qtWindow->isActiveWindow() && !window->qtWindow->isMinimized();
#else
return true;
#endif
}
static ui_window_t ui_window_qt = {
ui_window_qt_init,
ui_window_qt_destroy,
ui_window_qt_set_focused,
ui_window_qt_set_visible,
ui_window_qt_set_title,
ui_window_qt_set_droppable,
ui_window_qt_focused,
"qt"
};
static enum ui_msg_window_response ui_msg_window_qt_response(ui_msg_window_state *state, QMessageBox::StandardButtons response)
{
switch (response)
{
case QMessageBox::Ok:
return UI_MSG_RESPONSE_OK;
case QMessageBox::Cancel:
return UI_MSG_RESPONSE_CANCEL;
case QMessageBox::Yes:
return UI_MSG_RESPONSE_YES;
case QMessageBox::No:
return UI_MSG_RESPONSE_NO;
default:
break;
}
switch (state->buttons)
{
case UI_MSG_WINDOW_OK:
return UI_MSG_RESPONSE_OK;
case UI_MSG_WINDOW_OKCANCEL:
return UI_MSG_RESPONSE_CANCEL;
case UI_MSG_WINDOW_YESNO:
return UI_MSG_RESPONSE_NO;
case UI_MSG_WINDOW_YESNOCANCEL:
return UI_MSG_RESPONSE_CANCEL;
default:
break;
}
return UI_MSG_RESPONSE_NA;
}
static QFlags
ui_msg_window_qt_buttons(ui_msg_window_state *state)
{
switch (state->buttons)
{
case UI_MSG_WINDOW_OK:
return QMessageBox::Ok;
case UI_MSG_WINDOW_OKCANCEL:
return QMessageBox::Cancel;
case UI_MSG_WINDOW_YESNO:
return (QMessageBox::Yes | QMessageBox::No);
case UI_MSG_WINDOW_YESNOCANCEL:
return (QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
}
return QMessageBox::NoButton;
}
static enum ui_msg_window_response
ui_msg_window_qt_error(ui_msg_window_state *state)
{
QFlags flags = ui_msg_window_qt_buttons(state);
return ui_msg_window_qt_response(state, QMessageBox::critical((QWidget*)state->window, state->title, state->text, flags));
}
static enum ui_msg_window_response ui_msg_window_qt_information(ui_msg_window_state *state)
{
QFlags flags = ui_msg_window_qt_buttons(state);
return ui_msg_window_qt_response(state, QMessageBox::information((QWidget*)state->window, state->title, state->text, flags));
}
static enum ui_msg_window_response ui_msg_window_qt_question(ui_msg_window_state *state)
{
QFlags flags = ui_msg_window_qt_buttons(state);
return ui_msg_window_qt_response(state, QMessageBox::question((QWidget*)state->window, state->title, state->text, flags));
}
static enum ui_msg_window_response ui_msg_window_qt_warning(ui_msg_window_state *state)
{
QFlags flags = ui_msg_window_qt_buttons(state);
return ui_msg_window_qt_response(state, QMessageBox::warning((QWidget*)state->window, state->title, state->text, flags));
}
static ui_msg_window_t ui_msg_window_qt = {
ui_msg_window_qt_error,
ui_msg_window_qt_information,
ui_msg_window_qt_question,
ui_msg_window_qt_warning,
"qt"
};
static bool ui_browser_window_qt_open(ui_browser_window_state_t *state)
{
return true;
}
static bool ui_browser_window_qt_save(ui_browser_window_state_t *state)
{
return false;
}
static ui_browser_window_t ui_browser_window_qt = {
ui_browser_window_qt_open,
ui_browser_window_qt_save,
"qt"
};
static void* ui_application_qt_initialize(void)
{
/* These must last for the lifetime of the QApplication */
static int app_argc = 1;
static char app_name[] = "retroarch";
static char *app_argv[] = { app_name, NULL };
app_handler = new AppHandler();
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
/* HiDpi supported since Qt 5.6 */
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
/* Create QApplication() before calling QApplication::setStyle()
* to ensure that plugin path is determined correctly */
ui_application.app = new QApplication(app_argc, app_argv);
QApplication::setStyle("fusion");
ui_application.app->setOrganizationName("libretro");
ui_application.app->setApplicationName("RetroArch");
ui_application.app->setApplicationVersion(PACKAGE_VERSION);
ui_application.app->connect(ui_application.app, SIGNAL(lastWindowClosed()),
app_handler, SLOT(onLastWindowClosed()));
#ifdef Q_OS_UNIX
setlocale(LC_NUMERIC, "C");
#endif
{
/* Can't declare the pixmap at the top, because: "QPixmap: Must construct a QGuiApplication before a QPixmap" */
QImage iconImage(16, 16, QImage::Format_ARGB32);
QPixmap iconPixmap;
unsigned char *bits = iconImage.bits();
memcpy(bits, retroarch_qt_icon_data, 16 * 16 * sizeof(unsigned));
iconPixmap = QPixmap::fromImage(iconImage);
ui_application.app->setWindowIcon(QIcon(iconPixmap));
}
return &ui_application;
}
static void ui_application_qt_process_events(void)
{
QAbstractEventDispatcher *dispatcher = QApplication::eventDispatcher();
if (dispatcher && dispatcher->hasPendingEvents())
QApplication::processEvents();
}
static void ui_application_qt_quit(void)
{
if (app_handler)
app_handler->exit();
}
#ifdef HAVE_MAIN
#if defined(__cplusplus) && !defined(CXX_BUILD)
extern "C"
#endif
int main(int argc, char *argv[])
{
return rarch_main(argc, argv, NULL);
}
#endif
static ui_application_t ui_application_qt = {
ui_application_qt_initialize,
ui_application_qt_process_events,
ui_application_qt_quit,
false,
"qt"
};
AppHandler::AppHandler(QObject *parent) :
QObject(parent)
{
}
AppHandler::~AppHandler()
{
}
void AppHandler::exit()
{
ui_application_qt.exiting = true;
if (qApp)
qApp->closeAllWindows();
}
bool AppHandler::isExiting() const
{
return ui_application_qt.exiting;
}
void AppHandler::onLastWindowClosed()
{
}
typedef struct ui_companion_qt
{
ui_application_qt_t *app;
ui_window_qt_t *window;
} ui_companion_qt_t;
ThumbnailWidget::ThumbnailWidget(ThumbnailType type, QWidget *parent) :
QStackedWidget(parent)
,m_thumbnailType(type)
,m_thumbnailLabel(new ThumbnailLabel(this))
,m_dropIndicator(new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DROP_IMAGE_HERE), this))
{
m_dropIndicator->setObjectName("dropIndicator");
m_dropIndicator->setAlignment(Qt::AlignCenter);
addWidget(m_dropIndicator);
addWidget(m_thumbnailLabel);
}
void ThumbnailWidget::setPixmap(const QPixmap &pixmap, bool acceptDrops)
{
m_thumbnailLabel->setPixmap(pixmap);
if (acceptDrops && pixmap.isNull())
setCurrentWidget(m_dropIndicator);
else
setCurrentWidget(m_thumbnailLabel);
m_thumbnailLabel->update();
QWidget::setAcceptDrops(acceptDrops);
}
void ThumbnailWidget::dragEnterEvent(QDragEnterEvent *event)
{
const QMimeData *data = event->mimeData();
if (data->hasUrls())
event->acceptProposedAction();
}
/* 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
{
const char *string_data = QDir::toNativeSeparators(imageString).toUtf8().constData();
RARCH_ERR("[Qt]: Could not read image: %s\n", string_data);
}
}
}
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;
int w = width();
int h = height();
event->accept();
o.initFrom(this);
p.begin(this);
style()->drawPrimitive(
QStyle::PE_Widget, &o, &p, this);
p.end();
if (!m_pixmap || m_pixmap->isNull())
{
if (m_pixmap)
delete m_pixmap;
m_pixmap = new QPixmap(sizeHint());
m_pixmap->fill(QColor(0, 0, 0, 0));
}
if (w > 0 && h > 0 && m_pixmap && !m_pixmap->isNull())
{
int newHeight = (m_pixmap->height() / static_cast(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;
/* why won't deleteLater() here call the destructor? */
delete handle->window->qtWindow;
free(handle);
}
static void* ui_companion_qt_init(void)
{
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;
QMenu *helpMenu = NULL;
QDockWidget *thumbnailDock = NULL;
QDockWidget *thumbnail2Dock = NULL;
QDockWidget *thumbnail3Dock = NULL;
QDockWidget *browserAndPlaylistTabDock = NULL;
QDockWidget *coreSelectionDock = NULL;
QTabWidget *browserAndPlaylistTabWidget = NULL;
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;
if (!handle)
return NULL;
handle->app = static_cast
(ui_application_qt.initialize());
handle->window = static_cast(ui_window_qt.init());
desktop = qApp->desktop();
desktopRect = desktop->availableGeometry();
mainwindow = handle->window->qtWindow;
qsettings = mainwindow->settings();
initialPlaylist = qsettings->value("initial_playlist", mainwindow->getSpecialPlaylistPath(SPECIAL_PLAYLIST_HISTORY)).toString();
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);
listWidget = mainwindow->playlistListWidget();
widget = mainwindow->playlistViews();
widget->setContextMenuPolicy(Qt::CustomContextMenu);
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();
centralWidget->addWidget(mainwindow->playlistViewsAndFooter());
centralWidget->addWidget(mainwindow->fileTableView());
mainwindow->setCentralWidget(centralWidget);
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()));
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)
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS), mainwindow, SLOT(onShaderParamsClicked()));
#endif
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();
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS), mainwindow->viewOptionsDialog(), SLOT(showDialog()));
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()));
helpMenu->addAction("About Qt...", qApp, SLOT(aboutQt()));
playlistWidget = new QFrame();
playlistWidget->setLayout(new QVBoxLayout());
playlistWidget->setObjectName("playlistWidget");
playlistWidget->layout()->setContentsMargins(0, 0, 0, 0);
playlistWidget->layout()->addWidget(mainwindow->playlistListWidget());
browserWidget = new QFrame();
browserWidget->setLayout(new QVBoxLayout());
browserWidget->setObjectName("browserWidget");
browserWidget->layout()->setContentsMargins(0, 0, 0, 0);
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(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(browserAndPlaylistTabDock->property("default_area").toInt()), browserAndPlaylistTabDock);
browserButtonsHBoxLayout->addItem(new QSpacerItem(browserAndPlaylistTabWidget->tabBar()->width(), 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
thumbnailWidget = new ThumbnailWidget(THUMBNAIL_TYPE_BOXART);
thumbnailWidget->setObjectName("thumbnail");
thumbnail2Widget = new ThumbnailWidget(THUMBNAIL_TYPE_TITLE_SCREEN);
thumbnail2Widget->setObjectName("thumbnail2");
thumbnail3Widget = new ThumbnailWidget(THUMBNAIL_TYPE_SCREENSHOT);
thumbnail3Widget->setObjectName("thumbnail3");
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)));
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(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(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(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());
mainwindow->addDockWidget(static_cast(coreSelectionDock->property("default_area").toInt()), coreSelectionDock);
mainwindow->splitDockWidget(browserAndPlaylistTabDock, coreSelectionDock, Qt::Vertical);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
mainwindow->resizeDocks(QList() << coreSelectionDock, QList() << 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);
if (qsettings->contains("geometry"))
if (qsettings->contains("save_geometry"))
mainwindow->restoreGeometry(qsettings->value("geometry").toByteArray());
if (qsettings->contains("options_dialog_geometry"))
mainwindow->viewOptionsDialog()->restoreGeometry(qsettings->value("options_dialog_geometry").toByteArray());
if (qsettings->contains("save_dock_positions"))
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());
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;
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;
}
static void ui_companion_qt_notify_content_loaded(void *data) { }
static void ui_companion_qt_toggle(void *data, bool force)
{
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;
bool mouse_grabbed = input_mouse_grabbed();
if (ui_companion_toggle || force)
{
if (mouse_grabbed)
command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL);
video_driver_show_mouse();
if (video_fullscreen)
command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL);
win_handle->qtWindow->activateWindow();
win_handle->qtWindow->raise();
win_handle->qtWindow->show();
if (video_driver_started_fullscreen())
win_handle->qtWindow->lower();
if (!already_started)
{
already_started = true;
if (win_handle->qtWindow->settings()->value(
"show_welcome_screen", true).toBool())
win_handle->qtWindow->showWelcomeScreen();
}
}
}
static void ui_companion_qt_event_command(void *data, enum event_command cmd)
{
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
ui_window_qt_t *win_handle = (ui_window_qt_t*)handle->window;
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;
}
}
static void ui_companion_qt_notify_list_pushed(void *data, file_list_t *list,
file_list_t *menu_list) { }
static void ui_companion_qt_notify_refresh(void *data)
{
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
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)
{
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
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();
}
void ui_companion_qt_msg_queue_push(void *data,
const char *msg, unsigned priority, unsigned duration, bool flush)
{
ui_companion_qt_t *handle = (ui_companion_qt_t*)data;
ui_window_qt_t *win_handle = NULL;
if (!handle)
return;
win_handle = (ui_window_qt_t*)handle->window;
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,
ui_companion_qt_event_command,
ui_companion_qt_notify_content_loaded,
ui_companion_qt_notify_list_pushed,
ui_companion_qt_notify_refresh,
ui_companion_qt_msg_queue_push,
NULL,
NULL,
ui_companion_qt_log_msg,
ui_companion_qt_is_active,
&ui_browser_window_qt,
&ui_msg_window_qt,
&ui_window_qt,
&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 ? -1 : spl - at));
/* No more splits */
if (spl < 0)
break;
at = spl + 1;
}
return list;
}