diff --git a/TablePro/Resources/Localizable.xcstrings b/TablePro/Resources/Localizable.xcstrings index 158d1605b..5c862961e 100644 --- a/TablePro/Resources/Localizable.xcstrings +++ b/TablePro/Resources/Localizable.xcstrings @@ -2715,6 +2715,16 @@ } } }, + "Cell Value" : { + "localizations" : { + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Giá trị ô" + } + } + } + }, "Change Color" : { "localizations" : { "vi" : { @@ -4097,22 +4107,6 @@ } } }, - "Copy Cell Value" : { - "localizations" : { - "vi" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sao chép giá trị ô" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "复制单元格值" - } - } - } - }, "Copy Column Name" : { "localizations" : { "vi" : { @@ -4211,20 +4205,7 @@ } }, "Copy with Headers" : { - "localizations" : { - "vi" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sao chép kèm tiêu đề" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "复制(含表头)" - } - } - } + }, "Could not fetch plugin registry" : { @@ -17190,6 +17171,16 @@ } } }, + "With Headers" : { + "localizations" : { + "vi" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kèm tiêu đề" + } + } + } + }, "Word wrap" : { "localizations" : { "vi" : { diff --git a/TablePro/Views/Results/TableRowViewWithMenu.swift b/TablePro/Views/Results/TableRowViewWithMenu.swift index 29ac0863c..2551b9111 100644 --- a/TablePro/Views/Results/TableRowViewWithMenu.swift +++ b/TablePro/Views/Results/TableRowViewWithMenu.swift @@ -33,66 +33,38 @@ final class TableRowViewWithMenu: NSTableRowView { ).target = self } - // Normal row menu (or additional items for inserted rows) if !coordinator.changeManager.isRowDeleted(rowIndex) { - // Edit actions (if editable) - if coordinator.isEditable && dataColumnIndex >= 0 { - let setValueMenu = NSMenu() - - let emptyItem = NSMenuItem( - title: String(localized: "Empty"), action: #selector(setEmptyValue(_:)), keyEquivalent: "") - emptyItem.representedObject = dataColumnIndex - emptyItem.target = self - setValueMenu.addItem(emptyItem) - - let nullItem = NSMenuItem( - title: String(localized: "NULL"), action: #selector(setNullValue(_:)), keyEquivalent: "") - nullItem.representedObject = dataColumnIndex - nullItem.target = self - setValueMenu.addItem(nullItem) - - let defaultItem = NSMenuItem( - title: String(localized: "Default"), action: #selector(setDefaultValue(_:)), keyEquivalent: "") - defaultItem.representedObject = dataColumnIndex - defaultItem.target = self - setValueMenu.addItem(defaultItem) - - let setValueItem = NSMenuItem(title: String(localized: "Set Value"), action: nil, keyEquivalent: "") - setValueItem.submenu = setValueMenu - menu.addItem(setValueItem) + // Copy + let copyItem = NSMenuItem( + title: String(localized: "Copy"), action: #selector(copySelectedOrCurrentRow), keyEquivalent: "c") + copyItem.keyEquivalentModifierMask = .command + copyItem.target = self + menu.addItem(copyItem) - menu.addItem(NSMenuItem.separator()) - } + // "Copy as" submenu — always includes Cell Value + With Headers, conditionally adds SQL statements + let copyAsMenu = NSMenu() - // Copy actions if dataColumnIndex >= 0 { let copyCellItem = NSMenuItem( - title: String(localized: "Copy Cell Value"), action: #selector(copyCellValue(_:)), + title: String(localized: "Cell Value"), action: #selector(copyCellValue(_:)), keyEquivalent: "") copyCellItem.representedObject = dataColumnIndex copyCellItem.target = self - menu.addItem(copyCellItem) + copyAsMenu.addItem(copyCellItem) } - let copyItem = NSMenuItem( - title: String(localized: "Copy"), action: #selector(copySelectedOrCurrentRow), keyEquivalent: "c") - copyItem.keyEquivalentModifierMask = .command - copyItem.target = self - menu.addItem(copyItem) - let copyWithHeadersItem = NSMenuItem( - title: String(localized: "Copy with Headers"), + title: String(localized: "With Headers"), action: #selector(copySelectedOrCurrentRowWithHeaders), keyEquivalent: "c") copyWithHeadersItem.keyEquivalentModifierMask = [.command, .shift] copyWithHeadersItem.target = self - menu.addItem(copyWithHeadersItem) + copyAsMenu.addItem(copyWithHeadersItem) - // "Copy as" submenu — only for SQL databases with a known table if let dbType = coordinator.databaseType, dbType != .mongodb && dbType != .redis, coordinator.tableName != nil { - let copyAsMenu = NSMenu() + copyAsMenu.addItem(NSMenuItem.separator()) let insertItem = NSMenuItem( title: String(localized: "INSERT Statement(s)"), @@ -107,24 +79,54 @@ final class TableRowViewWithMenu: NSTableRowView { keyEquivalent: "") updateItem.target = self copyAsMenu.addItem(updateItem) - - let copyAsItem = NSMenuItem( - title: String(localized: "Copy as"), - action: nil, - keyEquivalent: "") - copyAsItem.submenu = copyAsMenu - menu.addItem(copyAsItem) } + let copyAsItem = NSMenuItem(title: String(localized: "Copy as"), action: nil, keyEquivalent: "") + copyAsItem.submenu = copyAsMenu + menu.addItem(copyAsItem) + + // Paste if coordinator.isEditable { let pasteItem = NSMenuItem( title: String(localized: "Paste"), action: #selector(pasteRows), keyEquivalent: "v") pasteItem.keyEquivalentModifierMask = .command pasteItem.target = self menu.addItem(pasteItem) + } + if coordinator.isEditable { menu.addItem(NSMenuItem.separator()) + } + + // Set Value (editable + column clicked) + if coordinator.isEditable && dataColumnIndex >= 0 { + let setValueMenu = NSMenu() + let emptyItem = NSMenuItem( + title: String(localized: "Empty"), action: #selector(setEmptyValue(_:)), keyEquivalent: "") + emptyItem.representedObject = dataColumnIndex + emptyItem.target = self + setValueMenu.addItem(emptyItem) + + let nullItem = NSMenuItem( + title: String(localized: "NULL"), action: #selector(setNullValue(_:)), keyEquivalent: "") + nullItem.representedObject = dataColumnIndex + nullItem.target = self + setValueMenu.addItem(nullItem) + + let defaultItem = NSMenuItem( + title: String(localized: "Default"), action: #selector(setDefaultValue(_:)), keyEquivalent: "") + defaultItem.representedObject = dataColumnIndex + defaultItem.target = self + setValueMenu.addItem(defaultItem) + + let setValueItem = NSMenuItem(title: String(localized: "Set Value"), action: nil, keyEquivalent: "") + setValueItem.submenu = setValueMenu + menu.addItem(setValueItem) + } + + // Duplicate & Delete + if coordinator.isEditable { let duplicateItem = NSMenuItem( title: String(localized: "Duplicate"), action: #selector(duplicateRow), keyEquivalent: "d") duplicateItem.keyEquivalentModifierMask = .command