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.
This commit is contained in:
David Korth 2018-09-17 20:42:44 -04:00
parent deb2ecd075
commit 6eef4a3c8f
24 changed files with 0 additions and 2783 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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?
}

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -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>

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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>

View File

@ -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();
}

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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>&amp;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>&amp;Help</string>
</property>
<addaction name="actionAbout"/>
</widget>
<widget class="QMenu" name="menuLanguage">
<property name="title">
<string>&amp;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>&amp;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&amp;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>&amp;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>&amp;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>