Warning, /network/kdenetwork-filesharing/samba/filepropertiesplugin/qml/ACLPage.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0003 SPDX-FileCopyrightText: 2020 Harald Sitter <sitter@kde.org> 0004 SPDX-FileCopyrightText: 2021 Slava Aseev <nullptrnine@basealt.ru> 0005 SPDX-FileCopyrightText: 2023 ivan tkachenko <me@ratijas.tk> 0006 */ 0007 0008 import QtQuick 2.12 0009 import QtQuick.Controls 2.5 as QQC2 0010 import QtQuick.Layouts 1.14 0011 import org.kde.kirigami 2.4 as Kirigami 0012 import org.kde.filesharing.samba 1.0 as Samba 0013 0014 // NOTE: sambaPlugin.shareContext is a singleton its properties cannot be bound and need manual syncing back. 0015 0016 Item { 0017 // NOTE: we cannot use a Kirigami.Page for this because it adds excessive padding that we can't disable 0018 // so it'd very awkwardly space within the properties dialog reducing the available space a lot and looking 0019 // silly. Alas, Column is also not grand because it gets collapsed by the sheet, so we use a fixed size 0020 // Item in place of a Page that gets covered by the Sheet and then that Item is filled by a Column. 0021 id: page 0022 0023 Kirigami.OverlaySheet { 0024 id: denialSheet 0025 property bool shownOnce: false // maybeShow() this sheet only once per run not annoy users too much 0026 parent: page // there's a bug where the sheet doesn't manage to find its parent, explicitly set it 0027 0028 header: Kirigami.Heading { 0029 text: i18nc("@title", "Denying Access") 0030 } 0031 0032 function maybeOpen() { 0033 if (shownOnce) { 0034 return 0035 } 0036 shownOnce = true 0037 open() 0038 } 0039 0040 QQC2.Label { 0041 Layout.fillWidth: true 0042 textFormat: Text.RichText // for xi18n markup; this also means newlines are ignored! 0043 text: xi18nc("@info", ` 0044 Denying access prevents using this share even when another access rule might grant access. A denial rule always 0045 takes precedence. In particular denying access to <resource>Everyone</resource> actually disables access for everyone. 0046 It is generally not necessary to deny anyone because the regular directory and file permissions still apply to shared 0047 directories. A user who does not have access to the directory locally will still not be able to access it remotely even 0048 when the Share access rules would allow it.`) 0049 wrapMode: Text.Wrap 0050 } 0051 } 0052 0053 ColumnLayout { 0054 anchors.fill: parent 0055 0056 Kirigami.InlineMessage { 0057 id: changePermissionsWarning 0058 Layout.fillWidth: true 0059 showCloseButton: true 0060 visible: sambaPlugin.permissionsHelper.permissionsChangeRequired 0061 type: Kirigami.MessageType.Warning 0062 text: i18nc("@label", "This folder needs extra permissions for sharing to work") 0063 0064 actions: [ 0065 Kirigami.Action { 0066 text: i18nc("@action:button opens the change permissions page", "Fix Permissions") 0067 onTriggered: stack.push("ChangePermissionsPage.qml") 0068 } 0069 ] 0070 } 0071 0072 Kirigami.InlineMessage { 0073 id: posixACLWarning 0074 Layout.fillWidth: true 0075 showCloseButton: true 0076 visible: sambaPlugin.permissionsHelper.hasPosixACL 0077 type: Kirigami.MessageType.Warning 0078 text: xi18nc("@label", "The share might not work properly because share folder or its paths has Advanced Permissions: %1", 0079 sambaPlugin.permissionsHelper.pathsWithPosixACL.join(", ")) 0080 } 0081 0082 QQC2.CheckBox { 0083 id: shareEnabled 0084 Layout.fillWidth: true 0085 text: i18nc("@option:check", "Share this folder with other computers on the local network") 0086 checked: sambaPlugin.shareContext.enabled 0087 onToggled: { 0088 sambaPlugin.shareContext.enabled = checked 0089 sambaPlugin.dirty = true 0090 } 0091 } 0092 0093 ColumnLayout { 0094 Layout.fillWidth: true 0095 Layout.fillHeight: true 0096 enabled: shareEnabled.checked 0097 0098 RowLayout { 0099 Layout.fillWidth: true 0100 QQC2.Label { 0101 Layout.maximumWidth: Math.round(page.width / 2.0) // Don't let the label use more than half the space, elide the rest. 0102 text: i18nc("@label", "Name:") 0103 elide: Text.ElideRight 0104 } 0105 QQC2.TextField { 0106 id: nameField 0107 Layout.fillWidth: true 0108 text: sambaPlugin.shareContext.name 0109 onTextEdited: { 0110 if (text.length > sambaPlugin.shareContext.maximumNameLength) { 0111 tooLongMessage.visible = true; 0112 // This is a soft limit, do not return. 0113 } else { 0114 tooLongMessage.visible = false 0115 } 0116 0117 if (!sambaPlugin.shareContext.isNameFree(text)) { 0118 alreadyUsedError.visible = true; 0119 return 0120 } 0121 alreadyUsedError.visible = false; 0122 0123 sambaPlugin.shareContext.name = text 0124 sambaPlugin.dirty = true 0125 } 0126 } 0127 } 0128 0129 Kirigami.InlineMessage { 0130 id: alreadyUsedError 0131 Layout.fillWidth: true 0132 type: Kirigami.MessageType.Error 0133 text: i18nc("@label", 0134 "This name cannot be used. Share names must not be user names and there must not be two shares with the same name on the entire system.") 0135 visible: false 0136 } 0137 0138 Kirigami.InlineMessage { 0139 id: tooLongMessage 0140 Layout.fillWidth: true 0141 type: Kirigami.MessageType.Warning 0142 text: i18nc("@label", 0143 "This name may be too long. It can cause interoperability problems or get rejected by Samba.") 0144 visible: false 0145 } 0146 0147 QQC2.CheckBox { 0148 id: allowGuestBox 0149 Layout.fillWidth: true 0150 text: i18nc("@option:check", "Allow guests") 0151 enabled: sambaPlugin.shareContext.canEnableGuest 0152 checked: sambaPlugin.shareContext.guestEnabled 0153 onToggled: { 0154 sambaPlugin.shareContext.guestEnabled = checked 0155 sambaPlugin.dirty = true 0156 } 0157 } 0158 0159 QQC2.Label { 0160 Layout.fillWidth: true 0161 enabled: false // looks more visually connected if both are disabled 0162 visible: !allowGuestBox.enabled 0163 text: i18nc("@label", "Guest access is disabled by the system's Samba configuration.") 0164 wrapMode: Text.Wrap 0165 font: Kirigami.Theme.smallFont 0166 } 0167 0168 // TODO: this could benefit form some splitting. This is half the file. 0169 QQC2.ScrollView { 0170 id: scroll 0171 0172 Layout.fillHeight: true 0173 Layout.fillWidth: true 0174 0175 activeFocusOnTab: false 0176 Kirigami.Theme.colorSet: Kirigami.Theme.View 0177 Kirigami.Theme.inherit: false 0178 0179 Component.onCompleted: { 0180 if (background) { 0181 background.visible = true 0182 } 0183 } 0184 0185 TableView { 0186 id: view 0187 0188 property bool itemComplete: false 0189 0190 model: sambaPlugin.userPermissionModel 0191 0192 topMargin: Kirigami.Units.smallSpacing 0193 // This wouldn't work with horizontal scrollbar, but here 0194 // it doesn't matter, because it is never visible. 0195 bottomMargin: Kirigami.Units.smallSpacing 0196 0197 rowSpacing: Kirigami.Units.smallSpacing 0198 columnSpacing: Kirigami.Units.smallSpacing 0199 0200 columnWidthProvider: column => { 0201 // Give 2/3 of the width to the access column for better looks. 0202 const availableWidth = width - columnSpacing 0203 var accessWidth = Math.round(availableWidth / 1.5) 0204 if (column === Samba.UserPermissionModel.ColumnAccess) { 0205 return accessWidth 0206 } 0207 return availableWidth - accessWidth 0208 } 0209 0210 Timer { 0211 // Helper timer to delay force layouting through the event loop. 0212 // We want width changes to recalculate the column widths so we need to force a layout run, 0213 // when doing that directly in onWidthChanged that has a chance to produce errors so instead 0214 // we'll queue a timeout for the next event loop to force the layout run. 0215 // TableView::forceLayout(): Cannot do an immediate re-layout during an ongoing layout! 0216 id: forceLayoutTimer 0217 interval: 0 0218 running: false 0219 repeat: false 0220 onTriggered: { 0221 // forceLayout docs say it must only be called after component completion, so make sure of that. 0222 if (view.itemComplete) { 0223 view.forceLayout() 0224 } 0225 } 0226 } 0227 0228 onWidthChanged: forceLayoutTimer.start() // make sure columns get recalculated 0229 0230 delegate: RowLayout { 0231 // This is only a layout to conveniently forward the child size regardless of which child is in 0232 // use. 0233 Layout.fillWidth: true 0234 TableView.onReused: combo.loadCurrentIndex() 0235 0236 QQC2.Label { 0237 Layout.fillWidth: true 0238 Layout.leftMargin: view.columnSpacing 0239 visible: column !== Samba.UserPermissionModel.ColumnAccess 0240 text: display === undefined ? "" : display 0241 elide: Text.ElideMiddle 0242 } 0243 0244 QQC2.ComboBox { 0245 id: combo 0246 Layout.fillWidth: true 0247 Layout.rightMargin: view.columnSpacing 0248 textRole: "text" 0249 valueRole: "value" 0250 visible: column === Samba.UserPermissionModel.ColumnAccess 0251 model: [ 0252 { value: undefined, text: "---" }, 0253 { value: "F", text: i18nc("@option:radio user can read&write", "Full Control") }, 0254 { value: "R", text: i18nc("@option:radio user can read", "Read Only") }, 0255 { value: "D", text: i18nc("@option:radio user not allowed to access share", "No Access") } 0256 ] 0257 onActivated: { 0258 edit = currentValue // setData on model with edit role 0259 if (currentValue === 'D') { 0260 denialSheet.maybeOpen() 0261 } 0262 sambaPlugin.dirty = true 0263 sambaPlugin.permissionsHelper.reload() 0264 } 0265 0266 function loadCurrentIndex() { 0267 currentIndex = indexOfValue(edit) 0268 } 0269 0270 Component.onCompleted: loadCurrentIndex() 0271 } 0272 } 0273 0274 Component.onCompleted: itemComplete = true 0275 } 0276 } 0277 } 0278 0279 QQC2.Button { 0280 Layout.fillWidth: true 0281 text: i18nc("@button", "Show Samba status monitor") 0282 onClicked: sambaPlugin.showSambaStatus() 0283 } 0284 } 0285 }