ui/utils: Added a source file filter for system selection menu.

* ui/selmenu.cpp: Show system source file in general info.
* frontend/infoxml.cpp: Consolidated source file path formatting in one place.
* ui/devopt.cpp: Get decimal separator from C++ locale.
This commit is contained in:
Vas Crabb 2023-08-19 03:21:05 +10:00
parent f0f9e45d62
commit 456e6948a8
10 changed files with 108 additions and 61 deletions

View File

@ -403,25 +403,10 @@ void cli_frontend::listsource(const std::vector<std::string> &args)
{
auto const list_system_source = [] (device_type type)
{
std::string_view src(type.source());
auto prefix(src.find("src/mame/"));
if (std::string_view::npos == prefix)
prefix = src.find("src\\mame\\");
if (std::string_view::npos != prefix)
{
src.remove_prefix(prefix + 9);
}
else
{
auto prefix(src.find("src/"));
if (std::string_view::npos == prefix)
prefix = src.find("src\\");
if (std::string_view::npos != prefix)
{
src.remove_prefix(prefix + 4);
}
}
osd_printf_info("%-16s %s\n", type.shortname(), src);
osd_printf_info(
"%-16s %s\n",
type.shortname(),
info_xml_creator::format_sourcefile(type.source()));
};
apply_action(
args,
@ -520,13 +505,8 @@ void cli_frontend::listbrothers(const std::vector<std::string> &args)
drivlist.reset();
while (drivlist.next())
{
std::string_view src(drivlist.driver().type.source());
auto prefix(src.find("src/mame/"));
if (std::string_view::npos == prefix)
prefix = src.find("src\\mame\\");
if (std::string_view::npos != prefix)
src.remove_prefix(prefix + 9);
int const clone_of = drivlist.clone();
auto const src(info_xml_creator::format_sourcefile(drivlist.driver().type.source()));
int const clone_of(drivlist.clone());
if (clone_of != -1)
osd_printf_info("%-20s %-16s %s\n", src, drivlist.driver().name, (clone_of == -1 ? "" : drivlist.driver(clone_of).name));
else

View File

@ -340,7 +340,7 @@ constexpr std::pair<device_t::feature_type, char const *> f_feature_names[] = {
//-------------------------------------------------
// get_feature_name - get XML name for feature
// feature_name - get XML name for feature
//-------------------------------------------------
char const *info_xml_creator::feature_name(device_t::feature_type feature)
@ -357,6 +357,33 @@ char const *info_xml_creator::feature_name(device_t::feature_type feature)
}
//-------------------------------------------------
// format_sourcefile - sanitise source file path
//-------------------------------------------------
std::string info_xml_creator::format_sourcefile(std::string_view path)
{
using namespace std::literals;
if (auto prefix(path.rfind("src/mame/"sv)); std::string_view::npos != prefix)
path.remove_prefix(prefix + 9);
else if (auto prefix(path.rfind("src\\mame\\"sv)); std::string_view::npos != prefix)
path.remove_prefix(prefix + 9);
else if (auto prefix(path.rfind("/src/"sv)); std::string_view::npos != prefix)
path.remove_prefix(prefix + 5);
else if (auto prefix(path.rfind("\\src\\"sv)); std::string_view::npos != prefix)
path.remove_prefix(prefix + 5);
else if (path.substr(0, 4) == "src/"sv)
path.remove_prefix(4);
else if (path.substr(0, 4) == "src\\"sv)
path.remove_prefix(4);
std::string result(path);
std::replace(result.begin(), result.end(), '\\', '/');
return result;
}
//-------------------------------------------------
// info_xml_creator - constructor
//-------------------------------------------------
@ -714,14 +741,8 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive
// print the header and the machine name
util::stream_format(out, "\t<%s name=\"%s\"", XML_TOP, normalize_string(driver.name));
// strip away any path information from the source_file and output it
std::string_view src(driver.type.source());
auto prefix(src.find("src/mame/"));
if (std::string_view::npos == prefix)
prefix = src.find("src\\mame\\");
if (std::string_view::npos != prefix)
src.remove_prefix(prefix + 9);
util::stream_format(out, " sourcefile=\"%s\"", normalize_string(src));
// strip away extra path information from the source file and output it
util::stream_format(out, " sourcefile=\"%s\"", normalize_string(info_xml_creator::format_sourcefile(driver.type.source())));
// append bios and runnable flags
if (driver.flags & machine_flags::IS_BIOS_ROOT)
@ -815,13 +836,7 @@ void output_one_device(std::ostream &out, machine_config &config, device_t &devi
// start to output info
util::stream_format(out, "\t<%s name=\"%s\"", XML_TOP, normalize_string(device.shortname()));
std::string_view src(device.source());
auto prefix(src.find("src/"));
if (std::string_view::npos == prefix)
prefix = src.find("src\\");
if (std::string_view::npos != prefix)
src.remove_prefix(prefix + 4);
util::stream_format(out, " sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", normalize_string(src));
util::stream_format(out, " sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", normalize_string(info_xml_creator::format_sourcefile(device.source())));
auto const parent(device.type().parent_rom_device_type());
if (parent)
util::stream_format(out, " romof=\"%s\"", normalize_string(parent->shortname()));

View File

@ -16,6 +16,8 @@
#include "emuopts.h"
#include <functional>
#include <string>
#include <string_view>
#include <vector>
@ -35,6 +37,7 @@ public:
void output(std::ostream &out, const std::function<bool(const char *shortname, bool &done)> &filter = { }, bool include_devices = true);
static char const *feature_name(device_t::feature_type feature);
static std::string format_sourcefile(std::string_view path);
private:
// internal state

View File

@ -15,7 +15,10 @@
#include "romload.h"
#include "screen.h"
#include "utf8.h"
#include "util/unicode.h"
#include "util/utf8.h"
#include <locale>
namespace ui {
@ -55,6 +58,13 @@ void menu_device_config::populate_text(std::optional<text_layout> &layout, float
if (!d.configured())
d.config_complete();
// get decimal separator
std::string point;
{
wchar_t const s(std::use_facet<std::numpunct<wchar_t> >(std::locale()).decimal_point());
point = utf8_from_wstring(std::wstring_view(&s, 1));
}
layout->add_text(
util::string_format(
m_mounted
@ -93,7 +103,7 @@ void menu_device_config::populate_text(std::optional<text_layout> &layout, float
if (d > 0)
{
size_t dpos = hz.length() - d;
hz.insert(dpos, ".");
hz.insert(dpos, point);
size_t last = hz.find_last_not_of('0');
hz = hz.substr(0, last + (last != dpos ? 1 : 0));
}
@ -129,7 +139,7 @@ void menu_device_config::populate_text(std::optional<text_layout> &layout, float
if (valid)
{
size_t dpos = hz.length() - 6;
hz.insert(dpos, ".");
hz.insert(dpos, point);
size_t last = hz.find_last_not_of('0');
hz = hz.substr(0, last + (last != dpos ? 1 : 0));
}
@ -175,7 +185,7 @@ void menu_device_config::populate_text(std::optional<text_layout> &layout, float
if (d > 0)
{
size_t dpos = hz.length() - d;
hz.insert(dpos, ".");
hz.insert(dpos, point);
size_t last = hz.find_last_not_of('0');
hz = hz.substr(0, last + (last != dpos ? 1 : 0));
}

View File

@ -14,6 +14,8 @@
#include "ui/systemlist.h"
#include "ui/ui.h"
#include "infoxml.h"
#include "drivenum.h"
#include "emuopts.h"
#include "romload.h"
@ -374,17 +376,11 @@ std::string machine_info::game_info_string() const
}
// print description, manufacturer, and CPU:
std::string_view src(m_machine.system().type.source());
auto prefix(src.find("src/mame/"));
if (std::string_view::npos == prefix)
prefix = src.find("src\\mame\\");
if (std::string_view::npos != prefix)
src.remove_prefix(prefix + 9);
util::stream_format(buf, _("%1$s\n%2$s %3$s\nDriver: %4$s\n\nCPU:\n"),
system_list::instance().systems()[driver_list::find(m_machine.system().name)].description,
m_machine.system().year,
m_machine.system().manufacturer,
src);
info_xml_creator::format_sourcefile(m_machine.system().type.source()));
// loop over all CPUs
execute_interface_enumerator execiter(m_machine.root_device());

View File

@ -17,6 +17,7 @@
#include "audit.h"
#include "cheat.h"
#include "infoxml.h"
#include "mame.h"
#include "mameopts.h"
@ -3124,6 +3125,8 @@ void menu_select_launch::general_info(ui_system_info const *system, game_driver
str << _("Media Audit\tDisabled\nSamples Audit\tDisabled\n");
}
util::stream_format(str, _("Source File\t%1$s\n"), info_xml_creator::format_sourcefile(driver.type.source()));
buffer = std::move(str).str();
}

View File

@ -17,6 +17,8 @@
#include "ui/ui.h"
#include "ui/utils.h"
#include "infoxml.h"
#include "audit.h"
#include "drivenum.h"
#include "emuopts.h"
@ -352,13 +354,7 @@ void simple_menu_select_game::custom_render(void *selectedref, float top, float
tempbuf[1] = string_format(_("%1$s, %2$-.100s"), driver->year, driver->manufacturer);
// next line source path
std::string_view src(driver->type.source());
auto prefix(src.find("src/mame/"));
if (std::string_view::npos == prefix)
prefix = src.find("src\\mame\\");
if (std::string_view::npos != prefix)
src.remove_prefix(prefix + 9);
tempbuf[2] = string_format(_("Driver: %1$s"), src);
tempbuf[2] = string_format(_("Driver: %1$s"), info_xml_creator::format_sourcefile(driver->type.source()));
// update cached values if selection changed
if (driver != m_cached_driver)

View File

@ -301,6 +301,7 @@ void system_list::populate_list(bool copydesc)
m_filter_data.add_manufacturer(driver.manufacturer);
m_filter_data.add_year(driver.year);
m_filter_data.add_source_file(driver.type.source());
}
}
}

View File

@ -14,6 +14,7 @@
#include "ui/inifile.h"
#include "ui/selector.h"
#include "infoxml.h"
#include "language.h"
#include "mame.h"
@ -96,6 +97,7 @@ constexpr char const *MACHINE_FILTER_NAMES[machine_filter::COUNT] = {
N_p("machine-filter", "Clones"),
N_p("machine-filter", "Manufacturer"),
N_p("machine-filter", "Year"),
N_p("machine-filter", "Source File"),
N_p("machine-filter", "Save Supported"),
N_p("machine-filter", "Save Unsupported"),
N_p("machine-filter", "CHD Required"),
@ -800,6 +802,18 @@ public:
};
class source_file_machine_filter : public choice_filter_impl_base<machine_filter, machine_filter::SOURCE_FILE>
{
public:
source_file_machine_filter(machine_filter_data const &data, char const *value, util::core_file *file, unsigned indent)
: choice_filter_impl_base<machine_filter, machine_filter::SOURCE_FILE>(data.source_files(), value)
{
}
virtual bool apply(ui_system_info const &system) const override { return !have_choices() || (selection_valid() && (selection_text() == info_xml_creator::format_sourcefile(system.driver->type.source()))); }
};
//-------------------------------------------------
// complementary machine filters
@ -1227,6 +1241,7 @@ public:
case FAVORITE:
case MANUFACTURER:
case YEAR:
case SOURCE_FILE:
case CUSTOM:
case COUNT:
break;
@ -1236,7 +1251,17 @@ public:
static bool is_inclusion(type n)
{
return (CATEGORY == n) || (MANUFACTURER == n) || (YEAR == n);
switch (n)
{
case CATEGORY:
case MANUFACTURER:
case YEAR:
case SOURCE_FILE:
return true;
default:
return false;
}
}
private:
@ -1602,10 +1627,21 @@ void machine_filter_data::add_year(std::string const &year)
m_years.emplace(pos, year);
}
void machine_filter_data::add_source_file(std::string_view path)
{
std::vector<std::string>::iterator const pos(std::lower_bound(m_source_files.begin(), m_source_files.end(), path));
if ((m_source_files.end() == pos) || (*pos != path))
m_source_files.emplace(pos, path);
}
void machine_filter_data::finalise()
{
for (std::string &path : m_source_files)
path = info_xml_creator::format_sourcefile(path);
std::stable_sort(m_manufacturers.begin(), m_manufacturers.end());
std::stable_sort(m_years.begin(), m_years.end());
std::stable_sort(m_source_files.begin(), m_source_files.end());
}
std::string machine_filter_data::extract_manufacturer(std::string const &manufacturer)
@ -1780,6 +1816,8 @@ machine_filter::ptr machine_filter::create(type n, machine_filter_data const &da
return std::make_unique<manufacturer_machine_filter>(data, value, file, indent);
case YEAR:
return std::make_unique<year_machine_filter>(data, value, file, indent);
case SOURCE_FILE:
return std::make_unique<source_file_machine_filter>(data, value, file, indent);
case SAVE:
return std::make_unique<save_machine_filter>(data, value, file, indent);
case NOSAVE:

View File

@ -186,6 +186,7 @@ public:
CLONES,
MANUFACTURER,
YEAR,
SOURCE_FILE,
SAVE,
NOSAVE,
CHD,
@ -276,10 +277,13 @@ class machine_filter_data
public:
std::vector<std::string> const &manufacturers() const { return m_manufacturers; }
std::vector<std::string> const &years() const { return m_years; }
std::vector<std::string> const &source_files() const { return m_source_files; }
// adding entries
void add_manufacturer(std::string const &manufacturer);
void add_year(std::string const &year);
void add_source_file(std::string_view path);
void finalise();
// use heuristics to extract meaningful parts from machine metadata
@ -306,6 +310,7 @@ private:
std::vector<std::string> m_manufacturers;
std::vector<std::string> m_years;
std::vector<std::string> m_source_files;
machine_filter::type m_current_filter = machine_filter::ALL;
filter_map m_filters;