From 7ee008e150bc5bcf76082d726f719ee0fdfda982 Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Wed, 11 Feb 2026 02:37:39 -0600 Subject: Fluorine Manager: full Linux port of Mod Organizer 2 Complete native Linux port with FUSE-based virtual filesystem, Proton/umu-run integration, and Flatpak packaging. Key features: - FUSE VFS replacing Windows USVFS (in-process + standalone helper for Flatpak) - Proton/GE-Proton/umu-run launcher with env var forwarding - Flatpak support (sandbox-aware VFS, NXM handler, umu-run) - Wine prefix management UI - Case-insensitive path resolution for Linux filesystems - QSettings-safe INI handling (avoids Bethesda INI corruption) - Portable instance support with auto-generated launcher scripts Co-Authored-By: Claude Opus 4.6 --- libs/uibase/src/questionboxmemory.cpp | 200 ++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 libs/uibase/src/questionboxmemory.cpp (limited to 'libs/uibase/src/questionboxmemory.cpp') diff --git a/libs/uibase/src/questionboxmemory.cpp b/libs/uibase/src/questionboxmemory.cpp new file mode 100644 index 0000000..586e52e --- /dev/null +++ b/libs/uibase/src/questionboxmemory.cpp @@ -0,0 +1,200 @@ +/* +Mod Organizer shared UI functionality + +Copyright (C) 2012 Sebastian Herbord. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "ui_questionboxmemory.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace MOBase +{ + +static QMutex g_mutex; +static QuestionBoxMemory::GetButton g_get; +static QuestionBoxMemory::SetWindowButton g_setWindow; +static QuestionBoxMemory::SetFileButton g_setFile; + +QuestionBoxMemory::QuestionBoxMemory(QWidget* parent, const QString& title, + const QString& text, QString const* filename, + const QDialogButtonBox::StandardButtons buttons, + QDialogButtonBox::StandardButton defaultButton) + : QDialog(parent), ui(new Ui::QuestionBoxMemory), m_Button(QDialogButtonBox::Cancel) +{ + ui->setupUi(this); + + setWindowFlag(Qt::WindowType::WindowContextHelpButtonHint, false); + setWindowTitle(title); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion); + ui->iconLabel->setPixmap(icon.pixmap(128)); + ui->messageLabel->setText(text); + + if (filename == nullptr) { + // delete the 2nd check box + QCheckBox* box = ui->rememberForCheckBox; + box->parentWidget()->layout()->removeWidget(box); + delete box; + } else { + ui->rememberForCheckBox->setText(ui->rememberForCheckBox->text().arg(*filename)); + } + + ui->buttonBox->setStandardButtons(buttons); + + if (defaultButton != QDialogButtonBox::NoButton) { + ui->buttonBox->button(defaultButton)->setDefault(true); + } + + connect(ui->buttonBox, SIGNAL(clicked(QAbstractButton*)), this, + SLOT(buttonClicked(QAbstractButton*))); +} + +QuestionBoxMemory::~QuestionBoxMemory() = default; + +void QuestionBoxMemory::setCallbacks(GetButton get, SetWindowButton setWindow, + SetFileButton setFile) +{ + QMutexLocker locker(&g_mutex); + + g_get = get; + g_setWindow = setWindow; + g_setFile = setFile; +} + +void QuestionBoxMemory::buttonClicked(QAbstractButton* button) +{ + m_Button = ui->buttonBox->standardButton(button); +} + +QDialogButtonBox::StandardButton +QuestionBoxMemory::query(QWidget* parent, const QString& windowName, + const QString& title, const QString& text, + QDialogButtonBox::StandardButtons buttons, + QDialogButtonBox::StandardButton defaultButton) +{ + return queryImpl(parent, windowName, nullptr, title, text, buttons, defaultButton); +} + +QDialogButtonBox::StandardButton +QuestionBoxMemory::query(QWidget* parent, const QString& windowName, + const QString& fileName, const QString& title, + const QString& text, QDialogButtonBox::StandardButtons buttons, + QDialogButtonBox::StandardButton defaultButton) +{ + return queryImpl(parent, windowName, &fileName, title, text, buttons, defaultButton); +} + +QDialogButtonBox::StandardButton +QuestionBoxMemory::queryImpl(QWidget* parent, const QString& windowName, + const QString* fileName, const QString& title, + const QString& text, + QDialogButtonBox::StandardButtons buttons, + QDialogButtonBox::StandardButton defaultButton) +{ + QMutexLocker locker(&g_mutex); + + const auto button = getMemory(windowName, (fileName ? *fileName : "")); + if (button != NoButton) { + log::debug("{}: not asking because user always wants response {}", + windowName + (fileName ? QString("/") + *fileName : ""), + buttonToString(button)); + + return button; + } + + QuestionBoxMemory dialog(parent, title, text, fileName, buttons, defaultButton); + dialog.exec(); + + if (dialog.m_Button != QDialogButtonBox::Cancel) { + if (dialog.ui->rememberCheckBox->isChecked()) { + setWindowMemory(windowName, dialog.m_Button); + } + + if (fileName != nullptr && dialog.ui->rememberForCheckBox->isChecked()) { + setFileMemory(windowName, *fileName, dialog.m_Button); + } + } + + return dialog.m_Button; +} + +void QuestionBoxMemory::setWindowMemory(const QString& windowName, Button b) +{ + log::debug("remembering choice {} for window {}", buttonToString(b), windowName); + + g_setWindow(windowName, b); +} + +void QuestionBoxMemory::setFileMemory(const QString& windowName, + const QString& filename, Button b) +{ + log::debug("remembering choice {} for file {}", buttonToString(b), + windowName + "/" + filename); + + g_setFile(windowName, filename, b); +} + +QuestionBoxMemory::Button QuestionBoxMemory::getMemory(const QString& windowName, + const QString& filename) +{ + return g_get(windowName, filename); +} + +QString QuestionBoxMemory::buttonToString(Button b) +{ + using BB = QDialogButtonBox; + + static const std::map map = { + {BB::NoButton, "none"}, + {BB::Ok, "ok"}, + {BB::Save, "save"}, + {BB::SaveAll, "saveall"}, + {BB::Open, "open"}, + {BB::Yes, "yes"}, + {BB::YesToAll, "yestoall"}, + {BB::No, "no"}, + {BB::NoToAll, "notoall"}, + {BB::Abort, "abort"}, + {BB::Retry, "retry"}, + {BB::Ignore, "ignore"}, + {BB::Close, "close"}, + {BB::Cancel, "cancel"}, + {BB::Discard, "discard"}, + {BB::Help, "help"}, + {BB::Apply, "apply"}, + {BB::Reset, "reset"}, + {BB::RestoreDefaults, "restoredefaults"}}; + + auto itor = map.find(b); + + if (itor == map.end()) { + return QString("0x%1").arg(static_cast(b), 0, 16); + } else { + return QString("'%1' (0x%2)").arg(itor->second).arg(static_cast(b), 0, 16); + } +} + +} // namespace MOBase -- cgit v1.3.1