mirror of https://github.com/cutefishos/settings
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
6.1 KiB
C++
190 lines
6.1 KiB
C++
// SPDX-FileCopyrightText: 2026 Reion Wong <reionwong@gmail.com>
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
#include "cutefish/networkmanager/connections.h"
|
|
#include "cutefish/networkmanager/handler.h"
|
|
#include "pages/network/common/detailsdialog.h"
|
|
#include "pages/network/common/networklist.h"
|
|
#include "pages/network/common/rows.h"
|
|
#include "ui/icon.h"
|
|
#include "ui/cell_layout.h"
|
|
#include "ui/theme.h"
|
|
#include "widgets/card.h"
|
|
#include "widgets/iconbutton.h"
|
|
#include "widgets/listrow.h"
|
|
#include "widgets/metrics.h"
|
|
#include "widgets/picture.h"
|
|
#include "window/options.h"
|
|
#include "window/page.h"
|
|
#include "window/pagelist.h"
|
|
#include "window/settingswindow.h"
|
|
|
|
using namespace cutefish::ui;
|
|
namespace nm = cutefish::networkmanager;
|
|
|
|
namespace settings::network {
|
|
|
|
namespace {
|
|
|
|
// One wired connection: a click activates or deactivates it; the info button
|
|
// opens its details.
|
|
class WiredRow : public ListRow
|
|
{
|
|
public:
|
|
WiredRow()
|
|
{
|
|
m_icon = setLeading<Picture>();
|
|
m_icon->setLayoutHints({.preferredWidth = 18, .preferredHeight = 18});
|
|
m_check = addContent<Icon>("check", 16);
|
|
m_info = addContent<IconButton>("info", 20);
|
|
m_info->onClicked = [this] {
|
|
if (onInfo)
|
|
onInfo(m_item);
|
|
};
|
|
}
|
|
|
|
void setItem(const nm::NetworkItem& item)
|
|
{
|
|
m_item = item;
|
|
setName("wired:" + item.name);
|
|
setText(item.uniqueName);
|
|
m_check->setVisible(item.connectionState == nm::ConnectionStatus::Activated);
|
|
}
|
|
|
|
const nm::NetworkItem& item() const { return m_item; }
|
|
|
|
std::function<void(const nm::NetworkItem& item)> onInfo;
|
|
|
|
protected:
|
|
void layout() override
|
|
{
|
|
const Theme& theme = Theme::current();
|
|
m_icon->setPath(dataPath(std::string("images/") + (theme.darkMode ? "dark/" : "light/") + "network-wired.svg"));
|
|
m_check->setColor(theme.highlight);
|
|
m_info->setColor(theme.highlight);
|
|
ListRow::layout();
|
|
}
|
|
|
|
private:
|
|
nm::NetworkItem m_item;
|
|
Picture* m_icon;
|
|
Icon* m_check;
|
|
IconButton* m_info;
|
|
};
|
|
|
|
class EthernetPage : public Page
|
|
{
|
|
public:
|
|
explicit EthernetPage(SettingsWindow& window)
|
|
: Page(window, "Ethernet")
|
|
{
|
|
// The switch and the wired connections share one card.
|
|
m_card = content()->addChild<Card>(Card::Style::List);
|
|
m_switch = m_card->addChild<SwitchRow>("Ethernet");
|
|
m_switch->setName("ethernet:switch");
|
|
m_switch->onToggled = [this](bool checked) {
|
|
if (!m_list.isMock())
|
|
m_handler.enableWired(checked);
|
|
};
|
|
m_rows = std::make_unique<KeyedRows<WiredRow>>([this](View* parent) {
|
|
WiredRow* row = parent->addChild<WiredRow>();
|
|
row->onClicked = [this, row] { toggle(row->item()); };
|
|
row->onInfo = [this](const nm::NetworkItem& item) {
|
|
m_details = std::make_unique<DetailsDialog>(settingsWindow(), m_list, DetailsDialog::Kind::Wired, item);
|
|
m_details->show();
|
|
};
|
|
return row;
|
|
});
|
|
|
|
m_subscriptions.push_back(m_list.changed.connect([this] { update(); }));
|
|
m_subscriptions.push_back(m_enabled.changed.connect([this] { update(); }));
|
|
update();
|
|
}
|
|
|
|
private:
|
|
void toggle(const nm::NetworkItem& item)
|
|
{
|
|
if (m_list.isMock())
|
|
return;
|
|
if (item.connectionState == nm::ConnectionStatus::Deactivated)
|
|
m_handler.activateConnection(item.connectionPath, item.devicePath, item.specificPath);
|
|
else
|
|
m_handler.deactivateConnection(item.connectionPath, item.devicePath);
|
|
}
|
|
|
|
void update()
|
|
{
|
|
const bool mock = m_list.isMock();
|
|
m_card->setVisible(mock || m_enabled.isWiredAvailable());
|
|
m_switch->setChecked(mock || m_enabled.isWiredEnabled());
|
|
|
|
const std::vector<nm::NetworkItem> items = m_list.rows(nm::ConnectionType::Wired);
|
|
std::vector<std::string> keys;
|
|
for (const nm::NetworkItem& item : items)
|
|
keys.push_back(item.key);
|
|
const std::vector<WiredRow*> rows = m_rows->update(m_card, keys);
|
|
std::vector<View*> order{m_switch};
|
|
for (size_t i = 0; i < rows.size(); ++i) {
|
|
rows[i]->setItem(items[i]);
|
|
rows[i]->setVisible(mock || m_enabled.isWiredEnabled());
|
|
order.push_back(rows[i]);
|
|
}
|
|
arrange(m_card, order);
|
|
requestLayout();
|
|
}
|
|
|
|
NetworkList m_list;
|
|
nm::EnabledConnections m_enabled;
|
|
nm::Handler m_handler;
|
|
std::vector<cutefish::base::Subscription> m_subscriptions;
|
|
std::unique_ptr<DetailsDialog> m_details;
|
|
Card* m_card;
|
|
SwitchRow* m_switch;
|
|
std::unique_ptr<KeyedRows<WiredRow>> m_rows;
|
|
};
|
|
|
|
// The Ethernet page lists only connections on a present wired device;
|
|
// without one it would be blank.
|
|
class WiredConnectionsWatch : public AvailabilityWatch
|
|
{
|
|
public:
|
|
explicit WiredConnectionsWatch(AvailabilityCallback callback)
|
|
: m_callback(std::move(callback))
|
|
{
|
|
m_subscriptions.push_back(m_list.changed.connect([this] { report(); }));
|
|
m_subscriptions.push_back(m_enabled.changed.connect([this] { report(); }));
|
|
report();
|
|
}
|
|
|
|
private:
|
|
void report()
|
|
{
|
|
// Known only once NetworkManager has been read.
|
|
if (!m_list.isMock() && !m_enabled.isReady())
|
|
return;
|
|
const bool available = !m_list.rows(nm::ConnectionType::Wired).empty();
|
|
if (m_reported && available == m_available)
|
|
return;
|
|
m_reported = true;
|
|
m_available = available;
|
|
m_callback(available);
|
|
}
|
|
|
|
NetworkList m_list;
|
|
nm::EnabledConnections m_enabled;
|
|
std::vector<cutefish::base::Subscription> m_subscriptions;
|
|
AvailabilityCallback m_callback;
|
|
bool m_reported = false;
|
|
bool m_available = false;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
static const PageRegistration registration(
|
|
"ethernet", [](SettingsWindow& window) -> std::unique_ptr<Page> { return std::make_unique<EthernetPage>(window); },
|
|
[](SettingsWindow&, AvailabilityCallback callback) -> std::unique_ptr<AvailabilityWatch> {
|
|
return std::make_unique<WiredConnectionsWatch>(std::move(callback));
|
|
});
|
|
|
|
} // namespace settings::network
|