diff --git a/launcher/BaseInstance.cpp b/launcher/BaseInstance.cpp index fdbcc11fe..b5d7b2a03 100644 --- a/launcher/BaseInstance.cpp +++ b/launcher/BaseInstance.cpp @@ -49,6 +49,7 @@ #include "settings/OverrideSetting.h" #include "settings/Setting.h" +#include "Application.h" #include "BuildConfig.h" #include "Commandline.h" #include "FileSystem.h" @@ -124,6 +125,14 @@ BaseInstance::BaseInstance(SettingsObjectPtr globalSettings, SettingsObjectPtr s m_settings->registerSetting("ManagedPackVersionName", ""); m_settings->registerSetting("Profiler", ""); + + // Shared folders + m_settings->registerSetting("UseSharedScreenshotsFolder", false); + m_settings->registerSetting("SharedScreenshotsPath", FS::PathCombine(APPLICATION->dataRoot(), "screenshots")); + m_settings->registerSetting("UseSharedSavesFolder", false); + m_settings->registerSetting("SharedSavesPath", FS::PathCombine(APPLICATION->dataRoot(), "saves")); + m_settings->registerSetting("UseSharedResourcePacksFolder", false); + m_settings->registerSetting("SharedResourcePacksPath", FS::PathCombine(APPLICATION->dataRoot(), "resourcepacks")); } QString BaseInstance::getPreLaunchCommand() diff --git a/launcher/BaseInstance.h b/launcher/BaseInstance.h index 6baac4ce8..ad5ac7b95 100644 --- a/launcher/BaseInstance.h +++ b/launcher/BaseInstance.h @@ -284,6 +284,11 @@ class BaseInstance : public QObject, public std::enable_shared_from_thisexec(); + return false; + } + + // Check if the destination already exists. + // If it's already a symlink, it might already be correct. + if (FS::isSymLink(destination)) { + // If the target of the symlink is already the source, there's nothing to do. + if (FS::getSymLinkTarget(destination) == source) { + return true; + } + + FS::deletePath(destination); + } else if (QFileInfo::exists(destination)) { + if (!FS::checkFolderPathEmpty(destination)) { + if (!interactiveMove(destination, source, true)) { + CustomMessageBox::selectable( + nullptr, QObject::tr("Failed"), + QObject::tr("Failed to create %1.\nEnsure that \"%2\" is empty.").arg(symlinkName).arg(destination), + QMessageBox::Warning, QMessageBox::Ok) + ->exec(); + return false; + } + } + + FS::deletePath(destination); + } + + // Make sure the source folder exists + if (!FS::ensureFolderPathExists(source)) { + CustomMessageBox::selectable(nullptr, QObject::tr("Failed"), + QObject::tr("Failed to create %1.\nEnsure that \"%2\" exists.").arg(symlinkName).arg(source), + QMessageBox::Warning, QMessageBox::Ok) + ->exec(); + return false; + } + + FS::create_link folderLink(source, destination); + folderLink.linkRecursively(false); + + if (!folderLink()) { + CustomMessageBox::selectable(nullptr, QObject::tr("Failed"), + QObject::tr("Failed to create %1. Error %2: %3") + .arg(symlinkName) + .arg(folderLink.getOSError().value()) + .arg(folderLink.getOSError().message().c_str()), + QMessageBox::Warning, QMessageBox::Ok) + ->exec(); + } + + return true; +} + } // namespace FS diff --git a/launcher/FileSystem.h b/launcher/FileSystem.h index 0e573a09e..1681c6093 100644 --- a/launcher/FileSystem.h +++ b/launcher/FileSystem.h @@ -99,6 +99,13 @@ bool ensureFolderPathExists(const QFileInfo folderPath); */ bool ensureFolderPathExists(const QString folderPathName); +/** + * @brief Check if the given folder is empty or doesn't exist + * @param folderPathName The path to a folder to check + * @return True if the given folder is empty or doesn't exist + */ +bool checkFolderPathEmpty(const QString& folderPathName); + /** * @brief Copies a directory and it's contents from src to dest */ @@ -286,6 +293,17 @@ class create_link : public QObject { */ bool move(const QString& source, const QString& dest); +/** + * @brief Move a file or folder, and ask the user what to do in case of a conflict. + * @param source What to move. + * @param destination Where to move it to. + * @param recursive If true, all direct children will be moved 1 by 1. + * If false, the source will be directly moved to the destination. + * @param parent The parent of the dialog. + * @return True if everything could be moved. + */ +bool interactiveMove(const QString& source, const QString& destination, bool recursive = false, QWidget* parent = nullptr); + /** * Delete a folder recursively */ @@ -566,4 +584,20 @@ QString getPathNameInLocal8bit(const QString& file); QString getUniqueResourceName(const QString& filePath); +/** + * @brief Check if a file or folder is a symbolic link + * @param path The path to check + * @return True if the object exists and is an symbolic link + */ +bool isSymLink(const QString& path); + +/** + * @brief Get the target of a symbolic link + * @param path The path to check + * @return The target of a symbolic link. Empty if path is not a symbolic link. + */ +QString getSymLinkTarget(const QString& path); + +bool tryCreateSymlink(const QString& source, const QString& destination, const QString& symlinkName = "symbolic link"); + } // namespace FS diff --git a/launcher/minecraft/MinecraftInstance.cpp b/launcher/minecraft/MinecraftInstance.cpp index 7749d0f6b..6c9d80d30 100644 --- a/launcher/minecraft/MinecraftInstance.cpp +++ b/launcher/minecraft/MinecraftInstance.cpp @@ -413,6 +413,11 @@ QString MinecraftInstance::dataPacksDir() return QDir(gameRoot()).filePath(relativePath); } +QString MinecraftInstance::screenshotsDir() const +{ + return FS::PathCombine(gameRoot(), "screenshots"); +} + QString MinecraftInstance::resourcePacksDir() const { return FS::PathCombine(gameRoot(), "resourcepacks"); @@ -1308,4 +1313,39 @@ QList MinecraftInstance::getJarMods() const return mods; } +void MinecraftInstance::applySettings() +{ + // Shared directories + updateSharedDirectories(); +} + +bool MinecraftInstance::updateSharedDirectories() +{ + const std::vector> sharedDirectories = { + { "UseSharedScreenshotsFolder", m_settings->get("SharedScreenshotsPath").toString(), screenshotsDir() }, + { "UseSharedSavesFolder", m_settings->get("SharedSavesPath").toString(), worldDir() }, + { "UseSharedResourcePacksFolder", m_settings->get("SharedResourcePacksPath").toString(), resourcePacksDir() }, + { "UseSharedResourcePacksFolder", m_settings->get("SharedResourcePacksPath").toString(), texturePacksDir() } + }; + + bool success = true; + for (const auto& [useSetting, source, destination] : sharedDirectories) { + // Create symlink if useSetting is true, remove symlink if false. + if (m_settings->get(useSetting).toBool()) { + // Try to create symlink, set setting to false if failed. + if (!FS::tryCreateSymlink(source, destination, tr("shared folder"))) { + m_settings->set(useSetting, false); + success = false; + } + } else { + // Safety check + if (FS::isSymLink(destination)) { + success = FS::deletePath(destination) && success; + } + } + } + + return success; +} + #include "MinecraftInstance.moc" diff --git a/launcher/minecraft/MinecraftInstance.h b/launcher/minecraft/MinecraftInstance.h index c6e519dd2..320c75c92 100644 --- a/launcher/minecraft/MinecraftInstance.h +++ b/launcher/minecraft/MinecraftInstance.h @@ -75,6 +75,7 @@ class MinecraftInstance : public BaseInstance { ////// Directories and files ////// QString jarModsDir() const; + QString screenshotsDir() const; QString resourcePacksDir() const; QString texturePacksDir() const; QString shaderPacksDir() const; @@ -158,9 +159,13 @@ class MinecraftInstance : public BaseInstance { virtual JavaVersion getJavaVersion(); + virtual void applySettings() override; + protected: QMap createCensorFilterFromSession(AuthSessionPtr session); + bool updateSharedDirectories(); + protected: // data std::shared_ptr m_components; mutable std::shared_ptr m_loader_mod_list; diff --git a/launcher/ui/dialogs/FileConflictDialog.cpp b/launcher/ui/dialogs/FileConflictDialog.cpp new file mode 100644 index 000000000..e1c8d490d --- /dev/null +++ b/launcher/ui/dialogs/FileConflictDialog.cpp @@ -0,0 +1,96 @@ +#include "FileConflictDialog.h" +#include "ui_FileConflictDialog.h" + +#include +#include +#include +#include + +#include "Application.h" + +FileConflictDialog::FileConflictDialog(QString source, QString destination, bool move, QWidget* parent) + : QDialog(parent), ui(new Ui::FileConflictDialog), m_result(Result::Cancel) +{ + ui->setupUi(this); + + // Setup buttons + connect(ui->buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &FileConflictDialog::cancel); + if (move) { + setWindowTitle(tr("File conflict while moving files")); + + auto chooseSourceButton = ui->buttonBox->addButton(tr("Keep source"), QDialogButtonBox::DestructiveRole); + chooseSourceButton->setIcon(APPLICATION->getThemedIcon("delete")); + connect(chooseSourceButton, &QPushButton::clicked, this, &FileConflictDialog::chooseSource); + + auto chooseDestinationButton = ui->buttonBox->addButton(tr("Keep destination"), QDialogButtonBox::DestructiveRole); + chooseDestinationButton->setIcon(APPLICATION->getThemedIcon("delete")); + connect(chooseDestinationButton, &QPushButton::clicked, this, &FileConflictDialog::chooseDestination); + } else { + setWindowTitle(tr("File conflict while copying files")); + + auto chooseSourceButton = ui->buttonBox->addButton(tr("Overwrite destination"), QDialogButtonBox::DestructiveRole); + chooseSourceButton->setIcon(APPLICATION->getThemedIcon("delete")); + connect(chooseSourceButton, &QPushButton::clicked, this, &FileConflictDialog::chooseSource); + + auto chooseDestinationButton = ui->buttonBox->addButton(tr("Skip"), QDialogButtonBox::DestructiveRole); + connect(chooseDestinationButton, &QPushButton::clicked, this, &FileConflictDialog::chooseDestination); + } + + // Setup info + ui->sourceInfoLabel->setText(GetFileInfoText(source)); + ui->destinationInfoLabel->setText(GetFileInfoText(destination)); +} + +FileConflictDialog::~FileConflictDialog() +{ + delete ui; +} + +FileConflictDialog::Result FileConflictDialog::execWithResult() +{ + exec(); + return m_result; +} + +FileConflictDialog::Result FileConflictDialog::getResult() const +{ + return m_result; +} + +void FileConflictDialog::chooseSource() +{ + m_result = Result::ChooseSource; + accept(); +} + +void FileConflictDialog::chooseDestination() +{ + m_result = Result::ChooseDestination; + accept(); +} + +void FileConflictDialog::cancel() +{ + m_result = Result::Cancel; + reject(); +} + +QString FileConflictDialog::GetFileInfoText(const QString& filePath) const +{ + QLocale locale; + QFileInfo fileInfo(filePath); + + if (fileInfo.isDir()) { + QDir dirInfo(filePath); + return tr("Name: %1
Size: %2
Last modified: %3
Items: %4") + .arg(filePath) + .arg("-") + .arg(fileInfo.lastModified().toString(locale.dateTimeFormat())) + .arg(dirInfo.entryList(QDir::AllEntries | QDir::NoDotAndDotDot).count()); + } else { + return tr("Name: %1
Size: %2
Last modified: %3") + .arg(filePath) + .arg(locale.formattedDataSize(fileInfo.size())) + .arg(fileInfo.lastModified().toString(locale.dateTimeFormat())); + } +} diff --git a/launcher/ui/dialogs/FileConflictDialog.h b/launcher/ui/dialogs/FileConflictDialog.h new file mode 100644 index 000000000..ef02f7a0e --- /dev/null +++ b/launcher/ui/dialogs/FileConflictDialog.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +namespace Ui { +class FileConflictDialog; +} + +class FileConflictDialog : public QDialog { + Q_OBJECT + + public: + enum Result { Cancel, ChooseSource, ChooseDestination }; + + /// @brief Create a new file conflict dialog + /// @param source The source path. What to copy/move. + /// @param destination The destination path. Where to copy/move. + /// @param move Whether the conflict is for a move or copy action + /// @param parent The parent of the dialog + explicit FileConflictDialog(QString source, QString destination, bool move = false, QWidget* parent = nullptr); + ~FileConflictDialog() override; + + Result execWithResult(); + Result getResult() const; + + private slots: + void chooseSource(); + void chooseDestination(); + void cancel(); + + private: + QString GetFileInfoText(const QString& filePath) const; + + Ui::FileConflictDialog* ui; + Result m_result; +}; diff --git a/launcher/ui/dialogs/FileConflictDialog.ui b/launcher/ui/dialogs/FileConflictDialog.ui new file mode 100644 index 000000000..207c16852 --- /dev/null +++ b/launcher/ui/dialogs/FileConflictDialog.ui @@ -0,0 +1,114 @@ + + + FileConflictDialog + + + + 0 + 0 + 411 + 219 + + + + + 0 + 0 + + + + + + + + + + Would you like to overwrite the destination? + + + Qt::AlignCenter + + + + + + + QLayout::SetDefaultConstraint + + + + + + + + 0 + 0 + + + + <html><head/><body><p><span style=" font-weight:700;">Source</span></p></body></html> + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + + + 0 + 0 + + + + <html><head/><body><p><b>Name:</b></p><p>Size:</p><p>Date:</p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + <html><head/><body><p><span style=" font-weight:700;">Destination</span></p></body></html> + + + Qt::AlignHCenter|Qt::AlignTop + + + + + + + <html><head/><body><p>Name:</p><p>Size:</p><p>Date:</p></body></html> + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel + + + + + + + + diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.cpp b/launcher/ui/pages/instance/ExternalResourcesPage.cpp index d38d16284..418046709 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.cpp +++ b/launcher/ui/pages/instance/ExternalResourcesPage.cpp @@ -38,6 +38,7 @@ #include "ui_ExternalResourcesPage.h" #include "DesktopServices.h" +#include "FileSystem.h" #include "Version.h" #include "minecraft/mod/ResourceFolderModel.h" #include "ui/GuiUtil.h" @@ -149,6 +150,9 @@ void ExternalResourcesPage::openedImpl() m_wide_bar_setting = APPLICATION->settings()->getOrRegisterSetting(setting_name); ui->actionsToolbar->setVisibilityState(QByteArray::fromBase64(m_wide_bar_setting->get().toString().toUtf8())); + + // Enable the symbolic link warning when the folder is a symbolic link + ui->isSymlinkWarning->setVisible(FS::isSymLink(m_model->dir().absolutePath())); } void ExternalResourcesPage::closedImpl() diff --git a/launcher/ui/pages/instance/ExternalResourcesPage.ui b/launcher/ui/pages/instance/ExternalResourcesPage.ui index 5df8aafa2..47b41320b 100644 --- a/launcher/ui/pages/instance/ExternalResourcesPage.ui +++ b/launcher/ui/pages/instance/ExternalResourcesPage.ui @@ -67,6 +67,13 @@ + + + + <html><head/><body><p><span style=" font-weight:700; color:#f5c211;">Warning</span><span style=" color:#f5c211;">: This is a shared folder and potentially shared with multiple instances</span></p></body></html> + + + diff --git a/launcher/ui/pages/instance/ScreenshotsPage.cpp b/launcher/ui/pages/instance/ScreenshotsPage.cpp index 082b44308..904ae1bd3 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.cpp +++ b/launcher/ui/pages/instance/ScreenshotsPage.cpp @@ -563,6 +563,9 @@ void ScreenshotsPage::openedImpl() m_wide_bar_setting = APPLICATION->settings()->getOrRegisterSetting(setting_name); ui->toolBar->setVisibilityState(QByteArray::fromBase64(m_wide_bar_setting->get().toString().toUtf8())); + + // Enable the symbolic link warning when the screenshots folder is a symbolic link + ui->sharedScreenshotsFolderWarninglabel->setVisible(FS::isSymLink(m_folder)); } void ScreenshotsPage::closedImpl() diff --git a/launcher/ui/pages/instance/ScreenshotsPage.ui b/launcher/ui/pages/instance/ScreenshotsPage.ui index 2e2227a29..225ab379f 100644 --- a/launcher/ui/pages/instance/ScreenshotsPage.ui +++ b/launcher/ui/pages/instance/ScreenshotsPage.ui @@ -11,7 +11,7 @@ - + 0 @@ -24,6 +24,19 @@ 0 + + + + false + + + <html><head/><body><p><span style=" font-weight:600; color:#f5c211;">Warning</span><span style=" color:#f5c211;">: This is a shared folder and potentially shared with multiple instances</span></p></body></html> + + + 0 + + + diff --git a/launcher/ui/pages/instance/WorldListPage.cpp b/launcher/ui/pages/instance/WorldListPage.cpp index 31f3bfd3e..247269703 100644 --- a/launcher/ui/pages/instance/WorldListPage.cpp +++ b/launcher/ui/pages/instance/WorldListPage.cpp @@ -48,10 +48,10 @@ #include #include #include +#include #include #include #include -#include #include "FileSystem.h" #include "tools/MCEditTool.h" @@ -126,6 +126,9 @@ void WorldListPage::openedImpl() m_wide_bar_setting = APPLICATION->settings()->getOrRegisterSetting(setting_name); ui->toolBar->setVisibilityState(QByteArray::fromBase64(m_wide_bar_setting->get().toString().toUtf8())); + + // Enable the symbolic link warning when the saves folder is a symbolic link + ui->sharedSavesFolderWarninglabel->setVisible(FS::isSymLink(FS::PathCombine(m_inst->gameRoot(), "saves"))); } void WorldListPage::closedImpl() diff --git a/launcher/ui/pages/instance/WorldListPage.ui b/launcher/ui/pages/instance/WorldListPage.ui index 22c93256c..f8ebae21b 100644 --- a/launcher/ui/pages/instance/WorldListPage.ui +++ b/launcher/ui/pages/instance/WorldListPage.ui @@ -11,7 +11,7 @@ - + 0 @@ -24,6 +24,13 @@ 0 + + + + <html><head/><body><p><span style=" font-weight:700; color:#f5c211;">Warning</span><span style=" color:#f5c211;">: This is a shared folder and potentially shared with multiple instances</span></p></body></html> + + + diff --git a/launcher/ui/widgets/MinecraftSettingsWidget.cpp b/launcher/ui/widgets/MinecraftSettingsWidget.cpp index f46786518..285d5fae3 100644 --- a/launcher/ui/widgets/MinecraftSettingsWidget.cpp +++ b/launcher/ui/widgets/MinecraftSettingsWidget.cpp @@ -53,7 +53,8 @@ MinecraftSettingsWidget::MinecraftSettingsWidget(MinecraftInstancePtr instance, m_ui->setupUi(this); if (m_instance == nullptr) { - m_ui->settingsTabs->removeTab(1); + m_ui->settingsTabs->removeTab(m_ui->settingsTabs->indexOf(m_ui->javaPage)); + m_ui->settingsTabs->removeTab(m_ui->settingsTabs->indexOf(m_ui->sharedFoldersTab)); m_ui->openGlobalSettingsButton->setVisible(false); m_ui->instanceAccountGroupBox->hide(); @@ -281,6 +282,13 @@ void MinecraftSettingsWidget::loadSettings() m_ui->fabric->blockSignals(false); m_ui->quilt->blockSignals(false); m_ui->liteLoader->blockSignals(false); + + // Shared folders + m_ui->sharedScreenshotsFolder->initialize(settings->get("UseSharedScreenshotsFolder").toBool(), + settings->get("SharedScreenshotsPath").toString()); + m_ui->sharedSavesFolder->initialize(settings->get("UseSharedSavesFolder").toBool(), settings->get("SharedSavesPath").toString()); + m_ui->sharedResourcePacksFolder->initialize(settings->get("UseSharedResourcePacksFolder").toBool(), + settings->get("SharedResourcePacksPath").toString()); } m_ui->legacySettingsGroupBox->setChecked(settings->get("OverrideLegacySettings").toBool()); @@ -469,8 +477,21 @@ void MinecraftSettingsWidget::saveSettings() } else { settings->reset("OnlineFixes"); } + + if (m_instance != nullptr) { + // Shared folders + settings->set("UseSharedScreenshotsFolder", m_ui->sharedScreenshotsFolder->isEnabled()); + settings->set("SharedScreenshotsPath", m_ui->sharedScreenshotsFolder->getPath()); + settings->set("UseSharedSavesFolder", m_ui->sharedSavesFolder->isEnabled()); + settings->set("SharedSavesPath", m_ui->sharedSavesFolder->getPath()); + settings->set("UseSharedResourcePacksFolder", m_ui->sharedResourcePacksFolder->isEnabled()); + settings->set("SharedResourcePacksPath", m_ui->sharedResourcePacksFolder->getPath()); + } } + if (m_instance != nullptr) + m_instance->applySettings(); + if (m_javaSettings != nullptr) m_javaSettings->saveSettings(); } diff --git a/launcher/ui/widgets/MinecraftSettingsWidget.ui b/launcher/ui/widgets/MinecraftSettingsWidget.ui index 4a35addc0..4fdb99f04 100644 --- a/launcher/ui/widgets/MinecraftSettingsWidget.ui +++ b/launcher/ui/widgets/MinecraftSettingsWidget.ui @@ -801,6 +801,75 @@ It is most likely you will need to change the path - please refer to the mod's w + + + + 0 + 0 + + + + Shared Folders + + + + + + + 0 + 0 + + + + Settings + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + <html><head/><body><p><span style=" font-weight:600; color:#f5c211;">Warning</span><span style=" color:#f5c211;">: After enabling files cannot be automatically restored to their original folder.</span></p></body></html> + + + + + + + + + + + + + + + + + + + + 0 + 11 + + + + <html><head/><body><p>A shared folder is a folder that can be shared across instances.</p><p>For example: If two instances share the same shared saves folder, they can both play on the same worlds without having to copy the world over.</p></body></html> + + + false + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + + + @@ -818,6 +887,12 @@ It is most likely you will need to change the path - please refer to the mod's w
ui/widgets/EnvironmentVariables.h
1 + + SharedFolderWidget + QWidget +
ui/widgets/SharedFolderWidget.h
+ 1 +
openGlobalSettingsButton diff --git a/launcher/ui/widgets/SharedFolderWidget.cpp b/launcher/ui/widgets/SharedFolderWidget.cpp new file mode 100644 index 000000000..3ae8d007b --- /dev/null +++ b/launcher/ui/widgets/SharedFolderWidget.cpp @@ -0,0 +1,53 @@ +#include "SharedFolderWidget.h" +#include "ui_SharedFolderWidget.h" + +#include + +#include "FileSystem.h" + +SharedFolderWidget::SharedFolderWidget(QWidget* parent) : QWidget(parent), ui(new Ui::SharedFolderWidget) +{ + ui->setupUi(this); +} + +SharedFolderWidget::~SharedFolderWidget() +{ + delete ui; +} + +void SharedFolderWidget::initialize(bool enabled, const QString& path, const QString& label) +{ + ui->enabledCheckBox->setChecked(enabled); + ui->enabledCheckBox->setText(label); + + ui->pathTextBox->setEnabled(enabled); + ui->pathTextBox->setText(path); + + ui->pathBrowseBtn->setEnabled(enabled); +} + +bool SharedFolderWidget::isEnabled() const +{ + return ui->enabledCheckBox->isChecked(); +} + +QString SharedFolderWidget::getPath() const +{ + return ui->pathTextBox->text(); +} + +void SharedFolderWidget::on_enabledCheckBox_toggled(bool checked) +{ + ui->pathTextBox->setEnabled(checked); + ui->pathBrowseBtn->setEnabled(checked); +} + +void SharedFolderWidget::on_pathBrowseBtn_clicked() +{ + QString path = QFileDialog::getExistingDirectory(this, tr("Select shared folder"), ui->pathTextBox->text()); + if (path.isEmpty()) { + return; + } + + ui->pathTextBox->setText(path); +} diff --git a/launcher/ui/widgets/SharedFolderWidget.h b/launcher/ui/widgets/SharedFolderWidget.h new file mode 100644 index 000000000..0d40df152 --- /dev/null +++ b/launcher/ui/widgets/SharedFolderWidget.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace Ui { +class SharedFolderWidget; +} + +class SharedFolderWidget : public QWidget { + Q_OBJECT + + public: + explicit SharedFolderWidget(QWidget* parent = 0); + virtual ~SharedFolderWidget(); + void initialize(bool enabled, const QString& path, const QString& label = ""); + + bool isEnabled() const; + QString getPath() const; + + private slots: + void on_enabledCheckBox_toggled(bool checked); + void on_pathBrowseBtn_clicked(); + + private: + Ui::SharedFolderWidget* ui; +}; diff --git a/launcher/ui/widgets/SharedFolderWidget.ui b/launcher/ui/widgets/SharedFolderWidget.ui new file mode 100644 index 000000000..6f0d857fd --- /dev/null +++ b/launcher/ui/widgets/SharedFolderWidget.ui @@ -0,0 +1,45 @@ + + + SharedFolderWidget + + + + 0 + 0 + 518 + 44 + + + + + + + + + + + + + + + + + false + + + + + + + false + + + Browse + + + + + + + +