qt: Add media history manager for recently used images
This commit is contained in:
18
src/config.c
18
src/config.c
@@ -1829,6 +1829,15 @@ load_floppy_and_cdrom_drives(void)
|
||||
|
||||
sprintf(temp, "cdrom_%02i_iso_path", c + 1);
|
||||
config_delete_var(cat, temp);
|
||||
|
||||
for (int i = 0; i < MAX_PREV_IMAGES; i++) {
|
||||
cdrom[c].image_history[i] = (char *) calloc(MAX_IMAGE_PATH_LEN + 1, sizeof(char));
|
||||
sprintf(temp, "cdrom_%02i_image_history_%02i", c + 1, i + 1);
|
||||
p = config_get_string(cat, temp, NULL);
|
||||
if(p) {
|
||||
sprintf(cdrom[c].image_history[i], "%s", p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3137,6 +3146,15 @@ save_floppy_and_cdrom_drives(void)
|
||||
} else {
|
||||
config_set_string(cat, temp, cdrom[c].image_path);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_PREV_IMAGES; i++) {
|
||||
sprintf(temp, "cdrom_%02i_image_history_%02i", c + 1, i + 1);
|
||||
if(strlen(cdrom[c].image_history[i]) == 0) {
|
||||
config_delete_var(cat, temp);
|
||||
} else {
|
||||
config_set_string(cat, temp, cdrom[c].image_history[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete_section_if_empty(cat);
|
||||
|
@@ -31,6 +31,10 @@
|
||||
#define NVR_PATH "nvr"
|
||||
#define SCREENSHOT_PATH "screenshots"
|
||||
|
||||
/* Recently used images */
|
||||
#define MAX_PREV_IMAGES 4
|
||||
#define MAX_IMAGE_PATH_LEN 256
|
||||
|
||||
/* Default language 0xFFFF = from system, 0x409 = en-US */
|
||||
#define DEFAULT_LANGUAGE 0x0409
|
||||
|
||||
|
@@ -39,6 +39,8 @@
|
||||
#define CD_TOC_SESSION 1
|
||||
#define CD_TOC_RAW 2
|
||||
|
||||
#define CD_IMAGE_HISTORY 4
|
||||
|
||||
#define BUF_SIZE 32768
|
||||
|
||||
#define CDROM_IMAGE 200
|
||||
@@ -110,6 +112,8 @@ typedef struct cdrom {
|
||||
char image_path[1024],
|
||||
prev_image_path[1024];
|
||||
|
||||
char *image_history[CD_IMAGE_HISTORY];
|
||||
|
||||
uint32_t sound_on, cdrom_capacity,
|
||||
pad, seek_pos,
|
||||
seek_diff, cd_end;
|
||||
|
@@ -166,6 +166,9 @@ add_library(ui STATIC
|
||||
qt_mcadevicelist.cpp
|
||||
qt_mcadevicelist.ui
|
||||
|
||||
qt_mediahistorymanager.cpp
|
||||
qt_mediahistorymanager.hpp
|
||||
|
||||
../qt_resources.qrc
|
||||
)
|
||||
|
||||
|
326
src/qt/qt_mediahistorymanager.cpp
Normal file
326
src/qt/qt_mediahistorymanager.cpp
Normal file
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Media history management module
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: cold-brewed
|
||||
*
|
||||
* Copyright 2022 The 86Box development team
|
||||
*/
|
||||
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QMetaEnum>
|
||||
#include <QStringBuilder>
|
||||
#include <utility>
|
||||
|
||||
#include "86box/cdrom.h"
|
||||
#include "qt_mediahistorymanager.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
MediaHistoryManager::MediaHistoryManager() {
|
||||
initializeImageHistory();
|
||||
deserializeAllImageHistory();
|
||||
initialDeduplication();
|
||||
|
||||
}
|
||||
|
||||
MediaHistoryManager::~MediaHistoryManager()
|
||||
= default;
|
||||
|
||||
master_list_t &
|
||||
MediaHistoryManager::blankImageHistory(master_list_t &initialized_master_list) const
|
||||
{
|
||||
for ( const auto device_type : ui::AllSupportedMediaHistoryTypes ) {
|
||||
device_media_history_t device_media_history;
|
||||
// Loop for all possible media devices
|
||||
for (int device_index = 0 ; device_index < maxDevicesSupported(device_type); device_index++) {
|
||||
device_index_list_t indexing_list;
|
||||
device_media_history[device_index] = indexing_list;
|
||||
// Loop for each history slot
|
||||
for (int slot_index = 0; slot_index < max_images; slot_index++) {
|
||||
device_media_history[device_index].append(QString());
|
||||
}
|
||||
}
|
||||
initialized_master_list.insert(device_type, device_media_history);
|
||||
}
|
||||
return initialized_master_list;
|
||||
}
|
||||
|
||||
|
||||
const device_index_list_t&
|
||||
MediaHistoryManager::getHistoryListForDeviceIndex(int index, ui::MediaType type)
|
||||
{
|
||||
if (master_list.contains(type)) {
|
||||
if ((index >= 0 ) && (index < master_list[type].size())) {
|
||||
return master_list[type][index];
|
||||
} else {
|
||||
qWarning("Media device index %i for device type %s was requested but index %i is out of range (valid range: >= 0 && < %i)",
|
||||
index, mediaTypeToString(type).toUtf8().constData(), index, master_list[type].size());
|
||||
}
|
||||
}
|
||||
// Failure gets an empty list
|
||||
return empty_device_index_list;
|
||||
}
|
||||
|
||||
void MediaHistoryManager::setHistoryListForDeviceIndex(int index, ui::MediaType type, device_index_list_t history_list)
|
||||
{
|
||||
master_list[type][index] = std::move(history_list);
|
||||
}
|
||||
|
||||
QString
|
||||
MediaHistoryManager::getImageForSlot(int index, int slot, ui::MediaType type)
|
||||
{
|
||||
QString image_name;
|
||||
device_index_list_t device_history = getHistoryListForDeviceIndex(index, type);
|
||||
if ((slot >= 0) && (slot < device_history.size())) {
|
||||
image_name = device_history[slot];
|
||||
} else {
|
||||
qWarning("Media history slot %i, index %i for device type %s was requested but slot %i is out of range (valid range: >= 0 && < %i, device_history.size() is %i)",
|
||||
slot, index, mediaTypeToString(type).toUtf8().constData(), slot, maxDevicesSupported(type), device_history.size());
|
||||
}
|
||||
return image_name;
|
||||
}
|
||||
|
||||
// These are hardcoded since we can't include the various
|
||||
// header files where they are defined (e.g., fdd.h, mo.h).
|
||||
// However, all in ui::MediaType support 4 except cassette.
|
||||
int MediaHistoryManager::maxDevicesSupported(ui::MediaType type)
|
||||
{
|
||||
return type == ui::MediaType::Cassette ? 1 : 4;
|
||||
|
||||
}
|
||||
|
||||
void MediaHistoryManager::deserializeImageHistoryType(ui::MediaType type)
|
||||
{
|
||||
for (int device = 0; device < maxDevicesSupported(type); device++) {
|
||||
char **device_history_ptr = getEmuHistoryVarForType(type, device);
|
||||
if(device_history_ptr == nullptr) {
|
||||
// Device not supported, return and do not deserialize.
|
||||
// This will leave the image listing at the default initialization state
|
||||
// from the ui side (this class)
|
||||
continue;
|
||||
}
|
||||
for ( int slot = 0; slot < MAX_PREV_IMAGES; slot++) {
|
||||
master_list[type][device][slot] = device_history_ptr[slot];
|
||||
}
|
||||
}
|
||||
}
|
||||
void MediaHistoryManager::deserializeAllImageHistory()
|
||||
{
|
||||
for ( const auto device_type : ui::AllSupportedMediaHistoryTypes ) {
|
||||
deserializeImageHistoryType(device_type);
|
||||
}
|
||||
}
|
||||
void MediaHistoryManager::serializeImageHistoryType(ui::MediaType type)
|
||||
{
|
||||
for (int device = 0; device < maxDevicesSupported(type); device++) {
|
||||
char **device_history_ptr = getEmuHistoryVarForType(type, device);
|
||||
if(device_history_ptr == nullptr) {
|
||||
// Device not supported, return and do not serialize.
|
||||
// This will leave the image listing at the current state,
|
||||
// and it will not be saved on the emu side
|
||||
continue;
|
||||
}
|
||||
for ( int slot = 0; slot < MAX_PREV_IMAGES; slot++) {
|
||||
strncpy(device_history_ptr[slot], master_list[type][device][slot].toUtf8().constData(), MAX_IMAGE_PATH_LEN);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MediaHistoryManager::serializeAllImageHistory()
|
||||
{
|
||||
for ( const auto device_type : ui::AllSupportedMediaHistoryTypes ) {
|
||||
serializeImageHistoryType(device_type);
|
||||
}
|
||||
}
|
||||
|
||||
void MediaHistoryManager::initialDeduplication()
|
||||
{
|
||||
|
||||
QString current_image;
|
||||
// Perform initial dedup if an image is loaded
|
||||
for ( const auto device_type : ui::AllSupportedMediaHistoryTypes ) {
|
||||
for (int device_index = 0; device_index < maxDevicesSupported(device_type); device_index++) {
|
||||
device_index_list_t device_history = getHistoryListForDeviceIndex(device_index, device_type);
|
||||
switch (device_type) {
|
||||
case ui::MediaType::Optical:
|
||||
current_image = cdrom[device_index].image_path;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
deduplicateList(device_history, QVector<QString> (1, current_image));
|
||||
// Fill in missing, if any
|
||||
int missing = MAX_PREV_IMAGES - device_history.size();
|
||||
if(missing) {
|
||||
for (int i = 0; i < missing; i++) {
|
||||
device_history.push_back(QString());
|
||||
}
|
||||
}
|
||||
setHistoryListForDeviceIndex(device_index, device_type, device_history);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char ** MediaHistoryManager::getEmuHistoryVarForType(ui::MediaType type, int index)
|
||||
{
|
||||
switch (type) {
|
||||
case ui::MediaType::Optical:
|
||||
return &cdrom[index].image_history[0];
|
||||
default:
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
device_index_list_t &
|
||||
MediaHistoryManager::deduplicateList(device_index_list_t &device_history, const QVector<QString>& filenames)
|
||||
{
|
||||
QVector<QString> items_to_delete;
|
||||
for (auto &list_item_path : device_history) {
|
||||
if(list_item_path.isEmpty()) {
|
||||
continue ;
|
||||
}
|
||||
for (const auto& path_to_check : filenames) {
|
||||
if(path_to_check.isEmpty()) {
|
||||
continue ;
|
||||
}
|
||||
QString adjusted_path = pathAdjustSingle(path_to_check);
|
||||
int match = QString::localeAwareCompare(list_item_path, adjusted_path);
|
||||
if (match == 0) {
|
||||
items_to_delete.append(list_item_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove by name rather than index because the index would change
|
||||
// after each removal
|
||||
for (const auto& path: items_to_delete) {
|
||||
device_history.removeAll(path);
|
||||
}
|
||||
return device_history;
|
||||
}
|
||||
|
||||
void MediaHistoryManager::addImageToHistory(int index, ui::MediaType type, const QString& image_name, const QString& new_image_name)
|
||||
{
|
||||
device_index_list_t device_history = getHistoryListForDeviceIndex(index, type);
|
||||
QVector<QString> files_to_check;
|
||||
|
||||
files_to_check.append(image_name);
|
||||
files_to_check.append(new_image_name);
|
||||
device_history = deduplicateList(device_history, files_to_check);
|
||||
|
||||
|
||||
if (!image_name.isEmpty()) {
|
||||
device_history.push_front(image_name);
|
||||
}
|
||||
|
||||
// Pop any extras
|
||||
if ((device_history.size() > MAX_PREV_IMAGES)) {
|
||||
device_history.pop_back();
|
||||
}
|
||||
|
||||
// Fill in missing, if any
|
||||
int missing = MAX_PREV_IMAGES - device_history.size();
|
||||
if(missing) {
|
||||
for (int i = 0; i < missing; i++) {
|
||||
device_history.push_back(QString());
|
||||
}
|
||||
}
|
||||
|
||||
device_history = removeMissingImages(device_history);
|
||||
device_history = pathAdjustFull(device_history);
|
||||
|
||||
setHistoryListForDeviceIndex(index, type, device_history);
|
||||
serializeImageHistoryType(type);
|
||||
}
|
||||
|
||||
QString MediaHistoryManager::mediaTypeToString(ui::MediaType type)
|
||||
{
|
||||
QMetaEnum qme = QMetaEnum::fromType<ui::MediaType>();
|
||||
return qme.valueToKey(static_cast<int>(type));
|
||||
}
|
||||
|
||||
QString
|
||||
MediaHistoryManager::pathAdjustSingle(QString checked_path)
|
||||
{
|
||||
QString current_usr_path = getUsrPath();
|
||||
QFileInfo file_info(checked_path);
|
||||
if (file_info.filePath().isEmpty() || current_usr_path.isEmpty() || file_info.isRelative()) {
|
||||
return checked_path;
|
||||
}
|
||||
if (file_info.filePath().startsWith(current_usr_path)) {
|
||||
checked_path = file_info.filePath().remove(current_usr_path);
|
||||
}
|
||||
return checked_path;
|
||||
}
|
||||
|
||||
device_index_list_t &
|
||||
MediaHistoryManager::pathAdjustFull(device_index_list_t &device_history)
|
||||
{
|
||||
for (auto &checked_path : device_history) {
|
||||
checked_path = pathAdjustSingle(checked_path);
|
||||
}
|
||||
return device_history;
|
||||
}
|
||||
QString MediaHistoryManager::getUsrPath()
|
||||
{
|
||||
QString current_usr_path(usr_path);
|
||||
// Ensure `usr_path` has a trailing slash
|
||||
return current_usr_path.endsWith("/") ? current_usr_path : current_usr_path.append("/");
|
||||
}
|
||||
device_index_list_t &
|
||||
MediaHistoryManager::removeMissingImages(device_index_list_t &device_history)
|
||||
{
|
||||
for (auto &checked_path : device_history) {
|
||||
QFileInfo file_info(checked_path);
|
||||
if (file_info.filePath().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// For this check, explicitly prepend `usr_path` to relative paths to account for $CWD platform variances
|
||||
QFileInfo absolute_path = file_info.isRelative() ? getUsrPath().append(file_info.filePath()) : file_info;
|
||||
if(!absolute_path.exists()) {
|
||||
qWarning("Image file %s does not exist - removing from history", qPrintable(file_info.filePath()));
|
||||
checked_path = "";
|
||||
}
|
||||
}
|
||||
return device_history;
|
||||
}
|
||||
|
||||
void MediaHistoryManager::initializeImageHistory()
|
||||
{
|
||||
auto initial_master_list = getMasterList();
|
||||
setMasterList(blankImageHistory(initial_master_list));
|
||||
}
|
||||
|
||||
const master_list_t &
|
||||
MediaHistoryManager::getMasterList() const
|
||||
{
|
||||
return master_list;
|
||||
}
|
||||
|
||||
void
|
||||
MediaHistoryManager::setMasterList(const master_list_t &masterList)
|
||||
{
|
||||
master_list = masterList;
|
||||
}
|
||||
|
||||
void
|
||||
MediaHistoryManager::clearImageHistory()
|
||||
{
|
||||
initializeImageHistory();
|
||||
serializeAllImageHistory();
|
||||
}
|
||||
|
||||
} // ui
|
139
src/qt/qt_mediahistorymanager.hpp
Normal file
139
src/qt/qt_mediahistorymanager.hpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Header for the media history management module
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: cold-brewed
|
||||
*
|
||||
* Copyright 2022 The 86Box development team
|
||||
*/
|
||||
|
||||
#ifndef QT_MEDIAHISTORYMANAGER_HPP
|
||||
#define QT_MEDIAHISTORYMANAGER_HPP
|
||||
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
#include <QVector>
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
}
|
||||
|
||||
// This macro helps give us the required `qHash()` function in order to use the
|
||||
// enum as a hash key
|
||||
#define QHASH_FOR_CLASS_ENUM(T) \
|
||||
inline uint qHash(const T &t, uint seed) { \
|
||||
return ::qHash(static_cast<typename std::underlying_type<T>::type>(t), seed); \
|
||||
}
|
||||
|
||||
typedef QVector<QString> device_index_list_t;
|
||||
typedef QHash<int, QVector<QString>> device_media_history_t;
|
||||
|
||||
|
||||
namespace ui {
|
||||
Q_NAMESPACE
|
||||
|
||||
enum class MediaType {
|
||||
Floppy,
|
||||
Optical,
|
||||
Zip,
|
||||
Mo,
|
||||
Cassette
|
||||
};
|
||||
// This macro allows us to do a reverse lookup of the enum with `QMetaEnum`
|
||||
Q_ENUM_NS(MediaType)
|
||||
|
||||
QHASH_FOR_CLASS_ENUM(MediaType)
|
||||
|
||||
typedef QHash<ui::MediaType, device_media_history_t> master_list_t;
|
||||
|
||||
// Used to iterate over all supported types when preparing data structures
|
||||
// Also useful to indicate which types support history
|
||||
static const MediaType AllSupportedMediaHistoryTypes[] = {
|
||||
MediaType::Optical
|
||||
};
|
||||
|
||||
class MediaHistoryManager {
|
||||
|
||||
public:
|
||||
MediaHistoryManager();
|
||||
virtual ~MediaHistoryManager();
|
||||
|
||||
// Get the image name for a particular slot,
|
||||
// index, and type combination
|
||||
QString getImageForSlot(int index, int slot, ui::MediaType type);
|
||||
|
||||
// Add an image to history
|
||||
void addImageToHistory(int index, ui::MediaType type, const QString& image_name, const QString& new_image_name);
|
||||
|
||||
// Convert the enum value to a string
|
||||
static QString mediaTypeToString(ui::MediaType type);
|
||||
|
||||
// Clear out the image history
|
||||
void clearImageHistory();
|
||||
|
||||
|
||||
private:
|
||||
int max_images = MAX_PREV_IMAGES;
|
||||
|
||||
// Main hash of hash of vector of strings
|
||||
master_list_t master_list;
|
||||
const master_list_t &getMasterList() const;
|
||||
void setMasterList(const master_list_t &masterList);
|
||||
|
||||
device_index_list_t index_list, empty_device_index_list;
|
||||
|
||||
// Return a blank, initialized image history list
|
||||
master_list_t &blankImageHistory(master_list_t &initialized_master_list) const;
|
||||
|
||||
// Initialize the image history
|
||||
void initializeImageHistory();
|
||||
|
||||
// Max number of devices supported by media type
|
||||
static int maxDevicesSupported(ui::MediaType type);
|
||||
|
||||
// Serialize the data back into the C array
|
||||
// on the emu side
|
||||
void serializeImageHistoryType(ui::MediaType type);
|
||||
void serializeAllImageHistory();
|
||||
|
||||
// Deserialize the data from C array on the emu side
|
||||
// for the ui side
|
||||
void deserializeImageHistoryType(ui::MediaType type);
|
||||
void deserializeAllImageHistory();
|
||||
|
||||
// Get emu history variable for a device type
|
||||
static char** getEmuHistoryVarForType(ui::MediaType type, int index);
|
||||
|
||||
// Get or set the history for a specific device/index combo
|
||||
const device_index_list_t &getHistoryListForDeviceIndex(int index, ui::MediaType type);
|
||||
void setHistoryListForDeviceIndex(int index, ui::MediaType type, device_index_list_t history_list);
|
||||
|
||||
// Remove missing image files from history list
|
||||
static device_index_list_t &removeMissingImages(device_index_list_t &device_history);
|
||||
|
||||
// If an absolute path is contained within `usr_path`, convert to a relative path
|
||||
static device_index_list_t &pathAdjustFull(device_index_list_t &device_history);
|
||||
static QString pathAdjustSingle(QString checked_path);
|
||||
|
||||
// Deduplicate history entries
|
||||
static device_index_list_t &deduplicateList(device_index_list_t &device_history, const QVector<QString>& filenames);
|
||||
void initialDeduplication();
|
||||
|
||||
// Gets the `usr_path` from the emu side and appends a
|
||||
// trailing slash if necessary
|
||||
static QString getUsrPath();
|
||||
};
|
||||
|
||||
} // ui
|
||||
|
||||
#endif // QT_MEDIAHISTORYMANAGER_HPP
|
@@ -52,6 +52,7 @@ extern "C" {
|
||||
#include "qt_newfloppydialog.hpp"
|
||||
#include "qt_util.hpp"
|
||||
#include "qt_deviceconfig.hpp"
|
||||
#include "qt_mediahistorymanager.hpp"
|
||||
|
||||
std::shared_ptr<MediaMenu> MediaMenu::ptr;
|
||||
|
||||
@@ -120,8 +121,11 @@ void MediaMenu::refresh(QMenu *parentMenu) {
|
||||
menu->addAction(tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true);
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("&Image..."), [this, i]() { cdromMount(i); })->setCheckable(false);
|
||||
cdromReloadPos = menu->children().count();
|
||||
menu->addAction(tr("&Reload previous image"), [this, i]() { cdromReload(i); });
|
||||
menu->addSeparator();
|
||||
for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) {
|
||||
cdromImageHistoryPos[slot] = menu->children().count();
|
||||
menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { cdromReload(i, slot); })->setCheckable(false);
|
||||
}
|
||||
menu->addSeparator();
|
||||
cdromImagePos = menu->children().count();
|
||||
menu->addAction(tr("E&ject"), [this, i]() { cdromEject(i); })->setCheckable(false);
|
||||
@@ -170,6 +174,7 @@ void MediaMenu::refresh(QMenu *parentMenu) {
|
||||
netMenus[i] = menu;
|
||||
nicUpdateMenu(i);
|
||||
});
|
||||
parentMenu->addAction(tr("Clear image history"), [this]() { clearImageHistory(); });
|
||||
}
|
||||
|
||||
void MediaMenu::cassetteNewImage() {
|
||||
@@ -404,14 +409,13 @@ void MediaMenu::cdromMount(int i, const QString &filename)
|
||||
} else {
|
||||
ui_sb_update_icon_state(SB_CDROM | i, 1);
|
||||
}
|
||||
mhm.addImageToHistory(i, ui::MediaType::Optical, cdrom[i].prev_image_path, cdrom[i].image_path);
|
||||
cdromUpdateMenu(i);
|
||||
ui_sb_update_tip(SB_CDROM | i);
|
||||
config_save();
|
||||
}
|
||||
|
||||
void MediaMenu::cdromMount(int i) {
|
||||
QString dir;
|
||||
QFileInfo fi(cdrom[i].image_path);
|
||||
|
||||
auto filename = QFileDialog::getOpenFileName(
|
||||
parentWidget,
|
||||
@@ -430,22 +434,60 @@ void MediaMenu::cdromMount(int i) {
|
||||
}
|
||||
|
||||
void MediaMenu::cdromEject(int i) {
|
||||
mhm.addImageToHistory(i, ui::MediaType::Optical, cdrom[i].image_path, QString());
|
||||
cdrom_eject(i);
|
||||
cdromUpdateMenu(i);
|
||||
ui_sb_update_tip(SB_CDROM | i);
|
||||
}
|
||||
|
||||
void MediaMenu::cdromReload(int i) {
|
||||
cdrom_reload(i);
|
||||
cdromUpdateMenu(i);
|
||||
ui_sb_update_tip(SB_CDROM | i);
|
||||
void MediaMenu::cdromReload(int index, int slot) {
|
||||
QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Optical);
|
||||
cdromMount(index, filename.toUtf8().constData());
|
||||
cdromUpdateMenu(index);
|
||||
ui_sb_update_tip(SB_CDROM | index);
|
||||
}
|
||||
|
||||
void MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) {
|
||||
QMenu* menu;
|
||||
QAction* imageHistoryUpdatePos;
|
||||
QString image_path;
|
||||
QObjectList children;
|
||||
|
||||
switch (type) {
|
||||
case ui::MediaType::Optical:
|
||||
if (!cdromMenus.contains(index))
|
||||
return;
|
||||
menu = cdromMenus[index];
|
||||
children = menu->children();
|
||||
imageHistoryUpdatePos = dynamic_cast<QAction*>(children[cdromImageHistoryPos[slot]]);
|
||||
image_path = mhm.getImageForSlot(index, slot, type);
|
||||
break;
|
||||
case ui::MediaType::Floppy:
|
||||
if (!floppyMenus.contains(index))
|
||||
return;
|
||||
menu = floppyMenus[index];
|
||||
children = menu->children();
|
||||
imageHistoryUpdatePos = dynamic_cast<QAction*>(children[floppyImageHistoryPos[slot]]);
|
||||
image_path = mhm.getImageForSlot(index, slot, type);
|
||||
break;
|
||||
default:
|
||||
pclog("History not yet implemented for media type %s\n", qPrintable(mhm.mediaTypeToString(type)));
|
||||
return;
|
||||
}
|
||||
|
||||
QFileInfo fi(image_path);
|
||||
imageHistoryUpdatePos->setText(QString::asprintf(tr("%s").toUtf8().constData(), fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData()));
|
||||
imageHistoryUpdatePos->setVisible(!fi.fileName().isEmpty());
|
||||
}
|
||||
|
||||
void MediaMenu::clearImageHistory() {
|
||||
mhm.clearImageHistory();
|
||||
ui_sb_update_panes();
|
||||
}
|
||||
|
||||
void MediaMenu::cdromUpdateMenu(int i) {
|
||||
QString name = cdrom[i].image_path;
|
||||
QString prev_name = cdrom[i].prev_image_path;
|
||||
QFileInfo fi(cdrom[i].image_path);
|
||||
QFileInfo fi_prev(cdrom[i].prev_image_path);
|
||||
|
||||
if (!cdromMenus.contains(i))
|
||||
return;
|
||||
@@ -459,9 +501,8 @@ void MediaMenu::cdromUpdateMenu(int i) {
|
||||
imageMenu->setEnabled(!name.isEmpty());
|
||||
imageMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), name.isEmpty() ? QString().toUtf8().constData() : fi.fileName().toUtf8().constData()));
|
||||
|
||||
auto* prevMenu = dynamic_cast<QAction*>(childs[cdromReloadPos]);
|
||||
prevMenu->setText(QString::asprintf(tr("Reload %s").toUtf8().constData(), prev_name.isEmpty() ? tr("previous image").toUtf8().constData() : fi_prev.fileName().toUtf8().constData()));
|
||||
prevMenu->setVisible(name.isEmpty() && cdrom[i].prev_host_drive != 0);
|
||||
for (int slot = 0; slot < MAX_PREV_IMAGES; slot++)
|
||||
updateImageHistory(i, slot, ui::MediaType::Optical);
|
||||
|
||||
QString busName = tr("Unknown Bus");
|
||||
switch (cdrom[i].bus_type) {
|
||||
|
@@ -3,7 +3,11 @@
|
||||
#include <memory>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include "qt_mediahistorymanager.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
}
|
||||
class QMenu;
|
||||
|
||||
class MediaMenu : QObject
|
||||
@@ -40,7 +44,9 @@ public:
|
||||
void cdromMount(int i);
|
||||
void cdromMount(int i, const QString& filename);
|
||||
void cdromEject(int i);
|
||||
void cdromReload(int i);
|
||||
void cdromReload(int index, int slot);
|
||||
void updateImageHistory(int index, int slot, ui::MediaType type);
|
||||
void clearImageHistory();
|
||||
void cdromUpdateMenu(int i);
|
||||
|
||||
void zipNewImage(int i);
|
||||
@@ -72,6 +78,7 @@ private:
|
||||
QMap<int, QMenu*> netMenus;
|
||||
|
||||
QString getMediaOpenDirectory();
|
||||
ui::MediaHistoryManager mhm;
|
||||
|
||||
int cassetteRecordPos;
|
||||
int cassettePlayPos;
|
||||
@@ -87,6 +94,8 @@ private:
|
||||
int cdromMutePos;
|
||||
int cdromReloadPos;
|
||||
int cdromImagePos;
|
||||
int cdromImageHistoryPos[MAX_PREV_IMAGES];
|
||||
int floppyImageHistoryPos[MAX_PREV_IMAGES];
|
||||
|
||||
int zipEjectPos;
|
||||
int zipReloadPos;
|
||||
|
@@ -167,7 +167,13 @@ plat_fopen(const char *path, const char *mode)
|
||||
FILE *
|
||||
plat_fopen64(const char *path, const char *mode)
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
QFileInfo fi(path);
|
||||
QString filename = fi.isRelative() ? usr_path + fi.filePath() : fi.filePath();
|
||||
return fopen(filename.toUtf8().constData(), mode);
|
||||
#else
|
||||
return fopen(QString::fromUtf8(path).toLocal8Bit(), mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
|
Reference in New Issue
Block a user