Page MenuHomePhorge

No OneTemporary

Size
16 KB
Referenced Files
None
Subscribers
None
diff --git a/src/contents/ui/ActionSettingsPage.qml b/src/contents/ui/ActionSettingsPage.qml
index a3ee8b6..01c9a21 100644
--- a/src/contents/ui/ActionSettingsPage.qml
+++ b/src/contents/ui/ActionSettingsPage.qml
@@ -1,21 +1,21 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2022 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import org.kde.kirigami 2.13 as Kirigami
import '.' as Kazv
import 'shortcuts' as KazvShortcuts
Kazv.ClosableScrollablePage {
id: page
- property alias actions: settings.actions
+ property alias actionsToConfigure: settings.actions
title: l10n.get('action-settings-page-title')
KazvShortcuts.ActionSettings {
id: settings
shortcutsConfig: kazvConfig
}
}
diff --git a/src/contents/ui/main.qml b/src/contents/ui/main.qml
index 65ea8ab..20b658d 100644
--- a/src/contents/ui/main.qml
+++ b/src/contents/ui/main.qml
@@ -1,274 +1,274 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.1
import org.kde.kirigami 2.4 as Kirigami
import QtQuick.Controls 2.0 as Controls
import moe.kazv.mxc.kazv 0.0 as MK
import '.' as Kazv
import 'shortcuts' as KazvShortcuts
import 'l10n.js' as L10n
Kirigami.ApplicationWindow {
id: root
property var kazvIOManager: MK.KazvIOManager {
cacheDirectory: kazvConfig.cacheDirectory
}
property var matrixSdk: MK.MatrixSdk {
onLoginSuccessful: {
switchToMainPage();
recordLastSession();
}
onLoginFailed: {
console.log("Login Failed");
showPassiveNotification(l10n.get('login-page-request-failed-prompt', { errorCode, errorMsg }));
}
onDiscoverFailed: {
console.log("Discover Failed");
showPassiveNotification(l10n.get('login-page-discover-failed-prompt', { errorCode, errorMsg }));
}
onSessionChanged: {
console.log('session changed');
reloadSdkVariables();
}
}
property var loggedIn: !!matrixSdk.token
property var sdkVars: QtObject {
property var roomList: matrixSdk.roomList()
property var userGivenNicknameMap: matrixSdk.userGivenNicknameMap()
property string currentRoomId: ''
}
property var l10nProvider: MK.L10nProvider {
}
property var kazvConfig: MK.KazvConfig {
}
function initializeL10n () {
const availableLocales = l10nProvider.availableLocaleCodes();
console.log('available locales:', availableLocales);
const desiredLanguages = [Qt.uiLanguage];
console.log('ui language is: ', desiredLanguages);
const defaultLocale = 'en';
const wantedLocales = L10n.negotiateLanguages(desiredLanguages, availableLocales, defaultLocale);
console.log('wanted locales:', wantedLocales);
const bundles = L10n.generateBundles(wantedLocales, l10nProvider.getFtlData(wantedLocales));
const provider = new L10n.FluentProvider(bundles);
return provider;
}
property var l10n: initializeL10n();
title: l10n.get('app-title')
globalDrawer: Kirigami.GlobalDrawer {
title: l10n.get('global-drawer-title')
titleIcon: "applications-graphics"
property var actionGroupName: 'global-drawer-actions'
actions: [
Kirigami.Action {
objectName: 'switch-account'
text: l10n.get('global-drawer-action-switch-account')
icon.name: 'system-switch-user'
onTriggered: switchAccount()
},
Kirigami.Action {
objectName: 'hard-logout'
text: l10n.get('global-drawer-action-hard-logout')
onTriggered: hardLogout()
},
Kirigami.Action {
objectName: 'save'
text: l10n.get('global-drawer-action-save-session')
onTriggered: {
recordLastSession()
matrixSdk.serializeToFile()
}
},
Kirigami.Action {
objectName: 'configure-shortcuts'
text: l10n.get('global-drawer-action-configure-shortcuts')
onTriggered: {
pushActionSettingsPage();
}
},
Kirigami.Action {
objectName: 'settings'
text: l10n.get('global-drawer-action-settings')
onTriggered: {
pushSettingsPage();
}
},
Kirigami.Action {
objectName: 'create-room'
enabled: root.loggedIn
icon.name: 'contact-new'
text: l10n.get('global-drawer-action-create-room')
onTriggered: {
pushCreateRoomPage();
}
},
Kirigami.Action {
objectName: 'join-room'
enabled: root.loggedIn
text: l10n.get('global-drawer-action-join-room')
onTriggered: {
pushJoinRoomPage();
}
}
]
}
contextDrawer: Kirigami.ContextDrawer {
id: contextDrawer
}
property var actionCollection: KazvShortcuts.ActionCollection {
id: globalActionCollection
children: [
root.globalDrawer,
root.contextDrawer,
]
shortcutsConfig: kazvConfig
}
property var notifier: Kazv.Notifier {
}
pageStack.initialPage: Qt.resolvedUrl("LoginPage.qml")
property var mainPage: Kazv.MainPage {
id: mainPage
}
property var emptyPage: Kirigami.Page {
title: l10n.get('empty-room-page-title')
Controls.Label {
text: l10n.get('empty-room-page-description')
}
}
signal switchToRoomRequested(string roomId)
property var pageManager: Kazv.PageManager {
pageStack: root.pageStack
sdkVars: root.sdkVars
main: root
}
function activateRoomSettingsPage(room) {
pageStack.push(Qt.resolvedUrl("room-settings/RoomSettingsPage.qml"), {
room
});
}
function activateRoomInvitePage(room) {
pageStack.push(Qt.resolvedUrl("room-settings/RoomInvitePage.qml"), {
room
});
}
function activateUserPage(user, room) {
pageStack.push(Qt.resolvedUrl("qrc:///UserPage.qml"), {
userId: user.userId,
user,
room
});
}
function switchToMainPage() {
pageStack.replace([mainPage])
pageStack.currentIndex = 0
}
function switchToLoginPage() {
pageStack.replace([Qt.resolvedUrl("LoginPage.qml")])
pageStack.currentIndex = 0
}
function pushLoginPage() {
pageStack.push(Qt.resolvedUrl("LoginPage.qml"), {
isSwitchingAccount: true,
});
}
function pushActionSettingsPage() {
pageStack.push(Qt.resolvedUrl("ActionSettingsPage.qml"), {
- actions: globalActionCollection.allActions(),
+ actionsToConfigure: globalActionCollection.allActions(),
});
}
function pushSettingsPage() {
pageStack.push(Qt.resolvedUrl("SettingsPage.qml"));
}
function pushCreateRoomPage() {
pageStack.push(Qt.resolvedUrl("CreateRoomPage.qml"), {});
}
function pushJoinRoomPage() {
pageStack.push(Qt.resolvedUrl("JoinRoomPage.qml"), {});
}
function sessionNameFor(userId, deviceId) {
return userId + '/' + deviceId;
}
function loadSession(sessionName) {
const succ = matrixSdk.loadSession(sessionName);
if (succ) {
console.log('load session successful');
switchToMainPage();
recordLastSession();
} else {
console.log('load session failed');
}
return succ;
}
function loadLastSession() {
console.log('last session is:', kazvConfig.lastSession);
return loadSession(kazvConfig.lastSession);
}
function recordLastSession() {
kazvConfig.lastSession = sessionNameFor(matrixSdk.userId, matrixSdk.deviceId);
}
function reloadSdkVariables() {
sdkVars.roomList = matrixSdk.roomList();
sdkVars.userGivenNicknameMap = matrixSdk.userGivenNicknameMap();
sdkVars.currentRoomId = '';
}
function switchAccount() {
pushLoginPage();
}
function hardLogout() {
}
Component.onCompleted: {
actionCollection.setupShortcuts();
loadLastSession();
}
onClosing: {
kazvIOManager.clearJobs()
}
}
diff --git a/src/contents/ui/shortcuts/ActionItem.qml b/src/contents/ui/shortcuts/ActionItem.qml
index b4b1316..8687e17 100644
--- a/src/contents/ui/shortcuts/ActionItem.qml
+++ b/src/contents/ui/shortcuts/ActionItem.qml
@@ -1,104 +1,136 @@
/*
* This file is part of kazv.
- * SPDX-FileCopyrightText: 2020-2022 Tusooa Zhu <tusooa@kazv.moe>
+ * SPDX-FileCopyrightText: 2020-2024 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import org.kde.kirigami 2.13 as Kirigami
import '.' as KazvShortcuts
-Kirigami.BasicListItem {
+Control {
id: actionItem
property var action
- icon: action.icon.name || action.icon.source
- label: action.text
- subtitle: l10n.get(
- 'action-settings-shortcut-prompt', {
- shortcut: action.shortcut || l10n.get('action-settings-shortcut-none')
- }
- )
+
+ implicitHeight: layout.implicitHeight
+ implicitWidth: layout.implicitWidth
+
+ background: Rectangle {
+ color: actionItem.hovered ? Kirigami.Theme.hoverColor : Kirigami.Theme.backgroundColor
+ }
property var sheet: Kirigami.OverlaySheet {
id: popup
property var shortcut: ''
property var conflictsName: []
property var conflictingActions: []
title: l10n.get('action-settings-shortcut-conflict-modal-title')
ColumnLayout {
Label {
text: l10n.get('action-settings-shortcut-conflict', {
shortcut: popup.shortcut,
conflictingAction: popup.conflictsName.join('<br>'),
})
Layout.fillWidth: true
}
RowLayout {
Button {
text: l10n.get('action-settings-shortcut-conflict-continue')
onClicked: {
actionItem.setShortcut(popup.shortcut);
actionSettings.purgeShortcutForActions(popup.conflictingActions);
popup.close();
}
}
Button {
text: l10n.get('action-settings-shortcut-conflict-cancel')
onClicked: {
popup.close();
}
}
}
}
}
RowLayout {
- Button {
- id: editButton
- text: checked ? shortcutInput.partialResult : l10n.get('action-settings-shortcut-edit-action')
- checkable: true
- onClicked: {
- if (checked) {
- shortcutInput.startRecording();
- } else {
- shortcutInput.cancel();
- }
+ id: layout
+ anchors.fill: parent
+ Kirigami.Icon {
+ source: action.icon.name || action.icon.source
+ }
+
+ ColumnLayout {
+ Layout.alignment: Qt.AlignLeft
+ Layout.fillWidth: true
+ Label {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignLeft
+ text: action.text
+ }
+
+ Label {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignLeft
+ text: l10n.get(
+ 'action-settings-shortcut-prompt', {
+ shortcut: action.shortcut || l10n.get('action-settings-shortcut-none')
+ }
+ )
}
}
- Button {
- text: l10n.get('action-settings-shortcut-remove-action')
- onClicked: {
- setShortcut("");
+ RowLayout {
+ Layout.alignment: Qt.AlignRight
+ Layout.fillWidth: false
+ Button {
+ id: editButton
+ objectName: 'editButton'
+ text: checked ? shortcutInput.partialResult : l10n.get('action-settings-shortcut-edit-action')
+ checkable: true
+ onClicked: {
+ if (checked) {
+ shortcutInput.startRecording();
+ } else {
+ shortcutInput.cancel();
+ }
+ }
+ }
+
+ Button {
+ objectName: 'removeShortcutButton'
+ text: l10n.get('action-settings-shortcut-remove-action')
+ onClicked: {
+ setShortcut("");
+ }
}
}
- }
- KazvShortcuts.ShortcutInput {
- id: shortcutInput
-
- onFinalResult: {
- editButton.checked = false;
- const conflicts = actionSettings
- .findConflicts(sequence)
- .filter(a => a.objectName !== action.objectName);
- if (!conflicts.length) {
- setShortcut(sequence);
- } else {
- popup.shortcut = sequence;
- popup.conflictingActions = conflicts;
- popup.conflictsName = conflicts.map(a => a.text);
- popup.open();
+ KazvShortcuts.ShortcutInput {
+ id: shortcutInput
+
+ onFinalResult: {
+ editButton.checked = false;
+ const conflicts = actionSettings
+ .findConflicts(sequence)
+ .filter(a => a.objectName !== action.objectName);
+ if (!conflicts.length) {
+ setShortcut(sequence);
+ } else {
+ popup.shortcut = sequence;
+ popup.conflictingActions = conflicts;
+ popup.conflictsName = conflicts.map(a => a.text);
+ popup.open();
+ }
}
}
}
function setShortcut(shortcut) {
actionSettings.setShortcutFor(action, shortcut);
}
}
diff --git a/src/contents/ui/shortcuts/ActionSettings.qml b/src/contents/ui/shortcuts/ActionSettings.qml
index 560337e..8190101 100644
--- a/src/contents/ui/shortcuts/ActionSettings.qml
+++ b/src/contents/ui/shortcuts/ActionSettings.qml
@@ -1,62 +1,63 @@
/*
* This file is part of kazv.
* SPDX-FileCopyrightText: 2020-2022 Tusooa Zhu <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.15
import '.' as KazvShortcuts
ListView {
id: actionSettings
property var actions
/// shortcutsConfig: {
/// QStringList shortcutForAction(QString actionName)
/// void setShortcutForAction(QString actionName, QStringList shortcut)
/// }
property var shortcutsConfig
model: actions.length
delegate: KazvShortcuts.ActionItem {
+ width: actionSettings.width
action: actions[index]
}
function shortcutToSequence(str) {
return str.split(',');
}
function findConflicts(shortcut) {
const sequence = shortcutToSequence(shortcut);
return actions.filter(a => {
const thoseShortcuts = shortcutsConfig.shortcutForAction(a.objectName);
for (let i = 0; i < thoseShortcuts.length; ++i) {
const thatShortcut = thoseShortcuts[i];
if (hasConflicts(sequence, shortcutToSequence(thatShortcut))) {
return true;
}
}
return false;
});
}
function hasConflicts(first, second) {
const smallerLen = Math.min(first.length, second.length);
for (let i = 0; i < smallerLen; ++i) {
if (first[i] !== second[i]) {
return false;
}
}
return true;
}
function setShortcutFor(action, shortcut) {
action.shortcut = shortcut;
shortcutsConfig.setShortcutForAction(action.objectName, [action.shortcut]);
}
function purgeShortcutForActions(actions, shortcut) {
actions.forEach(a => setShortcutFor(a, ""));
}
}
diff --git a/src/tests/quick-tests/tst_kazvshortcutsActionItem.qml b/src/tests/quick-tests/tst_kazvshortcutsActionItem.qml
new file mode 100644
index 0000000..e3d8345
--- /dev/null
+++ b/src/tests/quick-tests/tst_kazvshortcutsActionItem.qml
@@ -0,0 +1,67 @@
+/*
+ * This file is part of kazv.
+ * SPDX-FileCopyrightText: 2020-2024 tusooa <tusooa@kazv.moe>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+import QtQuick 2.15
+import QtTest 1.0
+import org.kde.kirigami 2.13 as Kirigami
+import moe.kazv.mxc.kazv 0.0 as MK
+import '../../contents/ui/shortcuts' as KazvShortcuts
+import 'test-helpers' as TestHelpers
+import 'test-helpers.js' as JsHelpers
+
+Item {
+ id: item
+ width: 800
+ height: 600
+
+ property var l10n: JsHelpers.fluentMock
+
+ property var mockHelper: TestHelpers.MockHelper {}
+ property var actionSettings: QtObject {
+ property var purgeShortcutForActions: mockHelper.noop()
+ property var findConflicts: mockHelper.func((seq) => {
+ if (seq === 'Ctrl+X') {
+ return [{ name: 'action1' }];
+ }
+ return [];
+ })
+ property var setShortcutFor: mockHelper.noop()
+ }
+
+ KazvShortcuts.ActionItem {
+ id: actionItem
+ action: Kirigami.Action {
+ text: 'some action'
+ }
+ }
+
+ TestCase {
+ id: kazvshortcutsActionItemTest
+ name: 'KazvshortcutsActionItemTest'
+ when: windowShown
+
+ function init() {
+ actionItem.action.shortcut = '';
+ mockHelper.clearAll();
+ }
+
+ function test_setShortcut() {
+ const editButton = findChild(actionItem, 'editButton');
+ mouseClick(editButton);
+ keySequence('Ctrl+A,Ctrl+K');
+ tryVerify(() => actionSettings.setShortcutFor.calledTimes(), 2000);
+ compare(actionSettings.setShortcutFor.lastArgs()[1], 'Ctrl+A,Ctrl+K');
+ }
+
+ function test_eraseShortcut() {
+ actionItem.action.shortcut = 'Ctrl+A,Ctrl+K';
+ const button = findChild(actionItem, 'removeShortcutButton');
+ mouseClick(button);
+ tryVerify(() => actionSettings.setShortcutFor.calledTimes());
+ compare(actionSettings.setShortcutFor.lastArgs()[1], '');
+ }
+ }
+}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Oct 13, 9:46 PM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1786914
Default Alt Text
(16 KB)

Event Timeline