Remove qrvthtool for v1.1.
I haven't gotten around to finishing it yet, but I need to release v1.1 to fix stuff, and there's too many low-level changes to simply cherry-pick fixes, so let's branch off of master and remove qrvthtool for now.
@ -17,4 +17,3 @@ CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/config.version.h.in" "${CMAKE_CURREN
|
||||
# Source Code subdirectories.
|
||||
ADD_SUBDIRECTORY(librvth)
|
||||
ADD_SUBDIRECTORY(rvthtool)
|
||||
ADD_SUBDIRECTORY(qrvthtool)
|
||||
|
@ -1,135 +0,0 @@
|
||||
PROJECT(qrvthtool)
|
||||
|
||||
# Main binary directory. Needed for git_version.h
|
||||
INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}")
|
||||
|
||||
# Find Qt5.
|
||||
# FIXME: Figure out a minimum Qt5 version.
|
||||
# QtWin::fromHICON was added in Qt 5.2.
|
||||
SET(Qt5_NO_LINK_QTMAIN 1)
|
||||
FIND_PACKAGE(Qt5 5.2.0 REQUIRED COMPONENTS Core Gui Widgets)
|
||||
|
||||
# Sources.
|
||||
SET(qrvthtool_SRCS
|
||||
qrvthtool.cpp
|
||||
RvtHModel.cpp
|
||||
RvtHSortFilterProxyModel.cpp
|
||||
|
||||
widgets/BankEntryView.cpp
|
||||
widgets/QTreeViewOpt.cpp
|
||||
|
||||
windows/QRvtHToolWindow.cpp
|
||||
)
|
||||
|
||||
# Headers with Qt objects.
|
||||
SET(qrvthtool_MOC_H
|
||||
RvtHModel.hpp
|
||||
RvtHSortFilterProxyModel.hpp
|
||||
|
||||
widgets/BankEntryView.hpp
|
||||
widgets/QTreeViewOpt.hpp
|
||||
|
||||
windows/QRvtHToolWindow.hpp
|
||||
)
|
||||
QT5_WRAP_CPP(qrvthtool_MOC_SRCS ${qrvthtool_MOC_H})
|
||||
|
||||
# UI files.
|
||||
SET(qrvthtool_UIS
|
||||
widgets/BankEntryView.ui
|
||||
|
||||
windows/QRvtHToolWindow.ui
|
||||
)
|
||||
QT5_WRAP_UI(qrvthtool_UIS_H ${qrvthtool_UIS})
|
||||
|
||||
######################
|
||||
# Qt resource files. #
|
||||
######################
|
||||
|
||||
SET(qrvthtool_RCC_SRCS
|
||||
resources/hw/hw.qrc
|
||||
)
|
||||
|
||||
QT5_ADD_RESOURCES(
|
||||
qrvthtool_RCC_O ${qrvthtool_RCC_SRCS}
|
||||
OPTIONS -no-compress
|
||||
)
|
||||
|
||||
#########################
|
||||
# Build the executable. #
|
||||
#########################
|
||||
|
||||
# TODO: Set Win32 when compiling release build
|
||||
# to disable the command prompt window.
|
||||
ADD_EXECUTABLE(qrvthtool WIN32 MACOSX_BUNDLE
|
||||
${qrvthtool_SRCS}
|
||||
${qrvthtool_UIS_H}
|
||||
${qrvthtool_MOC_SRCS}
|
||||
${qrvthtool_RCC_O}
|
||||
)
|
||||
ADD_DEPENDENCIES(qrvthtool git_version)
|
||||
DO_SPLIT_DEBUG(qrvthtool)
|
||||
SET_WINDOWS_SUBSYSTEM(qrvthtool WIN32)
|
||||
SET_WINDOWS_NO_MANIFEST(qrvthtool)
|
||||
SET_WINDOWS_ENTRYPOINT(qrvthtool WinMain OFF)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(qrvthtool
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
|
||||
PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/..>
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES(qrvthtool rvth)
|
||||
|
||||
# Qt libraries
|
||||
# NOTE: Libraries have to be linked in reverse order.
|
||||
TARGET_LINK_LIBRARIES(qrvthtool Qt5::Widgets Qt5::Gui Qt5::Core)
|
||||
IF(WIN32)
|
||||
TARGET_LINK_LIBRARIES(qrvthtool Qt5::WinMain)
|
||||
ENDIF(WIN32)
|
||||
|
||||
# Define -DQT_NO_DEBUG in release builds.
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-DQT_NO_DEBUG ${CMAKE_C_FLAGS_RELEASE}")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-DQT_NO_DEBUG ${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
|
||||
# Qt options:
|
||||
# - Fast QString concatenation. (Qt 4.6+, plus 4.8-specific version)
|
||||
# - Disable implicit QString ASCII casts.
|
||||
ADD_DEFINITIONS(-DQT_USE_FAST_CONCATENATION
|
||||
-DQT_USE_FAST_OPERATOR_PLUS
|
||||
-DQT_USE_QSTRINGBUILDER
|
||||
-DQT_NO_CAST_FROM_ASCII
|
||||
-DQT_NO_CAST_TO_ASCII
|
||||
-DQT_STRICT_ITERATORS
|
||||
-DQT_NO_URL_CAST_FROM_STRING
|
||||
)
|
||||
|
||||
# Win32: image version.
|
||||
INCLUDE(Win32ImageVersionLinkerFlags)
|
||||
WIN32_IMAGE_VERSION_LINKER_FLAGS(${VERSION_MAJOR} ${VERSION_MINOR})
|
||||
|
||||
#################
|
||||
# Installation. #
|
||||
#################
|
||||
|
||||
INCLUDE(DirInstallPaths)
|
||||
|
||||
INSTALL(TARGETS qrvthtool
|
||||
RUNTIME DESTINATION "${DIR_INSTALL_EXE}"
|
||||
LIBRARY DESTINATION "${DIR_INSTALL_DLL}"
|
||||
ARCHIVE DESTINATION "${DIR_INSTALL_LIB}"
|
||||
COMPONENT "program"
|
||||
)
|
||||
IF(INSTALL_DEBUG)
|
||||
IF(MSVC)
|
||||
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/qrvthtool.pdb"
|
||||
DESTINATION "${DIR_INSTALL_EXE_DEBUG}"
|
||||
COMPONENT "debug"
|
||||
)
|
||||
ELSEIF(SPLIT_DEBUG)
|
||||
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/qrvthtool.debug"
|
||||
DESTINATION "${DIR_INSTALL_EXE_DEBUG}"
|
||||
COMPONENT "debug"
|
||||
)
|
||||
ENDIF()
|
||||
ENDIF(INSTALL_DEBUG)
|
@ -1,606 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (librvth) *
|
||||
* RvtHModel.hpp: QAbstractListModel for RvtH objects. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "RvtHModel.hpp"
|
||||
|
||||
#include "librvth/rvth.h"
|
||||
|
||||
// C includes. (C++ namespace)
|
||||
#include <cassert>
|
||||
|
||||
// Qt includes.
|
||||
#include <QApplication>
|
||||
#include <QtGui/QBrush>
|
||||
#include <QtGui/QFont>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtGui/QPalette>
|
||||
|
||||
/** RvtHModelPrivate **/
|
||||
|
||||
class RvtHModelPrivate
|
||||
{
|
||||
public:
|
||||
explicit RvtHModelPrivate(RvtHModel *q);
|
||||
|
||||
protected:
|
||||
RvtHModel *const q_ptr;
|
||||
Q_DECLARE_PUBLIC(RvtHModel)
|
||||
private:
|
||||
Q_DISABLE_COPY(RvtHModelPrivate)
|
||||
|
||||
public:
|
||||
RvtH *rvth;
|
||||
|
||||
// Style variables.
|
||||
struct style_t {
|
||||
/**
|
||||
* Initialize the style variables.
|
||||
*/
|
||||
void init(void);
|
||||
|
||||
// Background colors for "deleted" banks.
|
||||
QBrush brush_lostFile;
|
||||
QBrush brush_lostFile_alt;
|
||||
|
||||
// Monosapced font.
|
||||
QFont fntMonospace;
|
||||
|
||||
// Icon IDs.
|
||||
enum IconID {
|
||||
ICON_GCN, // GameCube (retail)
|
||||
ICON_NR, // NR Reader (debug)
|
||||
|
||||
ICON_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* Load an icon.
|
||||
* @param id Icon ID.
|
||||
* @return Icon.
|
||||
*/
|
||||
QIcon getIcon(IconID id) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Load an icon from the Qt resources.
|
||||
* @param dir Base directory.
|
||||
* @param name Icon name.
|
||||
*/
|
||||
static QIcon loadIcon(const QString &dir, const QString &name);
|
||||
|
||||
// Icons for COL_TYPE.
|
||||
mutable QIcon m_icons[ICON_MAX];
|
||||
};
|
||||
style_t style;
|
||||
|
||||
/**
|
||||
* Get the icon for the specified bank.
|
||||
* @param bank Bank number.
|
||||
* @return QIcon.
|
||||
*/
|
||||
QIcon iconForBank(unsigned int bank) const;
|
||||
};
|
||||
|
||||
RvtHModelPrivate::RvtHModelPrivate(RvtHModel *q)
|
||||
: q_ptr(q)
|
||||
, rvth(nullptr)
|
||||
{
|
||||
// Initialize the style variables.
|
||||
style.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the style variables.
|
||||
*/
|
||||
void RvtHModelPrivate::style_t::init(void)
|
||||
{
|
||||
// TODO: Call this function if the UI style changes.
|
||||
|
||||
// Initialize the background colors for "lost" files.
|
||||
QPalette pal = QApplication::palette("QTreeView");
|
||||
QColor bgColor_lostFile = pal.base().color();
|
||||
QColor bgColor_lostFile_alt = pal.alternateBase().color();
|
||||
|
||||
// Adjust the colors to have a yellow hue.
|
||||
int h, s, v;
|
||||
|
||||
// "Lost" file. (Main)
|
||||
bgColor_lostFile.getHsv(&h, &s, &v, nullptr);
|
||||
h = 60;
|
||||
s = (255 - s);
|
||||
bgColor_lostFile.setHsv(h, s, v);
|
||||
|
||||
// "Lost" file. (Alternate)
|
||||
bgColor_lostFile_alt.getHsv(&h, &s, &v, nullptr);
|
||||
h = 60;
|
||||
s = (255 - s);
|
||||
bgColor_lostFile_alt.setHsv(h, s, v);
|
||||
|
||||
// Save the background colors in QBrush objects.
|
||||
brush_lostFile = QBrush(bgColor_lostFile);
|
||||
brush_lostFile_alt = QBrush(bgColor_lostFile_alt);
|
||||
|
||||
// Monospaced font.
|
||||
fntMonospace = QFont(QLatin1String("Monospace"));
|
||||
fntMonospace.setStyleHint(QFont::TypeWriter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an icon.
|
||||
* @param id Icon ID.
|
||||
* @return Icon.
|
||||
*/
|
||||
QIcon RvtHModelPrivate::style_t::getIcon(IconID id) const
|
||||
{
|
||||
assert(id >= 0);
|
||||
assert(id < ICON_MAX);
|
||||
if (id < 0 || id >= ICON_MAX) {
|
||||
return QIcon();
|
||||
}
|
||||
|
||||
if (m_icons[id].isNull()) {
|
||||
static const char *const names[] = {
|
||||
"gcn", "nr"
|
||||
};
|
||||
static_assert(ARRAY_SIZE(names) == ICON_MAX, "names[] needs to be updated!");
|
||||
m_icons[id] = loadIcon(QLatin1String("hw"), QLatin1String(names[id]));
|
||||
assert(!m_icons[id].isNull());
|
||||
}
|
||||
|
||||
return m_icons[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an icon from the Qt resources.
|
||||
* @param dir Base directory.
|
||||
* @param name Icon name.
|
||||
*/
|
||||
QIcon RvtHModelPrivate::style_t::loadIcon(const QString &dir, const QString &name)
|
||||
{
|
||||
// Icon sizes.
|
||||
static const unsigned int icoSz[] = {32, 48, 64, 128, 0};
|
||||
|
||||
QIcon icon;
|
||||
for (const unsigned int *p = icoSz; *p != 0; p++) {
|
||||
const QString s_sz = QString::number(*p);
|
||||
QString full_path = QLatin1String(":/") +
|
||||
dir + QChar(L'/') +
|
||||
s_sz + QChar(L'x') + s_sz + QChar(L'/') +
|
||||
name + QLatin1String(".png");;
|
||||
QPixmap pxm(full_path);
|
||||
if (!pxm.isNull()) {
|
||||
icon.addPixmap(pxm);
|
||||
}
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon for the specified bank.
|
||||
* @param bank Bank number.
|
||||
* @return QIcon.
|
||||
*/
|
||||
QIcon RvtHModelPrivate::iconForBank(unsigned int bank) const
|
||||
{
|
||||
if (!rvth) {
|
||||
// No RVT-H Reader image.
|
||||
return QIcon();
|
||||
}
|
||||
|
||||
const RvtH_BankEntry *entry = rvth_get_BankEntry(rvth, bank, nullptr);
|
||||
assert(entry != nullptr);
|
||||
if (!entry) {
|
||||
// No bank entry here...
|
||||
return QIcon();
|
||||
}
|
||||
const RvtH_ImageType_e imageType = rvth_get_ImageType(rvth);
|
||||
|
||||
switch (entry->type) {
|
||||
case RVTH_BankType_Empty:
|
||||
case RVTH_BankType_Unknown:
|
||||
case RVTH_BankType_Wii_DL_Bank2:
|
||||
default:
|
||||
// No icon for these banks.
|
||||
return QIcon();
|
||||
|
||||
case RVTH_BankType_GCN:
|
||||
// GameCube.
|
||||
if (imageType == RVTH_ImageType_GCM) {
|
||||
// Standalone GCM. Use the retail icon.
|
||||
return style.getIcon(style_t::ICON_GCN);
|
||||
} else {
|
||||
// GCM with SDK header, or RVT-H Reader.
|
||||
// Use the NR Reader icon.
|
||||
return style.getIcon(style_t::ICON_NR);
|
||||
}
|
||||
break;
|
||||
|
||||
case RVTH_BankType_Wii_SL:
|
||||
case RVTH_BankType_Wii_DL:
|
||||
// TODO: Wii icons.
|
||||
// Using NR Reader icon for now.
|
||||
if (imageType == RVTH_ImageType_GCM) {
|
||||
// Standalone GCM. Use the retail icon.
|
||||
return style.getIcon(style_t::ICON_GCN);
|
||||
} else {
|
||||
// GCM with SDK header, or RVT-H Reader.
|
||||
// Use the NR Reader icon.
|
||||
return style.getIcon(style_t::ICON_NR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
assert(!"Should not get here!");
|
||||
return QIcon();
|
||||
}
|
||||
|
||||
/** RvtHModel **/
|
||||
|
||||
RvtHModel::RvtHModel(QObject *parent)
|
||||
: super(parent)
|
||||
, d_ptr(new RvtHModelPrivate(this))
|
||||
{
|
||||
// TODO: Not implemented yet...
|
||||
#if 0
|
||||
// Connect the "themeChanged" signal.
|
||||
connect(qApp, SIGNAL(themeChanged()),
|
||||
this, SLOT(themeChanged_slot()));
|
||||
#endif
|
||||
}
|
||||
|
||||
RvtHModel::~RvtHModel()
|
||||
{
|
||||
Q_D(RvtHModel);
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
int RvtHModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
Q_D(const RvtHModel);
|
||||
if (d->rvth) {
|
||||
return rvth_get_BankCount(d->rvth);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RvtHModel::columnCount(const QModelIndex& parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
Q_D(const RvtHModel);
|
||||
if (d->rvth) {
|
||||
return COL_MAX;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QVariant RvtHModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
Q_D(const RvtHModel);
|
||||
if (!d->rvth || !index.isValid())
|
||||
return QVariant();
|
||||
if (index.row() >= rowCount())
|
||||
return QVariant();
|
||||
|
||||
// Get the bank entry.
|
||||
const unsigned int bank = static_cast<unsigned int>(index.row());
|
||||
const RvtH_BankEntry *const entry = rvth_get_BankEntry(d->rvth, bank, nullptr);
|
||||
if (!entry) {
|
||||
// No entry...
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
// HACK: Increase icon width on Windows.
|
||||
// Figure out a better method later.
|
||||
#ifdef Q_OS_WIN
|
||||
static const int iconWadj = 8;
|
||||
#else
|
||||
static const int iconWadj = 0;
|
||||
#endif
|
||||
|
||||
switch (entry->type) {
|
||||
case RVTH_BankType_Empty:
|
||||
// Empty slot.
|
||||
switch (index.column()) {
|
||||
case COL_BANKNUM:
|
||||
// Bank number.
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return QString::number(bank + 1);
|
||||
case Qt::TextAlignmentRole:
|
||||
// Center-align the text.
|
||||
return Qt::AlignCenter;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case COL_TYPE:
|
||||
if (role == Qt::SizeHintRole) {
|
||||
// Using 32x32 icons.
|
||||
// (Hi-DPI is handled by Qt automatically.)
|
||||
QSize size(32 + iconWadj, 32);
|
||||
if (entry->type == RVTH_BankType_Wii_DL) {
|
||||
// Double-size the row.
|
||||
size.setHeight(size.height() * 2);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// All other columns are empty.
|
||||
return QVariant();
|
||||
case RVTH_BankType_Wii_DL_Bank2:
|
||||
// TODO: Make the previous bank double-tall.
|
||||
return QVariant();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Move some of this to RvtHItemDelegate?
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
// TODO: Cache these?
|
||||
switch (index.column()) {
|
||||
case COL_BANKNUM: {
|
||||
QString banknum = QString::number(bank + 1);
|
||||
if (entry->type == RVTH_BankType_Wii_DL) {
|
||||
// Print both bank numbers.
|
||||
banknum += QChar(L'\n') + QString::number(bank + 2);
|
||||
}
|
||||
return banknum;
|
||||
}
|
||||
case COL_TITLE:
|
||||
// TODO: Convert from Japanese if necessary.
|
||||
// Also cp1252.
|
||||
return QString::fromLatin1(entry->discHeader.game_title, sizeof(entry->discHeader.game_title)).trimmed();
|
||||
case COL_GAMEID:
|
||||
return QLatin1String(entry->discHeader.id6, sizeof(entry->discHeader.id6));
|
||||
case COL_DISCNUM:
|
||||
return QString::number(entry->discHeader.disc_number);
|
||||
case COL_REVISION:
|
||||
// TODO: BCD?
|
||||
return QString::number(entry->discHeader.revision);
|
||||
case COL_REGION:
|
||||
// TODO: Icon?
|
||||
switch (entry->region_code) {
|
||||
default:
|
||||
return QString::number(entry->region_code);
|
||||
case GCN_REGION_JAPAN:
|
||||
return QLatin1String("JPN");
|
||||
case GCN_REGION_USA:
|
||||
return QLatin1String("USA");
|
||||
case GCN_REGION_PAL:
|
||||
return QLatin1String("EUR");
|
||||
case GCN_REGION_FREE:
|
||||
return QLatin1String("ALL");
|
||||
case GCN_REGION_SOUTH_KOREA:
|
||||
return QLatin1String("KOR");
|
||||
}
|
||||
break;
|
||||
|
||||
case COL_IOS_VERSION:
|
||||
// Wii only.
|
||||
if (entry->type == RVTH_BankType_Wii_SL ||
|
||||
entry->type == RVTH_BankType_Wii_DL)
|
||||
{
|
||||
return QString::number(entry->ios_version);
|
||||
}
|
||||
break;
|
||||
|
||||
case COL_ENCRYPTION:
|
||||
switch (entry->crypto_type) {
|
||||
case RVTH_CryptoType_Unknown:
|
||||
default:
|
||||
return QString::number(entry->crypto_type);
|
||||
case RVTH_CryptoType_None:
|
||||
return tr("None");
|
||||
case RVTH_CryptoType_Debug:
|
||||
return tr("Debug");
|
||||
case RVTH_CryptoType_Retail:
|
||||
return tr("Retail");
|
||||
case RVTH_CryptoType_Korean:
|
||||
return tr("Korean");
|
||||
}
|
||||
break;
|
||||
|
||||
case COL_SIG_TICKET:
|
||||
case COL_SIG_TMD:
|
||||
case COL_APPLOADER:
|
||||
// TODO
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::DecorationRole:
|
||||
if (index.column() == COL_TYPE) {
|
||||
// Get the icon for this bank.
|
||||
return d->iconForBank(bank);
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
switch (index.column()) {
|
||||
case COL_TITLE:
|
||||
// Left-align, center vertically.
|
||||
return (int)(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
|
||||
case COL_TYPE:
|
||||
case COL_BANKNUM:
|
||||
case COL_GAMEID:
|
||||
case COL_DISCNUM:
|
||||
case COL_REVISION:
|
||||
case COL_REGION:
|
||||
case COL_IOS_VERSION:
|
||||
case COL_ENCRYPTION:
|
||||
case COL_SIG_TICKET:
|
||||
case COL_SIG_TMD:
|
||||
case COL_APPLOADER:
|
||||
default:
|
||||
// Center-align the text.
|
||||
return Qt::AlignCenter;
|
||||
}
|
||||
|
||||
case Qt::FontRole:
|
||||
switch (index.column()) {
|
||||
case COL_GAMEID: {
|
||||
// These columns should be monospaced.
|
||||
return d->style.fntMonospace;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::BackgroundRole:
|
||||
// "Deleted" banks should be displayed using a different color.
|
||||
if (entry->is_deleted) {
|
||||
// TODO: Check if the item view is using alternating row colors before using them.
|
||||
if (bank & 1)
|
||||
return d->style.brush_lostFile_alt;
|
||||
else
|
||||
return d->style.brush_lostFile;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::SizeHintRole: {
|
||||
if (index.column() == COL_TYPE) {
|
||||
// Using 32x32 icons.
|
||||
// (Hi-DPI is handled by Qt automatically.)
|
||||
QSize size(32 + iconWadj, 32);
|
||||
if (entry->type == RVTH_BankType_Wii_DL) {
|
||||
// Double-size the row.
|
||||
size.setHeight(size.height() * 2);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DualLayerRole:
|
||||
return (entry->type == RVTH_BankType_Wii_DL);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Default value.
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant RvtHModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
Q_UNUSED(orientation);
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
switch (section) {
|
||||
case COL_BANKNUM: return tr("#");
|
||||
case COL_TYPE: return tr("Type");
|
||||
case COL_TITLE: return tr("Title");
|
||||
//: 6-digit game ID, e.g. GALE01.
|
||||
case COL_GAMEID: return tr("Game ID");
|
||||
case COL_DISCNUM: return tr("Disc #");
|
||||
case COL_REVISION: return tr("Revision");
|
||||
case COL_REGION: return tr("Region");
|
||||
case COL_IOS_VERSION: return tr("IOS");
|
||||
case COL_ENCRYPTION: return tr("Encryption");
|
||||
case COL_SIG_TICKET: return tr("Ticket Sig");
|
||||
case COL_SIG_TMD: return tr("TMD Sig");
|
||||
case COL_APPLOADER: return tr("AppLoader");
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
// Center-align the text.
|
||||
return Qt::AlignHCenter;
|
||||
}
|
||||
|
||||
// Default value.
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the RVT-H Reader disk image to use in this model.
|
||||
* @param card RVT-H Reader disk image.
|
||||
*/
|
||||
void RvtHModel::setRvtH(RvtH *rvth)
|
||||
{
|
||||
Q_D(RvtHModel);
|
||||
|
||||
// NOTE: No signals, since librvth is a C library.
|
||||
|
||||
// Disconnect the Card's changed() signal if a Card is already set.
|
||||
if (d->rvth) {
|
||||
// Notify the view that we're about to remove all rows.
|
||||
const int bankCount = rvth_get_BankCount(d->rvth);
|
||||
if (bankCount > 0) {
|
||||
beginRemoveRows(QModelIndex(), 0, (bankCount - 1));
|
||||
}
|
||||
|
||||
d->rvth = nullptr;
|
||||
|
||||
// Done removing rows.
|
||||
if (bankCount > 0) {
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
if (rvth) {
|
||||
// Notify the view that we're about to add rows.
|
||||
const int bankCount = rvth_get_BankCount(rvth);
|
||||
if (bankCount > 0) {
|
||||
beginInsertRows(QModelIndex(), 0, (bankCount - 1));
|
||||
}
|
||||
|
||||
d->rvth = rvth;
|
||||
|
||||
// Done adding rows.
|
||||
if (bankCount > 0) {
|
||||
endInsertRows();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Slots. **/
|
||||
|
||||
/**
|
||||
* The system theme has changed.
|
||||
*/
|
||||
void RvtHModel::themeChanged_slot(void)
|
||||
{
|
||||
// Reinitialize the style.
|
||||
Q_D(RvtHModel);
|
||||
d->style.init();
|
||||
|
||||
// TODO: Force an update?
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (librvth) *
|
||||
* RvtHModel.hpp: QAbstractListModel for RvtH objects. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __RVTHTOOL_QRVTHTOOL_RVTHMODEL_HPP__
|
||||
#define __RVTHTOOL_QRVTHTOOL_RVTHMODEL_HPP__
|
||||
|
||||
struct _RvtH;
|
||||
|
||||
// Qt includes.
|
||||
#include <QtCore/QAbstractListModel>
|
||||
|
||||
class RvtHModelPrivate;
|
||||
class RvtHModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
typedef QAbstractListModel super;
|
||||
|
||||
public:
|
||||
explicit RvtHModel(QObject *parent = 0);
|
||||
virtual ~RvtHModel();
|
||||
|
||||
protected:
|
||||
RvtHModelPrivate *const d_ptr;
|
||||
Q_DECLARE_PRIVATE(RvtHModel)
|
||||
private:
|
||||
Q_DISABLE_COPY(RvtHModel)
|
||||
|
||||
public:
|
||||
enum Column {
|
||||
COL_BANKNUM, // Bank #
|
||||
COL_TYPE, // Type (HW)
|
||||
COL_TITLE, // Title
|
||||
COL_GAMEID, // Game ID
|
||||
COL_DISCNUM, // Disc #
|
||||
COL_REVISION, // Revision
|
||||
COL_REGION, // Region
|
||||
COL_IOS_VERSION, // IOS version (Wii only)
|
||||
COL_ENCRYPTION, // Encryption type
|
||||
COL_SIG_TICKET, // Ticket signature
|
||||
COL_SIG_TMD, // TMD signature
|
||||
COL_APPLOADER, // AppLoader error
|
||||
|
||||
COL_MAX
|
||||
};
|
||||
|
||||
// Dual-layer role.
|
||||
// If true, this is a Wii DL image and should be
|
||||
// represented as taking up two banks.
|
||||
static const int DualLayerRole = Qt::UserRole;
|
||||
|
||||
// Qt Model/View interface.
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const final;
|
||||
int columnCount(const QModelIndex& parent = QModelIndex()) const final;
|
||||
|
||||
QVariant data(const QModelIndex& index, int role) const final;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const final;
|
||||
|
||||
/**
|
||||
* Set the RVT-H Reader disk image to use in this model.
|
||||
* @param rvth RVT-H Reader disk image.
|
||||
*/
|
||||
void setRvtH(struct _RvtH *rvth);
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* The system theme has changed.
|
||||
*/
|
||||
void themeChanged_slot(void);
|
||||
};
|
||||
|
||||
#endif /* __RVTHTOOL_QRVTHTOOL_RVTHMODEL_HPP__ */
|
@ -1,62 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (qrvthtool) *
|
||||
* RvtHSortFilterProxyModel.hpp: RvtHModel sort filter proxy. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "RvtHSortFilterProxyModel.hpp"
|
||||
|
||||
RvtHSortFilterProxyModel::RvtHSortFilterProxyModel(QObject *parent)
|
||||
: super(parent)
|
||||
{ }
|
||||
|
||||
bool RvtHSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
// If the bank number column is empty, don't show this row.
|
||||
QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
|
||||
if (!index.data().isValid()) {
|
||||
// Don't show this row.
|
||||
return false;
|
||||
}
|
||||
|
||||
return super::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
|
||||
bool RvtHSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
if (!left.isValid() || !right.isValid()) {
|
||||
// One or both indexes are invalid.
|
||||
// Use the default lessThan().
|
||||
return super::lessThan(left, right);
|
||||
}
|
||||
|
||||
const QVariant vLeft = left.data();
|
||||
const QVariant vRight = right.data();
|
||||
|
||||
if (vLeft.type() == QVariant::String &&
|
||||
vRight.type() == QVariant::String)
|
||||
{
|
||||
// String. Do a case-insensitive comparison.
|
||||
QString sLeft = vLeft.toString();
|
||||
QString sRight = vRight.toString();
|
||||
return (sLeft.compare(sRight, Qt::CaseInsensitive) < 0);
|
||||
}
|
||||
|
||||
// Unhandled type.
|
||||
// Use the default lessThan().
|
||||
return super::lessThan(left, right);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (qrvthtool) *
|
||||
* RvtHSortFilterProxyModel.hpp: RvtHModel sort filter proxy. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __RVTHTOOL_QRVTHTOOL_RVTHSORTFILTERPROXYMODEL_HPP__
|
||||
#define __RVTHTOOL_QRVTHTOOL_RVTHSORTFILTERPROXYMODEL_HPP__
|
||||
|
||||
#include <QtCore/QSortFilterProxyModel>
|
||||
|
||||
class RvtHSortFilterProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
typedef QSortFilterProxyModel super;
|
||||
|
||||
public:
|
||||
explicit RvtHSortFilterProxyModel(QObject *parent = 0);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(RvtHSortFilterProxyModel)
|
||||
|
||||
public:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const final;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const final;
|
||||
};
|
||||
|
||||
#endif /* __RVTHTOOL_QRVTHTOOL_RVTHSORTFILTERPROXYMODEL_HPP__ */
|
@ -1,62 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (librvth) *
|
||||
* qrvthtool.cpp: Main program. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "windows/QRvtHToolWindow.hpp"
|
||||
|
||||
// Qt includes.
|
||||
#include <QApplication>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
/**
|
||||
* Main entry point.
|
||||
* @param argc Number of arguments.
|
||||
* @param argv Array of arguments.
|
||||
* @return Return value.
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Enable High DPI.
|
||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true);
|
||||
#if QT_VERSION >= 0x050600
|
||||
// Enable High DPI pixmaps.
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
|
||||
#else
|
||||
// Hardcode the value in case the user upgrades to Qt 5.6 later.
|
||||
// http://doc.qt.io/qt-5/qt.html#ApplicationAttribute-enum
|
||||
QApplication::setAttribute((Qt::ApplicationAttribute)13, true);
|
||||
#endif /* QT_VERSION >= 0x050600 */
|
||||
|
||||
QApplication *app = new QApplication(argc, argv);
|
||||
|
||||
// Initialize the QRvtHToolWindow.
|
||||
QRvtHToolWindow *window = new QRvtHToolWindow();
|
||||
|
||||
// If a filename was specified, open it.
|
||||
QStringList args = app->arguments();
|
||||
if (args.size() >= 2) {
|
||||
window->openRvtH(QDir::fromNativeSeparators(args.at(1)));
|
||||
}
|
||||
|
||||
// Show the window.
|
||||
window->show();
|
||||
|
||||
// Run the Qt UI.
|
||||
return app->exec();
|
||||
}
|
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 5.2 KiB |
@ -1,13 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="hw">
|
||||
<file>32x32/gcn.png</file>
|
||||
<file>48x48/gcn.png</file>
|
||||
<file>64x64/gcn.png</file>
|
||||
<file>128x128/gcn.png</file>
|
||||
|
||||
<file>32x32/nr.png</file>
|
||||
<file>48x48/nr.png</file>
|
||||
<file>64x64/nr.png</file>
|
||||
<file>128x128/nr.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
@ -1,555 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (qrvthtool) *
|
||||
* BankEntryView.cpp: Bank Entry view widget. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "BankEntryView.hpp"
|
||||
|
||||
#include "librvth/rvth.h"
|
||||
|
||||
// C includes. (C++ namespace)
|
||||
#include <cassert>
|
||||
|
||||
// Qt includes.
|
||||
#include <QtCore/QLocale>
|
||||
|
||||
/** BankEntryViewPrivate **/
|
||||
|
||||
#include "ui_BankEntryView.h"
|
||||
class BankEntryViewPrivate
|
||||
{
|
||||
public:
|
||||
explicit BankEntryViewPrivate(BankEntryView *q);
|
||||
|
||||
protected:
|
||||
BankEntryView *const q_ptr;
|
||||
Q_DECLARE_PUBLIC(BankEntryView)
|
||||
private:
|
||||
Q_DISABLE_COPY(BankEntryViewPrivate)
|
||||
|
||||
public:
|
||||
// UI
|
||||
Ui::BankEntryView ui;
|
||||
|
||||
const RvtH_BankEntry *bankEntry;
|
||||
|
||||
static inline int calc_frac_part(quint64 size, quint64 mask);
|
||||
|
||||
/**
|
||||
* Format a file size.
|
||||
* TODO: Move to a common file so other files can use this?
|
||||
* @param size File size.
|
||||
* @return Formatted file size.
|
||||
*/
|
||||
static QString formatFileSize(quint64 size);
|
||||
|
||||
/**
|
||||
* Get a string for ticket/TMD status.
|
||||
* @param sig_type Signature type.
|
||||
* @param sig_status Signature status.
|
||||
* @return String for ticket/TMD status.
|
||||
*/
|
||||
static QString sigStatusString(RvtH_SigType_e sig_type, RvtH_SigStatus_e sig_status);
|
||||
|
||||
/**
|
||||
* Update the widget display.
|
||||
*/
|
||||
void updateWidgetDisplay(void);
|
||||
};
|
||||
|
||||
BankEntryViewPrivate::BankEntryViewPrivate(BankEntryView *q)
|
||||
: q_ptr(q)
|
||||
, bankEntry(nullptr)
|
||||
{ }
|
||||
|
||||
inline int BankEntryViewPrivate::calc_frac_part(quint64 size, quint64 mask)
|
||||
{
|
||||
float f = static_cast<float>(size & (mask - 1)) / static_cast<float>(mask);
|
||||
unsigned int frac_part = static_cast<unsigned int>(f * 1000.0f);
|
||||
|
||||
// MSVC added round() and roundf() in MSVC 2013.
|
||||
// Use our own rounding code instead.
|
||||
unsigned int round_adj = (frac_part % 10 > 5);
|
||||
frac_part /= 10;
|
||||
frac_part += round_adj;
|
||||
return frac_part;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a file size.
|
||||
* TODO: Move to a common file so other files can use this?
|
||||
* @param size File size.
|
||||
* @return Formatted file size.
|
||||
*/
|
||||
QString BankEntryViewPrivate::formatFileSize(quint64 size)
|
||||
{
|
||||
// System locale.
|
||||
QLocale locale = QLocale::system();
|
||||
|
||||
// Localized suffix.
|
||||
QString suffix;
|
||||
// frac_part is always 0 to 100.
|
||||
// If whole_part >= 10, frac_part is divided by 10.
|
||||
unsigned int whole_part, frac_part;
|
||||
|
||||
// TODO: Optimize this?
|
||||
if (size < (2ULL << 10)) {
|
||||
// tr: Bytes (< 1,024)
|
||||
suffix = BankEntryView::tr("byte(s)", "", (int)size);
|
||||
whole_part = static_cast<unsigned int>(size);
|
||||
frac_part = 0;
|
||||
} else if (size < (2ULL << 20)) {
|
||||
// tr: Kilobytes
|
||||
suffix = BankEntryView::tr("KiB");
|
||||
whole_part = static_cast<unsigned int>(size >> 10);
|
||||
frac_part = calc_frac_part(size, (1ULL << 10));
|
||||
} else if (size < (2ULL << 30)) {
|
||||
// tr: Megabytes
|
||||
suffix = BankEntryView::tr("MiB");
|
||||
whole_part = static_cast<unsigned int>(size >> 20);
|
||||
frac_part = calc_frac_part(size, (1ULL << 20));
|
||||
} else if (size < (2ULL << 40)) {
|
||||
// tr: Gigabytes
|
||||
suffix = BankEntryView::tr("GiB");
|
||||
whole_part = static_cast<unsigned int>(size >> 30);
|
||||
frac_part = calc_frac_part(size, (1ULL << 30));
|
||||
} else if (size < (2ULL << 50)) {
|
||||
// tr: Terabytes
|
||||
suffix = BankEntryView::tr("TiB");
|
||||
whole_part = static_cast<unsigned int>(size >> 40);
|
||||
frac_part = calc_frac_part(size, (1ULL << 40));
|
||||
} else if (size < (2ULL << 60)) {
|
||||
// tr: Petabytes
|
||||
suffix = BankEntryView::tr("PiB");
|
||||
whole_part = static_cast<unsigned int>(size >> 50);
|
||||
frac_part = calc_frac_part(size, (1ULL << 50));
|
||||
} else /*if (size < (2ULL << 70))*/ {
|
||||
// tr: Exabytes
|
||||
suffix = BankEntryView::tr("EiB");
|
||||
whole_part = static_cast<unsigned int>(size >> 60);
|
||||
frac_part = calc_frac_part(size, (1LL << 60));
|
||||
}
|
||||
|
||||
// Localize the whole part.
|
||||
QString s_value = locale.toString(whole_part);
|
||||
|
||||
if (size >= (2LL << 10)) {
|
||||
// Fractional part.
|
||||
unsigned int frac_digits = 2;
|
||||
if (whole_part >= 10) {
|
||||
unsigned int round_adj = (frac_part % 10 > 5);
|
||||
frac_part /= 10;
|
||||
frac_part += round_adj;
|
||||
frac_digits = 1;
|
||||
}
|
||||
|
||||
// Get the localized decimal point.
|
||||
s_value += locale.decimalPoint();
|
||||
|
||||
// Append the fractional part using the required number of digits.
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%0*u", frac_digits, frac_part);
|
||||
s_value += QLatin1String(buf);
|
||||
}
|
||||
|
||||
if (!suffix.isEmpty()) {
|
||||
//: %1 == localized value, %2 == suffix (e.g. MiB)
|
||||
return BankEntryView::tr("%1 %2").arg(s_value).arg(suffix);
|
||||
} else {
|
||||
return s_value;
|
||||
}
|
||||
|
||||
// Should not get here...
|
||||
assert(!"Invalid code path.");
|
||||
return QLatin1String("QUACK");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string for ticket/TMD status.
|
||||
* @param sig_type Signature type.
|
||||
* @param sig_status Signature status.
|
||||
* @return String for ticket/TMD status.
|
||||
*/
|
||||
QString BankEntryViewPrivate::sigStatusString(
|
||||
RvtH_SigType_e sig_type, RvtH_SigStatus_e sig_status)
|
||||
{
|
||||
QString status;
|
||||
|
||||
switch (sig_type) {
|
||||
case RVTH_SigType_Unknown:
|
||||
default:
|
||||
status = QString::number(sig_type);
|
||||
break;
|
||||
case RVTH_SigType_Debug:
|
||||
status = BankEntryView::tr("Debug");
|
||||
break;
|
||||
case RVTH_SigType_Retail:
|
||||
status = BankEntryView::tr("Retail");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (sig_status) {
|
||||
case RVTH_SigStatus_Unknown:
|
||||
default:
|
||||
status += QLatin1String(" (") +
|
||||
QString::number(sig_status) +
|
||||
QChar(L')');
|
||||
break;
|
||||
case RVTH_SigStatus_OK:
|
||||
break;
|
||||
case RVTH_SigStatus_Invalid:
|
||||
status += QLatin1String(" (") +
|
||||
BankEntryView::tr("INVALID") + QChar(L')');
|
||||
break;
|
||||
case RVTH_SigStatus_Fake:
|
||||
status += QLatin1String(" (") +
|
||||
BankEntryView::tr("fakesigned") + QChar(L')');
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the widget display.
|
||||
*/
|
||||
void BankEntryViewPrivate::updateWidgetDisplay(void)
|
||||
{
|
||||
Q_Q(BankEntryView);
|
||||
|
||||
if (!bankEntry || bankEntry->type <= RVTH_BankType_Unknown ||
|
||||
bankEntry->type == RVTH_BankType_Wii_DL_Bank2 ||
|
||||
bankEntry->type >= RVTH_BankType_MAX)
|
||||
{
|
||||
// No bank entry is loaded, or the selected bank
|
||||
// cannot be displayed. Hide all widgets.
|
||||
ui.lblGameTitle->hide();
|
||||
ui.lblTypeTitle->hide();
|
||||
ui.lblType->hide();
|
||||
ui.lblSizeTitle->hide();
|
||||
ui.lblSize->hide();
|
||||
ui.lblGameIDTitle->hide();
|
||||
ui.lblGameID->hide();
|
||||
ui.lblDiscNumTitle->hide();
|
||||
ui.lblDiscNum->hide();
|
||||
ui.lblRevisionTitle->hide();
|
||||
ui.lblRevision->hide();
|
||||
ui.lblRegionTitle->hide();
|
||||
ui.lblRegion->hide();
|
||||
ui.lblIOSVersionTitle->hide();
|
||||
ui.lblIOSVersion->hide();
|
||||
ui.lblEncryptionTitle->hide();
|
||||
ui.lblEncryption->hide();
|
||||
ui.lblTicketSigTitle->hide();
|
||||
ui.lblTicketSig->hide();
|
||||
ui.lblTMDSigTitle->hide();
|
||||
ui.lblTMDSig->hide();
|
||||
ui.lblAppLoader->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the widget display.
|
||||
|
||||
// Game title.
|
||||
// TODO: Is Shift-JIS permissible in the game title?
|
||||
// TODO: cp1252
|
||||
QString s_title = QString::fromLatin1(
|
||||
bankEntry->discHeader.game_title,
|
||||
sizeof(bankEntry->discHeader.game_title)).trimmed().toHtmlEscaped();
|
||||
if (bankEntry->is_deleted) {
|
||||
// Indicate that this bank is deleted.
|
||||
s_title += QLatin1String("<br/><b>");
|
||||
s_title += BankEntryView::tr("[DELETED]");
|
||||
s_title += QLatin1String("</b>");
|
||||
}
|
||||
ui.lblGameTitle->setText(s_title);
|
||||
ui.lblGameTitle->show();
|
||||
|
||||
// Type.
|
||||
QString s_type;
|
||||
switch (bankEntry->type) {
|
||||
case RVTH_BankType_Unknown:
|
||||
default:
|
||||
s_type = BankEntryView::tr("Unknown");
|
||||
break;
|
||||
case RVTH_BankType_Empty:
|
||||
s_type = BankEntryView::tr("Empty");
|
||||
break;
|
||||
case RVTH_BankType_GCN:
|
||||
s_type = BankEntryView::tr("GameCube");
|
||||
break;
|
||||
case RVTH_BankType_Wii_SL:
|
||||
s_type = BankEntryView::tr("Wii (Single-Layer)");
|
||||
break;
|
||||
case RVTH_BankType_Wii_DL:
|
||||
s_type = BankEntryView::tr("Wii (Dual-Layer)");
|
||||
break;
|
||||
case RVTH_BankType_Wii_DL_Bank2:
|
||||
s_type = BankEntryView::tr("Wii (DL Bank 2)");
|
||||
break;
|
||||
}
|
||||
ui.lblType->setText(s_type);
|
||||
ui.lblType->show();
|
||||
ui.lblTypeTitle->show();
|
||||
|
||||
// Size.
|
||||
ui.lblSize->setText(formatFileSize(LBA_TO_BYTES(bankEntry->lba_len)));
|
||||
ui.lblSize->show();
|
||||
ui.lblSizeTitle->show();
|
||||
|
||||
// Game ID.
|
||||
ui.lblGameID->setText(QLatin1String(
|
||||
bankEntry->discHeader.id6,
|
||||
sizeof(bankEntry->discHeader.id6)));
|
||||
ui.lblGameID->show();
|
||||
ui.lblGameIDTitle->show();
|
||||
|
||||
// Disc number.
|
||||
ui.lblDiscNum->setText(QString::number(bankEntry->discHeader.disc_number));
|
||||
ui.lblDiscNum->show();
|
||||
ui.lblDiscNumTitle->show();
|
||||
|
||||
// Revision. (TODO: BCD?)
|
||||
ui.lblRevision->setText(QString::number(bankEntry->discHeader.revision));
|
||||
ui.lblRevision->show();
|
||||
ui.lblRevisionTitle->show();
|
||||
|
||||
// Region. (TODO: Icon?)
|
||||
QString s_region;
|
||||
switch (bankEntry->region_code) {
|
||||
default:
|
||||
s_region = QString::number(bankEntry->region_code);
|
||||
break;
|
||||
case GCN_REGION_JAPAN:
|
||||
s_region = QLatin1String("JPN");
|
||||
break;
|
||||
case GCN_REGION_USA:
|
||||
s_region = QLatin1String("USA");
|
||||
break;
|
||||
case GCN_REGION_PAL:
|
||||
s_region = QLatin1String("EUR");
|
||||
break;
|
||||
case GCN_REGION_FREE:
|
||||
s_region = QLatin1String("ALL");
|
||||
break;
|
||||
case GCN_REGION_SOUTH_KOREA:
|
||||
s_region = QLatin1String("KOR");
|
||||
break;
|
||||
}
|
||||
ui.lblRegion->setText(s_region);
|
||||
ui.lblRegion->show();
|
||||
ui.lblRegionTitle->show();
|
||||
|
||||
// Wii-only fields.
|
||||
if (bankEntry->type == RVTH_BankType_Wii_SL ||
|
||||
bankEntry->type == RVTH_BankType_Wii_DL)
|
||||
{
|
||||
// IOS version.
|
||||
ui.lblIOSVersion->setText(QString::number(bankEntry->ios_version));
|
||||
ui.lblIOSVersion->show();
|
||||
ui.lblIOSVersionTitle->show();
|
||||
|
||||
// Encryption.
|
||||
QString s_encryption;
|
||||
switch (bankEntry->crypto_type) {
|
||||
case RVTH_CryptoType_Unknown:
|
||||
default:
|
||||
s_encryption = QString::number(bankEntry->crypto_type);
|
||||
break;
|
||||
case RVTH_CryptoType_None:
|
||||
s_encryption = BankEntryView::tr("None");
|
||||
break;
|
||||
case RVTH_CryptoType_Debug:
|
||||
s_encryption = BankEntryView::tr("Debug");
|
||||
break;
|
||||
case RVTH_CryptoType_Retail:
|
||||
s_encryption = BankEntryView::tr("Retail");
|
||||
break;
|
||||
case RVTH_CryptoType_Korean:
|
||||
s_encryption = BankEntryView::tr("Korean");
|
||||
break;
|
||||
}
|
||||
ui.lblEncryption->setText(s_encryption);
|
||||
ui.lblEncryption->show();
|
||||
ui.lblEncryptionTitle->show();
|
||||
|
||||
// Ticket signature status.
|
||||
ui.lblTicketSig->setText(sigStatusString(
|
||||
static_cast<RvtH_SigType_e>(bankEntry->ticket.sig_type),
|
||||
static_cast<RvtH_SigStatus_e>(bankEntry->ticket.sig_status)));
|
||||
ui.lblTicketSig->show();
|
||||
ui.lblTicketSigTitle->show();
|
||||
|
||||
// TMD signature status.
|
||||
ui.lblTMDSig->setText(sigStatusString(
|
||||
static_cast<RvtH_SigType_e>(bankEntry->tmd.sig_type),
|
||||
static_cast<RvtH_SigStatus_e>(bankEntry->tmd.sig_status)));
|
||||
ui.lblTMDSig->show();
|
||||
ui.lblTMDSigTitle->show();
|
||||
} else {
|
||||
// Not Wii. Hide the fields.
|
||||
ui.lblIOSVersionTitle->hide();
|
||||
ui.lblIOSVersion->hide();
|
||||
ui.lblEncryptionTitle->hide();
|
||||
ui.lblEncryption->hide();
|
||||
ui.lblTicketSigTitle->hide();
|
||||
ui.lblTicketSig->hide();
|
||||
ui.lblTMDSigTitle->hide();
|
||||
ui.lblTMDSig->hide();
|
||||
}
|
||||
|
||||
// AppLoader status.
|
||||
// Check the AppLoader status.
|
||||
// TODO: Move strings to librvth?
|
||||
if (bankEntry->aplerr > APLERR_OK) {
|
||||
// NOTE: Not translatable. These strings are based on
|
||||
// the strings from the original AppLoader.
|
||||
// NOTE: lblAppLoader uses RichText.
|
||||
QString aplerr = QLatin1String("<b>APPLOADER ERROR >>></b><br>\n");
|
||||
switch (bankEntry->aplerr) {
|
||||
default:
|
||||
aplerr += QString::fromLatin1("Unknown (%1)")
|
||||
.arg(bankEntry->aplerr);
|
||||
break;
|
||||
|
||||
// TODO: Get values for these errors.
|
||||
case APLERR_FSTLENGTH:
|
||||
aplerr += QString::fromLatin1("FSTLength(%1) in BB2 is greater than FSTMaxLength(%2).")
|
||||
.arg(bankEntry->aplerr_val[0])
|
||||
.arg(bankEntry->aplerr_val[1]);
|
||||
break;
|
||||
case APLERR_DEBUGMONSIZE_UNALIGNED:
|
||||
aplerr += QString::fromLatin1("Debug monitor size (%1) should be a multiple of 32.")
|
||||
.arg(bankEntry->aplerr_val[0]);
|
||||
break;
|
||||
case APLERR_SIMMEMSIZE_UNALIGNED:
|
||||
aplerr += QString::fromLatin1("Simulated memory size (%1) should be a multiple of 32.")
|
||||
.arg(bankEntry->aplerr_val[0]);
|
||||
break;
|
||||
case APLERR_PHYSMEMSIZE_MINUS_SIMMEMSIZE_NOT_GT_DEBUGMONSIZE:
|
||||
aplerr += QString::fromLatin1("[Physical memory size(0x%1)] - "
|
||||
"[Console simulated memory size(0x%2)] "
|
||||
"must be greater than debug monitor size(0x%3).")
|
||||
.arg(bankEntry->aplerr_val[0], 0, 16)
|
||||
.arg(bankEntry->aplerr_val[1], 0, 16)
|
||||
.arg(bankEntry->aplerr_val[2], 0, 16);
|
||||
break;
|
||||
case APLERR_SIMMEMSIZE_NOT_LE_PHYSMEMSIZE:
|
||||
aplerr += QString::fromLatin1("Physical memory size is 0x%1 bytes."
|
||||
"Console simulated memory size (0x%2) must be smaller than "
|
||||
"or equal to the Physical memory size.")
|
||||
.arg(bankEntry->aplerr_val[0], 0, 16)
|
||||
.arg(bankEntry->aplerr_val[1], 0, 16);
|
||||
break;
|
||||
case APLERR_ILLEGAL_FST_ADDRESS:
|
||||
aplerr += QString::fromLatin1("Illegal FST destination address! (0x%1)")
|
||||
.arg(bankEntry->aplerr_val[0], 0, 16);
|
||||
break;
|
||||
case APLERR_DOL_EXCEEDS_SIZE_LIMIT:
|
||||
aplerr += QString::fromLatin1("Total size of text/data sections of the dol file are too big (%1(0x%2) bytes). "
|
||||
"Currently the limit is set as %3(0x%4) bytes.")
|
||||
.arg(bankEntry->aplerr_val[0])
|
||||
.arg(bankEntry->aplerr_val[0], 0, 16, QChar(L'0'))
|
||||
.arg(bankEntry->aplerr_val[1])
|
||||
.arg(bankEntry->aplerr_val[1], 0, 16, QChar(L'0'));
|
||||
break;
|
||||
case APLERR_DOL_ADDR_LIMIT_RETAIL_EXCEEDED:
|
||||
aplerr += QString::fromLatin1("One of the sections in the dol file exceeded its boundary. "
|
||||
"All the sections should not exceed 0x%1 (production mode).<br>\n"
|
||||
"<i>*** NOTE: This disc will still boot on devkits.</i>")
|
||||
.arg(bankEntry->aplerr_val[0], 0, 16, QChar(L'0'));
|
||||
break;
|
||||
case APLERR_DOL_ADDR_LIMIT_DEBUG_EXCEEDED:
|
||||
aplerr += QString::fromLatin1("One of the sections in the dol file exceeded its boundary. "
|
||||
"All the sections should not exceed 0x%1 (development mode).")
|
||||
.arg(bankEntry->aplerr_val[0], 0, 16, QChar(L'0'));
|
||||
break;
|
||||
case APLERR_DOL_TEXTSEG2BIG:
|
||||
aplerr += QString::fromLatin1("Too big text segment! (0x%1 - 0x%2)")
|
||||
.arg(bankEntry->aplerr_val[0], 0, 16)
|
||||
.arg(bankEntry->aplerr_val[1], 0, 16);
|
||||
break;
|
||||
case APLERR_DOL_DATASEG2BIG:
|
||||
aplerr += QString::fromLatin1("Too big data segment! (0x%1 - 0x%2)")
|
||||
.arg(bankEntry->aplerr_val[0], 0, 16)
|
||||
.arg(bankEntry->aplerr_val[1], 0, 16);
|
||||
break;
|
||||
}
|
||||
ui.lblAppLoader->setText(aplerr);
|
||||
ui.lblAppLoader->show();
|
||||
} else {
|
||||
// No AppLoader error.
|
||||
ui.lblAppLoader->hide();
|
||||
}
|
||||
}
|
||||
|
||||
/** BankEntryView **/
|
||||
|
||||
BankEntryView::BankEntryView(QWidget *parent)
|
||||
: super(parent)
|
||||
, d_ptr(new BankEntryViewPrivate(this))
|
||||
{
|
||||
Q_D(BankEntryView);
|
||||
d->ui.setupUi(this);
|
||||
d->updateWidgetDisplay();
|
||||
}
|
||||
|
||||
BankEntryView::~BankEntryView()
|
||||
{
|
||||
Q_D(BankEntryView);
|
||||
delete d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the RvtH_BankEntry being displayed.
|
||||
* @return RvtH_BankEntry.
|
||||
*/
|
||||
const RvtH_BankEntry *BankEntryView::bankEntry(void) const
|
||||
{
|
||||
Q_D(const BankEntryView);
|
||||
return d->bankEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the RvtH_BankEntry being displayed.
|
||||
* @param bankEntry RvtH_BankEntry.
|
||||
*/
|
||||
void BankEntryView::setBankEntry(const RvtH_BankEntry *bankEntry)
|
||||
{
|
||||
Q_D(BankEntryView);
|
||||
d->bankEntry = bankEntry;
|
||||
d->updateWidgetDisplay();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Widget state has changed.
|
||||
* @param event State change event.
|
||||
*/
|
||||
void BankEntryView::changeEvent(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
// Retranslate the UI.
|
||||
Q_D(BankEntryView);
|
||||
d->ui.retranslateUi(this);
|
||||
d->updateWidgetDisplay();
|
||||
}
|
||||
|
||||
// Pass the event to the base class.
|
||||
super::changeEvent(event);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (qrvthtool) *
|
||||
* BankEntryView.hpp: Bank Entry view widget. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __RVTHTOOL_QRVTHTOOL_WIDGETS_BANKENTRYVIEW_HPP__
|
||||
#define __RVTHTOOL_QRVTHTOOL_WIDGETS_BANKENTRYVIEW_HPP__
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
struct _RvtH_BankEntry;
|
||||
|
||||
class BankEntryViewPrivate;
|
||||
class BankEntryView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
typedef QWidget super;
|
||||
|
||||
Q_PROPERTY(const struct _RvtH_BankEntry* bankEntry READ bankEntry WRITE setBankEntry)
|
||||
|
||||
public:
|
||||
explicit BankEntryView(QWidget *parent = 0);
|
||||
virtual ~BankEntryView();
|
||||
|
||||
protected:
|
||||
BankEntryViewPrivate *const d_ptr;
|
||||
Q_DECLARE_PRIVATE(BankEntryView)
|
||||
private:
|
||||
Q_DISABLE_COPY(BankEntryView)
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get the RvtH_BankEntry being displayed.
|
||||
* @return RvtH_BankEntry.
|
||||
*/
|
||||
const struct _RvtH_BankEntry *bankEntry(void) const;
|
||||
|
||||
/**
|
||||
* Set the RvtH_BankEntry being displayed.
|
||||
* @param bankEntry RvtH_BankEntry.
|
||||
*/
|
||||
void setBankEntry(const struct _RvtH_BankEntry *bankEntry);
|
||||
|
||||
protected:
|
||||
// State change event. (Used for switching the UI language at runtime.)
|
||||
void changeEvent(QEvent *event);
|
||||
};
|
||||
|
||||
#endif /* __RVTHTOOL_QRVTHTOOL_WIDGETS_BANKENTRYVIEW_HPP__ */
|
@ -1,238 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BankEntryView</class>
|
||||
<widget class="QWidget" name="BankEntryView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>163</width>
|
||||
<height>304</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lblGameTitle">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lblTypeTitle">
|
||||
<property name="text">
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="lblType">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lblSizeTitle">
|
||||
<property name="text">
|
||||
<string>Size:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="lblSize">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="lblGameIDTitle">
|
||||
<property name="text">
|
||||
<string>Game ID:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="lblGameID">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="lblDiscNumTitle">
|
||||
<property name="text">
|
||||
<string>Disc #:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="lblDiscNum">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="lblRevisionTitle">
|
||||
<property name="text">
|
||||
<string>Revision:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="lblRevision">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="lblRegionTitle">
|
||||
<property name="text">
|
||||
<string>Region:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="lblRegion">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="lblIOSVersionTitle">
|
||||
<property name="text">
|
||||
<string>IOS Version:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLabel" name="lblIOSVersion">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="lblEncryptionTitle">
|
||||
<property name="text">
|
||||
<string>Encryption:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="lblEncryption">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="lblTicketSigTitle">
|
||||
<property name="text">
|
||||
<string>Ticket Sig:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QLabel" name="lblTicketSig">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="lblTMDSigTitle">
|
||||
<property name="text">
|
||||
<string>TMD Sig:</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QLabel" name="lblTMDSig">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="2">
|
||||
<widget class="QLabel" name="lblAppLoader">
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -1,131 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (qrvthtool) *
|
||||
* QTreeViewOpt.cpp: QTreeView with drawing optimizations. *
|
||||
* Specifically, don't update rows that are offscreen. *
|
||||
* *
|
||||
* Copyright (c) 2013-2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "QTreeViewOpt.hpp"
|
||||
|
||||
// Qt classes.
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
|
||||
QTreeViewOpt::QTreeViewOpt(QWidget *parent)
|
||||
: super(parent)
|
||||
{
|
||||
// Connect the signal for hiding/showing columns.
|
||||
this->header()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this->header(), &QHeaderView::customContextMenuRequested,
|
||||
this, &QTreeViewOpt::showColumnContextMenu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data has changed in the item model.
|
||||
* @param topLeft [in] Top-left item.
|
||||
* @param bottomRight [in] Bottom-right item.
|
||||
* @param roles [in] (Qt5) Roles that have changed.
|
||||
*/
|
||||
void QTreeViewOpt::dataChanged(const QModelIndex &topLeft,
|
||||
const QModelIndex &bottomRight,
|
||||
const QVector<int> &roles)
|
||||
{
|
||||
bool propagateEvent = true;
|
||||
// TODO: Support for checking multiple items.
|
||||
if (topLeft == bottomRight) {
|
||||
// Single item. This might be an icon animation.
|
||||
// If it is, make sure the icon is onscreen.
|
||||
QRect itemRect = this->visualRect(topLeft);
|
||||
|
||||
// Get the viewport rect.
|
||||
QRect viewportRect(QPoint(0, 0), this->viewport()->size());
|
||||
if (!viewportRect.intersects(itemRect)) {
|
||||
// Item is NOT visible.
|
||||
// Don't propagate the event.
|
||||
propagateEvent = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (propagateEvent) {
|
||||
// Propagate the dataChanged() event.
|
||||
super::dataChanged(topLeft, bottomRight, roles);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the column context menu.
|
||||
* Based on KSysGuard's KSysGuardProcessList::showColumnContextMenu().
|
||||
* @param point Point where context menu was requested.
|
||||
*/
|
||||
void QTreeViewOpt::showColumnContextMenu(const QPoint &point)
|
||||
{
|
||||
QMenu *menu = new QMenu();
|
||||
QAction *action;
|
||||
|
||||
int index = this->header()->logicalIndexAt(point);
|
||||
if (index >= 0) {
|
||||
// Column is selected. Add an option to hide it.
|
||||
action = new QAction(menu);
|
||||
// Set data to negative index (minus 1) to hide a column,
|
||||
// and positive index to show a column.
|
||||
action->setData(-index - 1);
|
||||
action->setText(tr("Hide Column '%1'")
|
||||
.arg(this->model()->headerData(index, Qt::Horizontal, Qt::DisplayRole).toString()));
|
||||
menu->addAction(action);
|
||||
|
||||
if (this->header()->sectionsHidden())
|
||||
menu->addSeparator();
|
||||
}
|
||||
|
||||
// Add options to show hidden columns.
|
||||
if (this->header()->sectionsHidden()) {
|
||||
int num_sections = this->model()->columnCount();
|
||||
for (int i = 0; i < num_sections; i++) {
|
||||
if (this->header()->isSectionHidden(i)) {
|
||||
action = new QAction(menu);
|
||||
action->setText(tr("Show Column '%1'")
|
||||
.arg(this->model()->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString()));
|
||||
// Set data to negative index (minus 1) to hide a column,
|
||||
// and positive index to show a column.
|
||||
action->setData(i);
|
||||
menu->addAction(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show the menu and wait for the user to select an option.
|
||||
QAction *result = menu->exec(this->header()->mapToGlobal(point));
|
||||
if (!result) {
|
||||
// Menu was cancelled.
|
||||
menu->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
// Show/hide the selected column.
|
||||
// TODO: Save column visibility settings somewhere.
|
||||
int i = result->data().toInt();
|
||||
if (i < 0) {
|
||||
this->hideColumn(-1 - i);
|
||||
} else {
|
||||
this->showColumn(i);
|
||||
this->resizeColumnToContents(i);
|
||||
this->resizeColumnToContents(this->model()->columnCount());
|
||||
}
|
||||
|
||||
menu->deleteLater();
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (qrvthtool) *
|
||||
* QTreeViewOpt.hpp: QTreeView with drawing optimizations. *
|
||||
* Specifically, don't update rows that are offscreen. *
|
||||
* *
|
||||
* Copyright (c) 2013-2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __RVTHTOOL_QRVTHTOOL_WIDGETS_QTREEVIEWOPT_HPP__
|
||||
#define __RVTHTOOL_QRVTHTOOL_WIDGETS_QTREEVIEWOPT_HPP__
|
||||
|
||||
// Qt includes and classes.
|
||||
#include <QTreeView>
|
||||
class QKeyEvent;
|
||||
class QFocusEvent;
|
||||
|
||||
class QTreeViewOpt : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
typedef QTreeView super;
|
||||
|
||||
public:
|
||||
explicit QTreeViewOpt(QWidget *parent = 0);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QTreeViewOpt);
|
||||
|
||||
public:
|
||||
void dataChanged(const QModelIndex &topLeft,
|
||||
const QModelIndex &bottomRight,
|
||||
const QVector<int> &roles = QVector<int>()) final;
|
||||
|
||||
protected slots:
|
||||
void showColumnContextMenu(const QPoint &point);
|
||||
};
|
||||
|
||||
#endif /* __RVTHTOOL_QRVTHTOOL_WIDGETS_QTREEVIEWOPT_HPP__ */
|
@ -1,459 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (qrvthtool) *
|
||||
* QRvtHToolWindow.cpp: Main window. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "QRvtHToolWindow.hpp"
|
||||
|
||||
#include "librvth/rvth.h"
|
||||
#include "RvtHModel.hpp"
|
||||
#include "RvtHSortFilterProxyModel.hpp"
|
||||
|
||||
// Qt includes.
|
||||
#include <QtWidgets/QFileDialog>
|
||||
|
||||
/** QRvtHToolWindowPrivate **/
|
||||
|
||||
#include "ui_QRvtHToolWindow.h"
|
||||
class QRvtHToolWindowPrivate
|
||||
{
|
||||
public:
|
||||
explicit QRvtHToolWindowPrivate(QRvtHToolWindow *q);
|
||||
~QRvtHToolWindowPrivate();
|
||||
|
||||
protected:
|
||||
QRvtHToolWindow *const q_ptr;
|
||||
Q_DECLARE_PUBLIC(QRvtHToolWindow)
|
||||
private:
|
||||
Q_DISABLE_COPY(QRvtHToolWindowPrivate)
|
||||
|
||||
public:
|
||||
Ui::QRvtHToolWindow ui;
|
||||
|
||||
// RVT-H Reader disk image
|
||||
RvtH *rvth;
|
||||
RvtHModel *model;
|
||||
RvtHSortFilterProxyModel *proxyModel;
|
||||
|
||||
// Filename.
|
||||
QString filename;
|
||||
QString displayFilename; // filename without subdirectories
|
||||
|
||||
// TODO: Config class like mcrecover?
|
||||
QString lastPath;
|
||||
|
||||
// Initialized columns?
|
||||
bool cols_init;
|
||||
|
||||
/**
|
||||
* Update the RVT-H Reader disk image's QTreeView.
|
||||
*/
|
||||
void updateLstBankList(void);
|
||||
|
||||
/**
|
||||
* Update the window title.
|
||||
*/
|
||||
void updateWindowTitle(void);
|
||||
};
|
||||
|
||||
QRvtHToolWindowPrivate::QRvtHToolWindowPrivate(QRvtHToolWindow *q)
|
||||
: q_ptr(q)
|
||||
, rvth(nullptr)
|
||||
, model(new RvtHModel(q))
|
||||
, proxyModel(new RvtHSortFilterProxyModel(q))
|
||||
, cols_init(false)
|
||||
{
|
||||
// Connect the RvtHModel slots.
|
||||
QObject::connect(model, &RvtHModel::layoutChanged,
|
||||
q, &QRvtHToolWindow::rvthModel_layoutChanged);
|
||||
QObject::connect(model, &RvtHModel::rowsInserted,
|
||||
q, &QRvtHToolWindow::rvthModel_rowsInserted);
|
||||
}
|
||||
|
||||
QRvtHToolWindowPrivate::~QRvtHToolWindowPrivate()
|
||||
{
|
||||
// NOTE: Delete the MemCardModel first to prevent issues later.
|
||||
delete model;
|
||||
if (rvth) {
|
||||
rvth_close(rvth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the RVT-H Reader disk image's QTreeView.
|
||||
*/
|
||||
void QRvtHToolWindowPrivate::updateLstBankList(void)
|
||||
{
|
||||
if (!rvth) {
|
||||
// Set the group box's title.
|
||||
ui.grpBankList->setTitle(QRvtHToolWindow::tr("No RVT-H Reader disk image loaded."));
|
||||
} else {
|
||||
// Show the filename.
|
||||
ui.grpBankList->setTitle(displayFilename);
|
||||
}
|
||||
|
||||
// Show the QTreeView headers if an RVT-H Reader disk image is loaded.
|
||||
ui.lstBankList->setHeaderHidden(!rvth);
|
||||
|
||||
// Resize the columns to fit the contents.
|
||||
int num_sections = model->columnCount();
|
||||
for (int i = 0; i < num_sections; i++)
|
||||
ui.lstBankList->resizeColumnToContents(i);
|
||||
ui.lstBankList->resizeColumnToContents(num_sections);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the window title.
|
||||
*/
|
||||
void QRvtHToolWindowPrivate::updateWindowTitle(void)
|
||||
{
|
||||
QString windowTitle;
|
||||
if (rvth) {
|
||||
windowTitle += displayFilename;
|
||||
windowTitle += QLatin1String(" - ");
|
||||
}
|
||||
windowTitle += QApplication::applicationName();
|
||||
|
||||
Q_Q(QRvtHToolWindow);
|
||||
q->setWindowTitle(windowTitle);
|
||||
}
|
||||
|
||||
/** QRvtHToolWindow **/
|
||||
|
||||
QRvtHToolWindow::QRvtHToolWindow(QWidget *parent)
|
||||
: super(parent)
|
||||
, d_ptr(new QRvtHToolWindowPrivate(this))
|
||||
{
|
||||
Q_D(QRvtHToolWindow);
|
||||
d->ui.setupUi(this);
|
||||
|
||||
// Make sure the window is deleted on close.
|
||||
this->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// Remove the window icon. (Mac "proxy icon")
|
||||
// TODO: Use the memory card file?
|
||||
this->setWindowIcon(QIcon());
|
||||
#endif /* Q_OS_MAC */
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// Hide the QMenuBar border on Win32.
|
||||
// FIXME: This causes the menu bar to be "truncated" when using
|
||||
// the Aero theme on Windows Vista and 7.
|
||||
#if 0
|
||||
this->Ui_QRvtHToolWindow::menuBar->setStyleSheet(
|
||||
QLatin1String("QMenuBar { border: none }"));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Set up the main splitter sizes.
|
||||
// We want the card info panel to be 160px wide at startup.
|
||||
// TODO: Save positioning settings somewhere?
|
||||
static const int BankInfoPanelWidth = 256;
|
||||
QList<int> sizes;
|
||||
sizes.append(this->width() - BankInfoPanelWidth);
|
||||
sizes.append(BankInfoPanelWidth);
|
||||
d->ui.splitterMain->setSizes(sizes);
|
||||
|
||||
// Set the main splitter stretch factors.
|
||||
// We want the QTreeView to stretch, but not the card info panel.
|
||||
d->ui.splitterMain->setStretchFactor(0, 1);
|
||||
d->ui.splitterMain->setStretchFactor(1, 0);
|
||||
|
||||
// Set the models.
|
||||
d->proxyModel->setSourceModel(d->model);
|
||||
d->ui.lstBankList->setModel(d->proxyModel);
|
||||
|
||||
// Sort by COL_BANKNUM by default.
|
||||
// TODO: Disable sorting on specific columns.
|
||||
//d->proxyModel->setDynamicSortFilter(true);
|
||||
//d->ui.lstBankList->sortByColumn(RvtHModel::COL_BANKNUM, Qt::AscendingOrder);
|
||||
|
||||
// Connect the lstBankList slots.
|
||||
connect(d->ui.lstBankList->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &QRvtHToolWindow::lstBankList_selectionModel_selectionChanged);
|
||||
|
||||
// Initialize the UI.
|
||||
d->updateLstBankList();
|
||||
d->updateWindowTitle();
|
||||
}
|
||||
|
||||
QRvtHToolWindow::~QRvtHToolWindow()
|
||||
{
|
||||
delete d_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an RVT-H Reader disk image.
|
||||
* @param filename Filename.
|
||||
*/
|
||||
void QRvtHToolWindow::openRvtH(const QString &filename)
|
||||
{
|
||||
Q_D(QRvtHToolWindow);
|
||||
|
||||
if (d->rvth) {
|
||||
d->model->setRvtH(nullptr);
|
||||
rvth_close(d->rvth);
|
||||
}
|
||||
|
||||
// Open the specified RVT-H Reader disk image.
|
||||
#ifdef _WIN32
|
||||
d->rvth = rvth_open(reinterpret_cast<const wchar_t*>(filename.utf16()), nullptr);
|
||||
#else /* !_WIN32 */
|
||||
d->rvth = rvth_open(filename.toUtf8().constData(), nullptr);
|
||||
#endif
|
||||
if (!d->rvth) {
|
||||
// FIXME: Show an error message?
|
||||
return;
|
||||
}
|
||||
|
||||
d->filename = filename;
|
||||
d->model->setRvtH(d->rvth);
|
||||
|
||||
// Extract the filename from the path.
|
||||
d->displayFilename = filename;
|
||||
int lastSlash = d->displayFilename.lastIndexOf(QChar(L'/'));
|
||||
if (lastSlash >= 0) {
|
||||
d->displayFilename.remove(0, lastSlash + 1);
|
||||
}
|
||||
|
||||
// Update the UI.
|
||||
d->updateLstBankList();
|
||||
d->updateWindowTitle();
|
||||
|
||||
// FIXME: If a file is opened from the command line,
|
||||
// QTreeView sort-of selects the first file.
|
||||
// (Signal is emitted, but nothing is highlighted.)
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the currently-opened RVT-H Reader disk image.
|
||||
*/
|
||||
void QRvtHToolWindow::closeRvtH(void)
|
||||
{
|
||||
Q_D(QRvtHToolWindow);
|
||||
if (!d->rvth) {
|
||||
// Not open...
|
||||
return;
|
||||
}
|
||||
|
||||
d->model->setRvtH(nullptr);
|
||||
rvth_close(d->rvth);
|
||||
d->rvth = nullptr;
|
||||
|
||||
// Clear the filenames.
|
||||
d->filename.clear();
|
||||
d->displayFilename.clear();
|
||||
|
||||
// Update the UI.
|
||||
d->updateLstBankList();
|
||||
d->updateWindowTitle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Widget state has changed.
|
||||
* @param event State change event.
|
||||
*/
|
||||
void QRvtHToolWindow::changeEvent(QEvent *event)
|
||||
{
|
||||
Q_D(QRvtHToolWindow);
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::LanguageChange:
|
||||
// Retranslate the UI.
|
||||
d->ui.retranslateUi(this);
|
||||
d->updateLstBankList();
|
||||
d->updateWindowTitle();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Pass the event to the base class.
|
||||
super::changeEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Window show event.
|
||||
* @param event Window show event.
|
||||
*/
|
||||
void QRvtHToolWindow::showEvent(QShowEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
Q_D(QRvtHToolWindow);
|
||||
|
||||
// Show all columns except signature status by default.
|
||||
// TODO: Allow the user to customize the columns, and save the
|
||||
// customized columns somewhere.
|
||||
if (!d->cols_init) {
|
||||
d->cols_init = true;
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_BANKNUM, false);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_TYPE, false);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_TITLE, false);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_DISCNUM, false);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_REVISION, false);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_REGION, false);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_IOS_VERSION, false);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_ENCRYPTION, false);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_SIG_TICKET, true);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_SIG_TMD, true);
|
||||
d->ui.lstBankList->setColumnHidden(RvtHModel::COL_APPLOADER, true);
|
||||
static_assert(RvtHModel::COL_APPLOADER + 1 == RvtHModel::COL_MAX,
|
||||
"Default column visibility status needs to be updated!");
|
||||
}
|
||||
}
|
||||
|
||||
/** UI widget slots. **/
|
||||
|
||||
/**
|
||||
* Open a memory card image.
|
||||
*/
|
||||
void QRvtHToolWindow::on_actionOpen_triggered(void)
|
||||
{
|
||||
Q_D(QRvtHToolWindow);
|
||||
|
||||
// TODO: Remove the space before the "*.raw"?
|
||||
// On Linux, Qt shows an extra space after the filter name, since
|
||||
// it doesn't show the extension. Not sure about Windows...
|
||||
const QString allSupportedFilter = tr("All Supported Files") +
|
||||
QLatin1String(" (*.img *.bin *.gcm *.wbfs *.ciso *.cso *.iso)");
|
||||
const QString hddFilter = tr("RVT-H Reader Disk Image Files") +
|
||||
QLatin1String(" (*.img *.bin)");
|
||||
const QString gcmFilter = tr("GameCube/Wii Disc Image Files") +
|
||||
QLatin1String(" (*.gcm *.wbfs *.ciso *.cso *.iso)");
|
||||
const QString allFilter = tr("All Files") + QLatin1String(" (*)");
|
||||
|
||||
// NOTE: Using a QFileDialog instead of QFileDialog::getOpenFileName()
|
||||
// causes a non-native appearance on Windows. Hence, we should use
|
||||
// QFileDialog::getOpenFileName().
|
||||
const QString filters =
|
||||
allSupportedFilter + QLatin1String(";;") +
|
||||
hddFilter + QLatin1String(";;") +
|
||||
gcmFilter + QLatin1String(";;") +
|
||||
allFilter;
|
||||
|
||||
// Get the filename.
|
||||
// TODO: d->lastPath()
|
||||
QString filename = QFileDialog::getOpenFileName(this,
|
||||
tr("Open RVT-H Reader Disk Image"), // Dialog title
|
||||
d->lastPath, // Default filename
|
||||
filters); // Filters
|
||||
|
||||
if (!filename.isEmpty()) {
|
||||
// Filename is selected.
|
||||
|
||||
// Save the last path.
|
||||
d->lastPath = QFileInfo(filename).absolutePath();
|
||||
|
||||
// Open the RVT-H Reader disk image.
|
||||
openRvtH(filename);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the currently-opened memory card image.
|
||||
*/
|
||||
void QRvtHToolWindow::on_actionClose_triggered(void)
|
||||
{
|
||||
Q_D(QRvtHToolWindow);
|
||||
if (!d->rvth)
|
||||
return;
|
||||
|
||||
closeRvtH();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit the program.
|
||||
* TODO: Separate close/exit for Mac OS X?
|
||||
*/
|
||||
void QRvtHToolWindow::on_actionExit_triggered(void)
|
||||
{
|
||||
this->closeRvtH();
|
||||
this->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the About dialog.
|
||||
*/
|
||||
void QRvtHToolWindow::on_actionAbout_triggered(void)
|
||||
{
|
||||
// TODO
|
||||
//AboutDialog::ShowSingle(this);
|
||||
}
|
||||
|
||||
/** RvtHModel slots. **/
|
||||
|
||||
void QRvtHToolWindow::rvthModel_layoutChanged(void)
|
||||
{
|
||||
// Update the QTreeView columns, etc.
|
||||
// FIXME: This doesn't work the first time a file is added...
|
||||
// (possibly needs a dataChanged() signal)
|
||||
Q_D(QRvtHToolWindow);
|
||||
d->updateLstBankList();
|
||||
}
|
||||
|
||||
void QRvtHToolWindow::rvthModel_rowsInserted(void)
|
||||
{
|
||||
// A new file entry was added to the GcnCard.
|
||||
// Update the QTreeView columns.
|
||||
// FIXME: This doesn't work the first time a file is added...
|
||||
Q_D(QRvtHToolWindow);
|
||||
d->updateLstBankList();
|
||||
}
|
||||
|
||||
/** lstBankList slots. **/
|
||||
void QRvtHToolWindow::lstBankList_selectionModel_selectionChanged(
|
||||
const QItemSelection& selected, const QItemSelection& deselected)
|
||||
{
|
||||
Q_UNUSED(selected)
|
||||
Q_UNUSED(deselected)
|
||||
Q_D(QRvtHToolWindow);
|
||||
|
||||
if (!d->rvth) {
|
||||
// No RVT-H Reader disk image.
|
||||
d->ui.bevBankEntryView->setBankEntry(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: QItemSelection::indexes() *crashes* in MSVC debug builds. (Qt 4.8.6)
|
||||
// References: (search for "QModelIndexList assertion", no quotes)
|
||||
// - http://www.qtforum.org/article/13355/qt4-qtableview-assertion-failure.html#post66572
|
||||
// - http://www.qtcentre.org/threads/55614-QTableView-gt-selectionModel%20%20-gt-selection%20%20-indexes%20%20-crash#8766774666573257762
|
||||
// - https://forum.qt.io/topic/24664/crash-with-qitemselectionmodel-selectedindexes
|
||||
//QModelIndexList indexes = selected.indexes();
|
||||
int bank = -1;
|
||||
const RvtH_BankEntry *entry = nullptr;
|
||||
QItemSelectionModel *const selectionModel = d->ui.lstBankList->selectionModel();
|
||||
if (selectionModel->hasSelection()) {
|
||||
// TODO: If multiple banks are selected, and one of the
|
||||
// banks was just now unselected, this will still be the
|
||||
// unselected bank.
|
||||
QModelIndex index = d->ui.lstBankList->selectionModel()->currentIndex();
|
||||
if (index.isValid()) {
|
||||
// TODO: Sort proxy model like in mcrecover.
|
||||
bank = d->proxyModel->mapToSource(index).row();
|
||||
// TODO: Check for errors?
|
||||
entry = rvth_get_BankEntry(d->rvth, bank, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the BankView's BankEntry to the selected bank.
|
||||
// NOTE: Only handles the first selected bank.
|
||||
d->ui.bevBankEntryView->setBankEntry(entry);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool (qrvthtool) *
|
||||
* QRvtHToolWindow.hpp: Main window. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __RVTHTOOL_QRVTHTOOL_WINDOWS_QRVTHTOOLWINDOW_HPP__
|
||||
#define __RVTHTOOL_QRVTHTOOL_WINDOWS_QRVTHTOOLWINDOW_HPP__
|
||||
|
||||
class QItemSelection;
|
||||
#include <QMainWindow>
|
||||
|
||||
class QRvtHToolWindowPrivate;
|
||||
class QRvtHToolWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
typedef QMainWindow super;
|
||||
|
||||
public:
|
||||
explicit QRvtHToolWindow(QWidget *parent = 0);
|
||||
virtual ~QRvtHToolWindow();
|
||||
|
||||
protected:
|
||||
QRvtHToolWindowPrivate *const d_ptr;
|
||||
Q_DECLARE_PRIVATE(QRvtHToolWindow)
|
||||
private:
|
||||
Q_DISABLE_COPY(QRvtHToolWindow)
|
||||
|
||||
public:
|
||||
/**
|
||||
* Open an RVT-H Reader disk image.
|
||||
* @param filename Filename.
|
||||
*/
|
||||
void openRvtH(const QString &filename);
|
||||
|
||||
/**
|
||||
* Close the currently-opened RVT-H Reader disk image.
|
||||
*/
|
||||
void closeRvtH(void);
|
||||
|
||||
protected:
|
||||
// State change event. (Used for switching the UI language at runtime.)
|
||||
void changeEvent(QEvent *event) final;
|
||||
|
||||
// Window show event.
|
||||
void showEvent(QShowEvent *event) final;
|
||||
|
||||
protected slots:
|
||||
// Actions.
|
||||
void on_actionOpen_triggered(void);
|
||||
void on_actionClose_triggered(void);
|
||||
void on_actionExit_triggered(void);
|
||||
void on_actionAbout_triggered(void);
|
||||
|
||||
// RvtHModel slots.
|
||||
void rvthModel_layoutChanged(void);
|
||||
void rvthModel_rowsInserted(void);
|
||||
|
||||
// lstBankList slots.
|
||||
void lstBankList_selectionModel_selectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
|
||||
};
|
||||
|
||||
#endif /* __RVTHTOOL_QRVTHTOOL_WINDOWS_QRVTHTOOLWINDOW_HPP__ */
|
@ -1,200 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QRvtHToolWindow</class>
|
||||
<widget class="QMainWindow" name="QRvtHToolWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>890</width>
|
||||
<height>540</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::NoContextMenu</enum>
|
||||
</property>
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">RVT-H Tool</string>
|
||||
</property>
|
||||
<property name="unifiedTitleAndToolBarOnMac">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="vboxMain" stretch="0">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitterMain">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="grpBankList">
|
||||
<property name="title">
|
||||
<string notr="true">No RVT-H Reader disk image loaded.</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vboxBankList">
|
||||
<item>
|
||||
<widget class="QTreeViewOpt" name="lstBankList">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QSplitter" name="splitterInfo">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="grpBankInfo">
|
||||
<property name="title">
|
||||
<string>Bank Information</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="vboxBankInfo">
|
||||
<item>
|
||||
<widget class="BankEntryView" name="bevBankEntryView" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>890</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionClose"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="actionAbout"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuLanguage">
|
||||
<property name="title">
|
||||
<string>&Language</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuLanguage"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QStatusBar::item { border: none }</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<action name="actionOpen">
|
||||
<property name="icon">
|
||||
<iconset theme="document-open">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Open</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Open an RVT-H Reader disk image</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit">
|
||||
<property name="icon">
|
||||
<iconset theme="application-exit">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>E&xit</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Exit the program</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<property name="icon">
|
||||
<iconset theme="help-about">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&About</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>About this program</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClose">
|
||||
<property name="icon">
|
||||
<iconset theme="document-close">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Close</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Close the RVT-H Reader disk image</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+W</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>BankEntryView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/BankEntryView.hpp</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QTreeViewOpt</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/QTreeViewOpt.hpp</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|