add focusController class

This commit is contained in:
Cyril Anisimov 2024-09-14 19:42:55 +02:00
parent 8547de82ea
commit 02bbcd3a31
76 changed files with 1906 additions and 1576 deletions

View file

@ -404,6 +404,9 @@ void AmneziaApplication::initControllers()
m_pageController.reset(new PageController(m_serversModel, m_settings)); m_pageController.reset(new PageController(m_serversModel, m_settings));
m_engine->rootContext()->setContextProperty("PageController", m_pageController.get()); m_engine->rootContext()->setContextProperty("PageController", m_pageController.get());
m_focusController.reset(new FocusController(m_engine, this));
m_engine->rootContext()->setContextProperty("FocusController", m_focusController.get());
m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_clientManagementModel, m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_clientManagementModel,
m_apiServicesModel, m_settings)); m_apiServicesModel, m_settings));
m_engine->rootContext()->setContextProperty("InstallController", m_installController.get()); m_engine->rootContext()->setContextProperty("InstallController", m_installController.get());

View file

@ -19,6 +19,7 @@
#include "ui/controllers/exportController.h" #include "ui/controllers/exportController.h"
#include "ui/controllers/importController.h" #include "ui/controllers/importController.h"
#include "ui/controllers/installController.h" #include "ui/controllers/installController.h"
#include "ui/controllers/focusController.h"
#include "ui/controllers/pageController.h" #include "ui/controllers/pageController.h"
#include "ui/controllers/settingsController.h" #include "ui/controllers/settingsController.h"
#include "ui/controllers/sitesController.h" #include "ui/controllers/sitesController.h"
@ -124,6 +125,7 @@ private:
#endif #endif
QScopedPointer<ConnectionController> m_connectionController; QScopedPointer<ConnectionController> m_connectionController;
QScopedPointer<FocusController> m_focusController;
QScopedPointer<PageController> m_pageController; QScopedPointer<PageController> m_pageController;
QScopedPointer<InstallController> m_installController; QScopedPointer<InstallController> m_installController;
QScopedPointer<ImportController> m_importController; QScopedPointer<ImportController> m_importController;

View file

@ -1,225 +1,226 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>fonts/pt-root-ui_vf.ttf</file>
<file>images/amneziaBigLogo.png</file>
<file>images/AmneziaVPN.png</file>
<file>images/controls/alert-circle.svg</file>
<file>images/controls/amnezia.svg</file>
<file>images/controls/app.svg</file>
<file>images/controls/archive-restore.svg</file>
<file>images/controls/arrow-left.svg</file>
<file>images/controls/arrow-right.svg</file>
<file>images/controls/bug.svg</file>
<file>images/controls/check.svg</file>
<file>images/controls/chevron-down.svg</file>
<file>images/controls/chevron-right.svg</file>
<file>images/controls/chevron-up.svg</file>
<file>images/controls/close.svg</file>
<file>images/controls/copy.svg</file>
<file>images/controls/delete.svg</file>
<file>images/controls/download.svg</file>
<file>images/controls/edit-3.svg</file>
<file>images/controls/eye-off.svg</file>
<file>images/controls/eye.svg</file>
<file>images/controls/file-check-2.svg</file>
<file>images/controls/file-cog-2.svg</file>
<file>images/controls/folder-open.svg</file>
<file>images/controls/folder-search-2.svg</file>
<file>images/controls/gauge.svg</file>
<file>images/controls/github.svg</file>
<file>images/controls/help-circle.svg</file>
<file>images/controls/history.svg</file>
<file>images/controls/home.svg</file>
<file>images/controls/info.svg</file>
<file>images/controls/mail.svg</file>
<file>images/controls/map-pin.svg</file>
<file>images/controls/more-vertical.svg</file>
<file>images/controls/plus.svg</file>
<file>images/controls/qr-code.svg</file>
<file>images/controls/radio-button-inner-circle-pressed.png</file>
<file>images/controls/radio-button-inner-circle.png</file>
<file>images/controls/radio-button-pressed.svg</file>
<file>images/controls/radio-button.svg</file>
<file>images/controls/radio.svg</file>
<file>images/controls/refresh-cw.svg</file>
<file>images/controls/save.svg</file>
<file>images/controls/scan-line.svg</file>
<file>images/controls/search.svg</file>
<file>images/controls/server.svg</file>
<file>images/controls/settings-2.svg</file>
<file>images/controls/settings.svg</file>
<file>images/controls/share-2.svg</file>
<file>images/controls/split-tunneling.svg</file>
<file>images/controls/tag.svg</file>
<file>images/controls/telegram.svg</file>
<file>images/controls/text-cursor.svg</file>
<file>images/controls/trash.svg</file>
<file>images/controls/x-circle.svg</file>
<file>images/tray/active.png</file> <file>images/tray/active.png</file>
<file>images/tray/default.png</file> <file>images/tray/default.png</file>
<file>images/tray/error.png</file> <file>images/tray/error.png</file>
<file>images/AmneziaVPN.png</file> <file>server_scripts/awg/configure_container.sh</file>
<file>server_scripts/remove_container.sh</file> <file>server_scripts/awg/Dockerfile</file>
<file>server_scripts/setup_host_firewall.sh</file> <file>server_scripts/awg/run_container.sh</file>
<file>server_scripts/openvpn_cloak/Dockerfile</file> <file>server_scripts/awg/start.sh</file>
<file>server_scripts/awg/template.conf</file>
<file>server_scripts/build_container.sh</file>
<file>server_scripts/check_connection.sh</file>
<file>server_scripts/check_server_is_busy.sh</file>
<file>server_scripts/check_user_in_sudo.sh</file>
<file>server_scripts/dns/configure_container.sh</file>
<file>server_scripts/dns/Dockerfile</file>
<file>server_scripts/dns/run_container.sh</file>
<file>server_scripts/install_docker.sh</file>
<file>server_scripts/ipsec/configure_container.sh</file>
<file>server_scripts/ipsec/Dockerfile</file>
<file>server_scripts/ipsec/mobileconfig.plist</file>
<file>server_scripts/ipsec/run_container.sh</file>
<file>server_scripts/ipsec/start.sh</file>
<file>server_scripts/ipsec/strongswan.profile</file>
<file>server_scripts/openvpn_cloak/configure_container.sh</file> <file>server_scripts/openvpn_cloak/configure_container.sh</file>
<file>server_scripts/openvpn_cloak/Dockerfile</file>
<file>server_scripts/openvpn_cloak/run_container.sh</file>
<file>server_scripts/openvpn_cloak/start.sh</file> <file>server_scripts/openvpn_cloak/start.sh</file>
<file>server_scripts/openvpn_cloak/template.ovpn</file> <file>server_scripts/openvpn_cloak/template.ovpn</file>
<file>server_scripts/install_docker.sh</file>
<file>server_scripts/build_container.sh</file>
<file>server_scripts/prepare_host.sh</file>
<file>server_scripts/check_connection.sh</file>
<file>server_scripts/remove_all_containers.sh</file>
<file>server_scripts/openvpn_cloak/run_container.sh</file>
<file>server_scripts/openvpn/configure_container.sh</file>
<file>server_scripts/openvpn/run_container.sh</file>
<file>server_scripts/openvpn/template.ovpn</file>
<file>server_scripts/openvpn/Dockerfile</file>
<file>server_scripts/openvpn/start.sh</file>
<file>server_scripts/openvpn_shadowsocks/configure_container.sh</file> <file>server_scripts/openvpn_shadowsocks/configure_container.sh</file>
<file>server_scripts/openvpn_shadowsocks/Dockerfile</file> <file>server_scripts/openvpn_shadowsocks/Dockerfile</file>
<file>server_scripts/openvpn_shadowsocks/run_container.sh</file> <file>server_scripts/openvpn_shadowsocks/run_container.sh</file>
<file>server_scripts/openvpn_shadowsocks/start.sh</file> <file>server_scripts/openvpn_shadowsocks/start.sh</file>
<file>server_scripts/openvpn_shadowsocks/template.ovpn</file> <file>server_scripts/openvpn_shadowsocks/template.ovpn</file>
<file>server_scripts/openvpn/configure_container.sh</file>
<file>server_scripts/openvpn/Dockerfile</file>
<file>server_scripts/openvpn/run_container.sh</file>
<file>server_scripts/openvpn/start.sh</file>
<file>server_scripts/openvpn/template.ovpn</file>
<file>server_scripts/prepare_host.sh</file>
<file>server_scripts/remove_all_containers.sh</file>
<file>server_scripts/remove_container.sh</file>
<file>server_scripts/setup_host_firewall.sh</file>
<file>server_scripts/sftp/configure_container.sh</file>
<file>server_scripts/sftp/Dockerfile</file>
<file>server_scripts/sftp/run_container.sh</file>
<file>server_scripts/socks5_proxy/configure_container.sh</file>
<file>server_scripts/socks5_proxy/Dockerfile</file>
<file>server_scripts/socks5_proxy/run_container.sh</file>
<file>server_scripts/socks5_proxy/start.sh</file>
<file>server_scripts/website_tor/configure_container.sh</file>
<file>server_scripts/website_tor/Dockerfile</file>
<file>server_scripts/website_tor/run_container.sh</file>
<file>server_scripts/wireguard/configure_container.sh</file> <file>server_scripts/wireguard/configure_container.sh</file>
<file>server_scripts/wireguard/Dockerfile</file> <file>server_scripts/wireguard/Dockerfile</file>
<file>server_scripts/wireguard/run_container.sh</file> <file>server_scripts/wireguard/run_container.sh</file>
<file>server_scripts/wireguard/start.sh</file> <file>server_scripts/wireguard/start.sh</file>
<file>server_scripts/wireguard/template.conf</file> <file>server_scripts/wireguard/template.conf</file>
<file>server_scripts/website_tor/configure_container.sh</file>
<file>server_scripts/website_tor/run_container.sh</file>
<file>ui/qml/Config/GlobalConfig.qml</file>
<file>ui/qml/Config/qmldir</file>
<file>server_scripts/check_server_is_busy.sh</file>
<file>server_scripts/dns/configure_container.sh</file>
<file>server_scripts/dns/Dockerfile</file>
<file>server_scripts/dns/run_container.sh</file>
<file>server_scripts/sftp/configure_container.sh</file>
<file>server_scripts/sftp/Dockerfile</file>
<file>server_scripts/sftp/run_container.sh</file>
<file>server_scripts/ipsec/configure_container.sh</file>
<file>server_scripts/ipsec/Dockerfile</file>
<file>server_scripts/ipsec/run_container.sh</file>
<file>server_scripts/ipsec/start.sh</file>
<file>server_scripts/ipsec/mobileconfig.plist</file>
<file>server_scripts/ipsec/strongswan.profile</file>
<file>server_scripts/website_tor/Dockerfile</file>
<file>server_scripts/check_user_in_sudo.sh</file>
<file>ui/qml/Controls2/BasicButtonType.qml</file>
<file>ui/qml/Controls2/TextFieldWithHeaderType.qml</file>
<file>ui/qml/Controls2/LabelWithButtonType.qml</file>
<file>images/controls/arrow-right.svg</file>
<file>images/controls/chevron-right.svg</file>
<file>ui/qml/Controls2/ImageButtonType.qml</file>
<file>ui/qml/Controls2/CardType.qml</file>
<file>ui/qml/Controls2/CheckBoxType.qml</file>
<file>images/controls/check.svg</file>
<file>ui/qml/Controls2/DropDownType.qml</file>
<file>ui/qml/Pages2/PageSetupWizardStart.qml</file>
<file>ui/qml/main2.qml</file>
<file>images/amneziaBigLogo.png</file>
<file>ui/qml/Controls2/FlickableType.qml</file>
<file>ui/qml/Pages2/PageSetupWizardCredentials.qml</file>
<file>ui/qml/Controls2/HeaderType.qml</file>
<file>images/controls/arrow-left.svg</file>
<file>ui/qml/Pages2/PageSetupWizardProtocols.qml</file>
<file>ui/qml/Pages2/PageSetupWizardEasy.qml</file>
<file>images/controls/chevron-down.svg</file>
<file>images/controls/chevron-up.svg</file>
<file>ui/qml/Controls2/TextTypes/ParagraphTextType.qml</file>
<file>ui/qml/Controls2/TextTypes/Header2TextType.qml</file>
<file>ui/qml/Controls2/HorizontalRadioButton.qml</file>
<file>ui/qml/Controls2/VerticalRadioButton.qml</file>
<file>ui/qml/Controls2/SwitcherType.qml</file>
<file>ui/qml/Controls2/TabButtonType.qml</file>
<file>ui/qml/Pages2/PageSetupWizardProtocolSettings.qml</file>
<file>ui/qml/Pages2/PageSetupWizardInstalling.qml</file>
<file>ui/qml/Pages2/PageSetupWizardConfigSource.qml</file>
<file>images/controls/folder-open.svg</file>
<file>images/controls/qr-code.svg</file>
<file>images/controls/text-cursor.svg</file>
<file>ui/qml/Pages2/PageSetupWizardTextKey.qml</file>
<file>ui/qml/Pages2/PageStart.qml</file>
<file>ui/qml/Controls2/TabImageButtonType.qml</file>
<file>images/controls/home.svg</file>
<file>images/controls/settings-2.svg</file>
<file>images/controls/share-2.svg</file>
<file>ui/qml/Pages2/PageHome.qml</file>
<file>ui/qml/Pages2/PageSettingsServersList.qml</file>
<file>ui/qml/Pages2/PageShare.qml</file>
<file>ui/qml/Controls2/TextTypes/Header1TextType.qml</file>
<file>ui/qml/Controls2/TextTypes/LabelTextType.qml</file>
<file>ui/qml/Controls2/TextTypes/ButtonTextType.qml</file>
<file>ui/qml/Controls2/Header2Type.qml</file>
<file>images/controls/plus.svg</file>
<file>ui/qml/Components/ConnectButton.qml</file>
<file>images/controls/download.svg</file>
<file>ui/qml/Controls2/ProgressBarType.qml</file>
<file>ui/qml/Components/ConnectionTypeSelectionDrawer.qml</file>
<file>ui/qml/Components/HomeContainersListView.qml</file>
<file>ui/qml/Controls2/TextTypes/CaptionTextType.qml</file>
<file>images/controls/settings.svg</file>
<file>ui/qml/Pages2/PageSettingsServerInfo.qml</file>
<file>ui/qml/Controls2/PageType.qml</file>
<file>ui/qml/Controls2/PopupType.qml</file>
<file>images/controls/edit-3.svg</file>
<file>ui/qml/Pages2/PageSettingsServerData.qml</file>
<file>ui/qml/Components/SettingsContainersListView.qml</file>
<file>ui/qml/Controls2/TextTypes/ListItemTitleType.qml</file>
<file>ui/qml/Controls2/DividerType.qml</file>
<file>ui/qml/Controls2/StackViewType.qml</file>
<file>ui/qml/Pages2/PageSettings.qml</file>
<file>images/controls/amnezia.svg</file>
<file>images/controls/app.svg</file>
<file>images/controls/radio.svg</file>
<file>images/controls/save.svg</file>
<file>images/controls/server.svg</file>
<file>ui/qml/Pages2/PageSettingsServerProtocols.qml</file>
<file>ui/qml/Pages2/PageSettingsServerServices.qml</file>
<file>ui/qml/Pages2/PageSetupWizardViewConfig.qml</file>
<file>images/controls/file-cog-2.svg</file>
<file>ui/qml/Components/QuestionDrawer.qml</file>
<file>ui/qml/Pages2/PageDeinstalling.qml</file>
<file>ui/qml/Controls2/BackButtonType.qml</file>
<file>ui/qml/Pages2/PageSettingsServerProtocol.qml</file>
<file>ui/qml/Components/TransportProtoSelector.qml</file>
<file>ui/qml/Controls2/ListViewWithRadioButtonType.qml</file>
<file>images/controls/radio-button.svg</file>
<file>images/controls/radio-button-inner-circle.png</file>
<file>images/controls/radio-button-pressed.svg</file>
<file>images/controls/radio-button-inner-circle-pressed.png</file>
<file>ui/qml/Components/ShareConnectionDrawer.qml</file>
<file>ui/qml/Pages2/PageSettingsConnection.qml</file>
<file>ui/qml/Pages2/PageSettingsDns.qml</file>
<file>ui/qml/Pages2/PageSettingsApplication.qml</file>
<file>ui/qml/Pages2/PageSettingsBackup.qml</file>
<file>images/controls/delete.svg</file>
<file>ui/qml/Pages2/PageSettingsAbout.qml</file>
<file>images/controls/github.svg</file>
<file>images/controls/mail.svg</file>
<file>images/controls/telegram.svg</file>
<file>ui/qml/Controls2/TextTypes/SmallTextType.qml</file>
<file>ui/qml/Filters/ContainersModelFilters.qml</file>
<file>ui/qml/Components/SelectLanguageDrawer.qml</file>
<file>ui/qml/Controls2/BusyIndicatorType.qml</file>
<file>ui/qml/Pages2/PageProtocolOpenVpnSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolShadowSocksSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolCloakSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolXraySettings.qml</file>
<file>ui/qml/Pages2/PageProtocolRaw.qml</file>
<file>ui/qml/Pages2/PageSettingsLogging.qml</file>
<file>ui/qml/Pages2/PageServiceSftpSettings.qml</file>
<file>images/controls/copy.svg</file>
<file>ui/qml/Pages2/PageServiceTorWebsiteSettings.qml</file>
<file>ui/qml/Pages2/PageSetupWizardQrReader.qml</file>
<file>images/controls/eye.svg</file>
<file>images/controls/eye-off.svg</file>
<file>ui/qml/Pages2/PageSettingsSplitTunneling.qml</file>
<file>ui/qml/Controls2/ContextMenuType.qml</file>
<file>ui/qml/Controls2/TextAreaType.qml</file>
<file>images/controls/trash.svg</file>
<file>images/controls/more-vertical.svg</file>
<file>ui/qml/Controls2/ListViewWithLabelsType.qml</file>
<file>ui/qml/Pages2/PageServiceDnsSettings.qml</file>
<file>ui/qml/Controls2/TopCloseButtonType.qml</file>
<file>images/controls/x-circle.svg</file>
<file>ui/qml/Pages2/PageProtocolAwgSettings.qml</file>
<file>server_scripts/awg/template.conf</file>
<file>server_scripts/awg/start.sh</file>
<file>server_scripts/awg/configure_container.sh</file>
<file>server_scripts/awg/run_container.sh</file>
<file>server_scripts/awg/Dockerfile</file>
<file>ui/qml/Pages2/PageShareFullAccess.qml</file>
<file>images/controls/close.svg</file>
<file>images/controls/search.svg</file>
<file>server_scripts/xray/configure_container.sh</file> <file>server_scripts/xray/configure_container.sh</file>
<file>server_scripts/xray/Dockerfile</file> <file>server_scripts/xray/Dockerfile</file>
<file>server_scripts/xray/run_container.sh</file> <file>server_scripts/xray/run_container.sh</file>
<file>server_scripts/xray/start.sh</file> <file>server_scripts/xray/start.sh</file>
<file>server_scripts/xray/template.json</file> <file>server_scripts/xray/template.json</file>
<file>ui/qml/Pages2/PageProtocolWireGuardSettings.qml</file> <file>ui/qml/Components/ConnectButton.qml</file>
<file>ui/qml/Components/ConnectionTypeSelectionDrawer.qml</file>
<file>ui/qml/Components/HomeContainersListView.qml</file>
<file>ui/qml/Components/HomeSplitTunnelingDrawer.qml</file> <file>ui/qml/Components/HomeSplitTunnelingDrawer.qml</file>
<file>images/controls/split-tunneling.svg</file>
<file>ui/qml/Controls2/DrawerType2.qml</file>
<file>ui/qml/Pages2/PageSettingsAppSplitTunneling.qml</file>
<file>ui/qml/Components/InstalledAppsDrawer.qml</file> <file>ui/qml/Components/InstalledAppsDrawer.qml</file>
<file>images/controls/alert-circle.svg</file> <file>ui/qml/Components/QuestionDrawer.qml</file>
<file>images/controls/file-check-2.svg</file> <file>ui/qml/Components/SelectLanguageDrawer.qml</file>
<file>ui/qml/Components/ServersListView.qml</file>
<file>ui/qml/Components/SettingsContainersListView.qml</file>
<file>ui/qml/Components/ShareConnectionDrawer.qml</file>
<file>ui/qml/Components/TransportProtoSelector.qml</file>
<file>ui/qml/Config/GlobalConfig.qml</file>
<file>ui/qml/Config/qmldir</file>
<file>ui/qml/Controls2/BackButtonType.qml</file>
<file>ui/qml/Controls2/BasicButtonType.qml</file>
<file>ui/qml/Controls2/BusyIndicatorType.qml</file>
<file>ui/qml/Controls2/CardType.qml</file>
<file>ui/qml/Controls2/CardWithIconsType.qml</file>
<file>ui/qml/Controls2/CheckBoxType.qml</file>
<file>ui/qml/Controls2/ContextMenuType.qml</file>
<file>ui/qml/Controls2/DividerType.qml</file>
<file>ui/qml/Controls2/DrawerType2.qml</file>
<file>ui/qml/Controls2/DropDownType.qml</file>
<file>ui/qml/Controls2/FlickableType.qml</file>
<file>ui/qml/Controls2/Header2Type.qml</file>
<file>ui/qml/Controls2/HeaderType.qml</file>
<file>ui/qml/Controls2/HorizontalRadioButton.qml</file>
<file>ui/qml/Controls2/ImageButtonType.qml</file>
<file>ui/qml/Controls2/LabelWithButtonType.qml</file>
<file>ui/qml/Controls2/LabelWithImageType.qml</file>
<file>ui/qml/Controls2/ListViewWithLabelsType.qml</file>
<file>ui/qml/Controls2/ListViewWithRadioButtonType.qml</file>
<file>ui/qml/Controls2/PageType.qml</file>
<file>ui/qml/Controls2/PopupType.qml</file>
<file>ui/qml/Controls2/ProgressBarType.qml</file>
<file>ui/qml/Controls2/StackViewType.qml</file>
<file>ui/qml/Controls2/SwitcherType.qml</file>
<file>ui/qml/Controls2/TabButtonType.qml</file>
<file>ui/qml/Controls2/TabImageButtonType.qml</file>
<file>ui/qml/Controls2/TextAreaType.qml</file>
<file>ui/qml/Controls2/TextAreaWithFooterType.qml</file>
<file>ui/qml/Controls2/TextFieldWithHeaderType.qml</file>
<file>ui/qml/Controls2/TextTypes/ButtonTextType.qml</file>
<file>ui/qml/Controls2/TextTypes/CaptionTextType.qml</file>
<file>ui/qml/Controls2/TextTypes/Header1TextType.qml</file>
<file>ui/qml/Controls2/TextTypes/Header2TextType.qml</file>
<file>ui/qml/Controls2/TextTypes/LabelTextType.qml</file>
<file>ui/qml/Controls2/TextTypes/ListItemTitleType.qml</file>
<file>ui/qml/Controls2/TextTypes/ParagraphTextType.qml</file>
<file>ui/qml/Controls2/TextTypes/SmallTextType.qml</file>
<file>ui/qml/Controls2/TopCloseButtonType.qml</file>
<file>ui/qml/Controls2/VerticalRadioButton.qml</file>
<file>ui/qml/Controls2/WarningType.qml</file> <file>ui/qml/Controls2/WarningType.qml</file>
<file>fonts/pt-root-ui_vf.ttf</file> <file>ui/qml/Filters/ContainersModelFilters.qml</file>
<file>ui/qml/Modules/Style/qmldir</file> <file>ui/qml/main2.qml</file>
<file>ui/qml/Modules/Style/AmneziaStyle.qml</file> <file>ui/qml/Modules/Style/AmneziaStyle.qml</file>
<file>ui/qml/Modules/Style/qmldir</file>
<file>ui/qml/Pages2/PageDeinstalling.qml</file>
<file>ui/qml/Pages2/PageDevMenu.qml</file>
<file>ui/qml/Pages2/PageHome.qml</file>
<file>ui/qml/Pages2/PageProtocolAwgSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolCloakSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolOpenVpnSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolRaw.qml</file>
<file>ui/qml/Pages2/PageProtocolShadowSocksSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolWireGuardSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolXraySettings.qml</file>
<file>ui/qml/Pages2/PageServiceDnsSettings.qml</file>
<file>ui/qml/Pages2/PageServiceSftpSettings.qml</file>
<file>ui/qml/Pages2/PageServiceSocksProxySettings.qml</file> <file>ui/qml/Pages2/PageServiceSocksProxySettings.qml</file>
<file>server_scripts/socks5_proxy/run_container.sh</file> <file>ui/qml/Pages2/PageServiceTorWebsiteSettings.qml</file>
<file>server_scripts/socks5_proxy/Dockerfile</file> <file>ui/qml/Pages2/PageSettings.qml</file>
<file>server_scripts/socks5_proxy/configure_container.sh</file> <file>ui/qml/Pages2/PageSettingsAbout.qml</file>
<file>server_scripts/socks5_proxy/start.sh</file> <file>ui/qml/Pages2/PageSettingsApiLanguageList.qml</file>
<file>ui/qml/Pages2/PageSettingsApiServerInfo.qml</file>
<file>ui/qml/Pages2/PageSettingsApplication.qml</file>
<file>ui/qml/Pages2/PageSettingsAppSplitTunneling.qml</file>
<file>ui/qml/Pages2/PageSettingsBackup.qml</file>
<file>ui/qml/Pages2/PageSettingsConnection.qml</file>
<file>ui/qml/Pages2/PageSettingsDns.qml</file>
<file>ui/qml/Pages2/PageSettingsLogging.qml</file>
<file>ui/qml/Pages2/PageSettingsServerData.qml</file>
<file>ui/qml/Pages2/PageSettingsServerInfo.qml</file>
<file>ui/qml/Pages2/PageSettingsServerProtocol.qml</file>
<file>ui/qml/Pages2/PageSettingsServerProtocols.qml</file>
<file>ui/qml/Pages2/PageSettingsServerServices.qml</file>
<file>ui/qml/Pages2/PageSettingsServersList.qml</file>
<file>ui/qml/Pages2/PageSettingsSplitTunneling.qml</file>
<file>ui/qml/Pages2/PageProtocolAwgClientSettings.qml</file> <file>ui/qml/Pages2/PageProtocolAwgClientSettings.qml</file>
<file>ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml</file> <file>ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml</file>
<file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file>
<file>ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml</file> <file>ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml</file>
<file>ui/qml/Controls2/CardWithIconsType.qml</file> <file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file>
<file>images/controls/tag.svg</file> <file>ui/qml/Pages2/PageSetupWizardConfigSource.qml</file>
<file>images/controls/history.svg</file> <file>ui/qml/Pages2/PageSetupWizardCredentials.qml</file>
<file>images/controls/gauge.svg</file> <file>ui/qml/Pages2/PageSetupWizardEasy.qml</file>
<file>images/controls/map-pin.svg</file> <file>ui/qml/Pages2/PageSetupWizardInstalling.qml</file>
<file>ui/qml/Controls2/LabelWithImageType.qml</file> <file>ui/qml/Pages2/PageSetupWizardProtocols.qml</file>
<file>images/controls/info.svg</file> <file>ui/qml/Pages2/PageSetupWizardProtocolSettings.qml</file>
<file>ui/qml/Controls2/TextAreaWithFooterType.qml</file> <file>ui/qml/Pages2/PageSetupWizardQrReader.qml</file>
<file>images/controls/scan-line.svg</file> <file>ui/qml/Pages2/PageSetupWizardStart.qml</file>
<file>images/controls/folder-search-2.svg</file> <file>ui/qml/Pages2/PageSetupWizardTextKey.qml</file>
<file>ui/qml/Pages2/PageSettingsApiServerInfo.qml</file> <file>ui/qml/Pages2/PageSetupWizardViewConfig.qml</file>
<file>images/controls/bug.svg</file> <file>ui/qml/Pages2/PageShare.qml</file>
<file>ui/qml/Pages2/PageDevMenu.qml</file> <file>ui/qml/Pages2/PageShareFullAccess.qml</file>
<file>images/controls/refresh-cw.svg</file> <file>ui/qml/Pages2/PageStart.qml</file>
<file>ui/qml/Pages2/PageSettingsApiLanguageList.qml</file>
<file>images/controls/archive-restore.svg</file>
<file>images/controls/help-circle.svg</file>
</qresource> </qresource>
<qresource prefix="/countriesFlags"> <qresource prefix="/countriesFlags">
<file>images/flagKit/ZW.svg</file> <file>images/flagKit/ZW.svg</file>

View file

@ -0,0 +1,476 @@
#include "focusController.h"
#include <QQuickWindow>
#include <QQmlApplicationEngine>
#include <QQuickItem>
#include <QQueue>
#include <QPointF>
#include <QRectF>
bool isVisible(QObject* item)
{
const auto res = item->property("visible").toBool();
// qDebug() << "==>> " << (res ? "VISIBLE" : "NOT visible") << item;
return res;
}
bool isFocusable(QObject* item)
{
const auto res = item->property("isFocusable").toBool();
// qDebug() << "==>> " << (res ? "FOCUSABLE" : "NOT focusable") << item;
return res;
}
QRectF getItemCoordsOnScene(QQuickItem* item) // TODO: remove?
{
if (!item) return {};
return item->mapRectToScene(item->childrenRect());
}
QPointF getItemCenterPointOnScene(QQuickItem* item)
{
const auto x0 = item->x() + (item->width() / 2);
const auto y0 = item->y() + (item->height() / 2);
return item->parentItem()->mapToScene(QPointF{x0, y0});
}
bool isLess(QObject* item1, QObject* item2)
{
const auto p1 = getItemCenterPointOnScene(qobject_cast<QQuickItem*>(item1));
const auto p2 = getItemCenterPointOnScene(qobject_cast<QQuickItem*>(item2));
return (p1.y() == p2.y()) ? (p1.x() < p2.x()) : (p1.y() < p2.y());
}
bool isListView(QObject* item)
{
return item->inherits("QQuickListView");
}
bool isOnTheScene(QObject* object)
{
QQuickItem* item = qobject_cast<QQuickItem*>(object);
if (!item) {
qWarning() << "Couldn't recognize object as item";
return false;
}
if (!item->isVisible()) {
qInfo() << "The item is not visible: " << item;
return false;
}
QRectF itemRect{}; // TODO: ListView couln't get into list because it's children's rect is too large
// if (isListView(item)) {
// itemRect = QRectF(item->x(), item->y(), item->width(), item->height());
// } else {
itemRect = item->mapRectToScene(item->childrenRect());
// }
QQuickWindow* window = item->window();
if (!window) {
qWarning() << "Couldn't get the window on the Scene check";
return false;
}
// const auto contentItem = window->contentItem();
// if (!contentItem) {
// qWarning() << "Couldn't get the content item on the Scene check";
// return false;
// }
// QRectF windowRect = contentItem->childrenRect();
// const auto res = (windowRect.contains(itemRect) || isListView(item));
// // qDebug() << (res ? "===>> item is inside the Scene" : "===>> ITEM IS OUTSIDE THE SCENE") << " itemRect: " << itemRect << "; windowRect: " << windowRect;
// return res;
return true;
}
bool isEnabled(QObject* obj)
{
const auto item = qobject_cast<QQuickItem*>(obj);
return item && item->isEnabled();
}
QQuickItem* getPageOfItem(QQuickItem* item) // TODO: remove?
{
if(!item) {
qWarning() << "item is null";
return {};
}
const auto pagePattern = QString::fromLatin1("Page");
QString className{item->metaObject()->className()};
qDebug() << "=====================>> Item: " << item << " with name: " << item->metaObject()->className();
const auto isPage = className.contains(pagePattern, Qt::CaseSensitive);
if(isPage) {
return item;
} else {
return getPageOfItem(item->parentItem());
}
}
QList<QObject*> getSubChain(QObject* item)
{
QList<QObject*> res;
if (!item) {
qDebug() << "null top item";
return res;
}
const auto children = item->children();
for(const auto child : children) {
if (child
&& isFocusable(child)
&& (isOnTheScene(child))
&& isEnabled(child)
) {
res.append(child);
// qDebug() << "==>> [*** added ***] " << qobject_cast<QQuickItem*>(child);
} else {
// qDebug() << "==>> [** skipped **] " << qobject_cast<QQuickItem*>(child);
res.append(getSubChain(child));
}
}
return res;
}
template<typename T>
void printItems(const T& items, QObject* current_item)
{
qDebug() << "**********************************************";
for(const auto& item : items) {
QQuickItem* i = qobject_cast<QQuickItem*>(item);
QPointF coords {getItemCenterPointOnScene(i)};
QString prefix = current_item == i ? "==>" : " ";
qDebug() << prefix << " Item: " << i << " with coords: " << coords;
}
qDebug() << "**********************************************";
}
/*!
* \brief The ListViewFocusController class manages the focus of elements in ListView
* \details This class object moving focus to ListView's controls since ListView stores
* it's data implicitly and it could be got one by one.
*
* This class was made to store as less as possible data getting it from QML
* when it's needed.
*/
class ListViewFocusController : public QObject
{
public:
explicit ListViewFocusController(QQuickItem* listView, QObject* parent = nullptr);
~ListViewFocusController();
void incrementIndex();
void decrementCurrentIndex();
void positionViewAtIndex();
void focusNextItem();
void focusPreviousItem();
void resetFocusChain();
bool isListViewLastFocusItem();
bool isDelegateLastFocusItem();
private:
int size() const;
int currentIndex() const;
QQuickItem* itemAtIndex(const int index);
QQuickItem* currentDelegate();
QQuickItem* focusedItem();
QQuickItem* m_listView;
QList<QObject*> m_focusChain;
QQuickItem* m_focusedItem;
qsizetype m_focusedItemIndex;
qsizetype m_delegateIndex;
};
ListViewFocusController::ListViewFocusController(QQuickItem* listView, QObject* parent)
: QObject{parent}
, m_listView{listView}
, m_focusChain{}
, m_focusedItem{nullptr}
, m_focusedItemIndex{-1}
, m_delegateIndex{0}
{
}
ListViewFocusController::~ListViewFocusController()
{
}
void ListViewFocusController::positionViewAtIndex()
{
QMetaObject::invokeMethod(m_listView, "positionViewAtIndex",
Q_ARG(int, m_delegateIndex), // Index
Q_ARG(int, 2)); // PositionMode (0 = Visible)
}
int ListViewFocusController::size() const
{
return m_listView->property("count").toInt();
}
int ListViewFocusController::currentIndex() const
{
return m_delegateIndex;
}
void ListViewFocusController::incrementIndex()
{
m_delegateIndex++;
}
void ListViewFocusController::decrementCurrentIndex()
{
m_delegateIndex--;
}
QQuickItem* ListViewFocusController::itemAtIndex(const int index)
{
QQuickItem* item{nullptr};
QMetaObject::invokeMethod(m_listView, "itemAtIndex",
Q_RETURN_ARG(QQuickItem*, item),
Q_ARG(int, index));
return item;
}
QQuickItem* ListViewFocusController::currentDelegate()
{
return itemAtIndex(m_delegateIndex);
}
QQuickItem* ListViewFocusController::focusedItem()
{
return m_focusedItem;
}
void ListViewFocusController::focusNextItem()
{
if (m_focusChain.empty()) {
qWarning() << "Empty focusChain with current delegate: " << currentDelegate();
m_focusChain = getSubChain(currentDelegate());
}
m_focusedItemIndex++;
m_focusedItem = qobject_cast<QQuickItem*>(m_focusChain.at(m_focusedItemIndex));
m_focusedItem->forceActiveFocus();
}
void ListViewFocusController::focusPreviousItem()
{
// TODO: implement
}
void ListViewFocusController::resetFocusChain()
{
m_focusChain.clear();
m_focusedItem = nullptr;
m_focusedItemIndex = -1;
}
bool ListViewFocusController::isDelegateLastFocusItem()
{
return m_focusedItem && (m_focusedItem == m_focusChain.last());
}
bool ListViewFocusController::isListViewLastFocusItem()
{
return (m_delegateIndex == size() - 1) && isDelegateLastFocusItem();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
FocusController::FocusController(QQmlApplicationEngine* engine, QObject *parent)
: QObject{parent}
, m_engine{engine}
, m_focusChain{}
, m_focusedItem{nullptr}
, m_focusedItemIndex{-1}
, m_rootItem{nullptr}
, m_lvfc{nullptr}
{
connect(this, &FocusController::rootItemChanged, this, &FocusController::reload);
}
void FocusController::resetFocus()
{
reload();
if (m_focusChain.empty()) {
qWarning() << "There is no focusable elements";
return;
}
if(m_focusedItemIndex == -1) {
m_focusedItemIndex = 0;
m_focusedItem = qobject_cast<QQuickItem*>(m_focusChain.at(m_focusedItemIndex));
m_focusedItem->forceActiveFocus();
}
}
void FocusController::nextKeyTabItem()
{
if (m_lvfc) {
focusNextListViewItem(); // Need to go on first element by default?
return;
}
reload();
if(m_focusChain.empty()) {
qWarning() << "There are no items to navigate";
return;
}
if (m_focusedItemIndex == (m_focusChain.size() - 1)) {
qDebug() << "Last focus index. Making it zero";
m_focusedItemIndex = 0;
} else {
qDebug() << "Incrementing focus index";
m_focusedItemIndex++;
}
m_focusedItem = qobject_cast<QQuickItem*>(m_focusChain.at(m_focusedItemIndex));
if(m_focusedItem == nullptr) {
qWarning() << "Failed to get item to focus on";
return;
}
if(isListView(m_focusedItem)) {
qDebug() << "===>> Found ListView Item: " << m_focusedItem; // TODO: remove?
m_lvfc = new ListViewFocusController(m_focusedItem, this);
focusNextListViewItem();
return;
}
m_focusedItem->forceActiveFocus(Qt::TabFocusReason);
printItems(m_focusChain, m_focusedItem);
}
void FocusController::focusNextListViewItem()
{
m_lvfc->focusNextItem();
if (m_lvfc->isListViewLastFocusItem()) {
delete m_lvfc;
m_lvfc = nullptr;
} else if (m_lvfc->isDelegateLastFocusItem()) {
m_lvfc->resetFocusChain();
m_lvfc->incrementIndex();
m_lvfc->positionViewAtIndex();
}
}
void FocusController::focusPreviousListViewItem()
{
// TODO: implement
}
void FocusController::previousKeyTabItem()
{
reload();
if(m_focusChain.empty()) {
return;
}
if (m_focusedItemIndex <= 0) {
m_focusedItemIndex = m_focusChain.size() - 1;
} else {
m_focusedItemIndex--;
}
m_focusedItem = qobject_cast<QQuickItem*>(m_focusChain.at(m_focusedItemIndex));
m_focusedItem->forceActiveFocus(Qt::TabFocusReason);
qDebug() << "--> Current focus was changed to " << m_focusedItem;
}
void FocusController::nextKeyUpItem()
{
qDebug() << "nextKeyUpItem" << "triggered";
}
void FocusController::nextKeyDownItem()
{
qDebug() << "nextKeyDownItem" << "triggered";
}
void FocusController::nextKeyLeftItem()
{
qDebug() << "nextKeyLeftItem" << "triggered";
}
void FocusController::nextKeyRightItem()
{
qDebug() << "nextKeyRightItem" << "triggered";
}
void FocusController::reload()
{
m_focusChain.clear();
QObjectList rootObjects;
const auto rootItem = m_rootItem;
if (rootItem != nullptr) {
qDebug() << "*** root item: " << rootItem;
rootObjects << qobject_cast<QObject*>(rootItem);
} else {
qDebug() << "*** root item is null";
rootObjects = m_engine->rootObjects();
}
if(rootObjects.empty()) {
qWarning() << "Empty focus chain detected!";
emit focusChainChanged();
return;
}
for(const auto object : rootObjects) {
m_focusChain.append(getSubChain(object));
}
std::sort(m_focusChain.begin(), m_focusChain.end(), isLess);
printItems(m_focusChain, m_focusedItem);
emit focusChainChanged();
if (m_focusChain.empty()) {
m_focusedItemIndex = -1;
qWarning() << "reloaded to empty focus chain";
return;
}
QQuickWindow* window = qobject_cast<QQuickWindow*>(rootObjects[0]);
if (!window) {
window = qobject_cast<QQuickItem*>(rootObjects[0])->window();
}
if (!window) {
qCritical() << "Couldn't get the current window";
return;
}
// qDebug() << "==> Active Focused Item: " << window->activeFocusItem();
// qDebug() << "--> Active Focused Object: " << window->focusObject();
// qDebug() << ">>> Current Focused Item: " << m_focused_item;
m_focusedItemIndex = m_focusChain.indexOf(window->activeFocusItem());
if(m_focusedItemIndex == -1) {
qDebug() << "===>> No focus item in chain. Moving focus to begin...";
// m_focused_item_index = 0; // if not in focus chain current
return;
}
m_focusedItem = qobject_cast<QQuickItem*>(m_focusChain.at(m_focusedItemIndex));
m_focusedItem->forceActiveFocus();
}
void FocusController::setRootItem(QQuickItem* item)
{
m_rootItem = item;
}

View file

@ -0,0 +1,52 @@
#ifndef FOCUSCONTROLLER_H
#define FOCUSCONTROLLER_H
#include <QObject>
class QQuickItem;
class QQmlApplicationEngine;
class ListViewFocusController;
class FocusController : public QObject
{
Q_OBJECT
public:
explicit FocusController(QQmlApplicationEngine* engine, QObject *parent = nullptr);
~FocusController() override = default;
Q_INVOKABLE void nextKeyTabItem();
Q_INVOKABLE void previousKeyTabItem();
Q_INVOKABLE void nextKeyUpItem();
Q_INVOKABLE void nextKeyDownItem();
Q_INVOKABLE void nextKeyLeftItem();
Q_INVOKABLE void nextKeyRightItem();
signals:
void nextTabItemChanged(QObject* item);
void previousTabItemChanged(QObject* item);
void nextKeyUpItemChanged(QObject* item);
void nextKeyDownItemChanged(QObject* item);
void nextKeyLeftItemChanged(QObject* item);
void nextKeyRightItemChanged(QObject* item);
void focusChainChanged();
void rootItemChanged();
public slots:
void resetFocus();
void reload();
void setRootItem(QQuickItem* item);
private:
void focusNextListViewItem();
void focusPreviousListViewItem();
QQmlApplicationEngine* m_engine; // Pointer to engine to get root object
QList<QObject*> m_focusChain; // List of current objects to be focused
QQuickItem* m_focusedItem; // Pointer to the active focus item
qsizetype m_focusedItemIndex; // Active focus item's index in focus chain
QQuickItem* m_rootItem;
ListViewFocusController* m_lvfc; // ListView focus manager
};
#endif // FOCUSCONTROLLER_H

View file

@ -81,7 +81,7 @@ void PageController::keyPressEvent(Qt::Key key)
case Qt::Key_Escape: { case Qt::Key_Escape: {
if (m_drawerDepth) { if (m_drawerDepth) {
emit closeTopDrawer(); emit closeTopDrawer();
setDrawerDepth(getDrawerDepth() - 1); decrementDrawerDepth();
} else { } else {
emit escapePressed(); emit escapePressed();
} }
@ -142,11 +142,25 @@ void PageController::setDrawerDepth(const int depth)
} }
} }
int PageController::getDrawerDepth() int PageController::getDrawerDepth() const
{ {
return m_drawerDepth; return m_drawerDepth;
} }
int PageController::incrementDrawerDepth()
{
return ++m_drawerDepth;
}
int PageController::decrementDrawerDepth()
{
if (m_drawerDepth == 0) {
return m_drawerDepth;
} else {
return --m_drawerDepth;
}
}
void PageController::onShowErrorMessage(ErrorCode errorCode) void PageController::onShowErrorMessage(ErrorCode errorCode)
{ {
const auto fullErrorMessage = errorString(errorCode); const auto fullErrorMessage = errorString(errorCode);

View file

@ -100,7 +100,9 @@ public slots:
void closeApplication(); void closeApplication();
void setDrawerDepth(const int depth); void setDrawerDepth(const int depth);
int getDrawerDepth(); int getDrawerDepth() const;
int incrementDrawerDepth();
int decrementDrawerDepth();
private slots: private slots:
void onShowErrorMessage(amnezia::ErrorCode errorCode); void onShowErrorMessage(amnezia::ErrorCode errorCode);
@ -135,9 +137,6 @@ signals:
void escapePressed(); void escapePressed();
void closeTopDrawer(); void closeTopDrawer();
void forceTabBarActiveFocus();
void forceStackActiveFocus();
private: private:
QSharedPointer<ServersModel> m_serversModel; QSharedPointer<ServersModel> m_serversModel;

View file

@ -16,6 +16,16 @@ Button {
property string connectedButtonColor: AmneziaStyle.color.goldenApricot property string connectedButtonColor: AmneziaStyle.color.goldenApricot
property bool buttonActiveFocus: activeFocus && (Qt.platform.os !== "android" || SettingsController.isOnTv()) property bool buttonActiveFocus: activeFocus && (Qt.platform.os !== "android" || SettingsController.isOnTv())
property bool isFocusable: true
Keys.onTabPressed: {
FocusController.nextKeyTabItem()
}
Keys.onBacktabPressed: {
FocusController.previousKeyTabItem()
}
implicitWidth: 190 implicitWidth: 190
implicitHeight: 190 implicitHeight: 190

View file

@ -14,7 +14,7 @@ DrawerType2 {
width: parent.width width: parent.width
height: parent.height height: parent.height
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
id: content id: content
anchors.top: parent.top anchors.top: parent.top
@ -26,14 +26,6 @@ DrawerType2 {
root.expandedHeight = content.implicitHeight + 32 root.expandedHeight = content.implicitHeight + 32
} }
Connections {
target: root
enabled: !GC.isMobile()
function onOpened() {
focusItem.forceActiveFocus()
}
}
Header2Type { Header2Type {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 24 Layout.topMargin: 24
@ -44,11 +36,6 @@ DrawerType2 {
headerText: qsTr("Add new connection") headerText: qsTr("Add new connection")
} }
Item {
id: focusItem
KeyNavigation.tab: ip.rightButton
}
LabelWithButtonType { LabelWithButtonType {
id: ip id: ip
Layout.fillWidth: true Layout.fillWidth: true
@ -61,8 +48,6 @@ DrawerType2 {
PageController.goToPage(PageEnum.PageSetupWizardCredentials) PageController.goToPage(PageEnum.PageSetupWizardCredentials)
root.close() root.close()
} }
KeyNavigation.tab: qrCode.rightButton
} }
DividerType {} DividerType {}
@ -78,8 +63,6 @@ DrawerType2 {
PageController.goToPage(PageEnum.PageSetupWizardConfigSource) PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
root.close() root.close()
} }
KeyNavigation.tab: focusItem
} }
DividerType {} DividerType {}

View file

@ -20,52 +20,71 @@ ListView {
property bool a: true property bool a: true
width: rootWidth width: rootWidth
height: menuContent.contentItem.height height: contentItem.height // TODO: It should be fixed size, not content item height
clip: true clip: true
interactive: false // interactive: false
property FlickableType parentFlickable // property FlickableType parentFlickable
property var lastItemTabClicked // property var lastItemTabClicked
property int currentFocusIndex: 0 // property int currentFocusIndex: 0
activeFocusOnTab: true snapMode: ListView.SnapToItem
onActiveFocusChanged: {
if (activeFocus) { // ScrollBar.vertical: ScrollBar {}
this.currentFocusIndex = 0
this.itemAtIndex(currentFocusIndex).forceActiveFocus() property bool isFocusable: true
}
}
Keys.onTabPressed: { Keys.onTabPressed: {
if (currentFocusIndex < this.count - 1) { console.debug("--> Tab is pressed on HomeContainersListView: ", objectName)
currentFocusIndex += 1 FocusController.nextKeyTabItem()
this.itemAtIndex(currentFocusIndex).forceActiveFocus()
} else {
currentFocusIndex = 0
if (lastItemTabClicked && typeof lastItemTabClicked === "function") {
lastItemTabClicked()
}
}
} }
onVisibleChanged: { Keys.onBacktabPressed: {
if (visible) { console.debug("--> Shift+Tab is pressed on HomeContainersListView: ", objectName)
currentFocusIndex = 0 FocusController.previousKeyTabItem()
focusItem.forceActiveFocus()
}
}
Item {
id: focusItem
} }
onCurrentFocusIndexChanged: { // activeFocusOnTab: true
if (parentFlickable) { // onActiveFocusChanged: {
parentFlickable.ensureVisible(this.itemAtIndex(currentFocusIndex)) // console.log("===========================")
} // positionViewAtEnd()
} // parentFlickable.ensureVisible(this.itemAtIndex(6))
// if (activeFocus) {
// this.currentFocusIndex = 0
// this.itemAtIndex(currentFocusIndex).forceActiveFocus()
// }
// }
// Keys.onTabPressed: {
// if (currentFocusIndex < this.count - 1) {
// currentFocusIndex += 1
// this.itemAtIndex(currentFocusIndex).forceActiveFocus()
// } else {
// currentFocusIndex = 0
// if (lastItemTabClicked && typeof lastItemTabClicked === "function") {
// lastItemTabClicked()
// }
// }
// }
// onVisibleChanged: {
// if (visible) {
// currentFocusIndex = 0
// focusItem.forceActiveFocus()
// }
// }
// Item {
// id: focusItem
// }
// onCurrentFocusIndexChanged: {
// if (parentFlickable) {
// parentFlickable.ensureVisible(this.itemAtIndex(currentFocusIndex))
// }
// }
ButtonGroup { ButtonGroup {
id: containersRadioButtonGroup id: containersRadioButtonGroup
@ -75,12 +94,6 @@ ListView {
implicitWidth: rootWidth implicitWidth: rootWidth
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight
onActiveFocusChanged: {
if (activeFocus) {
containerRadioButton.forceActiveFocus()
}
}
ColumnLayout { ColumnLayout {
id: content id: content
@ -111,13 +124,13 @@ ListView {
} }
if (checked) { if (checked) {
containersDropDown.close() containersDropDown.closeTriggered() // TODO: containersDropDown is outside this file
ServersModel.setDefaultContainer(ServersModel.defaultIndex, proxyDefaultServerContainersModel.mapToSource(index)) ServersModel.setDefaultContainer(ServersModel.defaultIndex, proxyDefaultServerContainersModel.mapToSource(index))
} else { } else {
ContainersModel.setProcessedContainerIndex(proxyDefaultServerContainersModel.mapToSource(index)) ContainersModel.setProcessedContainerIndex(proxyDefaultServerContainersModel.mapToSource(index))
InstallController.setShouldCreateServer(false) InstallController.setShouldCreateServer(false)
PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings) PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings)
containersDropDown.close() containersDropDown.closeTriggered()
} }
} }

View file

@ -16,7 +16,7 @@ DrawerType2 {
anchors.fill: parent anchors.fill: parent
expandedHeight: parent.height * 0.9 expandedHeight: parent.height * 0.9
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
id: content id: content
anchors.top: parent.top anchors.top: parent.top
@ -24,14 +24,6 @@ DrawerType2 {
anchors.right: parent.right anchors.right: parent.right
spacing: 0 spacing: 0
Connections {
target: root
enabled: !GC.isMobile()
function onOpened() {
focusItem.forceActiveFocus()
}
}
Header2Type { Header2Type {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 24 Layout.topMargin: 24
@ -43,11 +35,6 @@ DrawerType2 {
descriptionText: qsTr("Allows you to connect to some sites or applications through a VPN connection and bypass others") descriptionText: qsTr("Allows you to connect to some sites or applications through a VPN connection and bypass others")
} }
Item {
id: focusItem
KeyNavigation.tab: splitTunnelingSwitch.visible ? splitTunnelingSwitch : siteBasedSplitTunnelingSwitch.rightButton
}
LabelWithButtonType { LabelWithButtonType {
id: splitTunnelingSwitch id: splitTunnelingSwitch
Layout.fillWidth: true Layout.fillWidth: true
@ -59,7 +46,7 @@ DrawerType2 {
descriptionText: qsTr("Enabled \nCan't be disabled for current server") descriptionText: qsTr("Enabled \nCan't be disabled for current server")
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
KeyNavigation.tab: siteBasedSplitTunnelingSwitch.visible ? siteBasedSplitTunnelingSwitch.rightButton : focusItem // KeyNavigation.tab: siteBasedSplitTunnelingSwitch.visible ? siteBasedSplitTunnelingSwitch.rightButton : focusItem
clickedFunction: function() { clickedFunction: function() {
// PageController.goToPage(PageEnum.PageSettingsSplitTunneling) // PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
@ -80,13 +67,13 @@ DrawerType2 {
descriptionText: enabled && SitesModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled") descriptionText: enabled && SitesModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled")
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
KeyNavigation.tab: appSplitTunnelingSwitch.visible ? // KeyNavigation.tab: appSplitTunnelingSwitch.visible ?
appSplitTunnelingSwitch.rightButton : // appSplitTunnelingSwitch.rightButton :
focusItem // focusItem
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsSplitTunneling) PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
root.close() root.closeTriggered()
} }
} }
@ -103,11 +90,11 @@ DrawerType2 {
descriptionText: AppSplitTunnelingModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled") descriptionText: AppSplitTunnelingModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled")
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
KeyNavigation.tab: focusItem // KeyNavigation.tab: focusItem
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsAppSplitTunneling) PageController.goToPage(PageEnum.PageSettingsAppSplitTunneling)
root.close() root.closeTriggered()
} }
} }

View file

@ -26,7 +26,7 @@ DrawerType2 {
id: installedAppsModel id: installedAppsModel
} }
expandedContent: Item { expandedStateContent: Item {
id: container id: container
implicitHeight: expandedHeight implicitHeight: expandedHeight

View file

@ -20,7 +20,7 @@ DrawerType2 {
property var yesButtonFunction property var yesButtonFunction
property var noButtonFunction property var noButtonFunction
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
id: content id: content
anchors.top: parent.top anchors.top: parent.top
@ -37,7 +37,11 @@ DrawerType2 {
target: root target: root
enabled: !GC.isMobile() enabled: !GC.isMobile()
function onOpened() { function onOpened() {
focusItem.forceActiveFocus() FocusController.setRoot(root)
}
function onClosed() {
FocusController.setRoot(null)
} }
} }
@ -59,11 +63,6 @@ DrawerType2 {
text: descriptionText text: descriptionText
} }
Item {
id: focusItem
KeyNavigation.tab: yesButton
}
BasicButtonType { BasicButtonType {
id: yesButton id: yesButton
Layout.fillWidth: true Layout.fillWidth: true
@ -78,8 +77,6 @@ DrawerType2 {
yesButtonFunction() yesButtonFunction()
} }
} }
KeyNavigation.tab: noButton
} }
BasicButtonType { BasicButtonType {
@ -102,8 +99,6 @@ DrawerType2 {
noButtonFunction() noButtonFunction()
} }
} }
KeyNavigation.tab: focusItem
} }
} }
} }

View file

@ -11,7 +11,7 @@ import "../Config"
DrawerType2 { DrawerType2 {
id: root id: root
expandedContent: Item { expandedStateContent: Item {
id: container id: container
implicitHeight: root.height * 0.9 implicitHeight: root.height * 0.9
@ -24,13 +24,12 @@ DrawerType2 {
target: root target: root
enabled: !GC.isMobile() enabled: !GC.isMobile()
function onOpened() { function onOpened() {
focusItem.forceActiveFocus() FocusController.setRoot(root)
} }
}
Item { function onClosed() {
id: focusItem FocusController.setRoot(null)
KeyNavigation.tab: backButton }
} }
ColumnLayout { ColumnLayout {
@ -44,8 +43,7 @@ DrawerType2 {
BackButtonType { BackButtonType {
id: backButton id: backButton
backButtonImage: "qrc:/images/controls/arrow-left.svg" backButtonImage: "qrc:/images/controls/arrow-left.svg"
backButtonFunction: function() { root.close() } backButtonFunction: function() { root.closeTriggered() }
KeyNavigation.tab: listView
} }
} }
@ -97,15 +95,15 @@ DrawerType2 {
} }
} }
Keys.onTabPressed: { // Keys.onTabPressed: {
if (currentFocusIndex < this.count - 1) { // if (currentFocusIndex < this.count - 1) {
currentFocusIndex += 1 // currentFocusIndex += 1
this.itemAtIndex(currentFocusIndex).forceActiveFocus() // this.itemAtIndex(currentFocusIndex).forceActiveFocus()
} else { // } else {
listViewFocusItem.forceActiveFocus() // listViewFocusItem.forceActiveFocus()
focusItem.forceActiveFocus() // focusItem.forceActiveFocus()
} // }
} // }
Item { Item {
id: listViewFocusItem id: listViewFocusItem
@ -195,7 +193,7 @@ DrawerType2 {
onClicked: { onClicked: {
listView.currentIndex = index listView.currentIndex = index
LanguageModel.changeLanguage(languageIndex) LanguageModel.changeLanguage(languageIndex)
root.close() root.closeTriggered()
} }
} }
} }

View file

@ -0,0 +1,208 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import SortFilterProxyModel 0.2
import PageEnum 1.0
import ProtocolEnum 1.0
import ContainerProps 1.0
import ContainersModelFilters 1.0
import Style 1.0
import "./"
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
ListView {
id: root
anchors.top: serversMenuHeader.bottom
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.topMargin: 16
model: ServersModel
currentIndex: ServersModel.defaultIndex
ScrollBar.vertical: ScrollBar {
id: scrollBar
objectName: "scrollBar"
policy: root.height >= root.contentHeight ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
}
readonly property bool isFocusable: true
// Keys.onTabPressed: {
// FocusController.nextKeyTabItem()
// }
// activeFocusOnTab: true
// focus: true
property int focusItemIndex: 0
// onFocusItemIndexChanged: {
// console.debug("===>> root onFocusItemIndexChanged")
// // const focusedElement = root.itemAtIndex(focusItemIndex)
// // if (focusedElement) {
// // if (focusedElement.y + focusedElement.height > root.height) {
// // root.contentY = focusedElement.y + focusedElement.height - root.height
// // } else {
// // root.contentY = 0
// // }
// // }
// }
Keys.onUpPressed: scrollBar.decrease()
Keys.onDownPressed: scrollBar.increase()
// Connections {
// target: drawer
// enabled: !GC.isMobile()
// function onIsCollapsedChanged() {
// if (drawer.isCollapsedStateActive) {
// const item = root.itemAtIndex(root.focusItemIndex)
// if (item) { item.serverRadioButtonProperty.focus = false }
// }
// }
// }
Connections {
target: ServersModel
function onDefaultServerIndexChanged(serverIndex) {
root.currentIndex = serverIndex
}
}
clip: true
delegate: Item {
id: menuContentDelegate
objectName: "menuContentDelegate"
property variant delegateData: model
property VerticalRadioButton serverRadioButtonProperty: serverRadioButton
implicitWidth: root.width
implicitHeight: serverRadioButtonContent.implicitHeight
ColumnLayout {
id: serverRadioButtonContent
objectName: "serverRadioButtonContent"
anchors.fill: parent
anchors.rightMargin: 16
anchors.leftMargin: 16
spacing: 0
RowLayout {
objectName: "serverRadioButtonRowLayout"
Layout.fillWidth: true
VerticalRadioButton {
id: serverRadioButton
objectName: "serverRadioButton"
Layout.fillWidth: true
focus: true
text: name
descriptionText: serverDescription
checked: index === root.currentIndex
checkable: !ConnectionController.isConnected
ButtonGroup.group: serversRadioButtonGroup
onClicked: {
if (ConnectionController.isConnected) {
PageController.showNotificationMessage(qsTr("Unable change server while there is an active connection"))
return
}
root.currentIndex = index
ServersModel.defaultIndex = index
}
MouseArea {
anchors.fill: serverRadioButton
cursorShape: Qt.PointingHandCursor
enabled: false
}
// Keys.onTabPressed: serverInfoButton.forceActiveFocus()
Keys.onEnterPressed: serverRadioButton.clicked()
Keys.onReturnPressed: serverRadioButton.clicked()
}
ImageButtonType {
id: serverInfoButton
objectName: "serverInfoButton"
// signal keyTabOnLastElement
// isFocusable: false
image: "qrc:/images/controls/settings.svg"
imageColor: AmneziaStyle.color.paleGray
implicitWidth: 56
implicitHeight: 56
z: 1
// onActiveFocusChanged: {
// console.debug("===>> serverInfoButton::activeFocusChanged")
// if (activeFocus) {
// if (currentIndex === root.count - 1) {
// console.log("---> Latest element")
// keyTabOnLastElement()
// }
// console.log("--->>", currentIndex)
// // serverRadioButton.forceActiveFocus()
// }
// }
// onKeyTabOnLastElement: {
// console.log("*** Signal emmited! ***")
// FocusController.nextKeyTabItem()
// }
// Keys.onTabPressed: {
// console.log("===>> serverInfoButton::Keys.onTabPressed")
// if (root.focusItemIndex < root.count - 1) {
// root.focusItemIndex++
// root.itemAtIndex(root.focusItemIndex).forceActiveFocus()
// } else {
// FocusController.nextKeyTabItem()
// root.contentY = 0
// }
// }
Keys.onEnterPressed: serverInfoButton.clicked()
Keys.onReturnPressed: serverInfoButton.clicked()
onClicked: function() {
console.debug("===>> onClicked serverInfoButton")
ServersModel.processedIndex = index
PageController.goToPage(PageEnum.PageSettingsServerInfo)
drawer.closeTriggered()
}
}
}
DividerType {
Layout.fillWidth: true
Layout.leftMargin: 0
Layout.rightMargin: 0
}
}
}
}

View file

@ -36,7 +36,7 @@ DrawerType2 {
configFileName = "amnezia_config" configFileName = "amnezia_config"
} }
expandedContent: Item { expandedStateContent: Item {
implicitHeight: root.expandedHeight implicitHeight: root.expandedHeight
Connections { Connections {
@ -57,8 +57,6 @@ DrawerType2 {
anchors.rightMargin: 16 anchors.rightMargin: 16
headerText: root.headerText headerText: root.headerText
KeyNavigation.tab: shareButton
} }
FlickableType { FlickableType {
@ -86,8 +84,6 @@ DrawerType2 {
text: qsTr("Share") text: qsTr("Share")
leftImageSource: "qrc:/images/controls/share-2.svg" leftImageSource: "qrc:/images/controls/share-2.svg"
KeyNavigation.tab: copyConfigTextButton
clickedFunc: function() { clickedFunc: function() {
var fileName = "" var fileName = ""
if (GC.isMobile()) { if (GC.isMobile()) {
@ -124,8 +120,6 @@ DrawerType2 {
Keys.onReturnPressed: { copyConfigTextButton.clicked() } Keys.onReturnPressed: { copyConfigTextButton.clicked() }
Keys.onEnterPressed: { copyConfigTextButton.clicked() } Keys.onEnterPressed: { copyConfigTextButton.clicked() }
KeyNavigation.tab: copyNativeConfigStringButton.visible ? copyNativeConfigStringButton : showSettingsButton
} }
BasicButtonType { BasicButtonType {
@ -166,8 +160,6 @@ DrawerType2 {
clickedFunc: function() { clickedFunc: function() {
configContentDrawer.open() configContentDrawer.open()
} }
KeyNavigation.tab: header
} }
DrawerType2 { DrawerType2 {
@ -184,24 +176,11 @@ DrawerType2 {
} }
} }
expandedContent: Item { expandedStateContent: Item {
id: configContentContainer id: configContentContainer
implicitHeight: configContentDrawer.expandedHeight implicitHeight: configContentDrawer.expandedHeight
Connections {
target: configContentDrawer
enabled: !GC.isMobile()
function onOpened() {
focusItem.forceActiveFocus()
}
}
Item {
id: focusItem
KeyNavigation.tab: backButton
}
Connections { Connections {
target: copyNativeConfigStringButton target: copyNativeConfigStringButton
function onClicked() { function onClicked() {
@ -232,8 +211,6 @@ DrawerType2 {
anchors.topMargin: 16 anchors.topMargin: 16
backButtonFunction: function() { configContentDrawer.close() } backButtonFunction: function() { configContentDrawer.close() }
KeyNavigation.tab: focusItem
} }
FlickableType { FlickableType {

View file

@ -39,8 +39,6 @@ Rectangle {
implicitWidth: (rootWidth - 32) / 2 implicitWidth: (rootWidth - 32) / 2
text: "UDP" text: "UDP"
KeyNavigation.tab: tcpButton
onClicked: { onClicked: {
root.currentIndex = 0 root.currentIndex = 0
} }

View file

@ -4,23 +4,27 @@ import Qt5Compat.GraphicalEffects
import Style 1.0 import Style 1.0
Item { FocusScope {
id: root id: root
property string backButtonImage: "qrc:/images/controls/arrow-left.svg" property string backButtonImage: "qrc:/images/controls/arrow-left.svg"
property var backButtonFunction property var backButtonFunction
// property bool isFocusable: true
// Keys.onTabPressed: {
// FocusController.nextKeyTabItem()
// }
// Keys.onBacktabPressed: {
// FocusController.previousKeyTabItem()
// }
implicitWidth: content.implicitWidth implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight
visible: backButtonImage !== "" visible: backButtonImage !== ""
onActiveFocusChanged: {
if (activeFocus) {
backButton.forceActiveFocus()
}
}
RowLayout { RowLayout {
id: content id: content
@ -35,6 +39,8 @@ Item {
implicitWidth: 40 implicitWidth: 40
implicitHeight: 40 implicitHeight: 40
// focus: true
onClicked: { onClicked: {
if (backButtonFunction && typeof backButtonFunction === "function") { if (backButtonFunction && typeof backButtonFunction === "function") {
backButtonFunction() backButtonFunction()

View file

@ -35,12 +35,25 @@ Button {
property alias buttonTextLabel: buttonText property alias buttonTextLabel: buttonText
property bool isFocusable: true
Keys.onTabPressed: {
console.debug("--> Tab is pressed on BasicButtonType: ", objectName)
FocusController.nextKeyTabItem()
}
Keys.onBacktabPressed: {
console.debug("--> Shift+Tab is pressed on ", objectName)
FocusController.previousKeyTabItem()
}
implicitHeight: 56 implicitHeight: 56
hoverEnabled: true hoverEnabled: true
focusPolicy: Qt.TabFocus focusPolicy: Qt.TabFocus
onFocusChanged: { onFocusChanged: {
console.debug("===>> BUTTON: active.focus: ", root.activeFocus, " parentFlickable: ", root.parentFlickable )
if (root.activeFocus) { if (root.activeFocus) {
if (root.parentFlickable) { if (root.parentFlickable) {
root.parentFlickable.ensureVisible(this) root.parentFlickable.ensureVisible(this)

View file

@ -25,10 +25,13 @@ Button {
property real textOpacity: 1.0 property real textOpacity: 1.0
property alias focusItem: rightImage
hoverEnabled: true hoverEnabled: true
background: Rectangle { background: Rectangle {
id: backgroundRect id: backgroundRect
anchors.fill: parent anchors.fill: parent
radius: 16 radius: 16
@ -44,8 +47,10 @@ Button {
anchors.right: parent.right anchors.right: parent.right
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight
RowLayout { RowLayout {
id: content id: content
anchors.fill: parent anchors.fill: parent
Image { Image {
@ -61,6 +66,7 @@ Button {
} }
ColumnLayout { ColumnLayout {
ListItemTitleType { ListItemTitleType {
text: root.headerText text: root.headerText
visible: text !== "" visible: text !== ""
@ -123,6 +129,7 @@ Button {
Rectangle { Rectangle {
id: rightImageBackground id: rightImageBackground
anchors.fill: parent anchors.fill: parent
radius: 12 radius: 12
color: "transparent" color: "transparent"
@ -131,10 +138,9 @@ Button {
PropertyAnimation { duration: 200 } PropertyAnimation { duration: 200 }
} }
} }
onClicked: { onClicked: {
if (clickedFunction && typeof clickedFunction === "function") { root.clicked()
clickedFunction()
}
} }
} }
} }

View file

@ -9,17 +9,17 @@ import "TextTypes"
Item { Item {
id: root id: root
readonly property string drawerExpanded: "expanded" readonly property string drawerExpandedStateName: "expanded"
readonly property string drawerCollapsed: "collapsed" readonly property string drawerCollapsedStateName: "collapsed"
readonly property bool isOpened: drawerContent.state === root.drawerExpanded || (drawerContent.state === root.drawerCollapsed && dragArea.drag.active === true) // readonly property bool isExpanded: isExpandedStateActive()
readonly property bool isClosed: drawerContent.state === root.drawerCollapsed && dragArea.drag.active === false // readonly property bool isCollapsed: isCollapsedStateActive()
readonly property bool isExpanded: drawerContent.state === root.drawerExpanded readonly property bool isOpened: isExpandedStateActive() || (isCollapsedStateActive && (dragArea.drag.active === true))
readonly property bool isCollapsed: drawerContent.state === root.drawerCollapsed readonly property bool isClosed: isCollapsedStateActive() && (dragArea.drag.active === false)
property Component collapsedContent property Component collapsedStateContent
property Component expandedContent property Component expandedStateContent
property string defaultColor: AmneziaStyle.color.onyxBlack property string defaultColor: AmneziaStyle.color.onyxBlack
property string borderColor: AmneziaStyle.color.slateGray property string borderColor: AmneziaStyle.color.slateGray
@ -29,29 +29,43 @@ Item {
property int depthIndex: 0 property int depthIndex: 0
signal entered signal cursorEntered
signal exited signal cursorExited
signal pressed(bool pressed, bool entered) signal pressed(bool pressed, bool entered)
signal aboutToHide signal aboutToHide
signal aboutToShow signal aboutToShow
signal close signal closeTriggered
signal open signal openTriggered
signal closed signal closed
signal opened signal opened
function isExpandedStateActive() {
return isStateActive(drawerExpandedStateName)
}
function isCollapsedStateActive() {
return isStateActive(drawerCollapsedStateName)
}
function isStateActive(stateName) {
return drawerContent.state === stateName
}
Connections { Connections {
target: PageController target: PageController
function onCloseTopDrawer() { function onCloseTopDrawer() {
console.debug("===>> onCloseTopDrawer function")
if (depthIndex === PageController.getDrawerDepth()) { if (depthIndex === PageController.getDrawerDepth()) {
if (isCollapsed) { if (isCollapsedStateActive()) {
return return
} }
aboutToHide() aboutToHide()
drawerContent.state = root.drawerCollapsed drawerContent.state = root.drawerCollapsedStateName
depthIndex = 0 depthIndex = 0
closed() closed()
} }
@ -61,30 +75,62 @@ Item {
Connections { Connections {
target: root target: root
function onClose() { function onCloseTriggered() {
if (isCollapsed) { console.debug("***>> onClose root connection")
if (isCollapsedStateActive()) {
return return
} }
aboutToHide() aboutToHide()
drawerContent.state = root.drawerCollapsed
depthIndex = 0
PageController.setDrawerDepth(PageController.getDrawerDepth() - 1)
closed() closed()
} }
function onOpen() { function onClosed() {
if (isExpanded) { console.debug("***>> onClosed root connection")
drawerContent.state = root.drawerCollapsedStateName
if (root.isCollapsedStateActive()) {
var initialPageNavigationBarColor = PageController.getInitialPageNavigationBarColor()
if (initialPageNavigationBarColor !== 0xFF1C1D21) {
PageController.updateNavigationBarColor(initialPageNavigationBarColor)
}
}
depthIndex = 0
PageController.decrementDrawerDepth()
FocusController.setRootItem(null)
}
function onOpenTriggered() {
console.debug("===>> onOpen root connection")
if (root.isExpandedStateActive()) {
return return
} }
aboutToShow() root.aboutToShow()
drawerContent.state = root.drawerExpanded root.opened()
depthIndex = PageController.getDrawerDepth() + 1 }
PageController.setDrawerDepth(depthIndex)
opened() function onOpened() {
drawerContent.state = root.drawerExpandedStateName
console.debug("===>> onOpened root connection")
if (isExpandedStateActive()) {
console.error("new state - extended")
if (PageController.getInitialPageNavigationBarColor() !== 0xFF1C1D21) {
PageController.updateNavigationBarColor(0xFF1C1D21)
}
}
depthIndex = PageController.incrementDrawerDepth()
FocusController.setRootItem(root)
console.debug("===>> Root item has changed to ", root)
} }
} }
@ -102,18 +148,18 @@ Item {
MouseArea { MouseArea {
id: emptyArea id: emptyArea
anchors.fill: parent anchors.fill: parent
enabled: root.isExpanded
visible: enabled
onClicked: { onClicked: {
root.close() console.debug("===>> onClicked emptyArea")
root.closeTriggered()
} }
} }
MouseArea { MouseArea {
id: dragArea id: dragArea
objectName: "dragArea"
anchors.fill: drawerContentBackground anchors.fill: drawerContentBackground
cursorShape: root.isCollapsed ? Qt.PointingHandCursor : Qt.ArrowCursor
hoverEnabled: true hoverEnabled: true
enabled: drawerContent.implicitHeight > 0 enabled: drawerContent.implicitHeight > 0
@ -125,35 +171,46 @@ Item {
/** If drag area is released at any point other than min or max y, transition to the other state */ /** If drag area is released at any point other than min or max y, transition to the other state */
onReleased: { onReleased: {
if (root.isCollapsed && drawerContent.y < dragArea.drag.maximumY) { console.debug("===>> onReleased dragArea")
root.open()
if (isCollapsedStateActive() && drawerContent.y < dragArea.drag.maximumY) {
root.openTriggered()
return return
} }
if (root.isExpanded && drawerContent.y > dragArea.drag.minimumY) { if (isExpandedStateActive() && drawerContent.y > dragArea.drag.minimumY) {
root.close() root.closeTriggered()
return return
} }
} }
onEntered: { onEntered: {
root.entered() console.debug("===>> onEntered dragArea")
root.cursorEntered()
} }
onExited: { onExited: {
root.exited() console.debug("===>> onExited dragArea")
root.cursorExited()
} }
onPressedChanged: { onPressedChanged: {
console.debug("===>> onPressedChanged dragArea")
root.pressed(pressed, entered) root.pressed(pressed, entered)
} }
onClicked: { onClicked: {
if (root.isCollapsed) { console.debug("===>> onClicked dragArea")
root.open()
if (isCollapsedStateActive()) {
root.openTriggered()
} }
} }
} }
Rectangle { Rectangle {
id: drawerContentBackground id: drawerContentBackground
objectName: "drawerContentBackground"
anchors { left: drawerContent.left; right: drawerContent.right; top: drawerContent.top } anchors { left: drawerContent.left; right: drawerContent.right; top: drawerContent.top }
height: root.height height: root.height
@ -174,53 +231,80 @@ Item {
Item { Item {
id: drawerContent id: drawerContent
objectName: "drawerContent"
Drag.active: dragArea.drag.active Drag.active: dragArea.drag.active
anchors.right: root.right anchors.right: root.right
anchors.left: root.left anchors.left: root.left
y: root.height - drawerContent.height
state: root.drawerCollapsed
implicitHeight: root.isCollapsed ? collapsedHeight : expandedHeight state: root.drawerCollapsedStateName
onStateChanged: {
if (root.isCollapsed) {
var initialPageNavigationBarColor = PageController.getInitialPageNavigationBarColor()
if (initialPageNavigationBarColor !== 0xFF1C1D21) {
PageController.updateNavigationBarColor(initialPageNavigationBarColor)
}
return
}
if (root.isExpanded) {
if (PageController.getInitialPageNavigationBarColor() !== 0xFF1C1D21) {
PageController.updateNavigationBarColor(0xFF1C1D21)
}
return
}
}
states: [ states: [
State { State {
name: root.drawerCollapsed name: root.drawerCollapsedStateName
PropertyChanges { PropertyChanges {
target: drawerContent target: drawerContent
implicitHeight: collapsedHeight
y: root.height - root.collapsedHeight y: root.height - root.collapsedHeight
} }
PropertyChanges {
target: background
color: AmneziaStyle.color.transparent
}
PropertyChanges {
target: dragArea
cursorShape: Qt.PointingHandCursor
}
PropertyChanges {
target: emptyArea
enabled: false
visible: false
}
PropertyChanges {
target: collapsedLoader
// visible: true
}
PropertyChanges {
target: expandedLoader
visible: false
}
}, },
State { State {
name: root.drawerExpanded name: root.drawerExpandedStateName
PropertyChanges { PropertyChanges {
target: drawerContent target: drawerContent
implicitHeight: expandedHeight
y: dragArea.drag.minimumY y: dragArea.drag.minimumY
}
PropertyChanges {
target: background
color: Qt.rgba(14/255, 14/255, 17/255, 0.8)
}
PropertyChanges {
target: dragArea
cursorShape: Qt.ArrowCursor
}
PropertyChanges {
target: emptyArea
enabled: true
visible: true
}
PropertyChanges {
target: collapsedLoader
// visible: false
}
PropertyChanges {
target: expandedLoader
visible: true
} }
} }
] ]
transitions: [ transitions: [
Transition { Transition {
from: root.drawerCollapsed from: root.drawerCollapsedStateName
to: root.drawerExpanded to: root.drawerExpandedStateName
PropertyAnimation { PropertyAnimation {
target: drawerContent target: drawerContent
properties: "y" properties: "y"
@ -228,8 +312,8 @@ Item {
} }
}, },
Transition { Transition {
from: root.drawerExpanded from: root.drawerExpandedStateName
to: root.drawerCollapsed to: root.drawerCollapsedStateName
PropertyAnimation { PropertyAnimation {
target: drawerContent target: drawerContent
properties: "y" properties: "y"
@ -241,7 +325,7 @@ Item {
Loader { Loader {
id: collapsedLoader id: collapsedLoader
sourceComponent: root.collapsedContent sourceComponent: root.collapsedStateContent
anchors.right: parent.right anchors.right: parent.right
anchors.left: parent.left anchors.left: parent.left
@ -250,8 +334,7 @@ Item {
Loader { Loader {
id: expandedLoader id: expandedLoader
visible: root.isExpanded sourceComponent: root.expandedStateContent
sourceComponent: root.expandedContent
anchors.right: parent.right anchors.right: parent.right
anchors.left: parent.left anchors.left: parent.left

View file

@ -45,33 +45,51 @@ Item {
property Item drawerParent property Item drawerParent
property Component listView property Component listView
signal open signal openTriggered
signal close signal closeTriggered
function popupClosedFunc() { readonly property bool isFocusable: true
if (!GC.isMobile()) {
this.forceActiveFocus() Keys.onTabPressed: {
} FocusController.nextKeyTabItem()
} }
property var parentFlickable // function popupClosedFunc() {
onFocusChanged: { // if (!GC.isMobile()) {
if (root.activeFocus) { // this.forceActiveFocus()
if (root.parentFlickable) { // }
root.parentFlickable.ensureVisible(root) // }
}
} // property var parentFlickable
} // onFocusChanged: {
// if (root.activeFocus) {
// if (root.parentFlickable) {
// root.parentFlickable.ensureVisible(root)
// }
// }
// }
implicitWidth: rootButtonContent.implicitWidth implicitWidth: rootButtonContent.implicitWidth
implicitHeight: rootButtonContent.implicitHeight implicitHeight: rootButtonContent.implicitHeight
onOpen: { onOpenTriggered: {
menu.open() menu.openTriggered()
} }
onClose: { onCloseTriggered: {
menu.close() menu.closeTriggered()
}
Keys.onEnterPressed: {
if (menu.isClosed) {
menu.openTriggered()
}
}
Keys.onReturnPressed: {
if (menu.isClosed) {
menu.openTriggered()
}
} }
Rectangle { Rectangle {
@ -153,6 +171,8 @@ Item {
} }
ImageButtonType { ImageButtonType {
// isFocusable: false
Layout.rightMargin: 16 Layout.rightMargin: 16
implicitWidth: 40 implicitWidth: 40
@ -173,7 +193,7 @@ Item {
if (rootButtonClickedFunction && typeof rootButtonClickedFunction === "function") { if (rootButtonClickedFunction && typeof rootButtonClickedFunction === "function") {
rootButtonClickedFunction() rootButtonClickedFunction()
} else { } else {
menu.open() menu.openTriggered()
} }
} }
} }
@ -186,27 +206,14 @@ Item {
anchors.fill: parent anchors.fill: parent
expandedHeight: drawerParent.height * drawerHeight expandedHeight: drawerParent.height * drawerHeight
onClosed: { // onClosed: {
root.popupClosedFunc() // root.popupClosedFunc()
} // }
expandedContent: Item { expandedStateContent: Item {
id: container id: container
implicitHeight: menu.expandedHeight implicitHeight: menu.expandedHeight
Connections {
target: menu
enabled: !GC.isMobile()
function onOpened() {
focusItem.forceActiveFocus()
}
}
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: header id: header
@ -218,61 +225,43 @@ Item {
BackButtonType { BackButtonType {
id: backButton id: backButton
backButtonImage: root.headerBackButtonImage backButtonImage: root.headerBackButtonImage
backButtonFunction: function() { menu.close() } backButtonFunction: function() { menu.closeTriggered() }
KeyNavigation.tab: listViewLoader.item // KeyNavigation.tab: listViewLoader.item
} }
} }
FlickableType { Column {
id: flickable id: col
anchors.top: header.bottom anchors.top: parent.top
anchors.topMargin: 16 anchors.left: parent.left
contentHeight: col.implicitHeight anchors.right: parent.right
Column { spacing: 16
id: col
anchors.top: parent.top Header2Type {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 16 headerText: root.headerText
Header2Type { width: parent.width
anchors.left: parent.left }
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
headerText: root.headerText Loader {
id: listViewLoader
sourceComponent: root.listView
width: parent.width onLoaded: {
} // listViewLoader.item.parentFlickable = flickable
// FocusController.reload()
Loader { // listViewLoader.item.lastItemTabClicked = function() {
id: listViewLoader // focusItem.forceActiveFocus()
sourceComponent: root.listView // }
onLoaded: {
listViewLoader.item.parentFlickable = flickable
listViewLoader.item.lastItemTabClicked = function() {
focusItem.forceActiveFocus()
}
}
} }
} }
} }
} }
} }
Keys.onEnterPressed: {
if (menu.isClosed) {
menu.open()
}
}
Keys.onReturnPressed: {
if (menu.isClosed) {
menu.open()
}
}
} }

View file

@ -7,7 +7,7 @@ Flickable {
function ensureVisible(item) { function ensureVisible(item) {
if (item.y < fl.contentY) { if (item.y < fl.contentY) {
fl.contentY = item.y fl.contentY = item.y - 40 // 40 is a top margin
} else if (item.y + item.height > fl.contentY + fl.height) { } else if (item.y + item.height > fl.contentY + fl.height) {
fl.contentY = item.y + item.height - fl.height + 40 // 40 is a bottom margin fl.contentY = item.y + item.height - fl.height + 40 // 40 is a bottom margin
} }

View file

@ -27,6 +27,18 @@ RadioButton {
implicitWidth: content.implicitWidth implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight
property bool isFocusable: true
Keys.onTabPressed: {
console.debug("--> Tab is pressed on BasicButtonType: ", objectName)
FocusController.nextKeyTabItem()
}
Keys.onBacktabPressed: {
console.debug("--> Shift+Tab is pressed on ", objectName)
FocusController.previousKeyTabItem()
}
indicator: Rectangle { indicator: Rectangle {
anchors.fill: parent anchors.fill: parent
radius: 16 radius: 16

View file

@ -24,22 +24,23 @@ Button {
property int borderFocusedWidth: 1 property int borderFocusedWidth: 1
hoverEnabled: true hoverEnabled: true
focus: true
focusPolicy: Qt.TabFocus
icon.source: image icon.source: image
icon.color: root.enabled ? imageColor : disableImageColor icon.color: root.enabled ? imageColor : disableImageColor
property Flickable parentFlickable property bool isFocusable: true
onFocusChanged: { Keys.onTabPressed: {
if (root.activeFocus) { FocusController.nextKeyTabItem()
if (root.parentFlickable) {
root.parentFlickable.ensureVisible(this)
}
}
} }
Keys.onBacktabPressed: {
FocusController.previousKeyTabItem()
}
Keys.onEnterPressed: root.clicked()
Keys.onReturnPressed: root.clicked()
Behavior on icon.color { Behavior on icon.color {
PropertyAnimation { duration: 200 } PropertyAnimation { duration: 200 }
} }

View file

@ -41,27 +41,37 @@ Item {
property bool descriptionOnTop: false property bool descriptionOnTop: false
property bool hideDescription: true property bool hideDescription: true
property bool isFocusable: !(eyeImage.visible || rightImage.visible) // TODO: this component already has focusable items
Keys.onTabPressed: {
FocusController.nextKeyTabItem()
}
Keys.onBacktabPressed: {
FocusController.previousKeyTabItem()
}
implicitWidth: content.implicitWidth + content.anchors.topMargin + content.anchors.bottomMargin implicitWidth: content.implicitWidth + content.anchors.topMargin + content.anchors.bottomMargin
implicitHeight: content.implicitHeight + content.anchors.leftMargin + content.anchors.rightMargin implicitHeight: content.implicitHeight + content.anchors.leftMargin + content.anchors.rightMargin
onFocusChanged: { // onFocusChanged: {
if (root.activeFocus) { // if (root.activeFocus) {
if (root.parentFlickable) { // if (root.parentFlickable) {
root.parentFlickable.ensureVisible(root) // root.parentFlickable.ensureVisible(root)
} // }
} // }
} // }
Connections { // Connections {
target: rightImage // target: rightImage
function onFocusChanged() { // function onFocusChanged() {
if (rightImage.activeFocus) { // if (rightImage.activeFocus) {
if (root.parentFlickable) { // if (root.parentFlickable) {
root.parentFlickable.ensureVisible(root) // root.parentFlickable.ensureVisible(root)
} // }
} // }
} // }
} // }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent

View file

@ -33,40 +33,14 @@ ListView {
property int currentFocusIndex: 0 property int currentFocusIndex: 0
activeFocusOnTab: true property bool isFocusable: true
onActiveFocusChanged: {
if (activeFocus) {
this.currentFocusIndex = 0
this.itemAtIndex(currentFocusIndex).forceActiveFocus()
}
}
Keys.onTabPressed: { Keys.onTabPressed: {
if (currentFocusIndex < this.count - 1) { FocusController.nextKeyTabItem()
currentFocusIndex += 1
} else {
currentFocusIndex = 0
}
this.itemAtIndex(currentFocusIndex).forceActiveFocus()
} }
Item { Keys.onBacktabPressed: {
id: focusItem FocusController.previousKeyTabItem()
Keys.onTabPressed: {
root.forceActiveFocus()
}
}
onVisibleChanged: {
if (visible) {
focusItem.forceActiveFocus()
}
}
onCurrentFocusIndexChanged: {
if (parentFlickable) {
parentFlickable.ensureVisible(this.itemAtIndex(currentFocusIndex))
}
} }
ButtonGroup { ButtonGroup {
@ -83,12 +57,6 @@ ListView {
implicitWidth: rootWidth implicitWidth: rootWidth
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight
onActiveFocusChanged: {
if (activeFocus) {
radioButton.forceActiveFocus()
}
}
ColumnLayout { ColumnLayout {
id: content id: content

View file

@ -9,30 +9,12 @@ Item {
property StackView stackView: StackView.view property StackView stackView: StackView.view
property var defaultActiveFocusItem: null
onVisibleChanged: { onVisibleChanged: {
if (visible && !GC.isMobile()) { if (visible && !GC.isMobile()) {
timer.start() timer.start()
} }
} }
function lastItemTabClicked(focusItem) {
if (GC.isMobile()) {
return
}
if (focusItem) {
focusItem.forceActiveFocus()
PageController.forceTabBarActiveFocus()
} else {
if (defaultActiveFocusItem) {
defaultActiveFocusItem.forceActiveFocus()
}
PageController.forceTabBarActiveFocus()
}
}
// MouseArea { // MouseArea {
// id: globalMouseArea // id: globalMouseArea
// z: 99 // z: 99
@ -49,11 +31,10 @@ Item {
// Set a timer to set focus after a short delay // Set a timer to set focus after a short delay
Timer { Timer {
id: timer id: timer
interval: 100 // Milliseconds interval: 1000 // Milliseconds // TODO: return to 500
onTriggered: { onTriggered: {
if (defaultActiveFocusItem) { console.debug("===>> Page creation completed")
defaultActiveFocusItem.forceActiveFocus() FocusController.resetFocus()
}
} }
repeat: false // Stop the timer after one trigger repeat: false // Stop the timer after one trigger
running: !GC.isMobile() // Start the timer running: !GC.isMobile() // Start the timer

View file

@ -28,11 +28,11 @@ Popup {
} }
onOpened: { onOpened: {
focusItem.forceActiveFocus() FocusController.setRoot(root)
} }
onClosed: { onClosed: {
PageController.forceStackActiveFocus() FocusController.setRoot(null)
} }
background: Rectangle { background: Rectangle {
@ -72,11 +72,6 @@ Popup {
} }
} }
Item {
id: focusItem
KeyNavigation.tab: closeButton
}
BasicButtonType { BasicButtonType {
id: closeButton id: closeButton
visible: closeButtonVisible visible: closeButtonVisible
@ -92,7 +87,6 @@ Popup {
borderWidth: 0 borderWidth: 0
text: qsTr("Close") text: qsTr("Close")
KeyNavigation.tab: focusItem
clickedFunc: function() { clickedFunc: function() {
root.close() root.close()

View file

@ -35,6 +35,16 @@ Switch {
property string hoveredIndicatorBackgroundColor: AmneziaStyle.color.translucentWhite property string hoveredIndicatorBackgroundColor: AmneziaStyle.color.translucentWhite
property string defaultIndicatorBackgroundColor: AmneziaStyle.color.transparent property string defaultIndicatorBackgroundColor: AmneziaStyle.color.transparent
property bool isFocusable: true
Keys.onTabPressed: {
FocusController.nextKeyTabItem()
}
Keys.onBacktabPressed: {
FocusController.previousKeyTabItem()
}
hoverEnabled: enabled ? true : false hoverEnabled: enabled ? true : false
focusPolicy: Qt.TabFocus focusPolicy: Qt.TabFocus

View file

@ -17,10 +17,19 @@ TabButton {
property bool isSelected: false property bool isSelected: false
property bool isFocusable: true
Keys.onTabPressed: {
FocusController.nextKeyTabItem()
}
Keys.onBacktabPressed: {
FocusController.previousKeyTabItem()
}
implicitHeight: 48 implicitHeight: 48
hoverEnabled: true hoverEnabled: true
focusPolicy: Qt.TabFocus
background: Rectangle { background: Rectangle {
id: background id: background

View file

@ -14,13 +14,23 @@ TabButton {
property bool isSelected: false property bool isSelected: false
property bool isFocusable: true
Keys.onTabPressed: {
FocusController.nextKeyTabItem()
}
Keys.onBacktabPressed: {
FocusController.previousKeyTabItem()
}
property string borderFocusedColor: AmneziaStyle.color.paleGray property string borderFocusedColor: AmneziaStyle.color.paleGray
property int borderFocusedWidth: 1 property int borderFocusedWidth: 1
property var clickedFunc property var clickedFunc
hoverEnabled: true hoverEnabled: true
focusPolicy: Qt.TabFocus // focusPolicy: Qt.TabFocus
icon.source: image icon.source: image
icon.color: isSelected ? selectedColor : defaultColor icon.color: isSelected ? selectedColor : defaultColor
@ -43,6 +53,7 @@ TabButton {
} }
Keys.onEnterPressed: { Keys.onEnterPressed: {
console.log("$$$$$$$$$ ENTER PRESSED INSIDE TABIMAGEBUTTONTYPE")
if (root.clickedFunc && typeof root.clickedFunc === "function") { if (root.clickedFunc && typeof root.clickedFunc === "function") {
root.clickedFunc() root.clickedFunc()
} }

View file

@ -78,9 +78,6 @@ Rectangle {
placeholderText: root.placeholderText placeholderText: root.placeholderText
text: root.text text: root.text
KeyNavigation.tab: firstButton
onCursorVisibleChanged: { onCursorVisibleChanged: {
if (textArea.cursorVisible) { if (textArea.cursorVisible) {
fl.interactive = true fl.interactive = true

View file

@ -84,7 +84,16 @@ Item {
TextField { TextField {
id: textField id: textField
activeFocusOnTab: false // activeFocusOnTab: false
property bool isFocusable: true
Keys.onTabPressed: {
FocusController.nextKeyTabItem()
}
Keys.onBacktabPressed: {
FocusController.previousKeyTabItem()
}
enabled: root.textFieldEditable enabled: root.textFieldEditable
color: root.enabled ? root.textFieldTextColor : root.textFieldTextDisabledColor color: root.enabled ? root.textFieldTextColor : root.textFieldTextDisabledColor
@ -209,9 +218,9 @@ Item {
clickedFunc() clickedFunc()
} }
if (KeyNavigation.tab) { // if (KeyNavigation.tab) {
KeyNavigation.tab.forceActiveFocus(); // KeyNavigation.tab.forceActiveFocus();
} // }
} }
Keys.onReturnPressed: { Keys.onReturnPressed: {
@ -219,8 +228,8 @@ Item {
clickedFunc() clickedFunc()
} }
if (KeyNavigation.tab) { // if (KeyNavigation.tab) {
KeyNavigation.tab.forceActiveFocus(); // KeyNavigation.tab.forceActiveFocus();
} // }
} }
} }

View file

@ -28,8 +28,14 @@ RadioButton {
property string imageSource property string imageSource
property bool showImage property bool showImage
property bool isFocusable: true
Keys.onTabPressed: {
FocusController.nextKeyTabItem()
}
hoverEnabled: true hoverEnabled: true
focusPolicy: Qt.TabFocus // focusPolicy: Qt.TabFocus
indicator: Rectangle { indicator: Rectangle {
id: background id: background

View file

@ -16,13 +16,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -34,7 +27,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
// KeyNavigation.tab: removeButton
} }
} }
@ -61,7 +53,6 @@ PageType {
headerText: "Dev menu" headerText: "Dev menu"
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
id: passwordTextField id: passwordTextField
@ -86,8 +77,6 @@ PageType {
SettingsController.gatewayEndpoint = textFieldText SettingsController.gatewayEndpoint = textFieldText
} }
} }
// KeyNavigation.tab: saveButton
} }
SwitcherType { SwitcherType {

View file

@ -19,13 +19,13 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
Connections { Connections {
objectName: "pageControllerConnections"
target: PageController target: PageController
function onRestorePageHomeState(isContainerInstalled) { function onRestorePageHomeState(isContainerInstalled) {
drawer.open() drawer.openTriggered()
if (isContainerInstalled) { if (isContainerInstalled) {
containersDropDown.rootButtonClickedFunction() containersDropDown.rootButtonClickedFunction()
} }
@ -33,23 +33,22 @@ PageType {
} }
Item { Item {
objectName: "homeColumnItem"
anchors.fill: parent anchors.fill: parent
anchors.bottomMargin: drawer.collapsedHeight anchors.bottomMargin: drawer.collapsedHeight
ColumnLayout { ColumnLayout {
objectName: "homeColumnLayout"
anchors.fill: parent anchors.fill: parent
anchors.topMargin: 34 anchors.topMargin: 34
anchors.bottomMargin: 34 anchors.bottomMargin: 34
Item {
id: focusItem
KeyNavigation.tab: loggingButton.visible ?
loggingButton :
connectButton
}
BasicButtonType { BasicButtonType {
id: loggingButton id: loggingButton
objectName: "loggingButton"
property bool isLoggingEnabled: SettingsController.isLoggingEnabled property bool isLoggingEnabled: SettingsController.isLoggingEnabled
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
@ -69,8 +68,6 @@ PageType {
Keys.onEnterPressed: loggingButton.clicked() Keys.onEnterPressed: loggingButton.clicked()
Keys.onReturnPressed: loggingButton.clicked() Keys.onReturnPressed: loggingButton.clicked()
KeyNavigation.tab: connectButton
onClicked: { onClicked: {
PageController.goToPage(PageEnum.PageSettingsLogging) PageController.goToPage(PageEnum.PageSettingsLogging)
} }
@ -78,13 +75,15 @@ PageType {
ConnectButton { ConnectButton {
id: connectButton id: connectButton
objectName: "connectButton"
Layout.fillHeight: true Layout.fillHeight: true
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
KeyNavigation.tab: splitTunnelingButton
} }
BasicButtonType { BasicButtonType {
id: splitTunnelingButton id: splitTunnelingButton
objectName: "splitTunnelingButton"
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
Layout.bottomMargin: 34 Layout.bottomMargin: 34
@ -115,53 +114,47 @@ PageType {
Keys.onEnterPressed: splitTunnelingButton.clicked() Keys.onEnterPressed: splitTunnelingButton.clicked()
Keys.onReturnPressed: splitTunnelingButton.clicked() Keys.onReturnPressed: splitTunnelingButton.clicked()
KeyNavigation.tab: drawer
onClicked: { onClicked: {
homeSplitTunnelingDrawer.open() homeSplitTunnelingDrawer.openTriggered()
} }
HomeSplitTunnelingDrawer { HomeSplitTunnelingDrawer {
id: homeSplitTunnelingDrawer id: homeSplitTunnelingDrawer
objectName: "homeSplitTunnelingDrawer"
parent: root parent: root
onClosed: { onClosed: {
if (!GC.isMobile()) { console.log(objectName, " was closed...")
focusItem.forceActiveFocus() FocusController.setRootItem(null)
}
} }
} }
} }
} }
} }
DrawerType2 { DrawerType2 {
id: drawer id: drawer
objectName: "drawerProtocol"
anchors.fill: parent anchors.fill: parent
onClosed: { collapsedStateContent: Item {
if (!GC.isMobile()) { objectName: "ProtocolDrawerCollapsedContent"
focusItem.forceActiveFocus()
}
}
collapsedContent: Item {
implicitHeight: Qt.platform.os !== "ios" ? root.height * 0.9 : screen.height * 0.77 implicitHeight: Qt.platform.os !== "ios" ? root.height * 0.9 : screen.height * 0.77
Component.onCompleted: { Component.onCompleted: {
drawer.expandedHeight = implicitHeight drawer.expandedHeight = implicitHeight
} }
Connections { Connections {
objectName: "drawerConnections"
target: drawer target: drawer
enabled: !GC.isMobile() enabled: !GC.isMobile()
function onActiveFocusChanged() {
if (drawer.activeFocus && !drawer.isOpened) {
collapsedButtonChevron.forceActiveFocus()
}
}
} }
ColumnLayout { ColumnLayout {
id: collapsed id: collapsed
objectName: "collapsedColumnLayout"
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@ -180,6 +173,8 @@ PageType {
} }
RowLayout { RowLayout {
objectName: "rowLayout"
Layout.topMargin: 14 Layout.topMargin: 14
Layout.leftMargin: 24 Layout.leftMargin: 24
Layout.rightMargin: 24 Layout.rightMargin: 24
@ -188,9 +183,11 @@ PageType {
spacing: 0 spacing: 0
Connections { Connections {
objectName: "drawerConnections"
target: drawer target: drawer
function onEntered() { function onCursorEntered() {
if (drawer.isCollapsed) { if (drawer.isCollapsedStateActive) {
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.hoveredColor collapsedButtonChevron.backgroundColor = collapsedButtonChevron.hoveredColor
collapsedButtonHeader.opacity = 0.8 collapsedButtonHeader.opacity = 0.8
} else { } else {
@ -198,8 +195,8 @@ PageType {
} }
} }
function onExited() { function onCursorExited() {
if (drawer.isCollapsed) { if (drawer.isCollapsedStateActive) {
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.defaultColor collapsedButtonChevron.backgroundColor = collapsedButtonChevron.defaultColor
collapsedButtonHeader.opacity = 1 collapsedButtonHeader.opacity = 1
} else { } else {
@ -208,7 +205,7 @@ PageType {
} }
function onPressed(pressed, entered) { function onPressed(pressed, entered) {
if (drawer.isCollapsed) { if (drawer.isCollapsedStateActive) {
collapsedButtonChevron.backgroundColor = pressed ? collapsedButtonChevron.pressedColor : entered ? collapsedButtonChevron.hoveredColor : collapsedButtonChevron.defaultColor collapsedButtonChevron.backgroundColor = pressed ? collapsedButtonChevron.pressedColor : entered ? collapsedButtonChevron.hoveredColor : collapsedButtonChevron.defaultColor
collapsedButtonHeader.opacity = 0.7 collapsedButtonHeader.opacity = 0.7
} else { } else {
@ -219,6 +216,8 @@ PageType {
Header1TextType { Header1TextType {
id: collapsedButtonHeader id: collapsedButtonHeader
objectName: "collapsedButtonHeader"
Layout.maximumWidth: drawer.width - 48 - 18 - 12 Layout.maximumWidth: drawer.width - 48 - 18 - 12
maximumLineCount: 2 maximumLineCount: 2
@ -227,8 +226,6 @@ PageType {
text: ServersModel.defaultServerName text: ServersModel.defaultServerName
horizontalAlignment: Qt.AlignHCenter horizontalAlignment: Qt.AlignHCenter
KeyNavigation.tab: tabBar
Behavior on opacity { Behavior on opacity {
PropertyAnimation { duration: 200 } PropertyAnimation { duration: 200 }
} }
@ -236,10 +233,11 @@ PageType {
ImageButtonType { ImageButtonType {
id: collapsedButtonChevron id: collapsedButtonChevron
objectName: "collapsedButtonChevron"
Layout.leftMargin: 8 Layout.leftMargin: 8
visible: drawer.isCollapsed visible: drawer.isCollapsedStateActive()
hoverEnabled: false hoverEnabled: false
image: "qrc:/images/controls/chevron-down.svg" image: "qrc:/images/controls/chevron-down.svg"
@ -254,18 +252,19 @@ PageType {
Keys.onEnterPressed: collapsedButtonChevron.clicked() Keys.onEnterPressed: collapsedButtonChevron.clicked()
Keys.onReturnPressed: collapsedButtonChevron.clicked() Keys.onReturnPressed: collapsedButtonChevron.clicked()
Keys.onTabPressed: lastItemTabClicked()
onClicked: { onClicked: {
if (drawer.isCollapsed) { console.debug("onClicked collapsedButtonChevron")
drawer.open() if (drawer.isCollapsedStateActive()) {
drawer.openTriggered()
FocusController.setRootItem(drawer)
} }
} }
} }
} }
RowLayout { RowLayout {
objectName: "rowLayoutLabel"
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
Layout.topMargin: 8 Layout.topMargin: 8
Layout.bottomMargin: drawer.isCollapsed ? 44 : ServersModel.isDefaultServerFromApi ? 61 : 16 Layout.bottomMargin: drawer.isCollapsed ? 44 : ServersModel.isDefaultServerFromApi ? 61 : 16
@ -316,6 +315,7 @@ PageType {
ColumnLayout { ColumnLayout {
id: serversMenuHeader id: serversMenuHeader
objectName: "serversMenuHeader"
anchors.top: collapsed.bottom anchors.top: collapsed.bottom
anchors.right: parent.right anchors.right: parent.right
@ -327,13 +327,9 @@ PageType {
visible: !ServersModel.isDefaultServerFromApi visible: !ServersModel.isDefaultServerFromApi
Item {
id: focusItem1
KeyNavigation.tab: containersDropDown
}
DropDownType { DropDownType {
id: containersDropDown id: containersDropDown
objectName: "containersDropDown"
rootButtonImageColor: AmneziaStyle.color.midnightBlack rootButtonImageColor: AmneziaStyle.color.midnightBlack
rootButtonBackgroundColor: AmneziaStyle.color.paleGray rootButtonBackgroundColor: AmneziaStyle.color.paleGray
@ -350,22 +346,23 @@ PageType {
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg" headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
rootButtonClickedFunction: function() { rootButtonClickedFunction: function() {
containersDropDown.open() containersDropDown.openTriggered()
} }
drawerParent: root drawerParent: root
KeyNavigation.tab: serversMenuContent
listView: HomeContainersListView { listView: HomeContainersListView {
id: containersListView id: containersListView
objectName: "containersListView"
rootWidth: root.width rootWidth: root.width
onVisibleChanged: { height: 500 // TODO: make calculated
if (containersDropDown.visible && !GC.isMobile()) {
focusItem1.forceActiveFocus() // isFocusable: false // TODO: this is a workaround. Need to remove it
}
}
Connections { Connections {
objectName: "rowLayoutConnections"
target: ServersModel target: ServersModel
function onDefaultServerIndexChanged() { function onDefaultServerIndexChanged() {
@ -407,169 +404,12 @@ PageType {
ButtonGroup { ButtonGroup {
id: serversRadioButtonGroup id: serversRadioButtonGroup
objectName: "serversRadioButtonGroup"
} }
ListView { ServersListView {
id: serversMenuContent id: serversMenuContent
objectName: "serversMenuContent"
anchors.top: serversMenuHeader.bottom
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.topMargin: 16
model: ServersModel
currentIndex: ServersModel.defaultIndex
ScrollBar.vertical: ScrollBar {
id: scrollBar
policy: serversMenuContent.height >= serversMenuContent.contentHeight ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
}
activeFocusOnTab: true
focus: true
property int focusItemIndex: 0
onActiveFocusChanged: {
if (activeFocus) {
serversMenuContent.focusItemIndex = 0
serversMenuContent.itemAtIndex(focusItemIndex).forceActiveFocus()
}
}
onFocusItemIndexChanged: {
const focusedElement = serversMenuContent.itemAtIndex(focusItemIndex)
if (focusedElement) {
if (focusedElement.y + focusedElement.height > serversMenuContent.height) {
serversMenuContent.contentY = focusedElement.y + focusedElement.height - serversMenuContent.height
} else {
serversMenuContent.contentY = 0
}
}
}
Keys.onUpPressed: scrollBar.decrease()
Keys.onDownPressed: scrollBar.increase()
Connections {
target: drawer
enabled: !GC.isMobile()
function onIsCollapsedChanged() {
if (drawer.isCollapsed) {
const item = serversMenuContent.itemAtIndex(serversMenuContent.focusItemIndex)
if (item) { item.serverRadioButtonProperty.focus = false }
}
}
}
Connections {
target: ServersModel
function onDefaultServerIndexChanged(serverIndex) {
serversMenuContent.currentIndex = serverIndex
}
}
clip: true
delegate: Item {
id: menuContentDelegate
property variant delegateData: model
property VerticalRadioButton serverRadioButtonProperty: serverRadioButton
implicitWidth: serversMenuContent.width
implicitHeight: serverRadioButtonContent.implicitHeight
onActiveFocusChanged: {
if (activeFocus) {
serverRadioButton.forceActiveFocus()
}
}
ColumnLayout {
id: serverRadioButtonContent
anchors.fill: parent
anchors.rightMargin: 16
anchors.leftMargin: 16
spacing: 0
RowLayout {
Layout.fillWidth: true
VerticalRadioButton {
id: serverRadioButton
Layout.fillWidth: true
text: name
descriptionText: serverDescription
checked: index === serversMenuContent.currentIndex
checkable: !ConnectionController.isConnected
ButtonGroup.group: serversRadioButtonGroup
onClicked: {
if (ConnectionController.isConnected) {
PageController.showNotificationMessage(qsTr("Unable change server while there is an active connection"))
return
}
serversMenuContent.currentIndex = index
ServersModel.defaultIndex = index
}
MouseArea {
anchors.fill: serverRadioButton
cursorShape: Qt.PointingHandCursor
enabled: false
}
Keys.onTabPressed: serverInfoButton.forceActiveFocus()
Keys.onEnterPressed: serverRadioButton.clicked()
Keys.onReturnPressed: serverRadioButton.clicked()
}
ImageButtonType {
id: serverInfoButton
image: "qrc:/images/controls/settings.svg"
imageColor: AmneziaStyle.color.paleGray
implicitWidth: 56
implicitHeight: 56
z: 1
Keys.onTabPressed: {
if (serversMenuContent.focusItemIndex < serversMenuContent.count - 1) {
serversMenuContent.focusItemIndex++
serversMenuContent.itemAtIndex(serversMenuContent.focusItemIndex).forceActiveFocus()
} else {
focusItem1.forceActiveFocus()
serversMenuContent.contentY = 0
}
}
Keys.onEnterPressed: serverInfoButton.clicked()
Keys.onReturnPressed: serverInfoButton.clicked()
onClicked: function() {
ServersModel.processedIndex = index
PageController.goToPage(PageEnum.PageSettingsServerInfo)
drawer.close()
}
}
}
DividerType {
Layout.fillWidth: true
Layout.leftMargin: 0
Layout.rightMargin: 0
}
}
}
} }
} }
} }

View file

@ -17,18 +17,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: listview.currentItem.portTextField.textField
Item {
id: focusItem
onFocusChanged: {
if (activeFocus) {
fl.ensureVisible(focusItem)
}
}
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -40,7 +28,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: listview.currentItem.portTextField.textField
} }
} }
@ -114,8 +101,26 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
}
KeyNavigation.tab: junkPacketCountTextField.textField TextFieldWithHeaderType {
id: mtuTextField
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("MTU")
textFieldText: mtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
textField.onEditingFinished: {
if (textFieldText === "") {
textFieldText = "0"
}
if (textFieldText !== mtu) {
mtu = textFieldText
}
}
checkEmptyText: true
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -139,8 +144,6 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: junkPacketMinSizeTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -160,8 +163,6 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: junkPacketMaxSizeTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -181,8 +182,6 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: initPacketJunkSizeTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -202,8 +201,6 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: responsePacketJunkSizeTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -223,8 +220,6 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: initPacketMagicHeaderTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -244,8 +239,6 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: responsePacketMagicHeaderTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -265,8 +258,6 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: transportPacketMagicHeaderTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -286,8 +277,6 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: underloadPacketMagicHeaderTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -307,8 +296,6 @@ PageType {
} }
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: saveRestartButton
} }
BasicButtonType { BasicButtonType {
@ -332,8 +319,6 @@ PageType {
text: qsTr("Save") text: qsTr("Save")
Keys.onTabPressed: lastItemTabClicked(focusItem)
clickedFunc: function() { clickedFunc: function() {
forceActiveFocus() forceActiveFocus()

View file

@ -16,13 +16,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: listview.currentItem.trafficFromField.textField
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -34,7 +27,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: listview.currentItem.trafficFromField.textField
} }
} }
@ -110,8 +102,6 @@ PageType {
} }
} }
} }
KeyNavigation.tab: portTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -130,8 +120,6 @@ PageType {
port = textFieldText port = textFieldText
} }
} }
KeyNavigation.tab: cipherDropDown
} }
DropDownType { DropDownType {
@ -143,7 +131,6 @@ PageType {
headerText: qsTr("Cipher") headerText: qsTr("Cipher")
drawerParent: root drawerParent: root
KeyNavigation.tab: saveRestartButton
listView: ListViewWithRadioButtonType { listView: ListViewWithRadioButtonType {
id: cipherListView id: cipherListView

View file

@ -17,18 +17,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: listview.currentItem.vpnAddressSubnetTextField.textField
Item {
id: focusItem
KeyNavigation.tab: backButton
onActiveFocusChanged: {
if (activeFocus) {
fl.ensureVisible(focusItem)
}
}
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -40,7 +28,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: listview.currentItem.vpnAddressSubnetTextField.textField
} }
} }
@ -104,7 +91,6 @@ PageType {
textFieldText: subnetAddress textFieldText: subnetAddress
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: transportProtoSelector
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== subnetAddress) { if (textFieldText !== subnetAddress) {
@ -132,8 +118,6 @@ PageType {
return transportProto === "tcp" ? 1 : 0 return transportProto === "tcp" ? 1 : 0
} }
KeyNavigation.tab: portTextField.enabled ? portTextField.textField : autoNegotiateEncryprionSwitcher
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (transportProto === "tcp" && currentIndex === 0) { if (transportProto === "tcp" && currentIndex === 0) {
transportProto = "udp" transportProto = "udp"
@ -162,8 +146,6 @@ PageType {
port = textFieldText port = textFieldText
} }
} }
KeyNavigation.tab: autoNegotiateEncryprionSwitcher
} }
SwitcherType { SwitcherType {
@ -181,10 +163,6 @@ PageType {
autoNegotiateEncryprion = checked autoNegotiateEncryprion = checked
} }
} }
KeyNavigation.tab: hashDropDown.enabled ?
hashDropDown :
tlsAuthCheckBox
} }
DropDownType { DropDownType {
@ -199,9 +177,6 @@ PageType {
drawerParent: root drawerParent: root
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: cipherDropDown.enabled ?
cipherDropDown :
tlsAuthCheckBox
listView: ListViewWithRadioButtonType { listView: ListViewWithRadioButtonType {
id: hashListView id: hashListView
@ -252,8 +227,6 @@ PageType {
drawerParent: root drawerParent: root
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: tlsAuthCheckBox
listView: ListViewWithRadioButtonType { listView: ListViewWithRadioButtonType {
id: cipherListView id: cipherListView
@ -320,8 +293,6 @@ PageType {
text: qsTr("TLS auth") text: qsTr("TLS auth")
checked: tlsAuth checked: tlsAuth
KeyNavigation.tab: blockDnsCheckBox
onCheckedChanged: { onCheckedChanged: {
if (checked !== tlsAuth) { if (checked !== tlsAuth) {
console.log("tlsAuth changed to: " + checked) console.log("tlsAuth changed to: " + checked)
@ -339,8 +310,6 @@ PageType {
text: qsTr("Block DNS requests outside of VPN") text: qsTr("Block DNS requests outside of VPN")
checked: blockDns checked: blockDns
KeyNavigation.tab: additionalClientCommandsSwitcher
onCheckedChanged: { onCheckedChanged: {
if (checked !== blockDns) { if (checked !== blockDns) {
blockDns = checked blockDns = checked
@ -355,9 +324,6 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 32 Layout.topMargin: 32
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: additionalClientCommandsTextArea.visible ?
additionalClientCommandsTextArea.textArea :
additionalServerCommandsSwitcher
checked: additionalClientCommands !== "" checked: additionalClientCommands !== ""
@ -376,7 +342,7 @@ PageType {
Layout.topMargin: 16 Layout.topMargin: 16
visible: additionalClientCommandsSwitcher.checked visible: additionalClientCommandsSwitcher.checked
KeyNavigation.tab: additionalServerCommandsSwitcher
parentFlickable: fl parentFlickable: fl
textAreaText: additionalClientCommands textAreaText: additionalClientCommands
@ -394,9 +360,6 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: 16 Layout.topMargin: 16
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: additionalServerCommandsTextArea.visible ?
additionalServerCommandsTextArea.textArea :
saveRestartButton
checked: additionalServerCommands !== "" checked: additionalServerCommands !== ""
@ -419,7 +382,6 @@ PageType {
textAreaText: additionalServerCommands textAreaText: additionalServerCommands
placeholderText: qsTr("Commands:") placeholderText: qsTr("Commands:")
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: saveRestartButton
textArea.onEditingFinished: { textArea.onEditingFinished: {
if (additionalServerCommands !== textAreaText) { if (additionalServerCommands !== textAreaText) {
additionalServerCommands = textAreaText additionalServerCommands = textAreaText

View file

@ -19,13 +19,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: header id: header
@ -37,7 +30,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: listView
} }
HeaderType { HeaderType {
@ -104,8 +96,6 @@ PageType {
configContentDrawer.open() configContentDrawer.open()
} }
KeyNavigation.tab: removeButton
MouseArea { MouseArea {
anchors.fill: button anchors.fill: button
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
@ -129,7 +119,7 @@ PageType {
parent: root parent: root
anchors.fill: parent anchors.fill: parent
expandedContent: Item { expandedStateContent: Item {
implicitHeight: configContentDrawer.expandedHeight implicitHeight: configContentDrawer.expandedHeight
Connections { Connections {
@ -140,11 +130,6 @@ PageType {
} }
} }
Item {
id: focusItem1
KeyNavigation.tab: backButton1
}
BackButtonType { BackButtonType {
id: backButton1 id: backButton1
@ -156,8 +141,6 @@ PageType {
backButtonFunction: function() { backButtonFunction: function() {
configContentDrawer.close() configContentDrawer.close()
} }
KeyNavigation.tab: focusItem1
} }
FlickableType { FlickableType {

View file

@ -16,15 +16,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: listview.currentItem.focusItemId.enabled ?
listview.currentItem.focusItemId.textField :
focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -36,9 +27,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: listview.currentItem.focusItemId.enabled ?
listview.currentItem.focusItemId.textField :
focusItem
} }
} }
@ -114,8 +102,6 @@ PageType {
port = textFieldText port = textFieldText
} }
} }
KeyNavigation.tab: cipherDropDown
} }
DropDownType { DropDownType {
@ -129,9 +115,9 @@ PageType {
headerText: qsTr("Cipher") headerText: qsTr("Cipher")
drawerParent: root drawerParent: root
KeyNavigation.tab: saveRestartButton
listView: ListViewWithRadioButtonType { listView: ListViewWithRadioButtonType {
id: cipherListView id: cipherListView
rootWidth: root.width rootWidth: root.width

View file

@ -16,13 +16,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: listview
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -34,7 +27,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: listview
} }
} }
@ -64,12 +56,12 @@ PageType {
model: WireGuardConfigModel model: WireGuardConfigModel
activeFocusOnTab: true // activeFocusOnTab: true
onActiveFocusChanged: { // onActiveFocusChanged: {
if (activeFocus) { // if (activeFocus) {
listview.itemAtIndex(0)?.focusItemId.forceActiveFocus() // listview.itemAtIndex(0)?.focusItemId.forceActiveFocus()
} // }
} // }
delegate: Item { delegate: Item {
id: delegateItem id: delegateItem
@ -109,8 +101,6 @@ PageType {
textField.maximumLength: 5 textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 } textField.validator: IntValidator { bottom: 1; top: 65535 }
KeyNavigation.tab: saveButton
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== port) { if (textFieldText !== port) {
port = textFieldText port = textFieldText
@ -120,6 +110,26 @@ PageType {
checkEmptyText: true checkEmptyText: true
} }
TextFieldWithHeaderType {
id: mtuTextField
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("MTU")
textFieldText: mtu
textField.validator: IntValidator { bottom: 576; top: 65535 }
textField.onEditingFinished: {
if (textFieldText === "") {
textFieldText = "0"
}
if (textFieldText !== mtu) {
mtu = textFieldText
}
}
checkEmptyText: true
}
BasicButtonType { BasicButtonType {
id: saveButton id: saveButton
Layout.fillWidth: true Layout.fillWidth: true

View file

@ -17,13 +17,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: listview
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -35,7 +28,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: listview
} }
} }
@ -65,12 +57,12 @@ PageType {
model: XrayConfigModel model: XrayConfigModel
activeFocusOnTab: true // activeFocusOnTab: true
onActiveFocusChanged: { // onActiveFocusChanged: {
if (activeFocus) { // if (activeFocus) {
listview.itemAtIndex(0)?.focusItemId.forceActiveFocus() // listview.itemAtIndex(0)?.focusItemId.forceActiveFocus()
} // }
} // }
delegate: Item { delegate: Item {
property alias focusItemId: textFieldWithHeaderType.textField property alias focusItemId: textFieldWithHeaderType.textField
@ -103,8 +95,6 @@ PageType {
headerText: qsTr("Disguised as traffic from") headerText: qsTr("Disguised as traffic from")
textFieldText: site textFieldText: site
KeyNavigation.tab: basicButton
textField.onEditingFinished: { textField.onEditingFinished: {
if (textFieldText !== site) { if (textFieldText !== site) {
var tmpText = textFieldText var tmpText = textFieldText

View file

@ -16,13 +16,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -34,7 +27,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: removeButton
} }
} }

View file

@ -16,8 +16,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
Connections { Connections {
target: InstallController target: InstallController
@ -26,11 +24,6 @@ PageType {
} }
} }
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -42,7 +35,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: listview
} }
} }
@ -107,7 +99,6 @@ PageType {
Layout.topMargin: 32 Layout.topMargin: 32
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: portLabel.rightButton
text: qsTr("Host") text: qsTr("Host")
descriptionText: ServersModel.getProcessedServerData("hostName") descriptionText: ServersModel.getProcessedServerData("hostName")
@ -136,7 +127,6 @@ PageType {
descriptionOnTop: true descriptionOnTop: true
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: usernameLabel.rightButton
rightImageSource: "qrc:/images/controls/copy.svg" rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: AmneziaStyle.color.paleGray rightImageColor: AmneziaStyle.color.paleGray
@ -160,7 +150,6 @@ PageType {
descriptionOnTop: true descriptionOnTop: true
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: passwordLabel.eyeButton
rightImageSource: "qrc:/images/controls/copy.svg" rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: AmneziaStyle.color.paleGray rightImageColor: AmneziaStyle.color.paleGray
@ -184,7 +173,7 @@ PageType {
descriptionOnTop: true descriptionOnTop: true
parentFlickable: fl parentFlickable: fl
eyeButton.KeyNavigation.tab: passwordLabel.rightButton
rightButton.Keys.onTabPressed: { rightButton.Keys.onTabPressed: {
if (mountButton.visible) { if (mountButton.visible) {
mountButton.forceActiveFocus() mountButton.forceActiveFocus()
@ -225,7 +214,6 @@ PageType {
borderWidth: 1 borderWidth: 1
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: detailedInstructionsButton
text: qsTr("Mount folder on device") text: qsTr("Mount folder on device")

View file

@ -17,8 +17,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: listview
Connections { Connections {
target: InstallController target: InstallController
@ -27,11 +25,6 @@ PageType {
} }
} }
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -43,7 +36,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: listview
} }
} }
@ -99,7 +91,6 @@ PageType {
Layout.topMargin: 32 Layout.topMargin: 32
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: portLabel.rightButton
text: qsTr("Host") text: qsTr("Host")
descriptionText: ServersModel.getProcessedServerData("hostName") descriptionText: ServersModel.getProcessedServerData("hostName")
@ -128,7 +119,6 @@ PageType {
descriptionOnTop: true descriptionOnTop: true
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: usernameLabel.rightButton
rightImageSource: "qrc:/images/controls/copy.svg" rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: AmneziaStyle.color.paleGray rightImageColor: AmneziaStyle.color.paleGray
@ -152,7 +142,6 @@ PageType {
descriptionOnTop: true descriptionOnTop: true
parentFlickable: fl parentFlickable: fl
KeyNavigation.tab: passwordLabel.eyeButton
rightImageSource: "qrc:/images/controls/copy.svg" rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: AmneziaStyle.color.paleGray rightImageColor: AmneziaStyle.color.paleGray
@ -176,8 +165,6 @@ PageType {
descriptionOnTop: true descriptionOnTop: true
parentFlickable: fl parentFlickable: fl
eyeButton.KeyNavigation.tab: passwordLabel.rightButton
rightButton.KeyNavigation.tab: changeSettingsButton
rightImageSource: "qrc:/images/controls/copy.svg" rightImageSource: "qrc:/images/controls/copy.svg"
rightImageColor: AmneziaStyle.color.paleGray rightImageColor: AmneziaStyle.color.paleGray
@ -206,7 +193,7 @@ PageType {
} }
} }
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
property string tempPort: port property string tempPort: port
property string tempUsername: username property string tempUsername: username
property string tempPassword: password property string tempPassword: password
@ -239,11 +226,6 @@ PageType {
} }
} }
Item {
id: drawerFocusItem
KeyNavigation.tab: portTextField.textField
}
HeaderType { HeaderType {
Layout.fillWidth: true Layout.fillWidth: true
@ -268,8 +250,6 @@ PageType {
port = textFieldText port = textFieldText
} }
} }
KeyNavigation.tab: usernameTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -290,8 +270,6 @@ PageType {
username = textFieldText username = textFieldText
} }
} }
KeyNavigation.tab: passwordTextField.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -322,8 +300,6 @@ PageType {
password = textFieldText password = textFieldText
} }
} }
KeyNavigation.tab: saveButton
} }
BasicButtonType { BasicButtonType {

View file

@ -17,8 +17,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
Connections { Connections {
target: InstallController target: InstallController
@ -27,11 +25,6 @@ PageType {
} }
} }
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: backButtonLayout id: backButtonLayout
@ -43,7 +36,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: websiteName.rightButton
} }
} }

View file

@ -14,9 +14,7 @@ import "../Config"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: header FlickableType { // TODO: refactor either replace with ListView or Repeater
FlickableType {
id: fl id: fl
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -39,8 +37,6 @@ PageType {
Layout.leftMargin: 16 Layout.leftMargin: 16
headerText: qsTr("Settings") headerText: qsTr("Settings")
KeyNavigation.tab: account.rightButton
} }
LabelWithButtonType { LabelWithButtonType {
@ -55,8 +51,6 @@ PageType {
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsServersList) PageController.goToPage(PageEnum.PageSettingsServersList)
} }
KeyNavigation.tab: connection.rightButton
} }
DividerType {} DividerType {}
@ -72,8 +66,6 @@ PageType {
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsConnection) PageController.goToPage(PageEnum.PageSettingsConnection)
} }
KeyNavigation.tab: application.rightButton
} }
DividerType {} DividerType {}
@ -89,8 +81,6 @@ PageType {
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsApplication) PageController.goToPage(PageEnum.PageSettingsApplication)
} }
KeyNavigation.tab: backup.rightButton
} }
DividerType {} DividerType {}
@ -106,8 +96,6 @@ PageType {
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsBackup) PageController.goToPage(PageEnum.PageSettingsBackup)
} }
KeyNavigation.tab: about.rightButton
} }
DividerType {} DividerType {}
@ -123,8 +111,6 @@ PageType {
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsAbout) PageController.goToPage(PageEnum.PageSettingsAbout)
} }
KeyNavigation.tab: close
} }
DividerType {} DividerType {}
@ -138,8 +124,6 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
leftImageSource: "qrc:/images/controls/bug.svg" leftImageSource: "qrc:/images/controls/bug.svg"
// Keys.onTabPressed: lastItemTabClicked(header)
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageDevMenu) PageController.goToPage(PageEnum.PageDevMenu)
} }
@ -156,10 +140,9 @@ PageType {
Layout.preferredHeight: about.height Layout.preferredHeight: about.height
text: qsTr("Close application") text: qsTr("Close application")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
leftImageSource: "qrc:/images/controls/x-circle.svg" leftImageSource: "qrc:/images/controls/x-circle.svg"
isLeftImageHoverEnabled: false // isLeftImageHoverEnabled: false
Keys.onTabPressed: lastItemTabClicked(header)
clickedFunction: function() { clickedFunction: function() {
PageController.closeApplication() PageController.closeApplication()

View file

@ -14,18 +14,16 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem // Item {
// id: focusItem
// KeyNavigation.tab: backButton
Item { // onFocusChanged: {
id: focusItem // if (focusItem.activeFocus) {
KeyNavigation.tab: backButton // fl.contentY = 0
// }
onFocusChanged: { // }
if (focusItem.activeFocus) { // }
fl.contentY = 0
}
}
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -34,8 +32,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: telegramButton
} }
FlickableType { FlickableType {
@ -106,7 +102,6 @@ PageType {
descriptionText: qsTr("To discuss features") descriptionText: qsTr("To discuss features")
leftImageSource: "qrc:/images/controls/telegram.svg" leftImageSource: "qrc:/images/controls/telegram.svg"
KeyNavigation.tab: mailButton
parentFlickable: fl parentFlickable: fl
clickedFunction: function() { clickedFunction: function() {
@ -124,7 +119,6 @@ PageType {
descriptionText: qsTr("For reviews and bug reports") descriptionText: qsTr("For reviews and bug reports")
leftImageSource: "qrc:/images/controls/mail.svg" leftImageSource: "qrc:/images/controls/mail.svg"
KeyNavigation.tab: githubButton
parentFlickable: fl parentFlickable: fl
clickedFunction: function() { clickedFunction: function() {
@ -143,7 +137,6 @@ PageType {
text: qsTr("GitHub") text: qsTr("GitHub")
leftImageSource: "qrc:/images/controls/github.svg" leftImageSource: "qrc:/images/controls/github.svg"
KeyNavigation.tab: websiteButton
parentFlickable: fl parentFlickable: fl
clickedFunction: function() { clickedFunction: function() {
@ -161,7 +154,6 @@ PageType {
text: qsTr("Website") text: qsTr("Website")
leftImageSource: "qrc:/images/controls/amnezia.svg" leftImageSource: "qrc:/images/controls/amnezia.svg"
KeyNavigation.tab: checkUpdatesButton
parentFlickable: fl parentFlickable: fl
clickedFunction: function() { clickedFunction: function() {
@ -209,7 +201,6 @@ PageType {
text: qsTr("Check for updates") text: qsTr("Check for updates")
KeyNavigation.tab: privacyPolicyButton
parentFlickable: fl parentFlickable: fl
clickedFunc: function() { clickedFunc: function() {

View file

@ -15,8 +15,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
FlickableType { FlickableType {
id: fl id: fl
anchors.top: parent.top anchors.top: parent.top
@ -32,11 +30,6 @@ PageType {
spacing: 0 spacing: 0
Item {
id: focusItem
// KeyNavigation.tab: backButton
}
LabelWithImageType { LabelWithImageType {
Layout.fillWidth: true Layout.fillWidth: true
Layout.margins: 16 Layout.margins: 16

View file

@ -21,8 +21,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
property bool pageEnabled property bool pageEnabled
Component.onCompleted: { Component.onCompleted: {
@ -66,11 +64,6 @@ PageType {
} }
} }
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: header id: header
@ -82,7 +75,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: switcher
} }
RowLayout { RowLayout {
@ -103,10 +95,6 @@ PageType {
enabled: root.pageEnabled enabled: root.pageEnabled
KeyNavigation.tab: selector.enabled ?
selector :
searchField.textField
checked: AppSplitTunnelingModel.isTunnelingEnabled checked: AppSplitTunnelingModel.isTunnelingEnabled
onToggled: { onToggled: {
AppSplitTunnelingModel.toggleSplitTunneling(checked) AppSplitTunnelingModel.toggleSplitTunneling(checked)
@ -130,8 +118,6 @@ PageType {
enabled: Qt.platform.os === "android" && root.pageEnabled enabled: Qt.platform.os === "android" && root.pageEnabled
KeyNavigation.tab: searchField.textField
listView: ListViewWithRadioButtonType { listView: ListViewWithRadioButtonType {
rootWidth: root.width rootWidth: root.width

View file

@ -14,18 +14,15 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem // Item {
// id: focusItem
Item { // onFocusChanged: {
id: focusItem // if (focusItem.activeFocus) {
KeyNavigation.tab: backButton // fl.contentY = 0
// }
onFocusChanged: { // }
if (focusItem.activeFocus) { // }
fl.contentY = 0
}
}
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -35,7 +32,7 @@ PageType {
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: GC.isMobile() ? switcher : switcherAutoStart // KeyNavigation.tab: GC.isMobile() ? switcher : switcherAutoStart
} }
FlickableType { FlickableType {
@ -77,8 +74,8 @@ PageType {
} }
} }
KeyNavigation.tab: Qt.platform.os === "android" && !SettingsController.isNotificationPermissionGranted ? // KeyNavigation.tab: Qt.platform.os === "android" && !SettingsController.isNotificationPermissionGranted ?
labelWithButtonNotification.rightButton : labelWithButtonLanguage.rightButton // labelWithButtonNotification.rightButton : labelWithButtonLanguage.rightButton
parentFlickable: fl parentFlickable: fl
} }
@ -95,7 +92,7 @@ PageType {
descriptionText: qsTr("Enable notifications to show the VPN state in the status bar") descriptionText: qsTr("Enable notifications to show the VPN state in the status bar")
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
KeyNavigation.tab: labelWithButtonLanguage.rightButton // KeyNavigation.tab: labelWithButtonLanguage.rightButton
parentFlickable: fl parentFlickable: fl
clickedFunction: function() { clickedFunction: function() {
@ -117,7 +114,6 @@ PageType {
text: qsTr("Auto start") text: qsTr("Auto start")
descriptionText: qsTr("Launch the application every time the device is starts") descriptionText: qsTr("Launch the application every time the device is starts")
KeyNavigation.tab: switcherAutoConnect
parentFlickable: fl parentFlickable: fl
checked: SettingsController.isAutoStartEnabled() checked: SettingsController.isAutoStartEnabled()
@ -142,7 +138,6 @@ PageType {
text: qsTr("Auto connect") text: qsTr("Auto connect")
descriptionText: qsTr("Connect to VPN on app start") descriptionText: qsTr("Connect to VPN on app start")
KeyNavigation.tab: switcherStartMinimized
parentFlickable: fl parentFlickable: fl
checked: SettingsController.isAutoConnectEnabled() checked: SettingsController.isAutoConnectEnabled()
@ -167,7 +162,6 @@ PageType {
text: qsTr("Start minimized") text: qsTr("Start minimized")
descriptionText: qsTr("Launch application minimized") descriptionText: qsTr("Launch application minimized")
KeyNavigation.tab: labelWithButtonLanguage.rightButton
parentFlickable: fl parentFlickable: fl
checked: SettingsController.isStartMinimizedEnabled() checked: SettingsController.isStartMinimizedEnabled()
@ -190,11 +184,10 @@ PageType {
descriptionText: LanguageModel.currentLanguageName descriptionText: LanguageModel.currentLanguageName
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
KeyNavigation.tab: labelWithButtonLogging.rightButton
parentFlickable: fl parentFlickable: fl
clickedFunction: function() { clickedFunction: function() {
selectLanguageDrawer.open() selectLanguageDrawer.openTriggered()
} }
} }
@ -208,7 +201,6 @@ PageType {
descriptionText: SettingsController.isLoggingEnabled ? qsTr("Enabled") : qsTr("Disabled") descriptionText: SettingsController.isLoggingEnabled ? qsTr("Enabled") : qsTr("Disabled")
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
KeyNavigation.tab: labelWithButtonReset.rightButton
parentFlickable: fl parentFlickable: fl
clickedFunction: function() { clickedFunction: function() {
@ -245,12 +237,12 @@ PageType {
} }
if (!GC.isMobile()) { if (!GC.isMobile()) {
root.defaultActiveFocusItem.forceActiveFocus() // root.defaultActiveFocusItem.forceActiveFocus()
} }
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) { if (!GC.isMobile()) {
root.defaultActiveFocusItem.forceActiveFocus() // root.defaultActiveFocusItem.forceActiveFocus()
} }
} }
@ -268,10 +260,10 @@ PageType {
width: root.width width: root.width
height: root.height height: root.height
onClosed: { // onClosed: {
if (!GC.isMobile()) { // if (!GC.isMobile()) {
focusItem.forceActiveFocus() // focusItem.forceActiveFocus()
} // }
} // }
} }
} }

View file

@ -17,7 +17,7 @@ import "../Controls2/TextTypes"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem // defaultActiveFocusItem: focusItem
Connections { Connections {
target: SettingsController target: SettingsController
@ -36,11 +36,6 @@ PageType {
} }
} }
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -48,8 +43,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: makeBackupButton
} }
FlickableType { FlickableType {
@ -111,8 +104,6 @@ PageType {
PageController.showNotificationMessage(qsTr("Backup file saved")) PageController.showNotificationMessage(qsTr("Backup file saved"))
} }
} }
KeyNavigation.tab: restoreBackupButton
} }
BasicButtonType { BasicButtonType {

View file

@ -12,15 +12,8 @@ import "../Config"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
property bool isAppSplitTinnelingEnabled: Qt.platform.os === "windows" || Qt.platform.os === "android" property bool isAppSplitTinnelingEnabled: Qt.platform.os === "windows" || Qt.platform.os === "android"
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -28,8 +21,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: amneziaDnsSwitch
} }
FlickableType { FlickableType {
@ -67,8 +58,6 @@ PageType {
SettingsController.toggleAmneziaDns(checked) SettingsController.toggleAmneziaDns(checked)
} }
} }
KeyNavigation.tab: dnsServersButton.rightButton
} }
DividerType {} DividerType {}
@ -84,8 +73,6 @@ PageType {
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsDns) PageController.goToPage(PageEnum.PageSettingsDns)
} }
KeyNavigation.tab: splitTunnelingButton.rightButton
} }
DividerType {} DividerType {}

View file

@ -14,13 +14,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: primaryDns.textField
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -28,8 +21,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: root.defaultActiveFocusItem
} }
FlickableType { FlickableType {
@ -80,8 +71,6 @@ PageType {
textField.validator: RegularExpressionValidator { textField.validator: RegularExpressionValidator {
regularExpression: InstallController.ipAddressRegExp() regularExpression: InstallController.ipAddressRegExp()
} }
KeyNavigation.tab: secondaryDns.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -94,8 +83,6 @@ PageType {
textField.validator: RegularExpressionValidator { textField.validator: RegularExpressionValidator {
regularExpression: InstallController.ipAddressRegExp() regularExpression: InstallController.ipAddressRegExp()
} }
KeyNavigation.tab: restoreDefaultButton
} }
BasicButtonType { BasicButtonType {
@ -124,19 +111,17 @@ PageType {
PageController.showNotificationMessage(qsTr("Settings have been reset")) PageController.showNotificationMessage(qsTr("Settings have been reset"))
if (!GC.isMobile()) { if (!GC.isMobile()) {
defaultActiveFocusItem.forceActiveFocus() // defaultActiveFocusItem.forceActiveFocus()
} }
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) { if (!GC.isMobile()) {
defaultActiveFocusItem.forceActiveFocus() // defaultActiveFocusItem.forceActiveFocus()
} }
} }
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
} }
KeyNavigation.tab: saveButton
} }
BasicButtonType { BasicButtonType {

View file

@ -16,13 +16,6 @@ import "../Controls2/TextTypes"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -30,8 +23,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: switcher
} }
FlickableType { FlickableType {
@ -68,12 +59,21 @@ PageType {
text: qsTr("Enable logs") text: qsTr("Enable logs")
checked: SettingsController.isLoggingEnabled checked: SettingsController.isLoggingEnabled
//KeyNavigation.tab: openFolderButton
onCheckedChanged: { onCheckedChanged: {
if (checked !== SettingsController.isLoggingEnabled) { if (checked !== SettingsController.isLoggingEnabled) {
SettingsController.isLoggingEnabled = checked SettingsController.isLoggingEnabled = checked
} }
} }
onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (activeFocus) {
if (fl) {
fl.ensureVisible(this)
}
}
}
} }
DividerType {} DividerType {}
@ -87,8 +87,6 @@ PageType {
leftImageSource: "qrc:/images/controls/trash.svg" leftImageSource: "qrc:/images/controls/trash.svg"
isSmallLeftImage: true isSmallLeftImage: true
// KeyNavigation.tab: labelWithButton3
clickedFunction: function() { clickedFunction: function() {
var headerText = qsTr("Clear logs?") var headerText = qsTr("Clear logs?")
var yesButtonText = qsTr("Continue") var yesButtonText = qsTr("Continue")
@ -104,9 +102,9 @@ PageType {
} }
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) { // if (!GC.isMobile()) {
focusItem.forceActiveFocus() // focusItem.forceActiveFocus()
} // }
} }
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
@ -142,8 +140,6 @@ PageType {
leftImageSource: "qrc:/images/controls/folder-open.svg" leftImageSource: "qrc:/images/controls/folder-open.svg"
isSmallLeftImage: true isSmallLeftImage: true
// KeyNavigation.tab: labelWithButton3
clickedFunction: function() { clickedFunction: function() {
SettingsController.openLogsFolder() SettingsController.openLogsFolder()
} }
@ -161,7 +157,14 @@ PageType {
leftImageSource: "qrc:/images/controls/save.svg" leftImageSource: "qrc:/images/controls/save.svg"
isSmallLeftImage: true isSmallLeftImage: true
// KeyNavigation.tab: labelWithButton3 onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (activeFocus) {
if (fl) {
fl.ensureVisible(this)
}
}
}
clickedFunction: function() { clickedFunction: function() {
var fileName = "" var fileName = ""
@ -221,7 +224,14 @@ PageType {
leftImageSource: "qrc:/images/controls/folder-open.svg" leftImageSource: "qrc:/images/controls/folder-open.svg"
isSmallLeftImage: true isSmallLeftImage: true
// KeyNavigation.tab: labelWithButton3 onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (activeFocus) {
if (fl) {
fl.ensureVisible(this)
}
}
}
clickedFunction: function() { clickedFunction: function() {
SettingsController.openServiceLogsFolder() SettingsController.openServiceLogsFolder()
@ -245,7 +255,14 @@ PageType {
leftImageSource: "qrc:/images/controls/save.svg" leftImageSource: "qrc:/images/controls/save.svg"
isSmallLeftImage: true isSmallLeftImage: true
// KeyNavigation.tab: labelWithButton3 onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (activeFocus) {
if (fl) {
fl.ensureVisible(this)
}
}
}
clickedFunction: function() { clickedFunction: function() {
var fileName = "" var fileName = ""

View file

@ -100,8 +100,6 @@ PageType {
text: qsTr("Check the server for previously installed Amnezia services") text: qsTr("Check the server for previously installed Amnezia services")
descriptionText: qsTr("Add them to the application if they were not displayed") descriptionText: qsTr("Add them to the application if they were not displayed")
KeyNavigation.tab: labelWithButton2
clickedFunction: function() { clickedFunction: function() {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
InstallController.scanServerForInstalledContainers() InstallController.scanServerForInstalledContainers()
@ -121,8 +119,6 @@ PageType {
text: qsTr("Reboot server") text: qsTr("Reboot server")
textColor: AmneziaStyle.color.vibrantRed textColor: AmneziaStyle.color.vibrantRed
KeyNavigation.tab: labelWithButton3
clickedFunction: function() { clickedFunction: function() {
var headerText = qsTr("Do you want to reboot the server?") var headerText = qsTr("Do you want to reboot the server?")
var descriptionText = qsTr("The reboot process may take approximately 30 seconds. Are you sure you wish to proceed?") var descriptionText = qsTr("The reboot process may take approximately 30 seconds. Are you sure you wish to proceed?")

View file

@ -25,7 +25,7 @@ PageType {
property int pageSettingsApiServerInfo: 3 property int pageSettingsApiServerInfo: 3
property int pageSettingsApiLanguageList: 4 property int pageSettingsApiLanguageList: 4
defaultActiveFocusItem: focusItem // defaultActiveFocusItem: focusItem
Connections { Connections {
target: PageController target: PageController
@ -46,11 +46,6 @@ PageType {
] ]
} }
Item {
id: focusItem
KeyNavigation.tab: header
}
ColumnLayout { ColumnLayout {
anchors.fill: parent anchors.fill: parent
@ -75,7 +70,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: headerContent.actionButton
backButtonFunction: function() { backButtonFunction: function() {
if (nestedStackView.currentIndex === root.pageSettingsApiServerInfo && if (nestedStackView.currentIndex === root.pageSettingsApiServerInfo &&
@ -108,13 +102,11 @@ PageType {
} }
} }
KeyNavigation.tab: tabBar
actionButtonFunction: function() { actionButtonFunction: function() {
if (nestedStackView.currentIndex === root.pageSettingsApiLanguageList) { if (nestedStackView.currentIndex === root.pageSettingsApiLanguageList) {
nestedStackView.currentIndex = root.pageSettingsApiServerInfo nestedStackView.currentIndex = root.pageSettingsApiServerInfo
} else { } else {
serverNameEditDrawer.open() serverNameEditDrawer.openTriggered()
} }
} }
} }
@ -133,7 +125,7 @@ PageType {
} }
} }
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@ -149,11 +141,6 @@ PageType {
} }
} }
Item {
id: focusItem1
KeyNavigation.tab: serverName.textField
}
TextFieldWithHeaderType { TextFieldWithHeaderType {
id: serverName id: serverName
@ -162,8 +149,6 @@ PageType {
textFieldText: name textFieldText: name
textField.maximumLength: 30 textField.maximumLength: 30
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: saveButton
} }
BasicButtonType { BasicButtonType {
@ -172,7 +157,6 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("Save") text: qsTr("Save")
KeyNavigation.tab: focusItem1
clickedFunc: function() { clickedFunc: function() {
if (serverName.textFieldText === "") { if (serverName.textFieldText === "") {
@ -182,7 +166,7 @@ PageType {
if (serverName.textFieldText !== name) { if (serverName.textFieldText !== name) {
name = serverName.textFieldText name = serverName.textFieldText
} }
serverNameEditDrawer.close() serverNameEditDrawer.closeTriggered()
} }
} }
} }
@ -219,7 +203,6 @@ PageType {
isSelected: tabBar.currentIndex === root.pageSettingsServerProtocols isSelected: tabBar.currentIndex === root.pageSettingsServerProtocols
text: qsTr("Protocols") text: qsTr("Protocols")
KeyNavigation.tab: servicesTab
Keys.onReturnPressed: tabBar.currentIndex = root.pageSettingsServerProtocols Keys.onReturnPressed: tabBar.currentIndex = root.pageSettingsServerProtocols
Keys.onEnterPressed: tabBar.currentIndex = root.pageSettingsServerProtocols Keys.onEnterPressed: tabBar.currentIndex = root.pageSettingsServerProtocols
} }
@ -231,7 +214,6 @@ PageType {
isSelected: tabBar.currentIndex === root.pageSettingsServerServices isSelected: tabBar.currentIndex === root.pageSettingsServerServices
text: qsTr("Services") text: qsTr("Services")
KeyNavigation.tab: dataTab
Keys.onReturnPressed: tabBar.currentIndex = root.pageSettingsServerServices Keys.onReturnPressed: tabBar.currentIndex = root.pageSettingsServerServices
Keys.onEnterPressed: tabBar.currentIndex = root.pageSettingsServerServices Keys.onEnterPressed: tabBar.currentIndex = root.pageSettingsServerServices
} }

View file

@ -21,13 +21,6 @@ PageType {
property bool isClearCacheVisible: ServersModel.isProcessedServerHasWriteAccess() && !ContainersModel.isServiceContainer(ContainersModel.getProcessedContainerIndex()) property bool isClearCacheVisible: ServersModel.isProcessedServerHasWriteAccess() && !ContainersModel.isServiceContainer(ContainersModel.getProcessedContainerIndex())
defaultActiveFocusItem: focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: header id: header
@ -39,7 +32,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: protocols
} }
HeaderType { HeaderType {
@ -168,7 +160,6 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
visible: root.isClearCacheVisible visible: root.isClearCacheVisible
KeyNavigation.tab: removeButton
text: qsTr("Clear profile") text: qsTr("Clear profile")

View file

@ -18,13 +18,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
ColumnLayout { ColumnLayout {
id: header id: header
@ -36,7 +29,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: servers
} }
HeaderType { HeaderType {
@ -48,95 +40,88 @@ PageType {
} }
} }
FlickableType { ListView {
id: fl id: servers
objectName: "servers"
width: parent.width
anchors.top: header.bottom anchors.top: header.bottom
anchors.topMargin: 16 anchors.topMargin: 16
contentHeight: col.implicitHeight anchors.left: parent.left
anchors.right: parent.right
Column { height: 500 // servers.contentItem.height // TODO: calculate height
id: col
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
ListView { model: ServersModel
id: servers
width: parent.width
height: servers.contentItem.height
model: ServersModel clip: true
interactive: false
clip: true // activeFocusOnTab: true
interactive: false // focus: true
// Keys.onTabPressed: {
// if (currentIndex < servers.count - 1) {
// servers.incrementCurrentIndex()
// } else {
// servers.currentIndex = 0
// focusItem.forceActiveFocus()
// root.lastItemTabClicked()
// }
activeFocusOnTab: true // fl.ensureVisible(this.currentItem)
focus: true // }
Keys.onTabPressed: {
if (currentIndex < servers.count - 1) {
servers.incrementCurrentIndex()
} else {
servers.currentIndex = 0
focusItem.forceActiveFocus()
root.lastItemTabClicked()
}
fl.ensureVisible(this.currentItem) onVisibleChanged: {
} if (visible) {
currentIndex = 0
}
}
onVisibleChanged: { delegate: Item {
if (visible) { implicitWidth: servers.width
currentIndex = 0 implicitHeight: delegateContent.implicitHeight
}
}
delegate: Item { // onFocusChanged: {
implicitWidth: servers.width // if (focus) {
implicitHeight: delegateContent.implicitHeight // server.rightButton.forceActiveFocus()
// }
// }
onFocusChanged: { ColumnLayout {
if (focus) { id: delegateContent
server.rightButton.forceActiveFocus()
}
}
ColumnLayout { anchors.top: parent.top
id: delegateContent anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top LabelWithButtonType {
anchors.left: parent.left id: server
anchors.right: parent.right Layout.fillWidth: true
LabelWithButtonType { text: name
id: server // parentFlickable: fl
Layout.fillWidth: true descriptionText: {
var servicesNameString = ""
text: name var servicesName = ServersModel.getAllInstalledServicesName(index)
parentFlickable: fl for (var i = 0; i < servicesName.length; i++) {
descriptionText: { servicesNameString += servicesName[i] + " · "
var servicesNameString = ""
var servicesName = ServersModel.getAllInstalledServicesName(index)
for (var i = 0; i < servicesName.length; i++) {
servicesNameString += servicesName[i] + " · "
}
if (ServersModel.isServerFromApi(index)) {
return servicesNameString + serverDescription
} else {
return servicesNameString + hostName
}
}
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
ServersModel.processedIndex = index
PageController.goToPage(PageEnum.PageSettingsServerInfo)
}
} }
DividerType {} if (ServersModel.isServerFromApi(index)) {
return servicesNameString + serverDescription
} else {
return servicesNameString + hostName
}
}
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
ServersModel.processedIndex = index
PageController.goToPage(PageEnum.PageSettingsServerInfo)
} }
} }
DividerType {}
} }
} }
} }

View file

@ -23,13 +23,6 @@ PageType {
property var isServerFromTelegramApi: ServersModel.getDefaultServerData("isServerFromTelegramApi") property var isServerFromTelegramApi: ServersModel.getDefaultServerData("isServerFromTelegramApi")
defaultActiveFocusItem: searchField.textField
Item {
id: focusItem
KeyNavigation.tab: backButton
}
property bool pageEnabled property bool pageEnabled
Component.onCompleted: { Component.onCompleted: {
@ -99,7 +92,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: switcher
} }
RowLayout { RowLayout {
@ -129,8 +121,6 @@ PageType {
onToggled: { onToggledFunc() } onToggled: { onToggledFunc() }
Keys.onEnterPressed: { onToggledFunc() } Keys.onEnterPressed: { onToggledFunc() }
Keys.onReturnPressed: { onToggledFunc() } Keys.onReturnPressed: { onToggledFunc() }
KeyNavigation.tab: selector
} }
} }
@ -180,11 +170,11 @@ PageType {
} }
} }
KeyNavigation.tab: { // KeyNavigation.tab: {
return sites.count > 0 ? // return sites.count > 0 ?
sites : // sites :
searchField.textField // searchField.textField
} // }
} }
} }
@ -325,7 +315,7 @@ PageType {
textFieldPlaceholderText: qsTr("website or IP") textFieldPlaceholderText: qsTr("website or IP")
buttonImageSource: "qrc:/images/controls/plus.svg" buttonImageSource: "qrc:/images/controls/plus.svg"
KeyNavigation.tab: GC.isMobile() ? focusItem : addSiteButtonImage // KeyNavigation.tab: GC.isMobile() ? focusItem : addSiteButtonImage
clickedFunc: function() { clickedFunc: function() {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
@ -344,7 +334,7 @@ PageType {
imageColor: AmneziaStyle.color.paleGray imageColor: AmneziaStyle.color.paleGray
onClicked: function () { onClicked: function () {
moreActionsDrawer.open() moreActionsDrawer.openTriggered()
} }
Keys.onReturnPressed: addSiteButtonImage.clicked() Keys.onReturnPressed: addSiteButtonImage.clicked()
@ -361,12 +351,12 @@ PageType {
expandedHeight: parent.height * 0.4375 expandedHeight: parent.height * 0.4375
onClosed: { onClosed: {
if (root.defaultActiveFocusItem && !GC.isMobile()) { // if (root.defaultActiveFocusItem && !GC.isMobile()) {
root.defaultActiveFocusItem.forceActiveFocus() // root.defaultActiveFocusItem.forceActiveFocus()
} // }
} }
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
id: moreActionsDrawerContent id: moreActionsDrawerContent
anchors.top: parent.top anchors.top: parent.top
@ -387,11 +377,6 @@ PageType {
} }
} }
Item {
id: focusItem1
KeyNavigation.tab: importSitesButton.rightButton
}
Header2Type { Header2Type {
Layout.fillWidth: true Layout.fillWidth: true
Layout.margins: 16 Layout.margins: 16
@ -407,10 +392,8 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() { clickedFunction: function() {
importSitesDrawer.open() importSitesDrawer.openTriggered()
} }
KeyNavigation.tab: exportSitesButton
} }
DividerType {} DividerType {}
@ -420,8 +403,6 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("Save site list") text: qsTr("Save site list")
KeyNavigation.tab: focusItem1
clickedFunction: function() { clickedFunction: function() {
var fileName = "" var fileName = ""
if (GC.isMobile()) { if (GC.isMobile()) {
@ -436,7 +417,7 @@ PageType {
if (fileName !== "") { if (fileName !== "") {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
SitesController.exportSites(fileName) SitesController.exportSites(fileName)
moreActionsDrawer.close() moreActionsDrawer.closeTriggered()
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
} }
} }
@ -458,7 +439,7 @@ PageType {
} }
} }
expandedContent: Item { expandedStateContent: Item {
implicitHeight: importSitesDrawer.expandedHeight implicitHeight: importSitesDrawer.expandedHeight
Connections { Connections {
@ -469,11 +450,6 @@ PageType {
} }
} }
Item {
id: focusItem2
KeyNavigation.tab: importSitesDrawerBackButton
}
BackButtonType { BackButtonType {
id: importSitesDrawerBackButton id: importSitesDrawerBackButton
@ -482,10 +458,8 @@ PageType {
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 16 anchors.topMargin: 16
KeyNavigation.tab: importSitesButton2
backButtonFunction: function() { backButtonFunction: function() {
importSitesDrawer.close() importSitesDrawer.closeTriggered()
} }
} }
@ -516,7 +490,6 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("Replace site list") text: qsTr("Replace site list")
KeyNavigation.tab: importSitesButton3
clickedFunction: function() { clickedFunction: function() {
var fileName = SystemController.getFileName(qsTr("Open sites file"), var fileName = SystemController.getFileName(qsTr("Open sites file"),
@ -533,7 +506,6 @@ PageType {
id: importSitesButton3 id: importSitesButton3
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("Add imported sites to existing ones") text: qsTr("Add imported sites to existing ones")
KeyNavigation.tab: focusItem2
clickedFunction: function() { clickedFunction: function() {
var fileName = SystemController.getFileName(qsTr("Open sites file"), var fileName = SystemController.getFileName(qsTr("Open sites file"),
@ -548,8 +520,8 @@ PageType {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
SitesController.importSites(fileName, replaceExistingSites) SitesController.importSites(fileName, replaceExistingSites)
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
importSitesDrawer.close() importSitesDrawer.closeTriggered()
moreActionsDrawer.close() moreActionsDrawer.closeTriggered()
} }
DividerType {} DividerType {}

View file

@ -15,8 +15,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
FlickableType { FlickableType {
id: fl id: fl
anchors.top: parent.top anchors.top: parent.top
@ -32,15 +30,9 @@ PageType {
spacing: 0 spacing: 0
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
Layout.topMargin: 20 Layout.topMargin: 20
// KeyNavigation.tab: fileButton.rightButton
} }
HeaderType { HeaderType {

View file

@ -14,8 +14,6 @@ import "../Config"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
FlickableType { FlickableType {
id: fl id: fl
anchors.top: parent.top anchors.top: parent.top
@ -31,15 +29,9 @@ PageType {
spacing: 0 spacing: 0
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
Layout.topMargin: 20 Layout.topMargin: 20
// KeyNavigation.tab: fileButton.rightButton
} }
HeaderType { HeaderType {

View file

@ -25,7 +25,7 @@ PageType {
} }
} }
defaultActiveFocusItem: focusItem // defaultActiveFocusItem: focusItem
FlickableType { FlickableType {
id: fl id: fl
@ -42,13 +42,9 @@ PageType {
spacing: 0 spacing: 0
Item {
id: focusItem
KeyNavigation.tab: textKey.textField
}
HeaderType { HeaderType {
id: moreButton
property bool isVisible: SettingsController.getInstallationUuid() !== "" || PageController.isStartPageVisible() property bool isVisible: SettingsController.getInstallationUuid() !== "" || PageController.isStartPageVisible()
Layout.fillWidth: true Layout.fillWidth: true
@ -60,7 +56,16 @@ PageType {
actionButtonImage: isVisible ? "qrc:/images/controls/more-vertical.svg" : "" actionButtonImage: isVisible ? "qrc:/images/controls/more-vertical.svg" : ""
actionButtonFunction: function() { actionButtonFunction: function() {
moreActionsDrawer.open() moreActionsDrawer.openTriggered()
}
actionButton.onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (actionButton.activeFocus) {
if (fl) {
fl.ensureVisible(moreButton)
}
}
} }
DrawerType2 { DrawerType2 {
@ -71,7 +76,7 @@ PageType {
anchors.fill: parent anchors.fill: parent
expandedHeight: root.height * 0.5 expandedHeight: root.height * 0.5
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@ -154,8 +159,6 @@ PageType {
textField.text = "" textField.text = ""
textField.paste() textField.paste()
} }
KeyNavigation.tab: continueButton
} }
BasicButtonType { BasicButtonType {
@ -166,10 +169,18 @@ PageType {
Layout.rightMargin: 16 Layout.rightMargin: 16
Layout.leftMargin: 16 Layout.leftMargin: 16
onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (activeFocus) {
if (fl) {
fl.ensureVisible(this)
}
}
}
visible: textKey.textFieldText !== "" visible: textKey.textFieldText !== ""
text: qsTr("Continue") text: qsTr("Continue")
Keys.onTabPressed: lastItemTabClicked(focusItem)
clickedFunc: function() { clickedFunc: function() {
if (ImportController.extractConfigFromData(textKey.textFieldText)) { if (ImportController.extractConfigFromData(textKey.textFieldText)) {
@ -203,6 +214,15 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
leftImageSource: "qrc:/images/controls/amnezia.svg" leftImageSource: "qrc:/images/controls/amnezia.svg"
focusItem.onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (focusItem.activeFocus) {
if (fl) {
fl.ensureVisible(apiInstalling)
}
}
}
onClicked: function() { onClicked: function() {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
var result = InstallController.fillAvailableServices() var result = InstallController.fillAvailableServices()
@ -227,6 +247,15 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
leftImageSource: "qrc:/images/controls/server.svg" leftImageSource: "qrc:/images/controls/server.svg"
focusItem.onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (focusItem.activeFocus) {
if (fl) {
fl.ensureVisible(manualInstalling)
}
}
}
onClicked: { onClicked: {
PageController.goToPage(PageEnum.PageSetupWizardCredentials) PageController.goToPage(PageEnum.PageSetupWizardCredentials)
} }
@ -247,6 +276,15 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
leftImageSource: "qrc:/images/controls/archive-restore.svg" leftImageSource: "qrc:/images/controls/archive-restore.svg"
focusItem.onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (focusItem.activeFocus) {
if (fl) {
fl.ensureVisible(backupRestore)
}
}
}
onClicked: { onClicked: {
var filePath = SystemController.getFileName(qsTr("Open backup file"), var filePath = SystemController.getFileName(qsTr("Open backup file"),
qsTr("Backup files (*.backup)")) qsTr("Backup files (*.backup)"))
@ -271,6 +309,13 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
leftImageSource: "qrc:/images/controls/folder-search-2.svg" leftImageSource: "qrc:/images/controls/folder-search-2.svg"
focusItem.onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (fl) {
fl.ensureVisible(openFile)
}
}
onClicked: { onClicked: {
var nameFilter = !ServersModel.getServersCount() ? "Config or backup files (*.vpn *.ovpn *.conf *.json *.backup)" : var nameFilter = !ServersModel.getServersCount() ? "Config or backup files (*.vpn *.ovpn *.conf *.json *.backup)" :
"Config files (*.vpn *.ovpn *.conf *.json)" "Config files (*.vpn *.ovpn *.conf *.json)"
@ -298,6 +343,15 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
leftImageSource: "qrc:/images/controls/scan-line.svg" leftImageSource: "qrc:/images/controls/scan-line.svg"
focusItem.onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (focusItem.activeFocus) {
if (fl) {
fl.ensureVisible(scanQr)
}
}
}
onClicked: { onClicked: {
ImportController.startDecodingQr() ImportController.startDecodingQr()
if (Qt.platform.os === "ios") { if (Qt.platform.os === "ios") {
@ -321,6 +375,15 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
leftImageSource: "qrc:/images/controls/help-circle.svg" leftImageSource: "qrc:/images/controls/help-circle.svg"
focusItem.onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (focusItem.activeFocus) {
if (fl) {
fl.ensureVisible(siteLink)
}
}
}
onClicked: { onClicked: {
Qt.openUrlExternally(LanguageModel.getCurrentSiteUrl()) Qt.openUrlExternally(LanguageModel.getCurrentSiteUrl())
} }

View file

@ -13,12 +13,7 @@ import "../Controls2/TextTypes"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: hostname.textField // defaultActiveFocusItem: hostname.textField
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -27,8 +22,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: hostname.textField
} }
FlickableType { FlickableType {
@ -64,8 +57,6 @@ PageType {
textField.onFocusChanged: { textField.onFocusChanged: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '') textField.text = textField.text.replace(/^\s+|\s+$/g, '')
} }
KeyNavigation.tab: username.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -78,8 +69,6 @@ PageType {
textField.onFocusChanged: { textField.onFocusChanged: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '') textField.text = textField.text.replace(/^\s+|\s+$/g, '')
} }
KeyNavigation.tab: secretData.textField
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -100,8 +89,6 @@ PageType {
textField.onFocusChanged: { textField.onFocusChanged: {
textField.text = textField.text.replace(/^\s+|\s+$/g, '') textField.text = textField.text.replace(/^\s+|\s+$/g, '')
} }
KeyNavigation.tab: continueButton
} }
BasicButtonType { BasicButtonType {
@ -112,8 +99,6 @@ PageType {
text: qsTr("Continue") text: qsTr("Continue")
Keys.onTabPressed: lastItemTabClicked(focusItem)
clickedFunc: function() { clickedFunc: function() {
forceActiveFocus() forceActiveFocus()
if (!isCredentialsFilled()) { if (!isCredentialsFilled()) {

View file

@ -17,7 +17,6 @@ PageType {
id: root id: root
property bool isEasySetup: true property bool isEasySetup: true
defaultActiveFocusItem: focusItem
SortFilterProxyModel { SortFilterProxyModel {
id: proxyContainersModel id: proxyContainersModel
@ -34,14 +33,6 @@ PageType {
} }
} }
Item {
id: focusItem
implicitWidth: 1
implicitHeight: 54
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -49,8 +40,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: continueButton
} }
FlickableType { FlickableType {
@ -163,7 +152,7 @@ PageType {
implicitWidth: parent.width implicitWidth: parent.width
text: qsTr("Continue") text: qsTr("Continue")
KeyNavigation.tab: setupLaterButton
parentFlickable: fl parentFlickable: fl
clickedFunc: function() { clickedFunc: function() {

View file

@ -62,19 +62,12 @@ PageType {
anchors.rightMargin: 16 anchors.rightMargin: 16
anchors.leftMargin: 16 anchors.leftMargin: 16
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
Layout.topMargin: 20 Layout.topMargin: 20
Layout.rightMargin: -16 Layout.rightMargin: -16
Layout.leftMargin: -16 Layout.leftMargin: -16
KeyNavigation.tab: showDetailsButton
} }
HeaderType { HeaderType {
@ -113,13 +106,13 @@ PageType {
parent: root parent: root
onClosed: { onClosed: {
if (!GC.isMobile()) { if (!GC.isMobile()) {
defaultActiveFocusItem.forceActiveFocus() // defaultActiveFocusItem.forceActiveFocus()
} }
} }
anchors.fill: parent anchors.fill: parent
expandedHeight: parent.height * 0.9 expandedHeight: parent.height * 0.9
expandedContent: Item { expandedStateContent: Item {
Connections { Connections {
target: showDetailsDrawer target: showDetailsDrawer
enabled: !GC.isMobile() enabled: !GC.isMobile()
@ -130,15 +123,15 @@ PageType {
implicitHeight: showDetailsDrawer.expandedHeight implicitHeight: showDetailsDrawer.expandedHeight
Item { // Item {
id: focusItem2 // id: focusItem2
KeyNavigation.tab: showDetailsBackButton // KeyNavigation.tab: showDetailsBackButton
onFocusChanged: { // onFocusChanged: {
if (focusItem2.activeFocus) { // if (focusItem2.activeFocus) {
fl.contentY = 0 // fl.contentY = 0
} // }
} // }
} // }
BackButtonType { BackButtonType {
id: showDetailsBackButton id: showDetailsBackButton
@ -148,8 +141,6 @@ PageType {
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 16 anchors.topMargin: 16
KeyNavigation.tab: showDetailsCloseButton
backButtonFunction: function() { backButtonFunction: function() {
showDetailsDrawer.close() showDetailsDrawer.close()
} }
@ -230,7 +221,7 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
rootWidth: root.width rootWidth: root.width
KeyNavigation.tab: (port.visible && port.enabled) ? port.textField : installButton // KeyNavigation.tab: (port.visible && port.enabled) ? port.textField : installButton
} }
TextFieldWithHeaderType { TextFieldWithHeaderType {
@ -242,8 +233,6 @@ PageType {
headerText: qsTr("Port") headerText: qsTr("Port")
textField.maximumLength: 5 textField.maximumLength: 5
textField.validator: IntValidator { bottom: 1; top: 65535 } textField.validator: IntValidator { bottom: 1; top: 65535 }
KeyNavigation.tab: installButton
} }
Rectangle { Rectangle {
@ -289,10 +278,10 @@ PageType {
transportProtoSelector.visible = protocolSelectorVisible transportProtoSelector.visible = protocolSelectorVisible
transportProtoHeader.visible = protocolSelectorVisible transportProtoHeader.visible = protocolSelectorVisible
if (port.visible && port.enabled) // if (port.visible && port.enabled)
defaultActiveFocusItem = port.textField // defaultActiveFocusItem = port.textField
else // else
defaultActiveFocusItem = focusItem // defaultActiveFocusItem = focusItem
} }
} }
} }

View file

@ -15,13 +15,6 @@ import "../Config"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
SortFilterProxyModel { SortFilterProxyModel {
id: proxyContainersModel id: proxyContainersModel
sourceModel: ContainersModel sourceModel: ContainersModel
@ -52,7 +45,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
KeyNavigation.tab: containers
} }
} }

View file

@ -14,8 +14,6 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem
ColumnLayout { ColumnLayout {
id: content id: content
@ -32,11 +30,6 @@ PageType {
Layout.preferredHeight: 287 Layout.preferredHeight: 287
} }
Item {
id: focusItem
KeyNavigation.tab: startButton
}
BasicButtonType { BasicButtonType {
id: startButton id: startButton
Layout.fillWidth: true Layout.fillWidth: true
@ -50,8 +43,6 @@ PageType {
clickedFunc: function() { clickedFunc: function() {
PageController.goToPage(PageEnum.PageSetupWizardConfigSource) PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
} }
Keys.onTabPressed: lastItemTabClicked(focusItem)
} }
} }
} }

View file

@ -13,14 +13,6 @@ import "../Config"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: textKey.textField
Item {
id: focusItem
KeyNavigation.tab: backButton
}
FlickableType { FlickableType {
id: fl id: fl
anchors.top: parent.top anchors.top: parent.top
@ -39,7 +31,6 @@ PageType {
BackButtonType { BackButtonType {
id: backButton id: backButton
Layout.topMargin: 20 Layout.topMargin: 20
KeyNavigation.tab: textKey.textField
} }
HeaderType { HeaderType {
@ -67,8 +58,6 @@ PageType {
textField.text = "" textField.text = ""
textField.paste() textField.paste()
} }
KeyNavigation.tab: continueButton
} }
} }
} }

View file

@ -16,13 +16,6 @@ PageType {
property bool showContent: false property bool showContent: false
defaultActiveFocusItem: focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -30,8 +23,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: showContentButton
} }
Connections { Connections {
@ -107,7 +98,6 @@ PageType {
textColor: AmneziaStyle.color.goldenApricot textColor: AmneziaStyle.color.goldenApricot
text: showContent ? qsTr("Collapse content") : qsTr("Show content") text: showContent ? qsTr("Collapse content") : qsTr("Show content")
KeyNavigation.tab: connectButton
clickedFunc: function() { clickedFunc: function() {
showContent = !showContent showContent = !showContent

View file

@ -18,8 +18,6 @@ import "../Config"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: clientNameTextField.textField
enum ConfigType { enum ConfigType {
AmneziaConnection, AmneziaConnection,
OpenVpn, OpenVpn,
@ -47,7 +45,7 @@ PageType {
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
shareConnectionDrawer.open() shareConnectionDrawer.
shareConnectionDrawer.contentVisible = false shareConnectionDrawer.contentVisible = false
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
@ -104,7 +102,7 @@ PageType {
} }
function onExportErrorOccurred(error) { function onExportErrorOccurred(error) {
shareConnectionDrawer.close() shareConnectionDrawer.closeTriggered()
PageController.showErrorMessage(error) PageController.showErrorMessage(error)
} }
@ -172,16 +170,6 @@ PageType {
spacing: 0 spacing: 0
Item {
id: focusItem
KeyNavigation.tab: header.actionButton
onFocusChanged: {
if (focusItem.activeFocus) {
a.contentY = 0
}
}
}
HeaderType { HeaderType {
id: header id: header
Layout.fillWidth: true Layout.fillWidth: true
@ -191,10 +179,18 @@ PageType {
actionButtonImage: "qrc:/images/controls/more-vertical.svg" actionButtonImage: "qrc:/images/controls/more-vertical.svg"
actionButtonFunction: function() { actionButtonFunction: function() {
shareFullAccessDrawer.open() shareFullAccessDrawer.openTriggered()
} }
KeyNavigation.tab: connectionRadioButton // KeyNavigation.tab: connectionRadioButton
actionButton.onFocusChanged: {
console.debug("MOVE THIS LOGIC TO CPP!")
if (actionButton.activeFocus) {
if (fl) {
fl.ensureVisible(moreButton)
}
}
}
DrawerType2 { DrawerType2 {
id: shareFullAccessDrawer id: shareFullAccessDrawer
@ -205,11 +201,11 @@ PageType {
expandedHeight: root.height expandedHeight: root.height
onClosed: { onClosed: {
if (!GC.isMobile()) { if (!GC.isMobile()) {
clientNameTextField.textField.forceActiveFocus() // clientNameTextField.textField.forceActiveFocus()
} }
} }
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
id: shareFullAccessDrawerContent id: shareFullAccessDrawerContent
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
@ -226,7 +222,7 @@ PageType {
target: shareFullAccessDrawer target: shareFullAccessDrawer
enabled: !GC.isMobile() enabled: !GC.isMobile()
function onOpened() { function onOpened() {
focusItem.forceActiveFocus() // focusItem.forceActiveFocus()
} }
} }
@ -240,10 +236,10 @@ PageType {
descriptionText: qsTr("Use for your own devices, or share with those you trust to manage the server.") descriptionText: qsTr("Use for your own devices, or share with those you trust to manage the server.")
} }
Item { // Item {
id: focusItem // id: focusItem
KeyNavigation.tab: shareFullAccessButton.rightButton // // KeyNavigation.tab: shareFullAccessButton.rightButton
} // }
LabelWithButtonType { LabelWithButtonType {
id: shareFullAccessButton id: shareFullAccessButton
@ -251,11 +247,11 @@ PageType {
text: qsTr("Share") text: qsTr("Share")
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
KeyNavigation.tab: focusItem // KeyNavigation.tab: focusItem
clickedFunction: function() { clickedFunction: function() {
PageController.goToPage(PageEnum.PageShareFullAccess) PageController.goToPage(PageEnum.PageShareFullAccess)
shareFullAccessDrawer.close() shareFullAccessDrawer.closeTriggered()
} }
} }
@ -288,12 +284,12 @@ PageType {
implicitWidth: (root.width - 32) / 2 implicitWidth: (root.width - 32) / 2
text: qsTr("Connection") text: qsTr("Connection")
KeyNavigation.tab: usersRadioButton // KeyNavigation.tab: usersRadioButton
onClicked: { onClicked: {
accessTypeSelector.currentIndex = 0 accessTypeSelector.currentIndex = 0
if (!GC.isMobile()) { if (!GC.isMobile()) {
clientNameTextField.textField.forceActiveFocus() // clientNameTextField.textField.forceActiveFocus()
} }
} }
} }
@ -305,7 +301,7 @@ PageType {
implicitWidth: (root.width - 32) / 2 implicitWidth: (root.width - 32) / 2
text: qsTr("Users") text: qsTr("Users")
KeyNavigation.tab: accessTypeSelector.currentIndex === 0 ? clientNameTextField.textField : serverSelector // KeyNavigation.tab: accessTypeSelector.currentIndex === 0 ? clientNameTextField.textField : serverSelector
onClicked: { onClicked: {
accessTypeSelector.currentIndex = 1 accessTypeSelector.currentIndex = 1
@ -313,7 +309,7 @@ PageType {
ExportController.updateClientManagementModel(ContainersModel.getProcessedContainerIndex(), ExportController.updateClientManagementModel(ContainersModel.getProcessedContainerIndex(),
ServersModel.getProcessedServerCredentials()) ServersModel.getProcessedServerCredentials())
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
focusItem.forceActiveFocus() // focusItem.forceActiveFocus()
} }
} }
} }
@ -343,7 +339,7 @@ PageType {
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: serverSelector // KeyNavigation.tab: serverSelector
} }
@ -390,7 +386,7 @@ PageType {
serverSelector.severSelectorIndexChanged() serverSelector.severSelectorIndexChanged()
} }
serverSelector.close() serverSelector.closeTriggered()
} }
Component.onCompleted: { Component.onCompleted: {
@ -409,7 +405,7 @@ PageType {
} }
} }
KeyNavigation.tab: protocolSelector // KeyNavigation.tab: protocolSelector
} }
DropDownType { DropDownType {
@ -450,7 +446,7 @@ PageType {
clickedFunction: function() { clickedFunction: function() {
handler() handler()
protocolSelector.close() protocolSelector.closeTriggered()
} }
Connections { Connections {
@ -509,11 +505,11 @@ PageType {
} }
} }
KeyNavigation.tab: accessTypeSelector.currentIndex === 0 ? // KeyNavigation.tab: accessTypeSelector.currentIndex === 0 ?
exportTypeSelector : // exportTypeSelector : searchTextField.textField
isSearchBarVisible ? // isSearchBarVisible ?
searchTextField.textField : // searchTextField.textField :
usersHeader.actionButton // usersHeader.actionButton
} }
DropDownType { DropDownType {
@ -549,7 +545,7 @@ PageType {
clickedFunction: function() { clickedFunction: function() {
exportTypeSelector.text = selectedText exportTypeSelector.text = selectedText
exportTypeSelector.currentIndex = currentIndex exportTypeSelector.currentIndex = currentIndex
exportTypeSelector.close() exportTypeSelector.closeTriggered()
} }
Component.onCompleted: { Component.onCompleted: {
@ -558,7 +554,7 @@ PageType {
} }
} }
KeyNavigation.tab: shareButton // KeyNavigation.tab: shareButton
} }
@ -622,11 +618,11 @@ PageType {
target: root target: root
function onIsSearchBarVisibleChanged() { function onIsSearchBarVisibleChanged() {
if (root.isSearchBarVisible) { if (root.isSearchBarVisible) {
searchTextField.textField.forceActiveFocus() // searchTextField.textField.forceActiveFocus()
} else { } else {
searchTextField.textFieldText = "" searchTextField.textFieldText = ""
if (!GC.isMobile()) { if (!GC.isMobile()) {
usersHeader.actionButton.forceActiveFocus() // usersHeader.actionButton.forceActiveFocus()
} }
} }
} }
@ -638,15 +634,15 @@ PageType {
function navigateTo() { function navigateTo() {
if (GC.isMobile()) { if (GC.isMobile()) {
focusItem.forceActiveFocus() // focusItem.forceActiveFocus()
return; return;
} }
if (searchTextField.textFieldText === "") { if (searchTextField.textFieldText === "") {
root.isSearchBarVisible = false root.isSearchBarVisible = false
usersHeader.actionButton.forceActiveFocus() // usersHeader.actionButton.forceActiveFocus()
} else { } else {
closeSearchButton.forceActiveFocus() // closeSearchButton.forceActiveFocus()
} }
} }
@ -663,9 +659,9 @@ PageType {
Keys.onTabPressed: { Keys.onTabPressed: {
if (!GC.isMobile()) { if (!GC.isMobile()) {
if (clientsListView.model.count > 0) { if (clientsListView.model.count > 0) {
clientsListView.forceActiveFocus() // clientsListView.forceActiveFocus()
} else { } else {
lastItemTabClicked(focusItem) // lastItemTabClicked(focusItem)
} }
} }
} }
@ -706,10 +702,10 @@ PageType {
if (!GC.isMobile()) { if (!GC.isMobile()) {
if (currentIndex < this.count - 1) { if (currentIndex < this.count - 1) {
this.incrementCurrentIndex() this.incrementCurrentIndex()
currentItem.focusItem.forceActiveFocus() // currentItem.focusItem.forceActiveFocus()
} else { } else {
this.currentIndex = 0 this.currentIndex = 0
lastItemTabClicked(focusItem) // lastItemTabClicked(focusItem)
} }
} }
} }
@ -717,7 +713,7 @@ PageType {
onActiveFocusChanged: { onActiveFocusChanged: {
if (focus && !GC.isMobile()) { if (focus && !GC.isMobile()) {
currentIndex = 0 currentIndex = 0
currentItem.focusItem.forceActiveFocus() // currentItem.focusItem.forceActiveFocus()
} }
} }
@ -735,7 +731,7 @@ PageType {
implicitWidth: clientsListView.width implicitWidth: clientsListView.width
implicitHeight: delegateContent.implicitHeight implicitHeight: delegateContent.implicitHeight
property alias focusItem: clientFocusItem.rightButton // property alias focusItem: clientFocusItem.rightButton
ColumnLayout { ColumnLayout {
id: delegateContent id: delegateContent
@ -755,7 +751,7 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() { clickedFunction: function() {
clientInfoDrawer.open() clientInfoDrawer.openTriggered()
} }
} }
@ -768,15 +764,15 @@ PageType {
onClosed: { onClosed: {
if (!GC.isMobile()) { if (!GC.isMobile()) {
focusItem.forceActiveFocus() // focusItem.forceActiveFocus()
} }
} }
width: root.width width: root.width
height: root.height height: root.height
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
id: expandedContent id: expandedStateContent
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@ -785,14 +781,14 @@ PageType {
anchors.rightMargin: 16 anchors.rightMargin: 16
onImplicitHeightChanged: { onImplicitHeightChanged: {
clientInfoDrawer.expandedHeight = expandedContent.implicitHeight + 32 clientInfoDrawer.expandedHeight = expandedStateContent.implicitHeight + 32
} }
Connections { Connections {
target: clientInfoDrawer target: clientInfoDrawer
enabled: !GC.isMobile() enabled: !GC.isMobile()
function onOpened() { function onOpened() {
focusItem1.forceActiveFocus() // focusItem1.forceActiveFocus()
} }
} }
@ -846,11 +842,6 @@ PageType {
text: qsTr("Allowed IPs: %1").arg(allowedIps) text: qsTr("Allowed IPs: %1").arg(allowedIps)
} }
Item {
id: focusItem1
KeyNavigation.tab: renameButton
}
BasicButtonType { BasicButtonType {
id: renameButton id: renameButton
Layout.fillWidth: true Layout.fillWidth: true
@ -865,10 +856,10 @@ PageType {
text: qsTr("Rename") text: qsTr("Rename")
KeyNavigation.tab: revokeButton // KeyNavigation.tab: revokeButton
clickedFunc: function() { clickedFunc: function() {
clientNameEditDrawer.open() clientNameEditDrawer.openTriggered()
} }
DrawerType2 { DrawerType2 {
@ -881,11 +872,11 @@ PageType {
onClosed: { onClosed: {
if (!GC.isMobile()) { if (!GC.isMobile()) {
focusItem1.forceActiveFocus() // focusItem1.forceActiveFocus()
} }
} }
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@ -897,15 +888,10 @@ PageType {
target: clientNameEditDrawer target: clientNameEditDrawer
enabled: !GC.isMobile() enabled: !GC.isMobile()
function onOpened() { function onOpened() {
clientNameEditor.textField.forceActiveFocus() // clientNameEditor.textField.forceActiveFocus()
} }
} }
Item {
id: focusItem2
KeyNavigation.tab: clientNameEditor.textField
}
TextFieldWithHeaderType { TextFieldWithHeaderType {
id: clientNameEditor id: clientNameEditor
Layout.fillWidth: true Layout.fillWidth: true
@ -914,7 +900,7 @@ PageType {
textField.maximumLength: 20 textField.maximumLength: 20
checkEmptyText: true checkEmptyText: true
KeyNavigation.tab: saveButton // KeyNavigation.tab: saveButton
} }
BasicButtonType { BasicButtonType {
@ -923,7 +909,7 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
text: qsTr("Save") text: qsTr("Save")
KeyNavigation.tab: focusItem2 // KeyNavigation.tab: focusItem2
clickedFunc: function() { clickedFunc: function() {
if (clientNameEditor.textFieldText === "") { if (clientNameEditor.textFieldText === "") {
@ -937,7 +923,7 @@ PageType {
ContainersModel.getProcessedContainerIndex(), ContainersModel.getProcessedContainerIndex(),
ServersModel.getProcessedServerCredentials()) ServersModel.getProcessedServerCredentials())
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
clientNameEditDrawer.close() clientNameEditDrawer.closeTriggered()
} }
} }
} }
@ -958,7 +944,7 @@ PageType {
borderWidth: 1 borderWidth: 1
text: qsTr("Revoke") text: qsTr("Revoke")
KeyNavigation.tab: focusItem1 // KeyNavigation.tab: focusItem1
clickedFunc: function() { clickedFunc: function() {
var headerText = qsTr("Revoke the config for a user - %1?").arg(clientName) var headerText = qsTr("Revoke the config for a user - %1?").arg(clientName)
@ -967,12 +953,12 @@ PageType {
var noButtonText = qsTr("Cancel") var noButtonText = qsTr("Cancel")
var yesButtonFunction = function() { var yesButtonFunction = function() {
clientInfoDrawer.close() clientInfoDrawer.closeTriggered()
root.revokeConfig(index) root.revokeConfig(index)
} }
var noButtonFunction = function() { var noButtonFunction = function() {
if (!GC.isMobile()) { if (!GC.isMobile()) {
focusItem1.forceActiveFocus() // focusItem1.forceActiveFocus()
} }
} }
@ -993,7 +979,7 @@ PageType {
anchors.fill: parent anchors.fill: parent
onClosed: { onClosed: {
if (!GC.isMobile()) { if (!GC.isMobile()) {
clientNameTextField.textField.forceActiveFocus() // clientNameTextField.textField.forceActiveFocus()
} }
} }
} }
@ -1001,7 +987,7 @@ PageType {
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onPressed: function(mouse) { onPressed: function(mouse) {
forceActiveFocus() // forceActiveFocus()
mouse.accepted = false mouse.accepted = false
} }
} }

View file

@ -18,12 +18,7 @@ import "../Config"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: focusItem // defaultActiveFocusItem: focusItem
Item {
id: focusItem
KeyNavigation.tab: backButton
}
BackButtonType { BackButtonType {
id: backButton id: backButton
@ -32,8 +27,6 @@ PageType {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.topMargin: 20 anchors.topMargin: 20
KeyNavigation.tab: serverSelector
} }
FlickableType { FlickableType {
@ -85,8 +78,6 @@ PageType {
descriptionText: qsTr("Server") descriptionText: qsTr("Server")
headerText: qsTr("Server") headerText: qsTr("Server")
KeyNavigation.tab: shareButton
listView: ListViewWithRadioButtonType { listView: ListViewWithRadioButtonType {
id: serverSelectorListView id: serverSelectorListView
@ -137,8 +128,6 @@ PageType {
text: qsTr("Share") text: qsTr("Share")
leftImageSource: "qrc:/images/controls/share-2.svg" leftImageSource: "qrc:/images/controls/share-2.svg"
Keys.onTabPressed: lastItemTabClicked(focusItem)
clickedFunc: function() { clickedFunc: function() {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
@ -166,10 +155,5 @@ PageType {
id: shareConnectionDrawer id: shareConnectionDrawer
anchors.fill: parent anchors.fill: parent
onClosed: {
if (!GC.isMobile()) {
focusItem.forceActiveFocus()
}
}
} }
} }

View file

@ -15,12 +15,12 @@ import "../Components"
PageType { PageType {
id: root id: root
defaultActiveFocusItem: homeTabButton
property bool isControlsDisabled: false property bool isControlsDisabled: false
property bool isTabBarDisabled: false property bool isTabBarDisabled: false
Connections { Connections {
objectName: "pageControllerConnection"
target: PageController target: PageController
function onGoToPageHome() { function onGoToPageHome() {
@ -91,18 +91,20 @@ PageType {
} }
} }
function onForceTabBarActiveFocus() { // function onForceTabBarActiveFocus() {
homeTabButton.focus = true // homeTabButton.focus = true
tabBar.forceActiveFocus() // tabBar.forceActiveFocus()
} // }
function onForceStackActiveFocus() { // function onForceStackActiveFocus() {
homeTabButton.focus = true // homeTabButton.focus = true
tabBarStackView.forceActiveFocus() // tabBarStackView.forceActiveFocus()
} // }
} }
Connections { Connections {
objectName: "installControllerConnections"
target: InstallController target: InstallController
function onInstallationErrorOccurred(error) { function onInstallationErrorOccurred(error) {
@ -165,6 +167,8 @@ PageType {
} }
Connections { Connections {
objectName: "connectionControllerConnections"
target: ConnectionController target: ConnectionController
function onReconnectWithUpdatedContainer(message) { function onReconnectWithUpdatedContainer(message) {
@ -182,6 +186,8 @@ PageType {
} }
Connections { Connections {
objectName: "importControllerConnections"
target: ImportController target: ImportController
function onImportErrorOccurred(error, goToPageHome) { function onImportErrorOccurred(error, goToPageHome) {
@ -196,6 +202,8 @@ PageType {
} }
Connections { Connections {
objectName: "settingsControllerConnections"
target: SettingsController target: SettingsController
function onLoggingDisableByWatcher() { function onLoggingDisableByWatcher() {
@ -218,6 +226,7 @@ PageType {
StackViewType { StackViewType {
id: tabBarStackView id: tabBarStackView
objectName: "tabBarStackView"
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
@ -254,6 +263,7 @@ PageType {
TabBar { TabBar {
id: tabBar id: tabBar
objectName: "tabBar"
anchors.right: parent.right anchors.right: parent.right
anchors.left: parent.left anchors.left: parent.left
@ -269,6 +279,8 @@ PageType {
enabled: !root.isControlsDisabled && !root.isTabBarDisabled enabled: !root.isControlsDisabled && !root.isTabBarDisabled
background: Shape { background: Shape {
objectName: "backgroundShape"
width: parent.width width: parent.width
height: parent.height height: parent.height
@ -289,21 +301,25 @@ PageType {
TabImageButtonType { TabImageButtonType {
id: homeTabButton id: homeTabButton
objectName: "homeTabButton"
isSelected: tabBar.currentIndex === 0 isSelected: tabBar.currentIndex === 0
image: "qrc:/images/controls/home.svg" image: "qrc:/images/controls/home.svg"
clickedFunc: function () { clickedFunc: function () {
tabBarStackView.goToTabBarPage(PageEnum.PageHome) tabBarStackView.goToTabBarPage(PageEnum.PageHome)
ServersModel.processedIndex = ServersModel.defaultIndex ServersModel.processedIndex = ServersModel.defaultIndex
tabBar.currentIndex = 0 tabBar.currentIndex = 0
FocusController.setRootItem(null) // TODO: move to do it automaticaly
} }
KeyNavigation.tab: shareTabButton // KeyNavigation.tab: shareTabButton
Keys.onEnterPressed: this.clicked() // Keys.onEnterPressed: this.clicked()
Keys.onReturnPressed: this.clicked() // Keys.onReturnPressed: this.clicked()
} }
TabImageButtonType { TabImageButtonType {
id: shareTabButton id: shareTabButton
objectName: "shareTabButton"
Connections { Connections {
target: ServersModel target: ServersModel
@ -325,11 +341,13 @@ PageType {
tabBar.currentIndex = 1 tabBar.currentIndex = 1
} }
KeyNavigation.tab: settingsTabButton // KeyNavigation.tab: settingsTabButton
} }
TabImageButtonType { TabImageButtonType {
id: settingsTabButton id: settingsTabButton
objectName: "settingsTabButton"
isSelected: tabBar.currentIndex === 2 isSelected: tabBar.currentIndex === 2
image: "qrc:/images/controls/settings-2.svg" image: "qrc:/images/controls/settings-2.svg"
clickedFunc: function () { clickedFunc: function () {
@ -337,11 +355,13 @@ PageType {
tabBar.currentIndex = 2 tabBar.currentIndex = 2
} }
KeyNavigation.tab: plusTabButton // KeyNavigation.tab: plusTabButton
} }
TabImageButtonType { TabImageButtonType {
id: plusTabButton id: plusTabButton
objectName: "plusTabButton"
isSelected: tabBar.currentIndex === 3 isSelected: tabBar.currentIndex === 3
image: "qrc:/images/controls/plus.svg" image: "qrc:/images/controls/plus.svg"
clickedFunc: function () { clickedFunc: function () {
@ -349,7 +369,7 @@ PageType {
tabBar.currentIndex = 3 tabBar.currentIndex = 3
} }
Keys.onTabPressed: PageController.forceStackActiveFocus() // Keys.onTabPressed: PageController.forceStackActiveFocus()
} }
} }
} }

View file

@ -33,6 +33,8 @@ Window {
title: "AmneziaVPN" title: "AmneziaVPN"
Connections { Connections {
objectName: "pageControllerConnections"
target: PageController target: PageController
function onRaiseMainWindow() { function onRaiseMainWindow() {
@ -72,6 +74,8 @@ Window {
} }
Connections { Connections {
objectName: "settingsControllerConnections"
target: SettingsController target: SettingsController
function onChangeSettingsFinished(finishedMessage) { function onChangeSettingsFinished(finishedMessage) {
@ -80,11 +84,15 @@ Window {
} }
PageStart { PageStart {
objectName: "pageStart"
width: root.width width: root.width
height: root.height height: root.height
} }
Item { Item {
objectName: "popupNotificationItem"
anchors.right: parent.right anchors.right: parent.right
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -108,6 +116,8 @@ Window {
} }
Item { Item {
objectName: "popupErrorMessageItem"
anchors.right: parent.right anchors.right: parent.right
anchors.left: parent.left anchors.left: parent.left
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
@ -120,6 +130,8 @@ Window {
} }
Item { Item {
objectName: "privateKeyPassphraseDrawerItem"
anchors.fill: parent anchors.fill: parent
DrawerType2 { DrawerType2 {
@ -128,7 +140,7 @@ Window {
anchors.fill: parent anchors.fill: parent
expandedHeight: root.height * 0.35 expandedHeight: root.height * 0.35
expandedContent: ColumnLayout { expandedStateContent: ColumnLayout {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
@ -168,7 +180,7 @@ Window {
hidePassword = !hidePassword hidePassword = !hidePassword
} }
KeyNavigation.tab: saveButton // KeyNavigation.tab: saveButton
} }
BasicButtonType { BasicButtonType {
@ -195,6 +207,8 @@ Window {
} }
Item { Item {
objectName: "questionDrawerItem"
anchors.fill: parent anchors.fill: parent
QuestionDrawer { QuestionDrawer {
@ -205,6 +219,8 @@ Window {
} }
Item { Item {
objectName: "busyIndicatorItem"
anchors.fill: parent anchors.fill: parent
BusyIndicatorType { BusyIndicatorType {
@ -221,26 +237,26 @@ Window {
questionDrawer.noButtonText = noButtonText questionDrawer.noButtonText = noButtonText
questionDrawer.yesButtonFunction = function() { questionDrawer.yesButtonFunction = function() {
questionDrawer.close() questionDrawer.closeTriggered()
if (yesButtonFunction && typeof yesButtonFunction === "function") { if (yesButtonFunction && typeof yesButtonFunction === "function") {
yesButtonFunction() yesButtonFunction()
} }
} }
questionDrawer.noButtonFunction = function() { questionDrawer.noButtonFunction = function() {
questionDrawer.close() questionDrawer.closeTriggered()
if (noButtonFunction && typeof noButtonFunction === "function") { if (noButtonFunction && typeof noButtonFunction === "function") {
noButtonFunction() noButtonFunction()
} }
} }
questionDrawer.open() questionDrawer.openTriggered()
} }
FileDialog { FileDialog {
id: mainFileDialog id: mainFileDialog
objectName: "mainFileDialog"
property bool isSaveMode: false property bool isSaveMode: false
objectName: "mainFileDialog"
fileMode: isSaveMode ? FileDialog.SaveFile : FileDialog.OpenFile fileMode: isSaveMode ? FileDialog.SaveFile : FileDialog.OpenFile
onAccepted: SystemController.fileDialogClosed(true) onAccepted: SystemController.fileDialogClosed(true)