diff --git a/src/main/kotlin/app/termora/transfer/PosixFilePermissionPanel.kt b/src/main/kotlin/app/termora/transfer/PosixFilePermissionPanel.kt index a21ae2e..c58a329 100644 --- a/src/main/kotlin/app/termora/transfer/PosixFilePermissionPanel.kt +++ b/src/main/kotlin/app/termora/transfer/PosixFilePermissionPanel.kt @@ -1,13 +1,17 @@ package app.termora.transfer +import app.termora.DocumentAdaptor import app.termora.I18n import app.termora.OptionsPane.Companion.FORM_MARGIN +import app.termora.OutlineTextField import com.jgoodies.forms.builder.FormBuilder import com.jgoodies.forms.layout.FormLayout import java.awt.BorderLayout import java.awt.Dimension import java.nio.file.attribute.PosixFilePermission +import java.util.* import javax.swing.* +import javax.swing.event.DocumentEvent import kotlin.math.max class PosixFilePermissionPanel(private val permissions: Set) : JPanel(BorderLayout()) { @@ -23,22 +27,16 @@ class PosixFilePermissionPanel(private val permissions: Set private val otherWrite = JCheckBox(I18n.getString("termora.transport.permissions.write")) private val otherExecute = JCheckBox(I18n.getString("termora.transport.permissions.execute")) private val includeSubFolder = JCheckBox(I18n.getString("termora.transport.permissions.include-subfolder")) + private val octalTextField = OutlineTextField() init { initView() + initEvents() } private fun initView() { - ownerRead.isSelected = permissions.contains(PosixFilePermission.OWNER_READ) - ownerWrite.isSelected = permissions.contains(PosixFilePermission.OWNER_WRITE) - ownerExecute.isSelected = permissions.contains(PosixFilePermission.OWNER_EXECUTE) - groupRead.isSelected = permissions.contains(PosixFilePermission.GROUP_READ) - groupWrite.isSelected = permissions.contains(PosixFilePermission.GROUP_WRITE) - groupExecute.isSelected = permissions.contains(PosixFilePermission.GROUP_EXECUTE) - otherRead.isSelected = permissions.contains(PosixFilePermission.OTHERS_READ) - otherWrite.isSelected = permissions.contains(PosixFilePermission.OTHERS_WRITE) - otherExecute.isSelected = permissions.contains(PosixFilePermission.OTHERS_EXECUTE) + initCheckBox(permissions) ownerRead.isFocusable = false ownerWrite.isFocusable = false @@ -51,6 +49,8 @@ class PosixFilePermissionPanel(private val permissions: Set otherExecute.isFocusable = false includeSubFolder.isFocusable = false + updateOctalMode() + add(createCenterPanel(), BorderLayout.CENTER) preferredSize = Dimension( @@ -60,11 +60,51 @@ class PosixFilePermissionPanel(private val permissions: Set } + private fun initCheckBox(permissions: Set) { + ownerRead.isSelected = permissions.contains(PosixFilePermission.OWNER_READ) + ownerWrite.isSelected = permissions.contains(PosixFilePermission.OWNER_WRITE) + ownerExecute.isSelected = permissions.contains(PosixFilePermission.OWNER_EXECUTE) + groupRead.isSelected = permissions.contains(PosixFilePermission.GROUP_READ) + groupWrite.isSelected = permissions.contains(PosixFilePermission.GROUP_WRITE) + groupExecute.isSelected = permissions.contains(PosixFilePermission.GROUP_EXECUTE) + otherRead.isSelected = permissions.contains(PosixFilePermission.OTHERS_READ) + otherWrite.isSelected = permissions.contains(PosixFilePermission.OTHERS_WRITE) + otherExecute.isSelected = permissions.contains(PosixFilePermission.OTHERS_EXECUTE) + + } + + private fun initEvents() { + ownerRead.addActionListener { updateOctalMode() } + ownerWrite.addActionListener { updateOctalMode() } + ownerExecute.addActionListener { updateOctalMode() } + groupRead.addActionListener { updateOctalMode() } + groupWrite.addActionListener { updateOctalMode() } + groupExecute.addActionListener { updateOctalMode() } + otherRead.addActionListener { updateOctalMode() } + otherWrite.addActionListener { updateOctalMode() } + otherExecute.addActionListener { updateOctalMode() } + + octalTextField.document.addDocumentListener(object : DocumentAdaptor() { + override fun changedUpdate(e: DocumentEvent) { + octalTextField.document.removeDocumentListener(this) + val text = octalTextField.text.trim() + val mode = text.toIntOrNull(radix = 8) ?: toOctalMode(getPermissions()) + initCheckBox(fromOctalMode(mode)) + octalTextField.document.addDocumentListener(this) + } + }) + + } + + private fun updateOctalMode() { + octalTextField.text = toOctalMode(getPermissions()).toString(8) + } + private fun createCenterPanel(): JComponent { val formMargin = FORM_MARGIN val layout = FormLayout( "default:grow, $formMargin, default:grow, $formMargin, default:grow", - "pref, $formMargin, pref, $formMargin, pref" + "pref, $formMargin, pref, $formMargin, pref, $formMargin, pref" ) val builder = FormBuilder.create().layout(layout).debug(false) @@ -92,7 +132,12 @@ class PosixFilePermissionPanel(private val permissions: Set otherBox.border = BorderFactory.createTitledBorder(I18n.getString("termora.transport.permissions.others")) builder.add(otherBox).xy(5, 3) - builder.add(includeSubFolder).xyw(1, 5, 5) + val box = Box.createHorizontalBox() + box.add(JLabel(I18n.getString("termora.transport.permissions.octal-mode") + ": ")) + box.add(octalTextField) + builder.add(box).xyw(1, 5, 5) + + builder.add(includeSubFolder).xyw(1, 7, 5) return builder.build() } @@ -102,6 +147,36 @@ class PosixFilePermissionPanel(private val permissions: Set return includeSubFolder.isSelected } + fun toOctalMode(p: Set): Int { + var mode = 0 + if (p.contains(PosixFilePermission.OWNER_READ)) mode = mode or 256 + if (p.contains(PosixFilePermission.OWNER_WRITE)) mode = mode or 128 + if (p.contains(PosixFilePermission.OWNER_EXECUTE)) mode = mode or 64 + if (p.contains(PosixFilePermission.GROUP_READ)) mode = mode or 32 + if (p.contains(PosixFilePermission.GROUP_WRITE)) mode = mode or 16 + if (p.contains(PosixFilePermission.GROUP_EXECUTE)) mode = mode or 8 + if (p.contains(PosixFilePermission.OTHERS_READ)) mode = mode or 4 + if (p.contains(PosixFilePermission.OTHERS_WRITE)) mode = mode or 2 + if (p.contains(PosixFilePermission.OTHERS_EXECUTE)) mode = mode or 1 + return mode + } + + fun fromOctalMode(mode: Int): Set { + val m = mode and 511 // 0777 == 511 + val set = EnumSet.noneOf(PosixFilePermission::class.java) + if ((m and 256) != 0) set.add(PosixFilePermission.OWNER_READ) + if ((m and 128) != 0) set.add(PosixFilePermission.OWNER_WRITE) + if ((m and 64) != 0) set.add(PosixFilePermission.OWNER_EXECUTE) + if ((m and 32) != 0) set.add(PosixFilePermission.GROUP_READ) + if ((m and 16) != 0) set.add(PosixFilePermission.GROUP_WRITE) + if ((m and 8) != 0) set.add(PosixFilePermission.GROUP_EXECUTE) + if ((m and 4) != 0) set.add(PosixFilePermission.OTHERS_READ) + if ((m and 2) != 0) set.add(PosixFilePermission.OTHERS_WRITE) + if ((m and 1) != 0) set.add(PosixFilePermission.OTHERS_EXECUTE) + return set + } + + fun getPermissions(): Set { val permissions = mutableSetOf() diff --git a/src/main/resources/i18n/messages.properties b/src/main/resources/i18n/messages.properties index 25697ab..ec45843 100644 --- a/src/main/resources/i18n/messages.properties +++ b/src/main/resources/i18n/messages.properties @@ -352,6 +352,7 @@ termora.transport.table.contextmenu.new.file=New File # Permission termora.transport.permissions=Change Permissions termora.transport.permissions.file-folder-permissions=File/Folder Permissions +termora.transport.permissions.octal-mode=Octal mode termora.transport.permissions.read=Read termora.transport.permissions.write=Write termora.transport.permissions.execute=Execute diff --git a/src/main/resources/i18n/messages_pt_BR.properties b/src/main/resources/i18n/messages_pt_BR.properties index 7c6417a..a7d7696 100644 --- a/src/main/resources/i18n/messages_pt_BR.properties +++ b/src/main/resources/i18n/messages_pt_BR.properties @@ -352,6 +352,7 @@ termora.transport.table.contextmenu.new.file=Novo Arquivo # Permission termora.transport.permissions=Alterar Permissões termora.transport.permissions.file-folder-permissions=Permissões de Arquivo/Pasta +termora.transport.permissions.octal-mode=Modo octal termora.transport.permissions.read=Leitura termora.transport.permissions.write=Escrita termora.transport.permissions.execute=Execução diff --git a/src/main/resources/i18n/messages_ru_RU.properties b/src/main/resources/i18n/messages_ru_RU.properties index 5cae657..02d4807 100644 --- a/src/main/resources/i18n/messages_ru_RU.properties +++ b/src/main/resources/i18n/messages_ru_RU.properties @@ -304,6 +304,7 @@ termora.transport.table.contextmenu.new.file=Новый Файл # Permission termora.transport.permissions=Изменить Разрешения termora.transport.permissions.file-folder-permissions=Файл/Папка Разрешения +termora.transport.permissions.octal-mode=Восьмеричный режим termora.transport.permissions.read=Чтение termora.transport.permissions.write=Запись termora.transport.permissions.execute=Выполнение diff --git a/src/main/resources/i18n/messages_zh_CN.properties b/src/main/resources/i18n/messages_zh_CN.properties index 7f3f37b..100a8d0 100644 --- a/src/main/resources/i18n/messages_zh_CN.properties +++ b/src/main/resources/i18n/messages_zh_CN.properties @@ -375,6 +375,7 @@ termora.transport.sftp.already-exists.actions=操作 # Permission termora.transport.permissions=更改权限 termora.transport.permissions.file-folder-permissions=文件/文件夹权限 +termora.transport.permissions.octal-mode=八进制模式 termora.transport.permissions.read=读取 termora.transport.permissions.write=写入 termora.transport.permissions.execute=执行 diff --git a/src/main/resources/i18n/messages_zh_TW.properties b/src/main/resources/i18n/messages_zh_TW.properties index 75cebf9..1a3eb59 100644 --- a/src/main/resources/i18n/messages_zh_TW.properties +++ b/src/main/resources/i18n/messages_zh_TW.properties @@ -364,6 +364,7 @@ termora.transport.sftp.already-exists.actions=操作 # permissions termora.transport.permissions=更改權限 termora.transport.permissions.file-folder-permissions=檔案/資料夾權限 +termora.transport.permissions.octal-mode=八進位模式 termora.transport.permissions.read=讀取 termora.transport.permissions.write=寫入 termora.transport.permissions.execute=執行