commit
f33a9ed439
|
@ -10,6 +10,7 @@ option(USE_SHARED_ENET "Use shared libenet if found rather than Dolphin's soon-t
|
||||||
option(USE_UPNP "Enables UPnP port mapping support" ON)
|
option(USE_UPNP "Enables UPnP port mapping support" ON)
|
||||||
option(DISABLE_WX "Disable wxWidgets (use Qt or CLI interface)" OFF)
|
option(DISABLE_WX "Disable wxWidgets (use Qt or CLI interface)" OFF)
|
||||||
option(ENABLE_QT "Enable Qt (use the experimental Qt interface)" OFF)
|
option(ENABLE_QT "Enable Qt (use the experimental Qt interface)" OFF)
|
||||||
|
option(ENABLE_QT2 "Enable Qt2 (use the other experimental Qt interface)" OFF)
|
||||||
option(ENABLE_PCH "Use PCH to speed up compilation" ON)
|
option(ENABLE_PCH "Use PCH to speed up compilation" ON)
|
||||||
option(ENABLE_LTO "Enables Link Time Optimization" OFF)
|
option(ENABLE_LTO "Enables Link Time Optimization" OFF)
|
||||||
option(ENABLE_GENERIC "Enables generic build that should run on any little-endian host" OFF)
|
option(ENABLE_GENERIC "Enables generic build that should run on any little-endian host" OFF)
|
||||||
|
@ -751,7 +752,7 @@ else()
|
||||||
mark_as_advanced(ICONV_INCLUDE_DIR ICONV_LIBRARIES)
|
mark_as_advanced(ICONV_INCLUDE_DIR ICONV_LIBRARIES)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_QT)
|
if(ENABLE_QT OR ENABLE_QT2)
|
||||||
find_package(Qt5Widgets REQUIRED)
|
find_package(Qt5Widgets REQUIRED)
|
||||||
message("Found Qt version ${Qt5Core_VERSION}, enabling the Qt backend")
|
message("Found Qt version ${Qt5Core_VERSION}, enabling the Qt backend")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -11,3 +11,6 @@ add_subdirectory(VideoBackends)
|
||||||
if(ENABLE_QT)
|
if(ENABLE_QT)
|
||||||
add_subdirectory(DolphinQt)
|
add_subdirectory(DolphinQt)
|
||||||
endif()
|
endif()
|
||||||
|
if(ENABLE_QT2)
|
||||||
|
add_subdirectory(DolphinQt2)
|
||||||
|
endif()
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
add_definitions(-DQT_USE_QSTRINGBUILDER -DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII)
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
|
set(SRCS
|
||||||
|
Main.cpp
|
||||||
|
MainWindow.cpp
|
||||||
|
Host.cpp
|
||||||
|
RenderWidget.cpp
|
||||||
|
Resources.cpp
|
||||||
|
GameList/GameFile.cpp
|
||||||
|
GameList/GameList.cpp
|
||||||
|
GameList/GameTracker.cpp
|
||||||
|
GameList/GameListModel.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND LIBS core uicommon)
|
||||||
|
|
||||||
|
set(DOLPHINQT2_BINARY dolphin-emu-qt2)
|
||||||
|
|
||||||
|
add_executable(${DOLPHINQT2_BINARY} ${SRCS} ${UI_HEADERS})
|
||||||
|
target_link_libraries(${DOLPHINQT2_BINARY} ${LIBS} Qt5::Widgets)
|
||||||
|
|
||||||
|
install(TARGETS ${DOLPHINQT2_BINARY} RUNTIME DESTINATION ${bindir})
|
|
@ -0,0 +1,202 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QImage>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "DiscIO/VolumeCreator.h"
|
||||||
|
#include "DolphinQt2/Resources.h"
|
||||||
|
#include "DolphinQt2/GameList/GameFile.h"
|
||||||
|
|
||||||
|
static const int CACHE_VERSION = 13; // Last changed in PR #3261
|
||||||
|
static const int DATASTREAM_VERSION = QDataStream::Qt_5_5;
|
||||||
|
|
||||||
|
static QMap<DiscIO::IVolume::ELanguage, QString> ConvertLanguageMap(
|
||||||
|
const std::map<DiscIO::IVolume::ELanguage, std::string>& map)
|
||||||
|
{
|
||||||
|
QMap<DiscIO::IVolume::ELanguage, QString> result;
|
||||||
|
for (auto entry : map)
|
||||||
|
result.insert(entry.first, QString::fromStdString(entry.second).trimmed());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameFile::GameFile(QString path) : m_path(path)
|
||||||
|
{
|
||||||
|
m_valid = false;
|
||||||
|
|
||||||
|
if (!LoadFileInfo(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TryLoadCache())
|
||||||
|
{
|
||||||
|
if (TryLoadVolume())
|
||||||
|
{
|
||||||
|
LoadState();
|
||||||
|
}
|
||||||
|
else if (!TryLoadElfDol())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiscIO::IVolume::ELanguage GameFile::GetDefaultLanguage() const
|
||||||
|
{
|
||||||
|
bool wii = m_platform != DiscIO::IVolume::GAMECUBE_DISC;
|
||||||
|
return SConfig::GetInstance().GetCurrentLanguage(wii);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GameFile::GetCacheFileName() const
|
||||||
|
{
|
||||||
|
QString folder = QString::fromStdString(File::GetUserPath(D_CACHE_IDX));
|
||||||
|
// Append a hash of the full path to prevent name clashes between
|
||||||
|
// files with the same names in different folders.
|
||||||
|
QString hash = QString::fromUtf8(
|
||||||
|
QCryptographicHash::hash(m_path.toUtf8(),
|
||||||
|
QCryptographicHash::Md5).toHex());
|
||||||
|
return folder + m_file_name + hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameFile::ReadBanner(const DiscIO::IVolume& volume)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
std::vector<u32> buffer = volume.GetBanner(&width, &height);
|
||||||
|
QImage banner(width, height, QImage::Format_RGB888);
|
||||||
|
for (int i = 0; i < width * height; i++)
|
||||||
|
{
|
||||||
|
int x = i % width, y = i / width;
|
||||||
|
banner.setPixel(x, y, qRgb((buffer[i] & 0xFF0000) >> 16,
|
||||||
|
(buffer[i] & 0x00FF00) >> 8,
|
||||||
|
(buffer[i] & 0x0000FF) >> 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!banner.isNull())
|
||||||
|
m_banner = QPixmap::fromImage(banner);
|
||||||
|
else
|
||||||
|
m_banner = Resources::GetMisc(Resources::BANNER_MISSING);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameFile::LoadFileInfo(QString path)
|
||||||
|
{
|
||||||
|
QFileInfo info(path);
|
||||||
|
if (!info.exists() || !info.isReadable())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_file_name = info.fileName();
|
||||||
|
m_extension = info.suffix();
|
||||||
|
m_folder = info.dir().dirName();
|
||||||
|
m_last_modified = info.lastModified();
|
||||||
|
m_size = info.size();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameFile::LoadState()
|
||||||
|
{
|
||||||
|
IniFile ini = SConfig::LoadGameIni(m_unique_id.toStdString(), m_revision);
|
||||||
|
std::string issues_temp;
|
||||||
|
ini.GetIfExists("EmuState", "EmulationStateId", &m_rating);
|
||||||
|
ini.GetIfExists("EmuState", "EmulationIssues", &issues_temp);
|
||||||
|
m_issues = QString::fromStdString(issues_temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameFile::IsElfOrDol()
|
||||||
|
{
|
||||||
|
return m_extension == QStringLiteral("elf") ||
|
||||||
|
m_extension == QStringLiteral("dol");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameFile::TryLoadCache()
|
||||||
|
{
|
||||||
|
QFile cache(GetCacheFileName());
|
||||||
|
if (!cache.exists())
|
||||||
|
return false;
|
||||||
|
if (!cache.open(QIODevice::ReadOnly))
|
||||||
|
return false;
|
||||||
|
if (QFileInfo(cache).lastModified() < m_last_modified)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QDataStream in(&cache);
|
||||||
|
in.setVersion(DATASTREAM_VERSION);
|
||||||
|
|
||||||
|
int cache_version;
|
||||||
|
in >> cache_version;
|
||||||
|
if (cache_version != CACHE_VERSION)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameFile::TryLoadVolume()
|
||||||
|
{
|
||||||
|
QSharedPointer<DiscIO::IVolume> volume(DiscIO::CreateVolumeFromFilename(m_path.toStdString()));
|
||||||
|
if (volume == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_unique_id = QString::fromStdString(volume->GetUniqueID());
|
||||||
|
m_maker_id = QString::fromStdString(volume->GetMakerID());
|
||||||
|
m_revision = volume->GetRevision();
|
||||||
|
m_internal_name = QString::fromStdString(volume->GetInternalName());
|
||||||
|
m_short_names = ConvertLanguageMap(volume->GetNames(false));
|
||||||
|
m_long_names = ConvertLanguageMap(volume->GetNames(true));
|
||||||
|
m_descriptions = ConvertLanguageMap(volume->GetDescriptions());
|
||||||
|
m_company = QString::fromStdString(volume->GetCompany());
|
||||||
|
m_disc_number = volume->GetDiscNumber();
|
||||||
|
m_platform = volume->GetVolumeType();
|
||||||
|
m_country = volume->GetCountry();
|
||||||
|
m_blob_type = volume->GetBlobType();
|
||||||
|
m_raw_size = volume->GetRawSize();
|
||||||
|
|
||||||
|
if (m_company.isEmpty() && m_unique_id.size() >= 6)
|
||||||
|
m_company = QString::fromStdString(
|
||||||
|
DiscIO::GetCompanyFromID(m_unique_id.mid(4, 2).toStdString()));
|
||||||
|
|
||||||
|
ReadBanner(*volume);
|
||||||
|
|
||||||
|
SaveCache();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GameFile::TryLoadElfDol()
|
||||||
|
{
|
||||||
|
if (!IsElfOrDol())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_revision = 0;
|
||||||
|
m_long_names[DiscIO::IVolume::LANGUAGE_ENGLISH] = m_file_name;
|
||||||
|
m_platform = DiscIO::IVolume::ELF_DOL;
|
||||||
|
m_country = DiscIO::IVolume::COUNTRY_UNKNOWN;
|
||||||
|
m_blob_type = DiscIO::BlobType::DIRECTORY;
|
||||||
|
m_raw_size = m_size;
|
||||||
|
m_banner = Resources::GetMisc(Resources::BANNER_MISSING);
|
||||||
|
m_rating = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void GameFile::SaveCache()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GameFile::GetLanguageString(QMap<DiscIO::IVolume::ELanguage, QString> m) const
|
||||||
|
{
|
||||||
|
// Try the settings language, then English, then just pick one.
|
||||||
|
if (m.isEmpty())
|
||||||
|
return QString();
|
||||||
|
DiscIO::IVolume::ELanguage current_lang = GetDefaultLanguage();
|
||||||
|
if (m.contains(current_lang))
|
||||||
|
return m[current_lang];
|
||||||
|
if (m.contains(DiscIO::IVolume::LANGUAGE_ENGLISH))
|
||||||
|
return m[DiscIO::IVolume::LANGUAGE_ENGLISH];
|
||||||
|
return m.first();
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "DiscIO/Volume.h"
|
||||||
|
|
||||||
|
// TODO cache
|
||||||
|
class GameFile final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit GameFile(QString path);
|
||||||
|
|
||||||
|
bool IsValid() const { return m_valid; }
|
||||||
|
|
||||||
|
// These will be properly initialized before we try to load the file.
|
||||||
|
QString GetPath() const { return m_path; }
|
||||||
|
QString GetFileName() const { return m_file_name; }
|
||||||
|
QString GetExtension() const { return m_extension; }
|
||||||
|
QString GetFolder() const { return m_folder; }
|
||||||
|
qint64 GetFileSize() const { return m_size; }
|
||||||
|
|
||||||
|
// The rest will not.
|
||||||
|
QString GetUniqueID() const { return m_unique_id; }
|
||||||
|
QString GetMakerID() const { return m_maker_id; }
|
||||||
|
u16 GetRevision() const { return m_revision; }
|
||||||
|
QString GetInternalName() const { return m_internal_name; }
|
||||||
|
QString GetCompany() const { return m_company; }
|
||||||
|
u8 GetDiscNumber() const { return m_disc_number; }
|
||||||
|
u64 GetRawSize() const { return m_raw_size; }
|
||||||
|
QPixmap GetBanner() const { return m_banner; }
|
||||||
|
QString GetIssues() const { return m_issues; }
|
||||||
|
int GetRating() const { return m_rating; }
|
||||||
|
|
||||||
|
DiscIO::IVolume::EPlatform GetPlatform() const { return m_platform; }
|
||||||
|
DiscIO::IVolume::ECountry GetCountry() const { return m_country; }
|
||||||
|
DiscIO::BlobType GetBlobType() const { return m_blob_type; }
|
||||||
|
|
||||||
|
QString GetShortName() const { return GetLanguageString(m_short_names); }
|
||||||
|
QString GetShortName(DiscIO::IVolume::ELanguage lang) const
|
||||||
|
{
|
||||||
|
return m_short_names[lang];
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GetLongName() const { return GetLanguageString(m_long_names); }
|
||||||
|
QString GetLongName(DiscIO::IVolume::ELanguage lang) const
|
||||||
|
{
|
||||||
|
return m_long_names[lang];
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GetDescription() const { return GetLanguageString(m_descriptions); }
|
||||||
|
QString GetDescription(DiscIO::IVolume::ELanguage lang) const
|
||||||
|
{
|
||||||
|
return m_descriptions[lang];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DiscIO::IVolume::ELanguage GetDefaultLanguage() const;
|
||||||
|
QString GetLanguageString(QMap<DiscIO::IVolume::ELanguage, QString> m) const;
|
||||||
|
|
||||||
|
QString GetCacheFileName() const;
|
||||||
|
void ReadBanner(const DiscIO::IVolume& volume);
|
||||||
|
bool LoadFileInfo(QString path);
|
||||||
|
void LoadState();
|
||||||
|
bool IsElfOrDol();
|
||||||
|
bool TryLoadElfDol();
|
||||||
|
bool TryLoadCache();
|
||||||
|
bool TryLoadVolume();
|
||||||
|
void SaveCache();
|
||||||
|
|
||||||
|
bool m_valid;
|
||||||
|
QString m_path;
|
||||||
|
QString m_file_name;
|
||||||
|
QString m_extension;
|
||||||
|
QString m_folder;
|
||||||
|
QDateTime m_last_modified;
|
||||||
|
qint64 m_size;
|
||||||
|
|
||||||
|
QString m_unique_id;
|
||||||
|
QString m_maker_id;
|
||||||
|
u16 m_revision;
|
||||||
|
QString m_internal_name;
|
||||||
|
QMap<DiscIO::IVolume::ELanguage, QString> m_short_names;
|
||||||
|
QMap<DiscIO::IVolume::ELanguage, QString> m_long_names;
|
||||||
|
QMap<DiscIO::IVolume::ELanguage, QString> m_descriptions;
|
||||||
|
QString m_company;
|
||||||
|
u8 m_disc_number;
|
||||||
|
DiscIO::IVolume::EPlatform m_platform;
|
||||||
|
DiscIO::IVolume::ECountry m_country;
|
||||||
|
DiscIO::BlobType m_blob_type;
|
||||||
|
u64 m_raw_size;
|
||||||
|
QPixmap m_banner;
|
||||||
|
QString m_issues;
|
||||||
|
int m_rating;
|
||||||
|
};
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QHeaderView>
|
||||||
|
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "DolphinQt2/GameList/GameList.h"
|
||||||
|
|
||||||
|
GameList::GameList(QWidget* parent): QStackedWidget(parent)
|
||||||
|
{
|
||||||
|
m_model = new GameListModel(this);
|
||||||
|
m_proxy = new QSortFilterProxyModel(this);
|
||||||
|
m_proxy->setSourceModel(m_model);
|
||||||
|
|
||||||
|
MakeTableView();
|
||||||
|
MakeListView();
|
||||||
|
|
||||||
|
connect(m_table, &QTableView::doubleClicked, this, &GameList::GameSelected);
|
||||||
|
connect(m_list, &QListView::doubleClicked, this, &GameList::GameSelected);
|
||||||
|
connect(this, &GameList::DirectoryAdded, m_model, &GameListModel::DirectoryAdded);
|
||||||
|
|
||||||
|
addWidget(m_table);
|
||||||
|
addWidget(m_list);
|
||||||
|
setCurrentWidget(m_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameList::MakeTableView()
|
||||||
|
{
|
||||||
|
m_table = new QTableView(this);
|
||||||
|
m_table->setModel(m_proxy);
|
||||||
|
m_table->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
m_table->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
m_table->setAlternatingRowColors(true);
|
||||||
|
m_table->setShowGrid(false);
|
||||||
|
m_table->setSortingEnabled(true);
|
||||||
|
m_table->setCurrentIndex(QModelIndex());
|
||||||
|
|
||||||
|
// These fixed column widths make it so that the DisplayRole is cut
|
||||||
|
// off, which lets us see the icon but sort by the actual value.
|
||||||
|
// It's a bit of a hack. To do it right we need to subclass
|
||||||
|
// QSortFilterProxyModel and not show those items.
|
||||||
|
m_table->setColumnWidth(GameListModel::COL_PLATFORM, 52);
|
||||||
|
m_table->setColumnWidth(GameListModel::COL_COUNTRY, 38);
|
||||||
|
m_table->setColumnWidth(GameListModel::COL_RATING, 52);
|
||||||
|
m_table->setColumnHidden(GameListModel::COL_LARGE_ICON, true);
|
||||||
|
|
||||||
|
m_table->horizontalHeader()->setSectionResizeMode(
|
||||||
|
GameListModel::COL_PLATFORM, QHeaderView::Fixed);
|
||||||
|
m_table->horizontalHeader()->setSectionResizeMode(
|
||||||
|
GameListModel::COL_COUNTRY, QHeaderView::Fixed);
|
||||||
|
m_table->horizontalHeader()->setSectionResizeMode(
|
||||||
|
GameListModel::COL_ID, QHeaderView::ResizeToContents);
|
||||||
|
m_table->horizontalHeader()->setSectionResizeMode(
|
||||||
|
GameListModel::COL_TITLE, QHeaderView::Stretch);
|
||||||
|
m_table->horizontalHeader()->setSectionResizeMode(
|
||||||
|
GameListModel::COL_MAKER, QHeaderView::ResizeToContents);
|
||||||
|
m_table->horizontalHeader()->setSectionResizeMode(
|
||||||
|
GameListModel::COL_SIZE, QHeaderView::ResizeToContents);
|
||||||
|
m_table->horizontalHeader()->setSectionResizeMode(
|
||||||
|
GameListModel::COL_DESCRIPTION, QHeaderView::Stretch);
|
||||||
|
m_table->horizontalHeader()->setSectionResizeMode(
|
||||||
|
GameListModel::COL_RATING, QHeaderView::Fixed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameList::MakeListView()
|
||||||
|
{
|
||||||
|
m_list = new QListView(this);
|
||||||
|
m_list->setModel(m_proxy);
|
||||||
|
m_list->setViewMode(QListView::IconMode);
|
||||||
|
m_list->setModelColumn(GameListModel::COL_LARGE_ICON);
|
||||||
|
m_list->setResizeMode(QListView::Adjust);
|
||||||
|
m_list->setUniformItemSizes(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GameList::GetSelectedGame() const
|
||||||
|
{
|
||||||
|
QItemSelectionModel* sel_model;
|
||||||
|
if (currentWidget() == m_table)
|
||||||
|
sel_model = m_table->selectionModel();
|
||||||
|
else
|
||||||
|
sel_model = m_list->selectionModel();
|
||||||
|
|
||||||
|
if (sel_model->hasSelection())
|
||||||
|
return m_model->GetPath(m_proxy->mapToSource(sel_model->selectedIndexes()[0]).row());
|
||||||
|
else
|
||||||
|
return QString();
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QListView>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
#include <QTableView>
|
||||||
|
|
||||||
|
#include "DolphinQt2/GameList/GameFile.h"
|
||||||
|
#include "DolphinQt2/GameList/GameListModel.h"
|
||||||
|
|
||||||
|
class GameList final : public QStackedWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GameList(QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
QString GetSelectedGame() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void SetTableView() { setCurrentWidget(m_table); }
|
||||||
|
void SetListView() { setCurrentWidget(m_list); }
|
||||||
|
void SetViewColumn(int col, bool view) { m_table->setColumnHidden(col, !view); }
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void GameSelected();
|
||||||
|
void DirectoryAdded(QString dir);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void MakeTableView();
|
||||||
|
void MakeListView();
|
||||||
|
|
||||||
|
GameListModel* m_model;
|
||||||
|
QSortFilterProxyModel* m_proxy;
|
||||||
|
QListView* m_list;
|
||||||
|
QTableView* m_table;
|
||||||
|
};
|
|
@ -0,0 +1,132 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "DolphinQt2/Resources.h"
|
||||||
|
#include "DolphinQt2/GameList/GameListModel.h"
|
||||||
|
|
||||||
|
static QString FormatSize(qint64 size)
|
||||||
|
{
|
||||||
|
QStringList units{
|
||||||
|
QStringLiteral("KB"),
|
||||||
|
QStringLiteral("MB"),
|
||||||
|
QStringLiteral("GB"),
|
||||||
|
QStringLiteral("TB")
|
||||||
|
};
|
||||||
|
QStringListIterator i(units);
|
||||||
|
QString unit = QStringLiteral("B");
|
||||||
|
double num = (double) size;
|
||||||
|
while (num > 1024.0 && i.hasNext())
|
||||||
|
{
|
||||||
|
unit = i.next();
|
||||||
|
num /= 1024.0;
|
||||||
|
}
|
||||||
|
return QStringLiteral("%1 %2").arg(QString::number(num, 'f', 1)).arg(unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
GameListModel::GameListModel(QObject* parent)
|
||||||
|
: QAbstractTableModel(parent)
|
||||||
|
{
|
||||||
|
connect(&m_tracker, &GameTracker::GameLoaded, this, &GameListModel::UpdateGame);
|
||||||
|
connect(&m_tracker, &GameTracker::GameRemoved, this, &GameListModel::RemoveGame);
|
||||||
|
connect(this, &GameListModel::DirectoryAdded, &m_tracker, &GameTracker::AddDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant GameListModel::data(const QModelIndex& index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
QSharedPointer<GameFile> game = m_games[index.row()];
|
||||||
|
if (index.column() == COL_PLATFORM && role == Qt::DecorationRole)
|
||||||
|
return QVariant(Resources::GetPlatform(game->GetPlatform()));
|
||||||
|
else if (index.column() == COL_PLATFORM && role == Qt::DisplayRole)
|
||||||
|
return QVariant(game->GetPlatform());
|
||||||
|
|
||||||
|
else if (index.column() == COL_TITLE && role == Qt::DecorationRole)
|
||||||
|
return QVariant(game->GetBanner());
|
||||||
|
else if (index.column() == COL_TITLE && role == Qt::DisplayRole)
|
||||||
|
return QVariant(game->GetLongName());
|
||||||
|
|
||||||
|
else if (index.column() == COL_ID && role == Qt::DisplayRole)
|
||||||
|
return QVariant(game->GetUniqueID());
|
||||||
|
|
||||||
|
else if (index.column() == COL_DESCRIPTION && role == Qt::DisplayRole)
|
||||||
|
return QVariant(game->GetDescription());
|
||||||
|
|
||||||
|
else if (index.column() == COL_MAKER && role == Qt::DisplayRole)
|
||||||
|
return QVariant(game->GetCompany());
|
||||||
|
|
||||||
|
// FIXME this sorts lexicographically, not by size.
|
||||||
|
else if (index.column() == COL_SIZE && role == Qt::DisplayRole)
|
||||||
|
return QVariant(FormatSize(game->GetFileSize()));
|
||||||
|
|
||||||
|
else if (index.column() == COL_COUNTRY && role == Qt::DecorationRole)
|
||||||
|
return QVariant(Resources::GetCountry(game->GetCountry()));
|
||||||
|
else if (index.column() == COL_COUNTRY && role == Qt::DisplayRole)
|
||||||
|
return QVariant(game->GetCountry());
|
||||||
|
|
||||||
|
else if (index.column() == COL_RATING && role == Qt::DecorationRole)
|
||||||
|
return QVariant(Resources::GetRating(game->GetRating()));
|
||||||
|
else if (index.column() == COL_RATING && role == Qt::DisplayRole)
|
||||||
|
return QVariant(game->GetRating());
|
||||||
|
|
||||||
|
else if (index.column() == COL_LARGE_ICON && role == Qt::DecorationRole)
|
||||||
|
return QVariant(game->GetBanner().scaled(144, 48));
|
||||||
|
else if (index.column() == COL_LARGE_ICON && role == Qt::DisplayRole)
|
||||||
|
return QVariant(game->GetLongName());
|
||||||
|
|
||||||
|
else
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant GameListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (orientation == Qt::Vertical || role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
switch (section)
|
||||||
|
{
|
||||||
|
case COL_TITLE: return QVariant(tr("Title"));
|
||||||
|
case COL_ID: return QVariant(tr("ID"));
|
||||||
|
case COL_DESCRIPTION: return QVariant(tr("Description"));
|
||||||
|
case COL_MAKER: return QVariant(tr("Maker"));
|
||||||
|
case COL_SIZE: return QVariant(tr("Size"));
|
||||||
|
case COL_RATING: return QVariant(tr("Quality"));
|
||||||
|
default: return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GameListModel::rowCount(const QModelIndex& parent) const
|
||||||
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return 0;
|
||||||
|
return m_games.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GameListModel::columnCount(const QModelIndex& parent) const
|
||||||
|
{
|
||||||
|
return NUM_COLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GameListModel::UpdateGame(QSharedPointer<GameFile> game)
|
||||||
|
{
|
||||||
|
QString path = game->GetPath();
|
||||||
|
if (m_entries.contains(path))
|
||||||
|
RemoveGame(path);
|
||||||
|
|
||||||
|
beginInsertRows(QModelIndex(), m_games.size(), m_games.size());
|
||||||
|
m_entries[path] = m_games.size();
|
||||||
|
m_games.append(game);
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameListModel::RemoveGame(QString path)
|
||||||
|
{
|
||||||
|
int entry = m_entries[path];
|
||||||
|
beginRemoveRows(QModelIndex(), entry, entry);
|
||||||
|
m_entries.remove(path);
|
||||||
|
m_games.removeAt(entry);
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "DolphinQt2/GameList/GameFile.h"
|
||||||
|
#include "DolphinQt2/GameList/GameTracker.h"
|
||||||
|
|
||||||
|
class GameListModel final : public QAbstractTableModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GameListModel(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
// Qt's Model/View stuff uses these overrides.
|
||||||
|
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
int rowCount(const QModelIndex& parent) const;
|
||||||
|
int columnCount(const QModelIndex& parent) const;
|
||||||
|
|
||||||
|
// Path of the Game at the specified index.
|
||||||
|
QString GetPath(int index) const { return m_games[index]->GetPath(); }
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
COL_PLATFORM = 0,
|
||||||
|
COL_ID,
|
||||||
|
COL_TITLE,
|
||||||
|
COL_DESCRIPTION,
|
||||||
|
COL_MAKER,
|
||||||
|
COL_SIZE,
|
||||||
|
COL_COUNTRY,
|
||||||
|
COL_RATING,
|
||||||
|
COL_LARGE_ICON,
|
||||||
|
NUM_COLS
|
||||||
|
};
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void UpdateGame(QSharedPointer<GameFile> game);
|
||||||
|
void RemoveGame(QString path);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void DirectoryAdded(QString dir);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GameTracker m_tracker;
|
||||||
|
QList<QSharedPointer<GameFile>> m_games;
|
||||||
|
// Path -> index in m_games
|
||||||
|
QMap<QString, int> m_entries;
|
||||||
|
};
|
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "DolphinQt2/GameList/GameTracker.h"
|
||||||
|
|
||||||
|
GameTracker::GameTracker(QObject* parent)
|
||||||
|
: QFileSystemWatcher(parent)
|
||||||
|
{
|
||||||
|
m_loader = new GameLoader;
|
||||||
|
m_loader->moveToThread(&m_loader_thread);
|
||||||
|
|
||||||
|
qRegisterMetaType<QSharedPointer<GameFile>>();
|
||||||
|
connect(&m_loader_thread, &QThread::finished, m_loader, &QObject::deleteLater);
|
||||||
|
connect(this, &QFileSystemWatcher::directoryChanged, this, &GameTracker::UpdateDirectory);
|
||||||
|
connect(this, &QFileSystemWatcher::fileChanged, this, &GameTracker::UpdateFile);
|
||||||
|
connect(this, &GameTracker::PathChanged, m_loader, &GameLoader::LoadGame);
|
||||||
|
connect(m_loader, &GameLoader::GameLoaded, this, &GameTracker::GameLoaded);
|
||||||
|
|
||||||
|
GenerateFilters();
|
||||||
|
|
||||||
|
m_loader_thread.start();
|
||||||
|
|
||||||
|
for (const std::string& dir : SConfig::GetInstance().m_ISOFolder)
|
||||||
|
AddDirectory(QString::fromStdString(dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
GameTracker::~GameTracker()
|
||||||
|
{
|
||||||
|
m_loader_thread.quit();
|
||||||
|
m_loader_thread.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTracker::AddDirectory(QString dir)
|
||||||
|
{
|
||||||
|
addPath(dir);
|
||||||
|
UpdateDirectory(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTracker::UpdateDirectory(QString dir)
|
||||||
|
{
|
||||||
|
QDirIterator it(dir, m_filters);
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
QString path = QFileInfo(it.next()).canonicalFilePath();
|
||||||
|
if (!m_tracked_files.contains(path))
|
||||||
|
{
|
||||||
|
addPath(path);
|
||||||
|
m_tracked_files.insert(path);
|
||||||
|
emit PathChanged(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTracker::UpdateFile(QString file)
|
||||||
|
{
|
||||||
|
if (QFileInfo(file).exists())
|
||||||
|
{
|
||||||
|
emit PathChanged(file);
|
||||||
|
}
|
||||||
|
else if (removePath(file))
|
||||||
|
{
|
||||||
|
m_tracked_files.remove(file);
|
||||||
|
emit GameRemoved(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameTracker::GenerateFilters()
|
||||||
|
{
|
||||||
|
m_filters.clear();
|
||||||
|
if (SConfig::GetInstance().m_ListGC)
|
||||||
|
m_filters << tr("*.gcm");
|
||||||
|
if (SConfig::GetInstance().m_ListWii || SConfig::GetInstance().m_ListGC)
|
||||||
|
m_filters << tr("*.iso") << tr("*.ciso") << tr("*.gcz") << tr("*.wbfs");
|
||||||
|
if (SConfig::GetInstance().m_ListWad)
|
||||||
|
m_filters << tr("*.wad");
|
||||||
|
if (SConfig::GetInstance().m_ListElfDol)
|
||||||
|
m_filters << tr("*.elf") << tr("*.dol");
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include "DolphinQt2/GameList/GameFile.h"
|
||||||
|
#include "DolphinQt2/GameList/GameTracker.h"
|
||||||
|
|
||||||
|
class GameLoader;
|
||||||
|
|
||||||
|
// Watches directories and loads GameFiles in a separate thread.
|
||||||
|
// To use this, just add directories using AddDirectory, and listen for the
|
||||||
|
// GameLoaded and GameRemoved signals.
|
||||||
|
class GameTracker final : public QFileSystemWatcher
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GameTracker(QObject* parent = nullptr);
|
||||||
|
~GameTracker();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void AddDirectory(QString dir);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void GameLoaded(QSharedPointer<GameFile> game);
|
||||||
|
void GameRemoved(QString path);
|
||||||
|
|
||||||
|
void PathChanged(QString path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UpdateDirectory(QString dir);
|
||||||
|
void UpdateFile(QString path);
|
||||||
|
void GenerateFilters();
|
||||||
|
|
||||||
|
QSet<QString> m_tracked_files;
|
||||||
|
QStringList m_filters;
|
||||||
|
QThread m_loader_thread;
|
||||||
|
GameLoader* m_loader;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GameLoader : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void LoadGame(QString path)
|
||||||
|
{
|
||||||
|
GameFile* game = new GameFile(path);
|
||||||
|
if (game->IsValid())
|
||||||
|
emit GameLoaded(QSharedPointer<GameFile>(game));
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void GameLoaded(QSharedPointer<GameFile> game);
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(QSharedPointer<GameFile>)
|
|
@ -0,0 +1,96 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QMutexLocker>
|
||||||
|
|
||||||
|
#include "Common/Common.h"
|
||||||
|
#include "Core/Host.h"
|
||||||
|
#include "DolphinQt2/Host.h"
|
||||||
|
#include "DolphinQt2/MainWindow.h"
|
||||||
|
|
||||||
|
Host* Host::m_instance = nullptr;
|
||||||
|
|
||||||
|
Host* Host::GetInstance()
|
||||||
|
{
|
||||||
|
if (m_instance == nullptr)
|
||||||
|
m_instance = new Host();
|
||||||
|
return m_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Host::GetRenderHandle()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_lock);
|
||||||
|
return m_render_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::SetRenderHandle(void* handle)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_lock);
|
||||||
|
m_render_handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Host::GetRenderFocus()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_lock);
|
||||||
|
return m_render_focus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::SetRenderFocus(bool focus)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_lock);
|
||||||
|
m_render_focus = focus;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Host::GetRenderFullscreen()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_lock);
|
||||||
|
return m_render_fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::SetRenderFullscreen(bool fullscreen)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&m_lock);
|
||||||
|
m_render_fullscreen = fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host_Message(int id)
|
||||||
|
{
|
||||||
|
if (id == WM_USER_STOP)
|
||||||
|
emit Host::GetInstance()->RequestStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host_UpdateTitle(const std::string& title)
|
||||||
|
{
|
||||||
|
emit Host::GetInstance()->RequestTitle(QString::fromStdString(title));
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Host_GetRenderHandle()
|
||||||
|
{
|
||||||
|
return Host::GetInstance()->GetRenderHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Host_RendererHasFocus()
|
||||||
|
{
|
||||||
|
return Host::GetInstance()->GetRenderFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Host_RendererIsFullscreen() {
|
||||||
|
return Host::GetInstance()->GetRenderFullscreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We ignore these, and their purpose should be questioned individually.
|
||||||
|
// In particular, RequestRenderWindowSize, RequestFullscreen, and
|
||||||
|
// UpdateMainFrame should almost certainly be removed.
|
||||||
|
void Host_UpdateMainFrame() {}
|
||||||
|
void Host_RequestFullscreen(bool enable) {}
|
||||||
|
void Host_RequestRenderWindowSize(int w, int h) {}
|
||||||
|
bool Host_UIHasFocus() { return false; }
|
||||||
|
void Host_NotifyMapLoaded() {}
|
||||||
|
void Host_UpdateDisasmDialog() {}
|
||||||
|
void Host_SetStartupDebuggingParameters() {}
|
||||||
|
void Host_SetWiiMoteConnectionState(int state) {}
|
||||||
|
void Host_ConnectWiimote(int wm_idx, bool connect) {}
|
||||||
|
void Host_ShowVideoConfig(void* parent, const std::string& backend_name,
|
||||||
|
const std::string& config_name) {}
|
||||||
|
void Host_RefreshDSPDebuggerWindow() {}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QSize>
|
||||||
|
|
||||||
|
// Singleton that talks to the Core via the interface defined in Core/Host.h.
|
||||||
|
// Because Host_* calls might come from different threads than the MainWindow,
|
||||||
|
// the Host class communicates with it via signals/slots only.
|
||||||
|
|
||||||
|
// Many of the Host_* functions are ignored, and some shouldn't exist.
|
||||||
|
class Host final : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
static Host* GetInstance();
|
||||||
|
|
||||||
|
void* GetRenderHandle();
|
||||||
|
bool GetRenderFocus();
|
||||||
|
bool GetRenderFullscreen();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void SetRenderHandle(void* handle);
|
||||||
|
void SetRenderFocus(bool focus);
|
||||||
|
void SetRenderFullscreen(bool fullscreen);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void RequestTitle(QString title);
|
||||||
|
void RequestStop();
|
||||||
|
void RequestRenderSize(int w, int h);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Host() {}
|
||||||
|
static Host* m_instance;
|
||||||
|
QMutex m_lock;
|
||||||
|
|
||||||
|
void* m_render_handle;
|
||||||
|
bool m_render_focus;
|
||||||
|
bool m_render_fullscreen;
|
||||||
|
};
|
|
@ -0,0 +1,33 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
#include "Core/BootManager.h"
|
||||||
|
#include "Core/Core.h"
|
||||||
|
#include "DolphinQt2/Host.h"
|
||||||
|
#include "DolphinQt2/MainWindow.h"
|
||||||
|
#include "DolphinQt2/Resources.h"
|
||||||
|
#include "UICommon/UICommon.h"
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
UICommon::SetUserDirectory("");
|
||||||
|
UICommon::CreateDirectories();
|
||||||
|
UICommon::Init();
|
||||||
|
Resources::Init();
|
||||||
|
|
||||||
|
MainWindow win;
|
||||||
|
win.show();
|
||||||
|
int retval = app.exec();
|
||||||
|
|
||||||
|
BootManager::Stop();
|
||||||
|
Core::Shutdown();
|
||||||
|
UICommon::Shutdown();
|
||||||
|
Host::GetInstance()->deleteLater();
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
|
@ -0,0 +1,404 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMenuBar>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Core/BootManager.h"
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "Core/Core.h"
|
||||||
|
#include "DolphinQt2/Host.h"
|
||||||
|
#include "DolphinQt2/MainWindow.h"
|
||||||
|
#include "DolphinQt2/Resources.h"
|
||||||
|
#include "DolphinQt2/GameList/GameListModel.h"
|
||||||
|
|
||||||
|
MainWindow::MainWindow() : QMainWindow(nullptr)
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("Dolphin"));
|
||||||
|
setWindowIcon(QIcon(Resources::GetMisc(Resources::LOGO_SMALL)));
|
||||||
|
|
||||||
|
MakeToolBar();
|
||||||
|
MakeGameList();
|
||||||
|
MakeRenderWidget();
|
||||||
|
MakeStack();
|
||||||
|
MakeMenus();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindow::~MainWindow()
|
||||||
|
{
|
||||||
|
m_render_widget->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::MakeMenus()
|
||||||
|
{
|
||||||
|
MakeFileMenu();
|
||||||
|
menuBar()->addMenu(tr("Emulation"));
|
||||||
|
menuBar()->addMenu(tr("Movie"));
|
||||||
|
menuBar()->addMenu(tr("Options"));
|
||||||
|
menuBar()->addMenu(tr("Tools"));
|
||||||
|
MakeViewMenu();
|
||||||
|
menuBar()->addMenu(tr("Help"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::MakeFileMenu()
|
||||||
|
{
|
||||||
|
QMenu* file_menu = menuBar()->addMenu(tr("File"));
|
||||||
|
file_menu->addAction(tr("Open"), this, SLOT(Open()));
|
||||||
|
file_menu->addAction(tr("Exit"), this, SLOT(close()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::MakeViewMenu()
|
||||||
|
{
|
||||||
|
QMenu* view_menu = menuBar()->addMenu(tr("View"));
|
||||||
|
AddTableColumnsMenu(view_menu);
|
||||||
|
AddListTypePicker(view_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::AddTableColumnsMenu(QMenu* view_menu)
|
||||||
|
{
|
||||||
|
QActionGroup* column_group = new QActionGroup(this);
|
||||||
|
QMenu* cols_menu = view_menu->addMenu(tr("Table Columns"));
|
||||||
|
column_group->setExclusive(false);
|
||||||
|
|
||||||
|
QStringList col_names{
|
||||||
|
tr("Platform"),
|
||||||
|
tr("ID"),
|
||||||
|
tr("Title"),
|
||||||
|
tr("Description"),
|
||||||
|
tr("Maker"),
|
||||||
|
tr("Size"),
|
||||||
|
tr("Country"),
|
||||||
|
tr("Quality")
|
||||||
|
};
|
||||||
|
// TODO we'll need to update SConfig with another column. Then we can clean this
|
||||||
|
// up significantly.
|
||||||
|
QList<bool> show_cols{
|
||||||
|
SConfig::GetInstance().m_showSystemColumn,
|
||||||
|
SConfig::GetInstance().m_showIDColumn,
|
||||||
|
SConfig::GetInstance().m_showBannerColumn,
|
||||||
|
false,
|
||||||
|
SConfig::GetInstance().m_showMakerColumn,
|
||||||
|
SConfig::GetInstance().m_showSizeColumn,
|
||||||
|
SConfig::GetInstance().m_showRegionColumn,
|
||||||
|
SConfig::GetInstance().m_showStateColumn,
|
||||||
|
};
|
||||||
|
// - 1 because we never show COL_LARGE_ICON column in the table.
|
||||||
|
for (int i = 0; i < GameListModel::NUM_COLS - 1; i++)
|
||||||
|
{
|
||||||
|
QAction* action = column_group->addAction(cols_menu->addAction(col_names[i]));
|
||||||
|
action->setCheckable(true);
|
||||||
|
action->setChecked(show_cols[i]);
|
||||||
|
m_game_list->SetViewColumn(i, show_cols[i]);
|
||||||
|
connect(action, &QAction::triggered, [=]()
|
||||||
|
{
|
||||||
|
m_game_list->SetViewColumn(i, action->isChecked());
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case GameListModel::COL_PLATFORM:
|
||||||
|
SConfig::GetInstance().m_showSystemColumn = action->isChecked();
|
||||||
|
break;
|
||||||
|
case GameListModel::COL_ID:
|
||||||
|
SConfig::GetInstance().m_showIDColumn = action->isChecked();
|
||||||
|
break;
|
||||||
|
case GameListModel::COL_TITLE:
|
||||||
|
SConfig::GetInstance().m_showBannerColumn = action->isChecked();
|
||||||
|
break;
|
||||||
|
case GameListModel::COL_MAKER:
|
||||||
|
SConfig::GetInstance().m_showMakerColumn = action->isChecked();
|
||||||
|
break;
|
||||||
|
case GameListModel::COL_SIZE:
|
||||||
|
SConfig::GetInstance().m_showSizeColumn = action->isChecked();
|
||||||
|
break;
|
||||||
|
case GameListModel::COL_COUNTRY:
|
||||||
|
SConfig::GetInstance().m_showRegionColumn = action->isChecked();
|
||||||
|
break;
|
||||||
|
case GameListModel::COL_RATING:
|
||||||
|
SConfig::GetInstance().m_showStateColumn = action->isChecked();
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
SConfig::GetInstance().SaveSettings();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::AddListTypePicker(QMenu* view_menu)
|
||||||
|
{
|
||||||
|
QActionGroup* list_group = new QActionGroup(this);
|
||||||
|
view_menu->addSection(tr("List Type"));
|
||||||
|
list_group->setExclusive(true);
|
||||||
|
|
||||||
|
QAction* set_table = list_group->addAction(view_menu->addAction(tr("Table")));
|
||||||
|
QAction* set_list = list_group->addAction(view_menu->addAction(tr("List")));
|
||||||
|
|
||||||
|
set_table->setCheckable(true);
|
||||||
|
set_table->setChecked(true);
|
||||||
|
set_list->setCheckable(true);
|
||||||
|
|
||||||
|
connect(set_table, &QAction::triggered, m_game_list, &GameList::SetTableView);
|
||||||
|
connect(set_list, &QAction::triggered, m_game_list, &GameList::SetListView);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::MakeToolBar()
|
||||||
|
{
|
||||||
|
setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
||||||
|
m_tool_bar = addToolBar(tr("ToolBar"));
|
||||||
|
m_tool_bar->setMovable(false);
|
||||||
|
m_tool_bar->setFloatable(false);
|
||||||
|
|
||||||
|
PopulateToolBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::MakeGameList()
|
||||||
|
{
|
||||||
|
m_game_list = new GameList(this);
|
||||||
|
connect(m_game_list, &GameList::GameSelected, this, &MainWindow::Play);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::MakeRenderWidget()
|
||||||
|
{
|
||||||
|
m_render_widget = new RenderWidget;
|
||||||
|
connect(m_render_widget, &RenderWidget::EscapePressed, this, &MainWindow::Stop);
|
||||||
|
connect(m_render_widget, &RenderWidget::Closed, this, &MainWindow::ForceStop);
|
||||||
|
m_render_widget->hide();
|
||||||
|
m_rendering_to_main = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::MakeStack()
|
||||||
|
{
|
||||||
|
m_stack = new QStackedWidget;
|
||||||
|
m_stack->setMinimumSize(800, 600);
|
||||||
|
m_stack->addWidget(m_game_list);
|
||||||
|
setCentralWidget(m_stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::PopulateToolBar()
|
||||||
|
{
|
||||||
|
m_tool_bar->clear();
|
||||||
|
|
||||||
|
QString dir = QString::fromStdString(File::GetThemeDir(SConfig::GetInstance().theme_name));
|
||||||
|
m_tool_bar->addAction(
|
||||||
|
QIcon(dir + QStringLiteral("open.png")), tr("Open"),
|
||||||
|
this, SLOT(Open()));
|
||||||
|
m_tool_bar->addAction(
|
||||||
|
QIcon(dir + QStringLiteral("browse.png")), tr("Browse"),
|
||||||
|
this, SLOT(Browse()));
|
||||||
|
|
||||||
|
m_tool_bar->addSeparator();
|
||||||
|
|
||||||
|
QAction* play_action = m_tool_bar->addAction(
|
||||||
|
QIcon(dir + QStringLiteral("play.png")), tr("Play"),
|
||||||
|
this, SLOT(Play()));
|
||||||
|
connect(this, &MainWindow::EmulationStarted, [=](){ play_action->setEnabled(false); });
|
||||||
|
connect(this, &MainWindow::EmulationPaused, [=](){ play_action->setEnabled(true); });
|
||||||
|
connect(this, &MainWindow::EmulationStopped, [=](){ play_action->setEnabled(true); });
|
||||||
|
|
||||||
|
QAction* pause_action = m_tool_bar->addAction(
|
||||||
|
QIcon(dir + QStringLiteral("pause.png")), tr("Pause"),
|
||||||
|
this, SLOT(Pause()));
|
||||||
|
pause_action->setEnabled(false);
|
||||||
|
connect(this, &MainWindow::EmulationStarted, [=](){ pause_action->setEnabled(true); });
|
||||||
|
connect(this, &MainWindow::EmulationPaused, [=](){ pause_action->setEnabled(false); });
|
||||||
|
connect(this, &MainWindow::EmulationStopped, [=](){ pause_action->setEnabled(false); });
|
||||||
|
|
||||||
|
QAction* stop_action = m_tool_bar->addAction(
|
||||||
|
QIcon(dir + QStringLiteral("stop.png")), tr("Stop"),
|
||||||
|
this, SLOT(Stop()));
|
||||||
|
stop_action->setEnabled(false);
|
||||||
|
connect(this, &MainWindow::EmulationStarted, [=](){ stop_action->setEnabled(true); });
|
||||||
|
connect(this, &MainWindow::EmulationPaused, [=](){ stop_action->setEnabled(true); });
|
||||||
|
connect(this, &MainWindow::EmulationStopped, [=](){ stop_action->setEnabled(false); });
|
||||||
|
|
||||||
|
QAction* fullscreen_action = m_tool_bar->addAction(
|
||||||
|
QIcon(dir + QStringLiteral("fullscreen.png")), tr("Full Screen"),
|
||||||
|
this, SLOT(FullScreen()));
|
||||||
|
fullscreen_action->setEnabled(false);
|
||||||
|
connect(this, &MainWindow::EmulationStarted, [=](){ fullscreen_action->setEnabled(true); });
|
||||||
|
connect(this, &MainWindow::EmulationStopped, [=](){ fullscreen_action->setEnabled(false); });
|
||||||
|
|
||||||
|
QAction* screenshot_action = m_tool_bar->addAction(
|
||||||
|
QIcon(dir + QStringLiteral("screenshot.png")), tr("Screen Shot"),
|
||||||
|
this, SLOT(ScreenShot()));
|
||||||
|
screenshot_action->setEnabled(false);
|
||||||
|
connect(this, &MainWindow::EmulationStarted, [=](){ screenshot_action->setEnabled(true); });
|
||||||
|
connect(this, &MainWindow::EmulationStopped, [=](){ screenshot_action->setEnabled(false); });
|
||||||
|
|
||||||
|
m_tool_bar->addSeparator();
|
||||||
|
m_tool_bar->addAction(QIcon(dir + QStringLiteral("config.png")), tr("Settings"))->setEnabled(false);
|
||||||
|
m_tool_bar->addAction(QIcon(dir + QStringLiteral("graphics.png")), tr("Graphics"))->setEnabled(false);
|
||||||
|
m_tool_bar->addAction(QIcon(dir + QStringLiteral("classic.png")), tr("Controllers"))->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::Open()
|
||||||
|
{
|
||||||
|
QString file = QFileDialog::getOpenFileName(this,
|
||||||
|
tr("Select a File"),
|
||||||
|
QDir::currentPath(),
|
||||||
|
tr("All GC/Wii files (*.elf *.dol *.gcm *.iso *.wbfs *.ciso *.gcz *.wad);;"
|
||||||
|
"All Files (*)"));
|
||||||
|
if (!file.isEmpty())
|
||||||
|
StartGame(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::Browse()
|
||||||
|
{
|
||||||
|
QString dir = QFileDialog::getExistingDirectory(this,
|
||||||
|
tr("Select a Directory"),
|
||||||
|
QDir::currentPath());
|
||||||
|
if (!dir.isEmpty())
|
||||||
|
{
|
||||||
|
std::vector<std::string>& iso_folders = SConfig::GetInstance().m_ISOFolder;
|
||||||
|
auto found = std::find(iso_folders.begin(), iso_folders.end(), dir.toStdString());
|
||||||
|
if (found == iso_folders.end())
|
||||||
|
{
|
||||||
|
iso_folders.push_back(dir.toStdString());
|
||||||
|
SConfig::GetInstance().SaveSettings();
|
||||||
|
emit m_game_list->DirectoryAdded(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::Play()
|
||||||
|
{
|
||||||
|
// If we're in a paused game, start it up again.
|
||||||
|
// Otherwise, play the selected game, if there is one.
|
||||||
|
// Otherwise, play the last played game, if there is one.
|
||||||
|
// Otherwise, prompt for a new game.
|
||||||
|
if (Core::GetState() == Core::CORE_PAUSE)
|
||||||
|
{
|
||||||
|
Core::SetState(Core::CORE_RUN);
|
||||||
|
emit EmulationStarted();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QString selection = m_game_list->GetSelectedGame();
|
||||||
|
if (selection.length() > 0)
|
||||||
|
{
|
||||||
|
StartGame(selection);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QString path = QString::fromStdString(SConfig::GetInstance().m_LastFilename);
|
||||||
|
if (QFile::exists(path))
|
||||||
|
StartGame(path);
|
||||||
|
else
|
||||||
|
Open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::Pause()
|
||||||
|
{
|
||||||
|
Core::SetState(Core::CORE_PAUSE);
|
||||||
|
emit EmulationPaused();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWindow::Stop()
|
||||||
|
{
|
||||||
|
bool stop = true;
|
||||||
|
if (SConfig::GetInstance().bConfirmStop)
|
||||||
|
{
|
||||||
|
// We could pause the game here and resume it if they say no.
|
||||||
|
QMessageBox::StandardButton confirm;
|
||||||
|
confirm = QMessageBox::question(m_render_widget, tr("Confirm"), tr("Stop emulation?"));
|
||||||
|
stop = (confirm == QMessageBox::Yes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stop)
|
||||||
|
ForceStop();
|
||||||
|
|
||||||
|
return stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ForceStop()
|
||||||
|
{
|
||||||
|
BootManager::Stop();
|
||||||
|
HideRenderWidget();
|
||||||
|
emit EmulationStopped();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::FullScreen()
|
||||||
|
{
|
||||||
|
// If the render widget is fullscreen we want to reset it to whatever is in
|
||||||
|
// SConfig. If it's set to be fullscreen then it just remakes the window,
|
||||||
|
// which probably isn't ideal.
|
||||||
|
bool was_fullscreen = m_render_widget->isFullScreen();
|
||||||
|
HideRenderWidget();
|
||||||
|
if (was_fullscreen)
|
||||||
|
ShowRenderWidget();
|
||||||
|
else
|
||||||
|
m_render_widget->showFullScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ScreenShot()
|
||||||
|
{
|
||||||
|
Core::SaveScreenShot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::StartGame(QString path)
|
||||||
|
{
|
||||||
|
// If we're running, only start a new game once we've stopped the last.
|
||||||
|
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
||||||
|
{
|
||||||
|
if (!Stop())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Boot up, show an error if it fails to load the game.
|
||||||
|
if (!BootManager::BootCore(path.toStdString()))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ShowRenderWidget();
|
||||||
|
emit EmulationStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ShowRenderWidget()
|
||||||
|
{
|
||||||
|
if (SConfig::GetInstance().bRenderToMain)
|
||||||
|
{
|
||||||
|
// If we're rendering to main, add it to the stack and update our title when necessary.
|
||||||
|
m_rendering_to_main = true;
|
||||||
|
m_stack->setCurrentIndex(m_stack->addWidget(m_render_widget));
|
||||||
|
connect(Host::GetInstance(), &Host::RequestTitle, this, &MainWindow::setWindowTitle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise, just show it.
|
||||||
|
m_rendering_to_main = false;
|
||||||
|
if (SConfig::GetInstance().bFullscreen)
|
||||||
|
{
|
||||||
|
m_render_widget->showFullScreen();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_render_widget->setFixedSize(
|
||||||
|
SConfig::GetInstance().iRenderWindowWidth,
|
||||||
|
SConfig::GetInstance().iRenderWindowHeight);
|
||||||
|
m_render_widget->showNormal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HideRenderWidget()
|
||||||
|
{
|
||||||
|
if (m_rendering_to_main)
|
||||||
|
{
|
||||||
|
// Remove the widget from the stack and reparent it to nullptr, so that it can draw
|
||||||
|
// itself in a new window if it wants. Disconnect the title updates.
|
||||||
|
m_stack->removeWidget(m_render_widget);
|
||||||
|
m_render_widget->setParent(nullptr);
|
||||||
|
m_rendering_to_main = false;
|
||||||
|
disconnect(Host::GetInstance(), &Host::RequestTitle, this, &MainWindow::setWindowTitle);
|
||||||
|
setWindowTitle(tr("Dolphin"));
|
||||||
|
}
|
||||||
|
m_render_widget->hide();
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
#include <QString>
|
||||||
|
#include <QToolBar>
|
||||||
|
|
||||||
|
#include "DolphinQt2/RenderWidget.h"
|
||||||
|
#include "DolphinQt2/GameList/GameList.h"
|
||||||
|
|
||||||
|
class MainWindow final : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MainWindow();
|
||||||
|
~MainWindow();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void EmulationStarted();
|
||||||
|
void EmulationPaused();
|
||||||
|
void EmulationStopped();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void Open();
|
||||||
|
void Browse();
|
||||||
|
void Play();
|
||||||
|
void Pause();
|
||||||
|
bool Stop();
|
||||||
|
void ForceStop();
|
||||||
|
void FullScreen();
|
||||||
|
void ScreenShot();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void MakeToolBar();
|
||||||
|
void MakeStack();
|
||||||
|
void MakeGameList();
|
||||||
|
void MakeRenderWidget();
|
||||||
|
|
||||||
|
void MakeMenus();
|
||||||
|
void MakeFileMenu();
|
||||||
|
void MakeViewMenu();
|
||||||
|
void AddTableColumnsMenu(QMenu* view_menu);
|
||||||
|
void AddListTypePicker(QMenu* view_menu);
|
||||||
|
|
||||||
|
void PopulateToolBar();
|
||||||
|
|
||||||
|
void StartGame(QString path);
|
||||||
|
void ShowRenderWidget();
|
||||||
|
void HideRenderWidget();
|
||||||
|
|
||||||
|
QStackedWidget* m_stack;
|
||||||
|
QToolBar* m_tool_bar;
|
||||||
|
GameList* m_game_list;
|
||||||
|
RenderWidget* m_render_widget;
|
||||||
|
bool m_rendering_to_main;
|
||||||
|
};
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QKeyEvent>
|
||||||
|
|
||||||
|
#include "DolphinQt2/Host.h"
|
||||||
|
#include "DolphinQt2/RenderWidget.h"
|
||||||
|
|
||||||
|
RenderWidget::RenderWidget(QWidget* parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
setAttribute(Qt::WA_OpaquePaintEvent, true);
|
||||||
|
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||||
|
|
||||||
|
connect(Host::GetInstance(), &Host::RequestTitle, this, &RenderWidget::setWindowTitle);
|
||||||
|
connect(this, &RenderWidget::FocusChanged, Host::GetInstance(), &Host::SetRenderFocus);
|
||||||
|
connect(this, &RenderWidget::StateChanged, Host::GetInstance(), &Host::SetRenderFullscreen);
|
||||||
|
connect(this, &RenderWidget::HandleChanged, Host::GetInstance(), &Host::SetRenderHandle);
|
||||||
|
emit HandleChanged((void*) winId());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderWidget::event(QEvent* event)
|
||||||
|
{
|
||||||
|
switch (event->type())
|
||||||
|
{
|
||||||
|
case QEvent::KeyPress:
|
||||||
|
{
|
||||||
|
QKeyEvent* ke = static_cast<QKeyEvent*>(event);
|
||||||
|
if (ke->key() == Qt::Key_Escape)
|
||||||
|
emit EscapePressed();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QEvent::WinIdChange:
|
||||||
|
emit HandleChanged((void*) winId());
|
||||||
|
break;
|
||||||
|
case QEvent::FocusIn:
|
||||||
|
case QEvent::FocusOut:
|
||||||
|
emit FocusChanged(hasFocus());
|
||||||
|
break;
|
||||||
|
case QEvent::WindowStateChange:
|
||||||
|
emit StateChanged(isFullScreen());
|
||||||
|
break;
|
||||||
|
case QEvent::Close:
|
||||||
|
emit Closed();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QWidget::event(event);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class RenderWidget final : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
RenderWidget(QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
bool event(QEvent* event);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void EscapePressed();
|
||||||
|
void Closed();
|
||||||
|
void HandleChanged(void* handle);
|
||||||
|
void FocusChanged(bool focus);
|
||||||
|
void StateChanged(bool fullscreen);
|
||||||
|
};
|
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "Common/FileUtil.h"
|
||||||
|
#include "Core/ConfigManager.h"
|
||||||
|
#include "DolphinQt2/Resources.h"
|
||||||
|
|
||||||
|
QList<QPixmap> Resources::m_platforms;
|
||||||
|
QList<QPixmap> Resources::m_countries;
|
||||||
|
QList<QPixmap> Resources::m_ratings;
|
||||||
|
QList<QPixmap> Resources::m_misc;
|
||||||
|
|
||||||
|
void Resources::Init()
|
||||||
|
{
|
||||||
|
QString sys_dir = QString::fromStdString(File::GetSysDirectory() + "Resources/");
|
||||||
|
|
||||||
|
QStringList platforms{
|
||||||
|
QStringLiteral("Platform_Gamecube.png"),
|
||||||
|
QStringLiteral("Platform_Wii.png"),
|
||||||
|
QStringLiteral("Platform_Wad.png"),
|
||||||
|
QStringLiteral("Platform_Wii.png")
|
||||||
|
};
|
||||||
|
for (QString platform : platforms)
|
||||||
|
m_platforms.append(QPixmap(platform.prepend(sys_dir)));
|
||||||
|
|
||||||
|
QStringList countries{
|
||||||
|
QStringLiteral("Flag_Europe.png"),
|
||||||
|
QStringLiteral("Flag_Japan.png"),
|
||||||
|
QStringLiteral("Flag_USA.png"),
|
||||||
|
QStringLiteral("Flag_Australia.png"),
|
||||||
|
QStringLiteral("Flag_France.png"),
|
||||||
|
QStringLiteral("Flag_Germany.png"),
|
||||||
|
QStringLiteral("Flag_Italy.png"),
|
||||||
|
QStringLiteral("Flag_Korea.png"),
|
||||||
|
QStringLiteral("Flag_Netherlands.png"),
|
||||||
|
QStringLiteral("Flag_Russia.png"),
|
||||||
|
QStringLiteral("Flag_Spain.png"),
|
||||||
|
QStringLiteral("Flag_Taiwan.png"),
|
||||||
|
QStringLiteral("Flag_International.png"),
|
||||||
|
QStringLiteral("Flag_Unknown.png")
|
||||||
|
};
|
||||||
|
for (QString country : countries)
|
||||||
|
m_countries.append(QPixmap(country.prepend(sys_dir)));
|
||||||
|
|
||||||
|
QStringList ratings{
|
||||||
|
QStringLiteral("rating0.png"),
|
||||||
|
QStringLiteral("rating1.png"),
|
||||||
|
QStringLiteral("rating2.png"),
|
||||||
|
QStringLiteral("rating3.png"),
|
||||||
|
QStringLiteral("rating4.png"),
|
||||||
|
QStringLiteral("rating5.png")
|
||||||
|
};
|
||||||
|
for (QString rating : ratings)
|
||||||
|
m_ratings.append(QPixmap(rating.prepend(sys_dir)));
|
||||||
|
|
||||||
|
QString theme_dir = QString::fromStdString(File::GetThemeDir(SConfig::GetInstance().theme_name));
|
||||||
|
m_misc.append(QPixmap(QStringLiteral("nobanner.png").prepend(theme_dir)));
|
||||||
|
m_misc.append(QPixmap(QStringLiteral("dolphin_logo.png").prepend(theme_dir)));
|
||||||
|
m_misc.append(QPixmap(QStringLiteral("Dolphin.png").prepend(theme_dir)));
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap Resources::GetPlatform(int platform)
|
||||||
|
{
|
||||||
|
return m_platforms[platform];
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap Resources::GetCountry(int country)
|
||||||
|
{
|
||||||
|
return m_countries[country];
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap Resources::GetRating(int rating)
|
||||||
|
{
|
||||||
|
return m_ratings[rating];
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap Resources::GetMisc(int id)
|
||||||
|
{
|
||||||
|
return m_misc[id];
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
// Copyright 2015 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QPixmap>
|
||||||
|
|
||||||
|
// Store for various QPixmaps that will be used repeatedly.
|
||||||
|
class Resources final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Init();
|
||||||
|
|
||||||
|
static QPixmap GetPlatform(int platform);
|
||||||
|
static QPixmap GetCountry(int country);
|
||||||
|
static QPixmap GetRating(int rating);
|
||||||
|
|
||||||
|
static QPixmap GetMisc(int id);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
BANNER_MISSING,
|
||||||
|
LOGO_LARGE,
|
||||||
|
LOGO_SMALL
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Resources() {}
|
||||||
|
|
||||||
|
static QList<QPixmap> m_platforms;
|
||||||
|
static QList<QPixmap> m_countries;
|
||||||
|
static QList<QPixmap> m_ratings;
|
||||||
|
static QList<QPixmap> m_misc;
|
||||||
|
};
|
Loading…
Reference in New Issue