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)
{
int 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);
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();
if (!(decompress_task = (retro_task_t*)task_push_decompress(
file, dir,
NULL, NULL, NULL,
cb, this, NULL, false)))
{
m_updateProgressDialog->cancel();
return -1;
}
return 1;
}
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)
{
/* TODO/FIXME - implement? */
}
static void ui_window_qt_set_focused(void *data)
{
/* TODO/FIXME - implement */
}
static void ui_window_qt_set_visible(void *data,
bool set_visible)
{
/* TODO/FIXME - implement */
}
static void ui_window_qt_set_title(void *data, char *buf)
{
/* TODO/FIXME - implement? */
}
static void ui_window_qt_set_droppable(void *data, bool droppable)
{
/* TODO/FIXME - implement */
}
static bool ui_window_qt_focused(void *data)
{
/* TODO/FIXME - implement? */
return true;
}
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();
}
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_MENU)
#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
#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_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_state_get_ptr()->flags & INP_FLAG_GRAB_MOUSE_STATE;
if (ui_companion_toggle || force)
{
video_driver_state_t *video_st = video_state_get_ptr();
if (mouse_grabbed)
command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL);
if ( video_st->poke
&& video_st->poke->show_mouse)
video_st->poke->show_mouse(video_st->data, true);
if (video_fullscreen)
command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL);
win_handle->qtWindow->activateWindow();
win_handle->qtWindow->raise();
win_handle->qtWindow->show();
if ( video_st
&& (video_st->flags & VIDEO_FLAG_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_MENU)
#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
#endif
break;
default:
break;
}
}
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 && (win_handle = (ui_window_qt_t*)handle->window))
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_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;
}
#define CORE_NAME_COLUMN 0
#define CORE_VERSION_COLUMN 1
LoadCoreTableWidget::LoadCoreTableWidget(QWidget *parent) :
QTableWidget(parent)
{
}
void LoadCoreTableWidget::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
{
event->accept();
emit enterPressed();
}
else
QTableWidget::keyPressEvent(event);
}
LoadCoreWindow::LoadCoreWindow(QWidget *parent) :
QMainWindow(parent)
,m_layout()
,m_table(new LoadCoreTableWidget())
,m_statusLabel(new QLabel())
{
QHBoxLayout *hbox = new QHBoxLayout();
QPushButton *customCoreButton = new QPushButton(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_LOAD_CUSTOM_CORE));
connect(customCoreButton, SIGNAL(clicked()), this, SLOT(onLoadCustomCoreClicked()));
connect(m_table, SIGNAL(enterPressed()), this, SLOT(onCoreEnterPressed()));
connect(m_table, SIGNAL(cellDoubleClicked(int,int)), this, SLOT(onCellDoubleClicked(int,int)));
setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_LOAD_CORE));
setCentralWidget(new QWidget());
centralWidget()->setLayout(&m_layout);
hbox->addWidget(customCoreButton);
hbox->addItem(new QSpacerItem(width(),
20, QSizePolicy::Expanding, QSizePolicy::Minimum));
m_layout.addWidget(m_table);
m_layout.addLayout(hbox);
statusBar()->addPermanentWidget(m_statusLabel);
}
void LoadCoreWindow::closeEvent(QCloseEvent *event)
{
emit windowClosed();
QWidget::closeEvent(event);
}
void LoadCoreWindow::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape)
{
event->accept();
close();
}
else
QMainWindow::keyPressEvent(event);
}
void LoadCoreWindow::setStatusLabel(QString label)
{
m_statusLabel->setText(label);
}
void LoadCoreWindow::onCellDoubleClicked(int, int)
{
onCoreEnterPressed();
}
void LoadCoreWindow::loadCore(const char *path)
{
QProgressDialog progress(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_LOADING_CORE), QString(), 0, 0, this);
progress.setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_LOAD_CORE));
progress.setMinimumDuration(0);
progress.setValue(progress.minimum());
progress.show();
/* Because core loading will block, we need to go ahead and process pending events that would allow the progress dialog to fully show its contents before actually starting the core loading process. Must call processEvents() twice. */
qApp->processEvents();
qApp->processEvents();
#ifdef HAVE_DYNAMIC
path_set(RARCH_PATH_CORE, path);
command_event(CMD_EVENT_CORE_INFO_DEINIT, NULL);
command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
core_info_init_current_core();
if (!command_event(CMD_EVENT_LOAD_CORE, NULL))
{
QMessageBox::critical(this, msg_hash_to_str(MSG_ERROR), msg_hash_to_str(MSG_FAILED_TO_OPEN_LIBRETRO_CORE));
return;
}
setProperty("last_launch_with_index", -1);
emit coreLoaded();
#endif
}
void LoadCoreWindow::onCoreEnterPressed()
{
QByteArray pathArray;
const char *pathData = NULL;
QTableWidgetItem *selectedCoreItem =
m_table->item(m_table->currentRow(), CORE_NAME_COLUMN);
QVariantHash hash = selectedCoreItem->data(
Qt::UserRole).toHash();
QString path = hash["path"].toString();
pathArray.append(path);
pathData = pathArray.constData();
loadCore(pathData);
}
void LoadCoreWindow::onLoadCustomCoreClicked()
{
QString path;
QByteArray pathArray;
char core_ext[255] = {0};
char filters[PATH_MAX_LENGTH] = {0};
const char *pathData = NULL;
settings_t *settings = config_get_ptr();
const char *path_dir_libretro = settings->paths.directory_libretro;
frontend_driver_get_core_extension(core_ext, sizeof(core_ext));
strlcpy(filters, "Cores (*.", sizeof(filters));
strlcat(filters, core_ext, sizeof(filters));
strlcat(filters, ");;All Files (*.*)", sizeof(filters));
path = QFileDialog::getOpenFileName(
this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_LOAD_CORE),
path_dir_libretro, filters, NULL);
if (path.isEmpty())
return;
pathArray.append(path);
pathData = pathArray.constData();
loadCore(pathData);
}
void LoadCoreWindow::initCoreList(const QStringList &extensionFilters)
{
int j;
unsigned i;
QStringList horizontal_header_labels;
core_info_list_t *cores = NULL;
QDesktopWidget *desktop = qApp->desktop();
QRect desktopRect = desktop->availableGeometry();
horizontal_header_labels << msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_NAME);
horizontal_header_labels << msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_CORE_VERSION);
core_info_get_list(&cores);
m_table->clear();
m_table->setColumnCount(0);
m_table->setRowCount(0);
m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
m_table->setSelectionMode(QAbstractItemView::SingleSelection);
m_table->setSortingEnabled(false);
m_table->setColumnCount(2);
m_table->setHorizontalHeaderLabels(horizontal_header_labels);
if (cores)
{
m_table->setRowCount(cores->count);
for (i = 0; i < cores->count; i++)
{
QVariantHash hash;
core_info_t *core = core_info_get(cores, i);
QTableWidgetItem *name_item = NULL;
QTableWidgetItem *version_item = new QTableWidgetItem(core->display_version);
const char *name = core->display_name;
if (string_is_empty(name))
name = path_basename(core->path);
name_item = new QTableWidgetItem(name);
hash["path"] = core->path;
hash["extensions"] = string_split_to_qt(QString(core->supported_extensions), '|');
name_item->setData(Qt::UserRole, hash);
name_item->setFlags(name_item->flags() & ~Qt::ItemIsEditable);
version_item->setFlags(version_item->flags() & ~Qt::ItemIsEditable);
m_table->setItem(i, CORE_NAME_COLUMN, name_item);
m_table->setItem(i, CORE_VERSION_COLUMN, version_item);
}
}
if (!extensionFilters.isEmpty())
{
QVector rowsToHide;
for (j = 0; j < m_table->rowCount(); j++)
{
int k;
QVariantHash hash;
QStringList extensions;
bool found = false;
QTableWidgetItem *item = m_table->item(j, CORE_NAME_COLUMN);
if (!item)
continue;
hash = item->data(Qt::UserRole).toHash();
extensions = hash["extensions"].toStringList();
if (!extensions.isEmpty())
{
for (k = 0; k < extensions.size(); k++)
{
QString ext = extensions.at(k).toLower();
if (extensionFilters.contains(ext, Qt::CaseInsensitive))
{
found = true;
break;
}
}
if (!found)
rowsToHide.append(j);
}
}
if (rowsToHide.size() != m_table->rowCount())
{
int i = 0;
for (i = 0; i < rowsToHide.count() && rowsToHide.count() > 0; i++)
{
const int &row = rowsToHide.at(i);
m_table->setRowHidden(row, true);
}
}
}
m_table->setSortingEnabled(true);
m_table->resizeColumnsToContents();
m_table->sortByColumn(0, Qt::AscendingOrder);
m_table->selectRow(0);
m_table->setAlternatingRowColors(true);
resize(qMin(desktopRect.width(), contentsMargins().left() + m_table->horizontalHeader()->length() + contentsMargins().right()), height());
}