mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
578 lines
20 KiB
C++
578 lines
20 KiB
C++
#include "shell/settings/widget_add_popup.h"
|
|
|
|
#include "config/config_service.h"
|
|
#include "core/deferred_call.h"
|
|
#include "i18n/i18n.h"
|
|
#include "render/render_context.h"
|
|
#include "render/scene/input_area.h"
|
|
#include "render/scene/node.h"
|
|
#include "shell/settings/widget_settings_registry.h"
|
|
#include "ui/controls/button.h"
|
|
#include "ui/controls/flex.h"
|
|
#include "ui/controls/input.h"
|
|
#include "ui/controls/label.h"
|
|
#include "ui/controls/toggle.h"
|
|
#include "ui/palette.h"
|
|
#include "ui/style.h"
|
|
#include "util/string_utils.h"
|
|
#include "wayland/wayland_connection.h"
|
|
#include "xdg-shell-client-protocol.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <cstddef>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <unordered_set>
|
|
#include <utility>
|
|
|
|
namespace settings {
|
|
namespace {
|
|
|
|
std::string laneLabel(std::string_view lane) {
|
|
if (lane == "start") {
|
|
return i18n::tr("settings.entities.widget.lanes.start");
|
|
}
|
|
if (lane == "center") {
|
|
return i18n::tr("settings.entities.widget.lanes.center");
|
|
}
|
|
if (lane == "end") {
|
|
return i18n::tr("settings.entities.widget.lanes.end");
|
|
}
|
|
return std::string(lane);
|
|
}
|
|
|
|
std::unique_ptr<Label> makeLabel(std::string_view text, float fontSize, const ColorSpec& color, bool bold = false) {
|
|
auto label = std::make_unique<Label>();
|
|
label->setText(text);
|
|
label->setFontSize(fontSize);
|
|
label->setColor(color);
|
|
label->setBold(bold);
|
|
return label;
|
|
}
|
|
|
|
void sortSearchOptions(std::vector<SearchPickerOption>& options) {
|
|
std::sort(options.begin(), options.end(), [](const SearchPickerOption& a, const SearchPickerOption& b) {
|
|
const std::string aLabel = StringUtils::toLower(a.label);
|
|
const std::string bLabel = StringUtils::toLower(b.label);
|
|
if (aLabel == bLabel) {
|
|
return a.value < b.value;
|
|
}
|
|
return aLabel < bLabel;
|
|
});
|
|
}
|
|
|
|
void collectWidgetReferenceNames(const std::vector<std::string>& widgets, std::unordered_set<std::string>& seen) {
|
|
for (const auto& widget : widgets) {
|
|
seen.insert(widget);
|
|
}
|
|
}
|
|
|
|
bool widgetReferenceNameExists(const Config& cfg, std::string_view name) {
|
|
const std::string key(name);
|
|
if (isBuiltInWidgetType(name) || cfg.widgets.contains(key)) {
|
|
return true;
|
|
}
|
|
|
|
std::unordered_set<std::string> seen;
|
|
for (const auto& bar : cfg.bars) {
|
|
collectWidgetReferenceNames(bar.startWidgets, seen);
|
|
collectWidgetReferenceNames(bar.centerWidgets, seen);
|
|
collectWidgetReferenceNames(bar.endWidgets, seen);
|
|
for (const auto& ovr : bar.monitorOverrides) {
|
|
if (ovr.startWidgets.has_value()) {
|
|
collectWidgetReferenceNames(*ovr.startWidgets, seen);
|
|
}
|
|
if (ovr.centerWidgets.has_value()) {
|
|
collectWidgetReferenceNames(*ovr.centerWidgets, seen);
|
|
}
|
|
if (ovr.endWidgets.has_value()) {
|
|
collectWidgetReferenceNames(*ovr.endWidgets, seen);
|
|
}
|
|
}
|
|
}
|
|
return seen.contains(key);
|
|
}
|
|
|
|
bool isValidWidgetInstanceId(std::string_view id) {
|
|
if (id.empty()) {
|
|
return false;
|
|
}
|
|
for (const unsigned char c : id) {
|
|
if (!std::isalnum(c) && c != '_' && c != '-') {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::string normalizedWidgetInstanceBase(std::string_view type) {
|
|
std::string out;
|
|
out.reserve(type.size());
|
|
bool lastUnderscore = false;
|
|
for (const unsigned char c : type) {
|
|
if (std::isalnum(c)) {
|
|
out.push_back(static_cast<char>(std::tolower(c)));
|
|
lastUnderscore = false;
|
|
} else if (!lastUnderscore && !out.empty()) {
|
|
out.push_back('_');
|
|
lastUnderscore = true;
|
|
}
|
|
}
|
|
while (!out.empty() && out.back() == '_') {
|
|
out.pop_back();
|
|
}
|
|
return out.empty() ? std::string("widget") : out;
|
|
}
|
|
|
|
std::string nextWidgetInstanceId(const Config& cfg, std::string_view type) {
|
|
const std::string base = normalizedWidgetInstanceBase(type);
|
|
for (std::size_t index = 2; index < 10000; ++index) {
|
|
const std::string candidate = base + "_" + std::to_string(index);
|
|
if (!widgetReferenceNameExists(cfg, candidate)) {
|
|
return candidate;
|
|
}
|
|
}
|
|
return base + "_custom";
|
|
}
|
|
|
|
std::string trimmedText(std::string_view text) {
|
|
std::size_t start = 0;
|
|
while (start < text.size() && std::isspace(static_cast<unsigned char>(text[start]))) {
|
|
++start;
|
|
}
|
|
|
|
std::size_t end = text.size();
|
|
while (end > start && std::isspace(static_cast<unsigned char>(text[end - 1]))) {
|
|
--end;
|
|
}
|
|
|
|
return std::string(text.substr(start, end - start));
|
|
}
|
|
|
|
PopupSurfaceConfig centeredPopupConfig(std::uint32_t parentWidth, std::uint32_t parentHeight, std::uint32_t width,
|
|
std::uint32_t height, std::uint32_t serial) {
|
|
return PopupSurfaceConfig{
|
|
.anchorX = static_cast<std::int32_t>(parentWidth / 2),
|
|
.anchorY = static_cast<std::int32_t>(parentHeight / 2),
|
|
.anchorWidth = 1,
|
|
.anchorHeight = 1,
|
|
.width = std::max<std::uint32_t>(1, width),
|
|
.height = std::max<std::uint32_t>(1, height),
|
|
.anchor = XDG_POSITIONER_ANCHOR_NONE,
|
|
.gravity = XDG_POSITIONER_GRAVITY_NONE,
|
|
.constraintAdjustment =
|
|
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y,
|
|
.offsetX = 0,
|
|
.offsetY = 0,
|
|
.serial = serial,
|
|
.grab = true,
|
|
};
|
|
}
|
|
|
|
} // namespace
|
|
|
|
WidgetAddPopup::~WidgetAddPopup() { destroyPopup(); }
|
|
|
|
void WidgetAddPopup::initialize(WaylandConnection& wayland, ConfigService& config, RenderContext& renderContext) {
|
|
initializeBase(wayland, config, renderContext);
|
|
}
|
|
|
|
void WidgetAddPopup::setOnSelect(SelectCallback callback) { m_onSelect = std::move(callback); }
|
|
|
|
void WidgetAddPopup::setOnDismissed(std::function<void()> callback) { m_onDismissed = std::move(callback); }
|
|
|
|
void WidgetAddPopup::open(xdg_surface* parentXdgSurface, wl_output* output, std::uint32_t serial,
|
|
wl_surface* parentWlSurface, std::uint32_t parentWidth, std::uint32_t parentHeight,
|
|
const std::vector<std::string>& lanePath, const Config& config, float scale) {
|
|
if (parentXdgSurface == nullptr || parentWlSurface == nullptr) {
|
|
return;
|
|
}
|
|
|
|
const auto pickerEntries = widgetPickerEntries(config);
|
|
std::vector<SearchPickerOption> normalOptions;
|
|
std::vector<SearchPickerOption> instanceOptions;
|
|
normalOptions.reserve(pickerEntries.size());
|
|
instanceOptions.reserve(pickerEntries.size());
|
|
|
|
for (const auto& entry : pickerEntries) {
|
|
normalOptions.push_back(SearchPickerOption{
|
|
.value = entry.value, .label = entry.label, .description = entry.description, .enabled = true});
|
|
|
|
if (entry.kind != WidgetReferenceKind::BuiltIn) {
|
|
continue;
|
|
}
|
|
for (const auto& spec : widgetTypeSpecs()) {
|
|
if (spec.type != entry.value || !spec.supportsMultipleInstances) {
|
|
continue;
|
|
}
|
|
instanceOptions.push_back(SearchPickerOption{
|
|
.value = entry.value,
|
|
.label = entry.label,
|
|
.description = i18n::tr("settings.entities.widget.picker.instance-description", "type", entry.value),
|
|
.enabled = true,
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (normalOptions.empty()) {
|
|
return;
|
|
}
|
|
|
|
sortSearchOptions(normalOptions);
|
|
sortSearchOptions(instanceOptions);
|
|
|
|
if (isOpen()) {
|
|
close();
|
|
}
|
|
|
|
m_scale = std::max(0.1f, scale);
|
|
m_config = &config;
|
|
m_normalOptions = std::move(normalOptions);
|
|
m_instanceOptions = std::move(instanceOptions);
|
|
m_lanePath = lanePath;
|
|
m_root = nullptr;
|
|
m_headerRow = nullptr;
|
|
m_createActions = nullptr;
|
|
m_searchPicker = nullptr;
|
|
m_createTitle = nullptr;
|
|
m_instanceInput = nullptr;
|
|
m_instanceModeEnabled = false;
|
|
m_createFormVisible = false;
|
|
m_createType.clear();
|
|
m_createLabel.clear();
|
|
|
|
m_parentXdgSurface = parentXdgSurface;
|
|
m_parentWlSurface = parentWlSurface;
|
|
m_output = output;
|
|
m_serial = serial;
|
|
m_parentWidth = parentWidth;
|
|
m_parentHeight = parentHeight;
|
|
|
|
reopenForCurrentMode();
|
|
}
|
|
|
|
void WidgetAddPopup::close() { destroyPopup(); }
|
|
|
|
bool WidgetAddPopup::isOpen() const noexcept { return DialogPopupHost::isOpen(); }
|
|
|
|
bool WidgetAddPopup::onPointerEvent(const PointerEvent& event) { return DialogPopupHost::onPointerEvent(event); }
|
|
|
|
void WidgetAddPopup::onKeyboardEvent(const KeyboardEvent& event) { DialogPopupHost::onKeyboardEvent(event); }
|
|
|
|
wl_surface* WidgetAddPopup::wlSurface() const noexcept { return DialogPopupHost::wlSurface(); }
|
|
|
|
void WidgetAddPopup::requestLayout() { DialogPopupHost::requestLayout(); }
|
|
|
|
void WidgetAddPopup::requestRedraw() { DialogPopupHost::requestRedraw(); }
|
|
|
|
void WidgetAddPopup::refreshPickerOptions() {
|
|
if (m_searchPicker == nullptr) {
|
|
return;
|
|
}
|
|
m_searchPicker->setOptions(m_instanceModeEnabled ? m_instanceOptions : m_normalOptions);
|
|
}
|
|
|
|
void WidgetAddPopup::refreshBodyState() {
|
|
if (m_searchPicker != nullptr) {
|
|
m_searchPicker->setVisible(!m_createFormVisible);
|
|
m_searchPicker->setParticipatesInLayout(!m_createFormVisible);
|
|
if (!m_createFormVisible) {
|
|
refreshPickerOptions();
|
|
}
|
|
}
|
|
if (m_createTitle != nullptr) {
|
|
m_createTitle->setVisible(m_createFormVisible);
|
|
m_createTitle->setParticipatesInLayout(m_createFormVisible);
|
|
}
|
|
if (m_instanceInput != nullptr) {
|
|
m_instanceInput->setVisible(m_createFormVisible);
|
|
m_instanceInput->setParticipatesInLayout(m_createFormVisible);
|
|
}
|
|
if (m_createActions != nullptr) {
|
|
m_createActions->setVisible(m_createFormVisible);
|
|
m_createActions->setParticipatesInLayout(m_createFormVisible);
|
|
}
|
|
|
|
if (!m_createFormVisible && m_searchPicker != nullptr) {
|
|
if (auto* filter = m_searchPicker->filterInputArea(); filter != nullptr) {
|
|
inputDispatcher().setFocus(filter);
|
|
}
|
|
}
|
|
if (m_createFormVisible && m_instanceInput != nullptr && m_instanceInput->inputArea() != nullptr) {
|
|
inputDispatcher().setFocus(m_instanceInput->inputArea());
|
|
}
|
|
}
|
|
|
|
std::string WidgetAddPopup::suggestedInstanceId(std::string_view type) const {
|
|
if (m_config == nullptr) {
|
|
return std::string(type);
|
|
}
|
|
return nextWidgetInstanceId(*m_config, type);
|
|
}
|
|
|
|
bool WidgetAddPopup::canCreateInstanceId(std::string_view id) const {
|
|
if (m_config == nullptr) {
|
|
return false;
|
|
}
|
|
return isValidWidgetInstanceId(id) && !widgetReferenceNameExists(*m_config, id);
|
|
}
|
|
|
|
void WidgetAddPopup::beginCreateFlow(const SearchPickerOption& option) {
|
|
m_createType = option.value;
|
|
m_createLabel = option.label;
|
|
m_createFormVisible = true;
|
|
if (m_createTitle != nullptr) {
|
|
m_createTitle->setText(i18n::tr("settings.entities.widget.instance.create-title", "type", m_createType));
|
|
}
|
|
if (m_instanceInput != nullptr) {
|
|
m_instanceInput->setValue(suggestedInstanceId(m_createType));
|
|
m_instanceInput->setInvalid(false);
|
|
}
|
|
reopenForCurrentMode();
|
|
}
|
|
|
|
void WidgetAddPopup::finishCreateFlow() {
|
|
if (m_instanceInput == nullptr) {
|
|
return;
|
|
}
|
|
const std::string id = trimmedText(m_instanceInput->value());
|
|
if (!canCreateInstanceId(id)) {
|
|
m_instanceInput->setInvalid(true);
|
|
return;
|
|
}
|
|
m_instanceInput->setInvalid(false);
|
|
if (m_onSelect) {
|
|
m_onSelect(m_lanePath, id, m_createType, id);
|
|
}
|
|
DeferredCall::callLater([this]() { close(); });
|
|
}
|
|
|
|
void WidgetAddPopup::populateContent(Node* contentParent, std::uint32_t /*width*/, std::uint32_t /*height*/) {
|
|
const float panelPadding = Style::spaceSm * m_scale;
|
|
const float panelGap = Style::spaceSm * m_scale;
|
|
|
|
auto root = std::make_unique<Flex>();
|
|
root->setDirection(FlexDirection::Vertical);
|
|
root->setAlign(FlexAlign::Stretch);
|
|
root->setGap(panelGap);
|
|
root->setPadding(panelPadding);
|
|
m_root = root.get();
|
|
|
|
auto header = std::make_unique<Flex>();
|
|
header->setDirection(FlexDirection::Horizontal);
|
|
header->setAlign(FlexAlign::Center);
|
|
header->setGap(Style::spaceSm * m_scale);
|
|
m_headerRow = header.get();
|
|
|
|
const std::string lane = laneLabel(m_lanePath.empty() ? "" : m_lanePath.back());
|
|
const std::string title =
|
|
m_createFormVisible
|
|
? i18n::tr("settings.entities.widget.inspector.add-instance-title", "widget", m_createLabel, "lane", lane)
|
|
: i18n::tr("settings.entities.widget.inspector.add-title", "lane", lane);
|
|
header->addChild(makeLabel(title, Style::fontSizeBody * m_scale, colorSpecFromRole(ColorRole::OnSurface), true));
|
|
|
|
auto spacer = std::make_unique<Flex>();
|
|
spacer->setFlexGrow(1.0f);
|
|
header->addChild(std::move(spacer));
|
|
|
|
if (!m_createFormVisible) {
|
|
header->addChild(makeLabel(i18n::tr("settings.entities.widget.picker.instance-toggle"),
|
|
Style::fontSizeCaption * m_scale, colorSpecFromRole(ColorRole::OnSurfaceVariant),
|
|
false));
|
|
|
|
auto instanceToggle = std::make_unique<Toggle>();
|
|
instanceToggle->setScale(m_scale);
|
|
instanceToggle->setChecked(m_instanceModeEnabled);
|
|
instanceToggle->setOnChange([this](bool value) {
|
|
m_instanceModeEnabled = value;
|
|
m_createFormVisible = false;
|
|
m_createType.clear();
|
|
m_createLabel.clear();
|
|
if (m_instanceInput != nullptr) {
|
|
m_instanceInput->setInvalid(false);
|
|
}
|
|
refreshBodyState();
|
|
requestLayout();
|
|
});
|
|
header->addChild(std::move(instanceToggle));
|
|
}
|
|
|
|
auto closeBtn = std::make_unique<Button>();
|
|
closeBtn->setGlyph("close");
|
|
closeBtn->setVariant(ButtonVariant::Default);
|
|
closeBtn->setGlyphSize(Style::fontSizeBody * m_scale);
|
|
closeBtn->setMinWidth(Style::controlHeightSm * m_scale);
|
|
closeBtn->setMinHeight(Style::controlHeightSm * m_scale);
|
|
closeBtn->setPadding(Style::spaceXs * m_scale);
|
|
closeBtn->setRadius(Style::radiusMd * m_scale);
|
|
closeBtn->setOnClick([this]() { DeferredCall::callLater([this]() { close(); }); });
|
|
header->addChild(std::move(closeBtn));
|
|
root->addChild(std::move(header));
|
|
|
|
auto picker = std::make_unique<SearchPicker>();
|
|
picker->setPlaceholder(i18n::tr("settings.entities.widget.picker.placeholder"));
|
|
picker->setEmptyText(i18n::tr("settings.entities.widget.picker.empty"));
|
|
picker->clearFill();
|
|
picker->clearBorder();
|
|
picker->setRadius(0.0f);
|
|
picker->setPadding(0.0f);
|
|
picker->setFlexGrow(1.0f);
|
|
picker->setOptions(m_normalOptions);
|
|
picker->setOnActivated([this](const SearchPickerOption& option) {
|
|
if (option.value.empty()) {
|
|
return;
|
|
}
|
|
if (m_instanceModeEnabled) {
|
|
beginCreateFlow(option);
|
|
return;
|
|
}
|
|
if (m_onSelect) {
|
|
m_onSelect(m_lanePath, option.value, {}, {});
|
|
}
|
|
DeferredCall::callLater([this]() { close(); });
|
|
});
|
|
picker->setOnCancel([this]() { DeferredCall::callLater([this]() { close(); }); });
|
|
m_searchPicker = picker.get();
|
|
root->addChild(std::move(picker));
|
|
|
|
auto createTitle = makeLabel("", Style::fontSizeCaption * m_scale, colorSpecFromRole(ColorRole::OnSurfaceVariant));
|
|
createTitle->setVisible(false);
|
|
createTitle->setParticipatesInLayout(false);
|
|
m_createTitle = createTitle.get();
|
|
root->addChild(std::move(createTitle));
|
|
|
|
auto instanceInput = std::make_unique<Input>();
|
|
instanceInput->setPlaceholder(i18n::tr("settings.entities.widget.instance.id-placeholder"));
|
|
instanceInput->setFontSize(Style::fontSizeBody * m_scale);
|
|
instanceInput->setControlHeight(Style::controlHeight * m_scale);
|
|
instanceInput->setHorizontalPadding(Style::spaceSm * m_scale);
|
|
instanceInput->setSize(260.0f * m_scale, Style::controlHeight * m_scale);
|
|
instanceInput->setVisible(false);
|
|
instanceInput->setParticipatesInLayout(false);
|
|
instanceInput->setOnChange([this](const std::string& /*value*/) {
|
|
if (m_instanceInput != nullptr) {
|
|
m_instanceInput->setInvalid(false);
|
|
}
|
|
});
|
|
instanceInput->setOnSubmit([this](const std::string& /*value*/) { finishCreateFlow(); });
|
|
m_instanceInput = instanceInput.get();
|
|
root->addChild(std::move(instanceInput));
|
|
|
|
auto actionRow = std::make_unique<Flex>();
|
|
actionRow->setDirection(FlexDirection::Horizontal);
|
|
actionRow->setAlign(FlexAlign::Center);
|
|
actionRow->setGap(Style::spaceSm * m_scale);
|
|
actionRow->setVisible(false);
|
|
actionRow->setParticipatesInLayout(false);
|
|
m_createActions = actionRow.get();
|
|
|
|
auto backBtn = std::make_unique<Button>();
|
|
backBtn->setText(i18n::tr("common.actions.cancel"));
|
|
backBtn->setVariant(ButtonVariant::Ghost);
|
|
backBtn->setFontSize(Style::fontSizeCaption * m_scale);
|
|
backBtn->setMinHeight(Style::controlHeightSm * m_scale);
|
|
backBtn->setPadding(Style::spaceXs * m_scale, Style::spaceSm * m_scale);
|
|
backBtn->setRadius(Style::radiusSm * m_scale);
|
|
backBtn->setOnClick([this]() {
|
|
m_createFormVisible = false;
|
|
m_createType.clear();
|
|
m_createLabel.clear();
|
|
if (m_instanceInput != nullptr) {
|
|
m_instanceInput->setInvalid(false);
|
|
}
|
|
reopenForCurrentMode();
|
|
});
|
|
actionRow->addChild(std::move(backBtn));
|
|
|
|
auto createBtn = std::make_unique<Button>();
|
|
createBtn->setText(i18n::tr("settings.entities.widget.instance.create-save"));
|
|
createBtn->setVariant(ButtonVariant::Default);
|
|
createBtn->setFontSize(Style::fontSizeCaption * m_scale);
|
|
createBtn->setMinHeight(Style::controlHeightSm * m_scale);
|
|
createBtn->setPadding(Style::spaceXs * m_scale, Style::spaceSm * m_scale);
|
|
createBtn->setRadius(Style::radiusSm * m_scale);
|
|
createBtn->setOnClick([this]() { finishCreateFlow(); });
|
|
actionRow->addChild(std::move(createBtn));
|
|
root->addChild(std::move(actionRow));
|
|
|
|
contentParent->addChild(std::move(root));
|
|
|
|
refreshBodyState();
|
|
}
|
|
|
|
void WidgetAddPopup::layoutSheet(float contentWidth, float contentHeight) {
|
|
if (m_root == nullptr || renderContext() == nullptr) {
|
|
return;
|
|
}
|
|
|
|
m_root->setSize(contentWidth, contentHeight);
|
|
m_root->layout(*renderContext());
|
|
}
|
|
|
|
std::pair<float, float> WidgetAddPopup::popupSize() const {
|
|
if (m_createFormVisible) {
|
|
return {360.0f * m_scale, 165.0f * m_scale};
|
|
}
|
|
return {520.0f * m_scale, 420.0f * m_scale};
|
|
}
|
|
|
|
void WidgetAddPopup::reopenForCurrentMode() {
|
|
if (m_parentXdgSurface == nullptr || m_parentWlSurface == nullptr) {
|
|
return;
|
|
}
|
|
|
|
const auto [panelWidth, panelHeight] = popupSize();
|
|
const auto cfg =
|
|
centeredPopupConfig(m_parentWidth, m_parentHeight, static_cast<std::uint32_t>(std::max(1.0f, panelWidth)),
|
|
static_cast<std::uint32_t>(std::max(1.0f, panelHeight)), m_serial);
|
|
|
|
m_internalReopen = true;
|
|
const bool opened = openPopupAsChild(cfg, m_parentXdgSurface, m_parentWlSurface, m_output);
|
|
m_internalReopen = false;
|
|
if (!opened) {
|
|
close();
|
|
}
|
|
}
|
|
|
|
void WidgetAddPopup::cancelToFacade() {}
|
|
|
|
InputArea* WidgetAddPopup::initialFocusArea() {
|
|
if (m_createFormVisible && m_instanceInput != nullptr) {
|
|
return m_instanceInput->inputArea();
|
|
}
|
|
return m_searchPicker != nullptr ? m_searchPicker->filterInputArea() : nullptr;
|
|
}
|
|
|
|
void WidgetAddPopup::onSheetClose() {
|
|
if (m_internalReopen) {
|
|
return;
|
|
}
|
|
m_normalOptions.clear();
|
|
m_instanceOptions.clear();
|
|
m_config = nullptr;
|
|
m_parentXdgSurface = nullptr;
|
|
m_parentWlSurface = nullptr;
|
|
m_output = nullptr;
|
|
m_serial = 0;
|
|
m_parentWidth = 0;
|
|
m_parentHeight = 0;
|
|
m_lanePath.clear();
|
|
m_root = nullptr;
|
|
m_headerRow = nullptr;
|
|
m_createActions = nullptr;
|
|
m_searchPicker = nullptr;
|
|
m_createTitle = nullptr;
|
|
m_instanceInput = nullptr;
|
|
m_instanceModeEnabled = false;
|
|
m_createFormVisible = false;
|
|
m_createType.clear();
|
|
m_createLabel.clear();
|
|
if (m_onDismissed) {
|
|
m_onDismissed();
|
|
}
|
|
}
|
|
|
|
} // namespace settings
|