diff --git a/HNHUi b/HNHUi index 435f37c2..61feaeb1 160000 --- a/HNHUi +++ b/HNHUi @@ -1 +1 @@ -Subproject commit 435f37c2540bf66698eb66b6990343c35937eafb +Subproject commit 61feaeb15171a73b9678cca936c1087f66be9084 diff --git a/KeePassKit b/KeePassKit index b77e7142..42f7564a 160000 --- a/KeePassKit +++ b/KeePassKit @@ -1 +1 @@ -Subproject commit b77e7142317490365d0fdfa381177306f93272e1 +Subproject commit 42f7564afd30b8359478d9c8f6b0fda40a185c28 diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index 8b13aebf..0d9ef6bb 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -36,11 +36,11 @@ 4C1842C6179BF52100E2F5BC /* KPKLegacyHeaderReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1842C5179BF52000E2F5BC /* KPKLegacyHeaderReader.m */; }; 4C1842D0179C64DD00E2F5BC /* KPKLegacyTreeCryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1842CF179C64DD00E2F5BC /* KPKLegacyTreeCryptor.m */; }; 4C1842D3179C64F000E2F5BC /* KPKXmlTreeCryptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1842D2179C64EF00E2F5BC /* KPKXmlTreeCryptor.m */; }; - 4C18816C179E06920045C5B7 /* TrashBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C18816B179E06920045C5B7 /* TrashBar.xib */; }; 4C18F9AB178E122500890BCE /* Test_Password_1234.kdb in Resources */ = {isa = PBXBuildFile; fileRef = 4C18F9AA178E122500890BCE /* Test_Password_1234.kdb */; }; 4C19E500178E26EF002F2CD0 /* Test_Password_1234.kdbx in Resources */ = {isa = PBXBuildFile; fileRef = 4C19E4FF178E26EF002F2CD0 /* Test_Password_1234.kdbx */; }; 4C19E503178E2871002F2CD0 /* MPDatabasePasswordAndKeyfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C19E502178E2871002F2CD0 /* MPDatabasePasswordAndKeyfile.m */; }; 4C1DDCDD1711ECEB00C98DA3 /* PasswordCreatorWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C1DDCDC1711ECEB00C98DA3 /* PasswordCreatorWindow.xib */; }; + 4C1E9885185F71A800943563 /* MPContextBarViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1E9884185F71A800943563 /* MPContextBarViewController.m */; }; 4C1FA07B18231900003A3F8C /* MPDocument+Autotype.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1FA07A18231900003A3F8C /* MPDocument+Autotype.m */; }; 4C224B4217DFCB2400FF6AEE /* MPNumericalInputFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C224B4117DFCB2400FF6AEE /* MPNumericalInputFormatter.m */; }; 4C245B76176E1E3D0086100E /* DDData.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C245A6A176E1E3C0086100E /* DDData.m */; }; @@ -88,7 +88,7 @@ 4C3BD51516D276F800389F1F /* MPToolbarDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C3BD51416D276F800389F1F /* MPToolbarDelegate.m */; }; 4C3D4C0817594CA40038DAAC /* HNHSeparator.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C3D4C0717594CA40038DAAC /* HNHSeparator.m */; }; 4C3F28541791EDFD00703281 /* KPKErrors.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C3F28531791EDFD00703281 /* KPKErrors.m */; }; - 4C3FFD9E16DAF60600DF9186 /* FilterBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C3FFD9D16DAF60600DF9186 /* FilterBar.xib */; }; + 4C3FFD9E16DAF60600DF9186 /* ContextBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C3FFD9D16DAF60600DF9186 /* ContextBar.xib */; }; 4C431BCD16E2A82800700A81 /* MPPasteBoardController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C431BCC16E2A82700700A81 /* MPPasteBoardController.m */; }; 4C431BCF16E2BAB000700A81 /* OverlayWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C431BCE16E2BAB000700A81 /* OverlayWindow.xib */; }; 4C4436771792BE810099E220 /* KPKFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C4436761792BE810099E220 /* KPKFormat.m */; }; @@ -194,8 +194,6 @@ 4C8A173D1790AA41008B5C17 /* NSData+Keyfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C8A173C1790AA41008B5C17 /* NSData+Keyfile.m */; }; 4C8B36AB17A6ED4B005E1FF1 /* MPOutlineContextMenuDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C8B36AA17A6ED4B005E1FF1 /* MPOutlineContextMenuDelegate.m */; }; 4C8FECC816D57E3200BF26CF /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C8FECC716D57E3200BF26CF /* QuartzCore.framework */; }; - 4C964D44184BE8720050B74E /* KPKEntry+TemplateCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C964D43184BE8720050B74E /* KPKEntry+TemplateCopy.m */; }; - 4C964D47184BE9090050B74E /* KPKGroup+TemplateCopy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C964D46184BE9090050B74E /* KPKGroup+TemplateCopy.m */; }; 4C96D15417A12E4F00D931FA /* 99_CreatedTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4C96D15317A12E4F00D931FA /* 99_CreatedTemplate.pdf */; }; 4C9D6AA917615199001C660C /* HNHRoundedSecureTextFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C9D6AA817615199001C660C /* HNHRoundedSecureTextFieldCell.m */; }; 4CA08DA017A831B200A6544B /* MPAddEntryContextMenuDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CA08D9F17A831B200A6544B /* MPAddEntryContextMenuDelegate.m */; }; @@ -278,6 +276,7 @@ 4CFC873B179DEDF3000DFC03 /* KPKMetaData.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CFC873A179DEDF3000DFC03 /* KPKMetaData.m */; }; 4CFC873E179DF200000DFC03 /* KPKTimeInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CFC873D179DF200000DFC03 /* KPKTimeInfo.m */; }; 4CFC8743179DFD3E000DFC03 /* KPKTestXmlLoading.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CFC8742179DFD3E000DFC03 /* KPKTestXmlLoading.m */; }; + 4CFDDDE9185E92A600A9E7F1 /* HNHTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CFDDDE8185E92A600A9E7F1 /* HNHTextView.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -340,12 +339,13 @@ 4C1842D2179C64EF00E2F5BC /* KPKXmlTreeCryptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = KPKXmlTreeCryptor.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 4C1842D4179C6DE400E2F5BC /* KPKHeaderReading.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KPKHeaderReading.h; sourceTree = ""; }; 4C1842D5179C6F1800E2F5BC /* KPKHeaderWriting.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KPKHeaderWriting.h; sourceTree = ""; }; - 4C18816B179E06920045C5B7 /* TrashBar.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TrashBar.xib; sourceTree = ""; }; 4C18F9AA178E122500890BCE /* Test_Password_1234.kdb */ = {isa = PBXFileReference; lastKnownFileType = file; name = Test_Password_1234.kdb; path = Databases/Test_Password_1234.kdb; sourceTree = ""; }; 4C19E4FF178E26EF002F2CD0 /* Test_Password_1234.kdbx */ = {isa = PBXFileReference; lastKnownFileType = file; name = Test_Password_1234.kdbx; path = Databases/Test_Password_1234.kdbx; sourceTree = ""; }; 4C19E501178E2871002F2CD0 /* MPDatabasePasswordAndKeyfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPDatabasePasswordAndKeyfile.h; sourceTree = ""; }; 4C19E502178E2871002F2CD0 /* MPDatabasePasswordAndKeyfile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPDatabasePasswordAndKeyfile.m; sourceTree = ""; }; 4C1DDCDC1711ECEB00C98DA3 /* PasswordCreatorWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PasswordCreatorWindow.xib; sourceTree = ""; }; + 4C1E9883185F71A800943563 /* MPContextBarViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPContextBarViewController.h; sourceTree = ""; }; + 4C1E9884185F71A800943563 /* MPContextBarViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPContextBarViewController.m; sourceTree = ""; }; 4C1FA07918231900003A3F8C /* MPDocument+Autotype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MPDocument+Autotype.h"; sourceTree = ""; }; 4C1FA07A18231900003A3F8C /* MPDocument+Autotype.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MPDocument+Autotype.m"; sourceTree = ""; }; 4C224B4017DFCB2300FF6AEE /* MPNumericalInputFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPNumericalInputFormatter.h; sourceTree = ""; }; @@ -434,7 +434,7 @@ 4C3D4C0717594CA40038DAAC /* HNHSeparator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HNHSeparator.m; sourceTree = ""; }; 4C3F28521791EDE800703281 /* KPKErrors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KPKErrors.h; sourceTree = ""; }; 4C3F28531791EDFD00703281 /* KPKErrors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KPKErrors.m; sourceTree = ""; }; - 4C3FFD9D16DAF60600DF9186 /* FilterBar.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FilterBar.xib; sourceTree = ""; }; + 4C3FFD9D16DAF60600DF9186 /* ContextBar.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContextBar.xib; sourceTree = ""; }; 4C431BCB16E2A82700700A81 /* MPPasteBoardController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPasteBoardController.h; sourceTree = ""; }; 4C431BCC16E2A82700700A81 /* MPPasteBoardController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPasteBoardController.m; sourceTree = ""; }; 4C431BCE16E2BAB000700A81 /* OverlayWindow.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OverlayWindow.xib; sourceTree = ""; }; @@ -626,10 +626,6 @@ 4C8B36A917A6ED4B005E1FF1 /* MPOutlineContextMenuDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPOutlineContextMenuDelegate.h; sourceTree = ""; }; 4C8B36AA17A6ED4B005E1FF1 /* MPOutlineContextMenuDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOutlineContextMenuDelegate.m; sourceTree = ""; }; 4C8FECC716D57E3200BF26CF /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - 4C964D42184BE8720050B74E /* KPKEntry+TemplateCopy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KPKEntry+TemplateCopy.h"; sourceTree = ""; }; - 4C964D43184BE8720050B74E /* KPKEntry+TemplateCopy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "KPKEntry+TemplateCopy.m"; sourceTree = ""; }; - 4C964D45184BE9090050B74E /* KPKGroup+TemplateCopy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KPKGroup+TemplateCopy.h"; sourceTree = ""; }; - 4C964D46184BE9090050B74E /* KPKGroup+TemplateCopy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "KPKGroup+TemplateCopy.m"; sourceTree = ""; }; 4C96D15317A12E4F00D931FA /* 99_CreatedTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; name = 99_CreatedTemplate.pdf; path = Icons/99_CreatedTemplate.pdf; sourceTree = ""; }; 4C9D6AA717615199001C660C /* HNHRoundedSecureTextFieldCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HNHRoundedSecureTextFieldCell.h; sourceTree = ""; }; 4C9D6AA817615199001C660C /* HNHRoundedSecureTextFieldCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HNHRoundedSecureTextFieldCell.m; sourceTree = ""; }; @@ -787,6 +783,8 @@ 4CFC873F179DF295000DFC03 /* KPKTimerecording.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KPKTimerecording.h; sourceTree = ""; }; 4CFC8741179DFD3E000DFC03 /* KPKTestXmlLoading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KPKTestXmlLoading.h; sourceTree = ""; }; 4CFC8742179DFD3E000DFC03 /* KPKTestXmlLoading.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KPKTestXmlLoading.m; sourceTree = ""; }; + 4CFDDDE7185E92A600A9E7F1 /* HNHTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HNHTextView.h; sourceTree = ""; }; + 4CFDDDE8185E92A600A9E7F1 /* HNHTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HNHTextView.m; sourceTree = ""; }; 6E719715172058BA00E4C5FC /* MPDatabaseVersion.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPDatabaseVersion.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -843,11 +841,10 @@ children = ( 4CF78060176E75180032EE71 /* Settings */, 4C25D58616CF0FAA00F6806C /* EntryView.xib */, + 4C3FFD9D16DAF60600DF9186 /* ContextBar.xib */, 4C77E37B15B84A240093A587 /* MainMenu.xib */, 4C61EA0416D2FFE200AC519E /* OutlineView.xib */, 4CF78061176E752E0032EE71 /* PasswordInputs */, - 4C3FFD9D16DAF60600DF9186 /* FilterBar.xib */, - 4C18816B179E06920045C5B7 /* TrashBar.xib */, 4C4B7EF517A46815000234C7 /* Inspector */, 4CE39AC016ECE359000FE29D /* IconSelection.xib */, 4C2C8B331787500E009649F3 /* UnprotectedWarningView.xib */, @@ -884,10 +881,6 @@ 4CC6DB7917D23719002C6091 /* KPKNode+IconImage.m */, 4CEED1C417D7BD0E007180F1 /* NSError+Messages.h */, 4CEED1C517D7BD0E007180F1 /* NSError+Messages.m */, - 4C964D42184BE8720050B74E /* KPKEntry+TemplateCopy.h */, - 4C964D43184BE8720050B74E /* KPKEntry+TemplateCopy.m */, - 4C964D45184BE9090050B74E /* KPKGroup+TemplateCopy.h */, - 4C964D46184BE9090050B74E /* KPKGroup+TemplateCopy.m */, ); name = Categories; sourceTree = ""; @@ -1386,6 +1379,8 @@ 4C4B7EF117A467FC000234C7 /* MPEntryInspectorViewController.m */, 4C0F647917B6BC9C00D9522A /* MPSavePanelAccessoryViewController.h */, 4C0F647A17B6BC9C00D9522A /* MPSavePanelAccessoryViewController.m */, + 4C1E9883185F71A800943563 /* MPContextBarViewController.h */, + 4C1E9884185F71A800943563 /* MPContextBarViewController.m */, ); name = "View Controller"; sourceTree = ""; @@ -1482,6 +1477,8 @@ 4C52A243177D7B9F0000D88F /* HNHScrollView.m */, 4C2671AB17A7D8FC00F3A645 /* HNHColorWell.h */, 4C2671AC17A7D8FC00F3A645 /* HNHColorWell.m */, + 4CFDDDE7185E92A600A9E7F1 /* HNHTextView.h */, + 4CFDDDE8185E92A600A9E7F1 /* HNHTextView.m */, ); path = HNHUi; sourceTree = ""; @@ -1831,7 +1828,7 @@ 4CD78AC016D155FF00768A1D /* 11_CameraTemplate.pdf in Resources */, 4C61EA0516D2FFE200AC519E /* OutlineView.xib in Resources */, 4CB9339916D3A0DD00A13B5D /* Credits.rtf in Resources */, - 4C3FFD9E16DAF60600DF9186 /* FilterBar.xib in Resources */, + 4C3FFD9E16DAF60600DF9186 /* ContextBar.xib in Resources */, 4C431BCF16E2BAB000700A81 /* OverlayWindow.xib in Resources */, 4C17F105184E630200E85625 /* 14_BatteryTemplate.pdf in Resources */, 4C76156D1764C0E20015A1A6 /* InspectorView.xib in Resources */, @@ -1854,7 +1851,6 @@ 4C52A88F1788628B00868229 /* 13_KeysTemplate.pdf in Resources */, 4C52A8901788628B00868229 /* 18_DisplayTemplate.pdf in Resources */, 4C52A892178863B000868229 /* 68_PhoneTemplate.pdf in Resources */, - 4C18816C179E06920045C5B7 /* TrashBar.xib in Resources */, 4C96D15417A12E4F00D931FA /* 99_CreatedTemplate.pdf in Resources */, 4C4B7EEA17A45EC6000234C7 /* DatePickingView.xib in Resources */, 4C4B7EEF17A467E1000234C7 /* GroupInspectorView.xib in Resources */, @@ -1920,6 +1916,7 @@ files = ( 4C77E37315B84A240093A587 /* main.m in Sources */, 4CBA2ABA17074C07006D8139 /* MPSettingsHelper.m in Sources */, + 4CFDDDE9185E92A600A9E7F1 /* HNHTextView.m in Sources */, 4C77E37A15B84A240093A587 /* MPAppDelegate.m in Sources */, 4CAD747B15B887FD00104512 /* DDXMLElementAdditions.m in Sources */, 4CAD747C15B887FD00104512 /* NSString+DDXML.m in Sources */, @@ -1946,7 +1943,6 @@ 4C89F524182FB4740069C73C /* MPAutotypeCommand.m in Sources */, 4CFC53BF16E94729007396BE /* MPShadowBox.m in Sources */, 4C888C9316EB6F5E003D34A1 /* MPToolbarItem.m in Sources */, - 4C964D47184BE9090050B74E /* KPKGroup+TemplateCopy.m in Sources */, 4C888C9716EB754B003D34A1 /* MPActionHelper.m in Sources */, 4C811C8316ECD06E00C4BAC6 /* MPKeyfilePathControlDelegate.m in Sources */, 4CE39ABF16ECE34A000FE29D /* MPIconSelectViewController.m in Sources */, @@ -1995,7 +1991,6 @@ 4C245BED176E1E3D0086100E /* DDFileLogger.m in Sources */, 4C245BEE176E1E3D0086100E /* DDLog.m in Sources */, 4C245BEF176E1E3D0086100E /* DDTTYLogger.m in Sources */, - 4C964D44184BE8720050B74E /* KPKEntry+TemplateCopy.m in Sources */, 4C245BF0176E1E3D0086100E /* ContextFilterLogFormatter.m in Sources */, 4C245BF1176E1E3D0086100E /* DispatchQueueLogFormatter.m in Sources */, 4CF78057176E5CFD0032EE71 /* MPConnection.m in Sources */, @@ -2056,6 +2051,7 @@ 4CCEDE32179F5B6C008402BE /* KPKDataStreamReader.m in Sources */, 4C17D8E517A1C780006C8C1E /* MPDocumentWindowDelegate.m in Sources */, 4C63B8FB17A3154D0091BD72 /* MPContextToolbarButton.m in Sources */, + 4C1E9885185F71A800943563 /* MPContextBarViewController.m in Sources */, 4C1FA07B18231900003A3F8C /* MPDocument+Autotype.m in Sources */, 4C4B7EE917A45EC6000234C7 /* MPDatePickingViewController.m in Sources */, 4C4B7EEE17A467E1000234C7 /* MPGroupInspectorViewController.m in Sources */, diff --git a/MacPass/ContextBar.xib b/MacPass/ContextBar.xib new file mode 100644 index 00000000..b8089f82 --- /dev/null +++ b/MacPass/ContextBar.xib @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MacPass/EntryInspectorView.xib b/MacPass/EntryInspectorView.xib index 9fb70102..99a9453b 100644 --- a/MacPass/EntryInspectorView.xib +++ b/MacPass/EntryInspectorView.xib @@ -13,6 +13,7 @@ + @@ -31,7 +32,7 @@ - + @@ -39,6 +40,7 @@ + @@ -430,6 +432,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -440,6 +514,8 @@ + + diff --git a/MacPass/EntryView.xib b/MacPass/EntryView.xib index a499ba7a..61c0891c 100644 --- a/MacPass/EntryView.xib +++ b/MacPass/EntryView.xib @@ -269,11 +269,24 @@ + + + diff --git a/MacPass/FilterBar.xib b/MacPass/FilterBar.xib deleted file mode 100644 index 496912d4..00000000 --- a/MacPass/FilterBar.xib +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MacPass/KPKEntry+TemplateCopy.h b/MacPass/KPKEntry+TemplateCopy.h deleted file mode 100644 index 3ae51c35..00000000 --- a/MacPass/KPKEntry+TemplateCopy.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// KPKEntry+TemplateCopy.h -// MacPass -// -// Created by Michael Starke on 01/12/13. -// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved. -// - -#import "KPKEntry.h" - -@interface KPKEntry (TemplateCopy) - -- (instancetype)copyWithTitle:(NSString *)title; - -@end diff --git a/MacPass/KPKEntry+TemplateCopy.m b/MacPass/KPKEntry+TemplateCopy.m deleted file mode 100644 index 0f5679fe..00000000 --- a/MacPass/KPKEntry+TemplateCopy.m +++ /dev/null @@ -1,22 +0,0 @@ -// -// KPKEntry+TemplateCopy.m -// MacPass -// -// Created by Michael Starke on 01/12/13. -// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved. -// - -#import "KPKEntry+TemplateCopy.h" -#import "KPKTimeInfo.h" - -@implementation KPKEntry (TemplateCopy) - -- (instancetype)copyWithTitle:(NSString *)title { - KPKEntry *copy = [self copy]; - copy.uuid = [[NSUUID alloc] init]; - copy.timeInfo.creationTime = [NSDate date]; - copy.title = title; - return copy; -} - -@end diff --git a/MacPass/KPKGroup+TemplateCopy.h b/MacPass/KPKGroup+TemplateCopy.h deleted file mode 100644 index db0e6ec3..00000000 --- a/MacPass/KPKGroup+TemplateCopy.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// KPKGroup+TemplateCopy.h -// MacPass -// -// Created by Michael Starke on 01/12/13. -// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved. -// - -#import "KPKGroup.h" - -@interface KPKGroup (TemplateCopy) - -- (instancetype)copyWithName:(NSString *)name; - -@end diff --git a/MacPass/KPKGroup+TemplateCopy.m b/MacPass/KPKGroup+TemplateCopy.m deleted file mode 100644 index 085dca50..00000000 --- a/MacPass/KPKGroup+TemplateCopy.m +++ /dev/null @@ -1,22 +0,0 @@ -// -// KPKGroup+TemplateCopy.m -// MacPass -// -// Created by Michael Starke on 01/12/13. -// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved. -// - -#import "KPKGroup+TemplateCopy.h" -#import "KPKTimeInfo.h" - -@implementation KPKGroup (TemplateCopy) - -- (instancetype)copyWithName:(NSString *)name { - KPKGroup *copy = [self copy]; - copy.uuid = [[NSUUID alloc] init]; - copy.timeInfo.creationTime = [NSDate date]; - copy.name = name; - return copy; -} - -@end diff --git a/MacPass/KPKNode+IconImage.m b/MacPass/KPKNode+IconImage.m index a20988ea..fbec8b84 100644 --- a/MacPass/KPKNode+IconImage.m +++ b/MacPass/KPKNode+IconImage.m @@ -9,18 +9,23 @@ #import "KPKNode+IconImage.h" #import "KPKIcon.h" +#import "KPKTree.h" +#import "KPKMetaData.h" #import "MPIconHelper.h" @implementation KPKNode (IconImage) + (NSSet *)keyPathsForValuesAffectingIconImage { - return [NSSet setWithArray:@[@"customIcon", @"iconId"]]; + return [NSSet setWithArray:@[@"iconUUID", @"iconId"]]; } - (NSImage *)iconImage { - if(self.customIcon) { - return self.customIcon.image; + if(self.iconUUID) { + KPKIcon *icon = [self.tree.metaData findIcon:self.iconUUID]; + if(icon && icon.image) { + return icon.image; + } } return [MPIconHelper icon:(MPIconType)self.iconId]; } diff --git a/MacPass/MPActionHelper.m b/MacPass/MPActionHelper.m index 6cf49d84..a58e4531 100644 --- a/MacPass/MPActionHelper.m +++ b/MacPass/MPActionHelper.m @@ -20,7 +20,7 @@ @(MPActionCopyPassword) : @"copyPassword:", @(MPActionCopyURL) : @"copyURL:", @(MPActionCopyUsername) : @"copyUsername:", - @(MPActionDelete) : @"deleteNode:", + @(MPActionDelete) : @"delete:", @(MPActionEditPassword) : @"editPassword:", @(MPActionOpenURL) : @"openURL:", @(MPActionToggleInspector) : @"toggleInspector:", @@ -45,6 +45,7 @@ NSArray *selectors = [[self _actionDictionary] allValues]; NSUInteger index = [selectors indexOfObject:selectorString]; if(index == NSNotFound) { + // Test for default Actions? return MPUnkownAction; } NSArray *keys = [[self _actionDictionary] allKeysForObject:selectorString]; diff --git a/MacPass/MPContextBarViewController.h b/MacPass/MPContextBarViewController.h new file mode 100644 index 00000000..032845ec --- /dev/null +++ b/MacPass/MPContextBarViewController.h @@ -0,0 +1,54 @@ +// +// MPContextBarViewController.h +// MacPass +// +// Created by Michael Starke on 16/12/13. +// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved. +// + +#import "MPViewController.h" + +@protocol MPContextBarDelegate + +@optional +- (void)contextBarDidChangeFilter; +- (void)contextBarDidExitFilter; +- (void)contextBarDidExitHistory; +- (void)contextBarShouldEmptyTrash; +@end + +typedef NS_OPTIONS(NSUInteger, MPFilterModeType) { + MPFilterNone = 0, + MPFilterUrls = (1<<0), + MPFilterUsernames = (1<<1), + MPFilterTitles = (1<<2), + MPFilterPasswords = (1<<3), +}; + +@class HNHGradientView; + +@interface MPContextBarViewController : MPViewController + +@property (nonatomic, assign) MPFilterModeType filterMode; +@property (nonatomic, readonly) BOOL hasFilter; +@property (nonatomic, weak) id delegate; + +- (NSString *)filterString; +- (NSArray *)filterPredicates; + +- (IBAction)toggleFilterSpace:(id)sender; + +- (BOOL)showsFilter; +- (BOOL)showsHistory; +- (BOOL)showsTrash; + +- (void)exitFilter; +- (void)showFilter; + +- (void)showHistory; +- (void)showTrash; + +- (void)enable; +- (void)disable; + +@end diff --git a/MacPass/MPContextBarViewController.m b/MacPass/MPContextBarViewController.m new file mode 100644 index 00000000..96803c5d --- /dev/null +++ b/MacPass/MPContextBarViewController.m @@ -0,0 +1,267 @@ +// +// MPContextBarViewController.m +// MacPass +// +// Created by Michael Starke on 16/12/13. +// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved. +// + +#import "MPContextBarViewController.h" +#import "HNHGradientView.h" + +typedef NS_ENUM(NSUInteger, MPContextTab) { + MPContextTabFilter, + MPContextTabTrash, + MPContextTabHistory +}; + +@interface MPContextBarViewController () { +@private + BOOL _delegateRespondsToDidChangeFilter; + BOOL _delegateRespondsToDidExitFilter; + BOOL _delegateRespondsToDidExitHistory; + BOOL _delegateRespondsToShouldEmptyTrash; +} + +@property (nonatomic, assign) MPContextTab activeTab; +@property (nonatomic, assign) BOOL hasFilter; + +@property (weak) IBOutlet NSButton *filterDoneButton; +@property (weak) IBOutlet NSButton *filterTitleButton; +@property (weak) IBOutlet NSButton *filterUsernameButton; +@property (weak) IBOutlet NSButton *filterURLButton; +@property (weak) IBOutlet NSButton *filterPasswordButton; +@property (weak) IBOutlet NSTextField *filterLabelTextField; +@property (weak) IBOutlet NSSearchField *filterSearchField; +@property (weak) IBOutlet HNHGradientView *historyBar; +@property (weak) IBOutlet HNHGradientView *trashBar; + +@end + +@implementation MPContextBarViewController + +- (instancetype)init { + self = [self initWithNibName:@"ContextBar" bundle:nil]; + return self; +} + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + _hasFilter = NO; + _filterMode = MPFilterTitles; + _delegateRespondsToDidExitFilter = NO; + _delegateRespondsToDidExitHistory = NO; + _delegateRespondsToShouldEmptyTrash = NO; + _delegateRespondsToDidChangeFilter = NO; + } + return self; +} + +- (void)didLoadView { + [self.filterURLButton setTag:MPFilterUrls]; + [self.filterUsernameButton setTag:MPFilterUsernames]; + [self.filterTitleButton setTag:MPFilterTitles]; + [self.filterPasswordButton setTag:MPFilterPasswords]; + [[self.filterLabelTextField cell] setBackgroundStyle:NSBackgroundStyleRaised]; + [self.filterDoneButton setAction:@selector(exitFilter)]; + [self.filterDoneButton setTarget:self]; + + [self.filterSearchField setAction:@selector(_didChangeFilter)]; + [[self.filterSearchField cell] setSendsSearchStringImmediately:NO]; + + self.historyBar.activeGradient = [[NSGradient alloc] initWithStartingColor:[NSColor redColor] endingColor:[NSColor greenColor]]; + + NSArray *activeColors = @[ + [NSColor colorWithCalibratedWhite:0.2 alpha:1], + [NSColor colorWithCalibratedWhite:0.4 alpha:1] + ]; + NSArray *inactiveColors = @[ [NSColor colorWithCalibratedWhite:0.3 alpha:1], + [NSColor colorWithCalibratedWhite:0.6 alpha:1] + ]; + self.trashBar.activeGradient = [[NSGradient alloc] initWithColors:activeColors]; + self.trashBar.inactiveGradient = [[NSGradient alloc] initWithColors:inactiveColors]; + + [[self view] bind:NSSelectedIndexBinding toObject:self withKeyPath:@"activeTab" options:nil]; + +} + +#pragma mark Properties +- (void)setFilterMode:(MPFilterModeType)newFilterMode { + if(_filterMode != newFilterMode) { + if(newFilterMode == MPFilterNone) { + newFilterMode = MPFilterTitles; + } + _filterMode = newFilterMode; + [self _updateFilterButtons]; + [self _didChangeFilter]; + } +} + +- (void)setDelegate:(id)delegate { + if(self.delegate != delegate) { + _delegate = delegate; + _delegateRespondsToDidChangeFilter = [_delegate respondsToSelector:@selector(contextBarDidChangeFilter)]; + _delegateRespondsToDidExitFilter = [_delegate respondsToSelector:@selector(contextBarDidExitFilter)]; + _delegateRespondsToDidExitHistory = [_delegate respondsToSelector:@selector(contextBarDidExitHistory)]; + _delegateRespondsToShouldEmptyTrash = [_delegate respondsToSelector:@selector(contextBarShouldEmptyTrash)]; + } +} + +- (void)disable { + [self.filterSearchField setEnabled:NO]; +} + +- (void)enable { + [self.filterSearchField setEnabled:YES]; + /* First responder handling */ + switch (self.activeTab) { + case MPContextTabTrash: + break; + + case MPContextTabFilter: + [[[self view] window] makeFirstResponder:self.filterSearchField]; + break; + + case MPContextTabHistory: + break; + + default: + break; + } +} + +- (NSArray *)filterPredicates { + if(![self hasFilter]) { + return nil; + } + NSMutableArray *prediactes = [[NSMutableArray alloc] initWithCapacity:4]; + if([self _shouldFilterTitles]) { + [prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.title CONTAINS[cd] %@", [self filterString]]]; + } + if([self _shouldFilterUsernames]) { + [prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.username CONTAINS[cd] %@", [self filterString]]]; + } + if([self _shouldFilterURLs]) { + [prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.url CONTAINS[cd] %@", [self filterString]]]; + } + if([self _shouldFilterPasswords]) { + [prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.password CONTAINS[cd] %@", [self filterString]]]; + } + return prediactes; +} + +- (IBAction)toggleFilterSpace:(id)sender { + if(![sender isKindOfClass:[NSButton class]]) { + return; // Wrong sender + } + NSButton *button = sender; + MPFilterModeType toggledMode = [button tag]; + switch ([button state]) { + case NSOnState: + self.filterMode |= toggledMode; + break; + + case NSOffState: + self.filterMode ^= toggledMode; + break; + + default: + break; + } +} + +- (void)showFilter { + self.hasFilter = YES; + /* Select text if already visible */ + if([self showsFilter]) { + [self.filterSearchField selectText:self]; + } + self.activeTab = MPContextTabFilter; + [self _updateFilterButtons]; +} + +- (void)showHistory { + [self exitFilter]; + self.activeTab = MPContextTabHistory; + [self _updateBindings]; +} + +- (void)showTrash { + [self exitFilter]; + self.activeTab = MPContextTabTrash; + [self _updateBindings]; +} + +- (BOOL)showsFilter { + return self.activeTab == MPContextTabFilter; +} + +- (BOOL)showsHistory { + return self.activeTab == MPContextTabHistory; +} + +- (BOOL)showsTrash { + return self.activeTab == MPContextTabTrash; +} + +- (NSString *)filterString { + return [self.filterSearchField stringValue]; +} + +- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector { + if(commandSelector == @selector(insertNewline:)) { + [self _didChangeFilter]; + } + return NO; +} + +- (void)exitFilter { + if(!self.hasFilter) { + return; // Nothing to do; + } + if(![self showsFilter]) { + return; // We arent displaying the filter view + } + self.hasFilter = NO; + [self.filterSearchField setStringValue:@""]; + if(_delegateRespondsToDidExitFilter) { + [self.delegate contextBarDidExitFilter]; + } +} + +- (void)_didChangeFilter { + if(_delegateRespondsToDidChangeFilter) { + [self.delegate contextBarDidChangeFilter]; + } +} + +- (void)_updateBindings { + // only the entry view has to be bound, the rest not +} + +- (void)_updateFilterButtons { + [self.filterTitleButton setState:[self _shouldFilterTitles] ? NSOnState : NSOffState]; + [self.filterURLButton setState:[self _shouldFilterURLs] ? NSOnState : NSOffState ]; + [self.filterUsernameButton setState:[self _shouldFilterUsernames] ? NSOnState : NSOffState]; + [self.filterPasswordButton setState:[self _shouldFilterPasswords] ? NSOnState : NSOffState]; +} + +- (BOOL)_shouldFilterTitles { + return (MPFilterNone != (self.filterMode & MPFilterTitles)); +} + +- (BOOL)_shouldFilterURLs { + return (MPFilterNone != (self.filterMode & MPFilterUrls)); +} + +- (BOOL)_shouldFilterUsernames { + return (MPFilterNone != (self.filterMode & MPFilterUsernames)); +} + +- (BOOL)_shouldFilterPasswords { + return (MPFilterNone != (self.filterMode & MPFilterPasswords)); +} + + +@end diff --git a/MacPass/MPDocument.m b/MacPass/MPDocument.m index 67bd3d5b..d50263b1 100644 --- a/MacPass/MPDocument.m +++ b/MacPass/MPDocument.m @@ -33,7 +33,6 @@ #import "DDXMLNode.h" #import "KPKEntry.h" -#import "KPKEntry+TemplateCopy.h" #import "KPKGroup.h" #import "KPKTree.h" #import "KPKTree+Serializing.h" @@ -446,6 +445,7 @@ typedef NS_ENUM(NSUInteger, MPAlertType) { newEntry.title = self.tree.metaData.defaultUserName; } [parent addEntry:newEntry]; + [parent.undoManager setActionName:NSLocalizedString(@"ADD_ENTRY", "")]; return newEntry; } @@ -540,8 +540,9 @@ typedef NS_ENUM(NSUInteger, MPAlertType) { if(entryUUID) { KPKEntry *templateEntry = [self findEntry:entryUUID]; if(templateEntry && self.selectedGroup) { - KPKEntry *copy = [templateEntry copyWithTitle:templateEntry.title]; + KPKEntry *copy = [templateEntry copyWithTitle:templateEntry.title options:0]; [self.selectedGroup addEntry:copy]; + [self.selectedGroup.undoManager setActionName:NSLocalizedString(@"ADD_TREMPLATE_ENTRY", "")]; } } return; diff --git a/MacPass/MPEntryInspectorViewController.h b/MacPass/MPEntryInspectorViewController.h index 89628422..77f41f2d 100644 --- a/MacPass/MPEntryInspectorViewController.h +++ b/MacPass/MPEntryInspectorViewController.h @@ -24,6 +24,7 @@ @property (weak) IBOutlet NSSegmentedControl *infoTabControl; @property (weak) IBOutlet NSTableView *attachmentTableView; @property (weak) IBOutlet NSTableView *customFieldsTableView; +@property (weak) IBOutlet NSTableView *historyTableView; @property (unsafe_unretained) IBOutlet NSTextView *notesTextView; @property (weak) IBOutlet NSButton *generatePasswordButton; @property (weak) IBOutlet NSButton *togglePassword; diff --git a/MacPass/MPEntryInspectorViewController.m b/MacPass/MPEntryInspectorViewController.m index b8ac3ef0..9f364fbc 100644 --- a/MacPass/MPEntryInspectorViewController.m +++ b/MacPass/MPEntryInspectorViewController.m @@ -24,13 +24,15 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { MPEntryTabGeneral, MPEntryTabFiles, - MPEntryTabCustomFields + MPEntryTabCustomFields, + MPEntryTabHistory }; @interface MPEntryInspectorViewController () { @private NSArrayController *_attachmentsController; NSArrayController *_customFieldsController; + NSArrayController *_historyController; MPAttachmentTableViewDelegate *_attachmentTableDelegate; MPCustomFieldTableViewDelegate *_customFieldTableDelegate; MPAttachmentTableDataSource *_attachmentDataSource; @@ -57,6 +59,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { _showPassword = NO; _attachmentsController = [[NSArrayController alloc] init]; _customFieldsController = [[NSArrayController alloc] init]; + _historyController = [[NSArrayController alloc] init]; _attachmentTableDelegate = [[MPAttachmentTableViewDelegate alloc] init]; _customFieldTableDelegate = [[MPCustomFieldTableViewDelegate alloc] init]; _attachmentDataSource = [[MPAttachmentTableDataSource alloc] init]; @@ -105,7 +108,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { [[self view] layoutSubtreeIfNeeded]; [_infoTabControl bind:NSSelectedIndexBinding toObject:self withKeyPath:@"activeTab" options:nil]; - [_tabView bind:NSSelectedIndexBinding toObject:self withKeyPath:@"activeTab" options:nil]; + [_tabView bind:NSSelectedIndexBinding toObject:self withKeyPath:@"activeTab" options:nil]; /* Set background to clearcolor so we can draw in the scrollview */ [_attachmentTableView setBackgroundColor:[NSColor clearColor]]; @@ -118,6 +121,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { [_customFieldsTableView bind:NSContentBinding toObject:_customFieldsController withKeyPath:@"arrangedObjects" options:nil]; [_customFieldsTableView setDelegate:_customFieldTableDelegate]; + [_historyTableView bind:NSContentBinding toObject:_historyController withKeyPath:@"arrangedObjects" options:nil]; [self.passwordTextField bind:@"showPassword" toObject:self withKeyPath:@"showPassword" options:nil]; [self.togglePassword bind:NSValueBinding toObject:self withKeyPath:@"showPassword" options:nil]; @@ -224,6 +228,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { [self _bindEntry]; [self _bindAttachments]; [self _bindCustomFields]; + [self _bindHistory]; } - (void)_bindEntry { @@ -261,4 +266,14 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) { [_customFieldsController bind:NSContentArrayBinding toObject:self.entry withKeyPath:@"customAttributes" options:nil]; } +- (void)_bindHistory { + if(self.entry) { + [_historyController bind:NSContentArrayBinding toObject:self.entry withKeyPath:@"history" options:nil]; + } + else if([_historyController content] != nil) { + [_historyController unbind:NSContentArrayBinding]; + [_historyController setContent:nil]; + } +} + @end diff --git a/MacPass/MPEntryViewController.h b/MacPass/MPEntryViewController.h index 2b229baf..064e72d3 100644 --- a/MacPass/MPEntryViewController.h +++ b/MacPass/MPEntryViewController.h @@ -7,6 +7,7 @@ // #import "MPViewController.h" +#import "MPContextBarViewController.h" APPKIT_EXTERN NSString *const MPEntryTableUserNameColumnIdentifier; APPKIT_EXTERN NSString *const MPEntryTableTitleColumnIdentifier; @@ -26,19 +27,16 @@ typedef NS_ENUM( NSUInteger, MPCopyContentTypeTag) { @class MPOutlineViewDelegate; @class MPDocumentWindowController; -@interface MPEntryViewController : MPViewController +@interface MPEntryViewController : MPViewController @property (weak,readonly) NSTableView *entryTable; @property (readonly, strong) NSArrayController *entryArrayController; -@property (nonatomic, strong) NSString *filter; - /* Call this after alle viewcontroller are loaded */ - (void)setupNotifications:(MPDocumentWindowController *)windowController; /* Clear the Search filter*/ - (void)showFilter:(id)sender; -- (void)clearFilter:(id)sender; /* Copy/Paste */ - (void)copyUsername:(id)sender; @@ -47,8 +45,8 @@ typedef NS_ENUM( NSUInteger, MPCopyContentTypeTag) { - (void)copyURL:(id)sender; - (void)openURL:(id)sender; - -/* Entry Handling*/ -- (void)deleteNode:(id)sender; +/* History*/ +- (IBAction)enterHistoryBrowser:(id)sender; +- (IBAction)exitHistoryBrowser:(id)sender; @end diff --git a/MacPass/MPEntryViewController.m b/MacPass/MPEntryViewController.m index 6b596bbe..baec98b7 100644 --- a/MacPass/MPEntryViewController.m +++ b/MacPass/MPEntryViewController.m @@ -14,6 +14,7 @@ #import "MPDocumentWindowController.h" #import "MPPasteBoardController.h" #import "MPOverlayWindowController.h" +#import "MPContextBarViewController.h" #import "MPContextMenuHelper.h" #import "MPActionHelper.h" @@ -37,19 +38,11 @@ #define STATUS_BAR_ANIMATION_TIME 0.15 -typedef NS_OPTIONS(NSUInteger, MPFilterModeType) { - MPFilterNone = 0, - MPFilterUrls = (1<<0), - MPFilterUsernames = (1<<1), - MPFilterTitles = (1<<2), - MPFilterPasswords = (1<<3), -}; - typedef NS_ENUM(NSUInteger,MPOVerlayInfoType) { MPOverlayInfoPassword, MPOverlayInfoUsername, MPOverlayInfoURL, - MPOverlayInfoCustom + MPOverlayInfoCustom, }; NSString *const MPEntryTableUserNameColumnIdentifier = @"MPUserNameColumnIdentifier"; @@ -67,32 +60,24 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; @interface MPEntryViewController () { MPEntryContextMenuDelegate *_menuDelegate; + BOOL _isDisplayingContextBar; } @property (strong) NSArrayController *entryArrayController; +@property (strong) MPContextBarViewController *contextBarViewController; @property (strong) NSArray *filteredEntries; -@property (strong) IBOutlet NSView *filterBar; -@property (strong) IBOutlet HNHGradientView *trashBar; -@property (weak) IBOutlet NSTableView *entryTable; -@property (strong) IBOutlet NSLayoutConstraint *tableToTopConstraint; -@property (strong) NSLayoutConstraint *filterbarTopConstraint; -@property (weak) IBOutlet NSButton *filterDoneButton; -@property (weak) IBOutlet NSButton *filterTitleButton; -@property (weak) IBOutlet NSButton *filterUsernameButton; -@property (weak) IBOutlet NSButton *filterURLButton; -@property (weak) IBOutlet NSButton *filterPasswordButton; -@property (weak) IBOutlet NSTextField *filterLabelTextField; -@property (weak) IBOutlet NSSearchField *filterSearchField; +@property (weak) IBOutlet NSTableView *entryTable; + +/* Constraints */ +@property (strong) IBOutlet NSLayoutConstraint *tableToTopConstraint; +@property (strong) NSLayoutConstraint *contextBarTopConstraint; + @property (weak) IBOutlet HNHGradientView *bottomBar; @property (weak) IBOutlet NSButton *addEntryButton; -@property (weak) IBOutlet NSTextField *entryCountTextField; @property (nonatomic, strong) MPEntryTableDataSource *dataSource; -@property (assign, nonatomic) MPFilterModeType filterMode; -@property (assign, nonatomic) BOOL isDisplayingFilterbar; - @end @implementation MPEntryViewController @@ -105,12 +90,13 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if(self) { - _filterMode = MPFilterTitles; - _isDisplayingFilterbar = NO; + _isDisplayingContextBar = NO; _entryArrayController = [[NSArrayController alloc] init]; _dataSource = [[MPEntryTableDataSource alloc] init]; _dataSource.viewController = self; _menuDelegate = [[MPEntryContextMenuDelegate alloc] init]; + _contextBarViewController = [[MPContextBarViewController alloc] init]; + } return self; } @@ -123,7 +109,6 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; - (void)didLoadView { [[self view] setWantsLayer:YES]; - [self _hideFilterBar]; [_bottomBar setBorderType:HNHBorderTop]; [self.addEntryButton setAction:[MPActionHelper actionOfType:MPActionAddEntry]]; @@ -133,11 +118,13 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; [self.entryTable setTarget:self]; [self.entryTable setFloatsGroupRows:NO]; [self.entryTable registerForDraggedTypes:@[KPKEntryUTI]]; + /* First responder notifications */ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didBecomFirstResponder:) name:MPDidActivateViewNotification object:_entryTable]; - + /* Filter bar notifications */ + self.contextBarViewController.delegate = self; [self _setupEntryMenu]; NSTableColumn *parentColumn = [self.entryTable tableColumns][0]; @@ -239,7 +226,7 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; [[view imageView] bind:NSValueBinding toObject:entry withKeyPath:@"iconImage" options:nil]; } else { - assert(entry.parent); + NSAssert(entry.parent != nil, @"Entry needs to have a parent"); [[view textField] bind:NSValueBinding toObject:entry.parent withKeyPath:@"name" options:nil]; [[view imageView] bind:NSValueBinding toObject:entry.parent withKeyPath:@"iconImage" options:nil]; } @@ -307,19 +294,14 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; return; } /* - If a grup is the current item, see if we already show that group + If a group is the current item, see if we already show that group */ if(document.selectedItem == document.selectedGroup) { - /* - If we reselect the group, or just another group - we clear the filter and bind to the new selected group - */ - if(self.isDisplayingFilterbar && ![document.selectedItem isKindOfClass:[KPKEntry class]]) { - [self clearFilter:nil]; - [self.entryArrayController bind:NSContentArrayBinding toObject:document.selectedGroup withKeyPath:@"entries" options:nil]; - return; + /* If we change to a group selection, we should clear the filter */ + if(_isDisplayingContextBar) { + [self.contextBarViewController exitFilter]; } - if([[self.entryArrayController content] count] > 0) { + else if([[self.entryArrayController content] count] > 0) { KPKEntry *entry = [[self.entryArrayController content] lastObject]; if(entry.parent == document.selectedGroup) { return; // we are showing the correct object right now. @@ -327,127 +309,35 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; } [self.entryArrayController bind:NSContentArrayBinding toObject:document.selectedGroup withKeyPath:@"entries" options:nil]; } + [self _updateContextBar]; } - (void)_didBecomFirstResponder:(NSNotification *)notification { MPDocument *document = [[self windowController] document]; - if(document.selectedEntry.parent == document.selectedGroup || self.isDisplayingFilterbar) { + if(document.selectedEntry.parent == document.selectedGroup || [self.contextBarViewController showsFilter]) { document.selectedItem = document.selectedEntry; } else { document.selectedEntry = nil; } } - -#pragma mark Filtering -- (void)showFilter:(id)sender { - if(self.isDisplayingFilterbar) { - [self.filterSearchField selectText:self]; - } - - BOOL didLoadFilterBar = NO; - if(!self.filterBar) { - [self _setupFilterBar]; - didLoadFilterBar = YES; - } - /* - Make sure the buttons are set correctyl every time - */ - [self.filterTitleButton setState:[self _shouldFilterTitles] ? NSOnState : NSOffState]; - [self.filterURLButton setState:[self _shouldFilterURLs] ? NSOnState : NSOffState ]; - [self.filterUsernameButton setState:[self _shouldFilterUsernames] ? NSOnState : NSOffState]; - [self.filterPasswordButton setState:[self _shouldFilterPasswords] ? NSOnState : NSOffState]; - - if(self.isDisplayingFilterbar) { - return; // nothing to to - } - - /* Install any constraints we need for the first time */ - - self.isDisplayingFilterbar = YES; - - if(didLoadFilterBar) { - /* Add the view for the first time */ - [[self view] addSubview:self.filterBar]; - - NSView *scrollView = [_entryTable enclosingScrollView]; - NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, _filterBar); - - /* Pin to the left */ - [[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_filterBar]|" options:0 metrics:nil views:views]]; - /* Pin height and to top of entry table */ - [[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[_filterBar(==30)]-0-[scrollView]" options:0 metrics:nil views:views]]; - /* Create the top constraint for the filter bar where we can change the contanst instaed of removing/adding constraints all the time */ - self.filterbarTopConstraint = [NSLayoutConstraint constraintWithItem:self.filterBar - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:[self view] - attribute:NSLayoutAttributeTop - multiplier:1 - constant:-31]; - } - [[self view] removeConstraint:self.tableToTopConstraint]; - [[self view] addConstraint:self.filterbarTopConstraint]; - [[self view] layoutSubtreeIfNeeded]; - self.filterbarTopConstraint.constant = 0; - - [NSAnimationContext runAnimationGroup:^(NSAnimationContext* context) { - context.duration = STATUS_BAR_ANIMATION_TIME; - context.allowsImplicitAnimation = YES; - [self.view layoutSubtreeIfNeeded]; - } completionHandler:^{ - [self.filterSearchField setEnabled:YES]; - [[[self windowController] window] makeFirstResponder:self.filterSearchField]; - }]; -} - -- (BOOL)hasFilter { - return ([self.filter length] > 0); -} - -- (void)setFilter:(NSString *)filter { - if(_filter != filter) { - _filter = filter; - [self updateFilter]; - } -} - -- (void)clearFilter:(id)sender { - self.filter = nil; - [self.filterSearchField setStringValue:@""]; +#pragma mark MPContextBarDelegate +- (void)contextBarDidExitFilter { [[self.entryTable tableColumnWithIdentifier:MPEntryTableParentColumnIdentifier] setHidden:YES]; - [self _hideFilterBar]; MPDocument *document = [[self windowController] document]; - document.selectedGroup = document.selectedGroup; + document.selectedItem = document.selectedGroup; + [self _updateContextBar]; } -- (void)updateFilter { - [self showFilter:nil]; - if(![self hasFilter]) { - return; - } - +- (void)contextBarDidChangeFilter { dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(backgroundQueue, ^{ MPDocument *document = [[self windowController] document]; - if([self hasFilter]) { - NSMutableArray *prediactes = [NSMutableArray arrayWithCapacity:4]; - if([self _shouldFilterTitles]) { - [prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.title CONTAINS[cd] %@", self.filter]]; - } - if([self _shouldFilterUsernames]) { - [prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.username CONTAINS[cd] %@", self.filter]]; - } - if([self _shouldFilterURLs]) { - [prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.url CONTAINS[cd] %@", self.filter]]; - } - if([self _shouldFilterPasswords]) { - [prediactes addObject:[NSPredicate predicateWithFormat:@"SELF.password CONTAINS[cd] %@", self.filter]]; - } - NSPredicate *fullFilter = [NSCompoundPredicate orPredicateWithSubpredicates:prediactes]; + NSArray *predicates = [self.contextBarViewController filterPredicates]; + if(predicates) { + NSPredicate *fullFilter = [NSCompoundPredicate orPredicateWithSubpredicates:predicates]; self.filteredEntries = [[document.root childEntries] filteredArrayUsingPredicate:fullFilter]; } - else { self.filteredEntries = [document.root childEntries]; } @@ -459,65 +349,90 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; [[self.entryTable tableColumnWithIdentifier:MPEntryTableParentColumnIdentifier] setHidden:NO]; }); }); - } -- (void)updateFilterText:(id)sender { - self.filter = [self.filterSearchField stringValue]; +- (void)showFilter:(id)sender { + [self.contextBarViewController showFilter]; + [self _showContextBar]; } -- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector -{ - if(commandSelector == @selector(insertNewline:)) - { - self.filter = [self.filterSearchField stringValue]; +#pragma mark ContextBar +- (void)_showTrashBar { + [self.contextBarViewController showTrash]; + [self _showContextBar]; +} + +- (void)_updateContextBar { + MPDocument *document = [[self windowController] document]; + if(![self.contextBarViewController hasFilter]) { + BOOL showTrash = (document.selectedGroup == document.trash || [document isItemTrashed:document.selectedItem]); + if(showTrash) { + [self _showTrashBar]; + } + else { + [self _hideContextBar]; } - - return NO; -} - - -- (void)_setupFilterBar { - if(!self.filterBar) { - [[NSBundle mainBundle] loadNibNamed:@"FilterBar" owner:self topLevelObjects:nil]; - [self.filterURLButton setTag:MPFilterUrls]; - [self.filterUsernameButton setTag:MPFilterUsernames]; - [self.filterTitleButton setTag:MPFilterTitles]; - [self.filterPasswordButton setTag:MPFilterPasswords]; - [[self.filterLabelTextField cell] setBackgroundStyle:NSBackgroundStyleRaised]; - [self.filterDoneButton setAction:@selector(clearFilter:)]; - [self.filterDoneButton setTarget:nil]; - - [self.filterSearchField setAction:@selector(updateFilterText:)]; - [[self.filterSearchField cell] setSendsSearchStringImmediately:NO]; - /* - [self bind:@"filterMode" - toObject:[NSUserDefaultsController sharedUserDefaultsController] - withKeyPath:[MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyEntrySearchFilterMode] - options:nil]; - */ } } -#pragma mark UI Feedback -- (void)_hideFilterBar { - if(!self.isDisplayingFilterbar) { - return; // nothing to do; +- (void)_showContextBar { + if(_isDisplayingContextBar) { + return; } - self.filterbarTopConstraint.constant = -31; - [[self view] addConstraint:self.tableToTopConstraint]; + _isDisplayingContextBar = YES; + if(![[self.contextBarViewController view] superview]) { + [[self view] addSubview:[self.contextBarViewController view]]; + [self.contextBarViewController updateResponderChain]; + NSView *contextBar = [self.contextBarViewController view]; + NSView *scrollView = [_entryTable enclosingScrollView]; + NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, contextBar); + + /* Pin to the left */ + [[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[contextBar]|" options:0 metrics:nil views:views]]; + /* Pin height and to top of entry table */ + [[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[contextBar(==30)]-0-[scrollView]" options:0 metrics:nil views:views]]; + /* Create the top constraint for the filter bar where we can change the contanst instaed of removing/adding constraints all the time */ + self.contextBarTopConstraint = [NSLayoutConstraint constraintWithItem:contextBar + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:[self view] + attribute:NSLayoutAttributeTop + multiplier:1 + constant:-31]; + } + /* Add the view for the first time */ + [[self view] removeConstraint:self.tableToTopConstraint]; + [[self view] addConstraint:self.contextBarTopConstraint]; + [[self view] layout]; + self.contextBarTopConstraint.constant = 0; [NSAnimationContext runAnimationGroup:^(NSAnimationContext* context) { context.duration = STATUS_BAR_ANIMATION_TIME; context.allowsImplicitAnimation = YES; [self.view layoutSubtreeIfNeeded]; } completionHandler:^{ - self.isDisplayingFilterbar = NO; - [self.filterSearchField setEnabled:NO]; - }] ; + [self.contextBarViewController enable]; + }]; } +- (void)_hideContextBar { + if(!_isDisplayingContextBar) { + return; // nothing to do; + } + self.contextBarTopConstraint.constant = -31; + [[self view] addConstraint:self.tableToTopConstraint]; + [self.contextBarViewController disable]; + + [NSAnimationContext runAnimationGroup:^(NSAnimationContext* context) { + context.duration = STATUS_BAR_ANIMATION_TIME; + context.allowsImplicitAnimation = YES; + [self.view layoutSubtreeIfNeeded]; + } completionHandler:^{ + _isDisplayingContextBar = NO; + }]; +} +#pragma mark Copy/Paste Overlays - (void)_copyToPasteboard:(NSString *)data overlayInfo:(MPOVerlayInfoType)overlayInfoType name:(NSString *)name{ if(data) { [[MPPasteBoardController defaultController] copyObjects:@[ data ]]; @@ -548,56 +463,6 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; [[MPOverlayWindowController sharedController] displayOverlayImage:infoImage label:infoText atView:self.view]; } -- (void)_showTrashBar { - if([self hasFilter]) { - [self clearFilter:nil]; - } - if(!self.trashBar) { - [self _setupTrashBar]; - } - NSView *scrollView = [_entryTable enclosingScrollView]; - NSDictionary *views = NSDictionaryOfVariableBindings(scrollView, _trashBar); - [[self view] layout]; - [[self view] removeConstraint:self.tableToTopConstraint]; - [[self view] addSubview:self.trashBar]; - [[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_trashBar]|" options:0 metrics:nil views:views]]; - [[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_trashBar(==30)]-0-[scrollView]" options:0 metrics:nil views:views]]; - - [NSAnimationContext runAnimationGroup:^(NSAnimationContext* context) { - context.duration = STATUS_BAR_ANIMATION_TIME; - context.allowsImplicitAnimation = YES; - [[self view] layoutSubtreeIfNeeded]; - } completionHandler:nil] ; - - - //[[self view] layoutSubtreeIfNeeded]; - -} - -- (void)_hideTrashBar { - if(![self.trashBar superview]) { - return; // Trahsbar is not visible - } - - [self.trashBar removeFromSuperview]; - [[self view] addConstraint:self.tableToTopConstraint]; - [[self view] layoutSubtreeIfNeeded]; -} - -- (void)_setupTrashBar { - /* Load the bundle */ - [[NSBundle mainBundle] loadNibNamed:@"TrashBar" owner:self topLevelObjects:nil]; - NSArray *activeColors = @[ - [NSColor colorWithCalibratedWhite:0.2 alpha:1], - [NSColor colorWithCalibratedWhite:0.4 alpha:1] - ]; - NSArray *inactiveColors = @[ [NSColor colorWithCalibratedWhite:0.3 alpha:1], - [NSColor colorWithCalibratedWhite:0.6 alpha:1] - ]; - self.trashBar.activeGradient = [[NSGradient alloc] initWithColors:activeColors]; - self.trashBar.inactiveGradient = [[NSGradient alloc] initWithColors:inactiveColors]; -} - #pragma mark Validation - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { MPDocument *document = [[self windowController] document]; @@ -609,7 +474,6 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; } #pragma mark ContextMenu - - (void)_setupEntryMenu { NSMenu *menu = [[NSMenu alloc] init]; @@ -711,35 +575,19 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; } } -- (void)deleteNode:(id)sender { +- (IBAction)enterHistoryBrowser:(id)sender { + +} + +- (void)delete:(id)sender { KPKEntry *entry =[self _clickedOrSelectedEntry]; + if(!entry) { + return; + } MPDocument *document = [[self windowController] document]; [document deleteEntry:entry]; } -//- (void)toggleHeader:(id)sender { -// // -//} - -- (IBAction)_toggleFilterSpace:(id)sender { - if(![sender isKindOfClass:[NSButton class]]) { - return; // Wrong sender - } - NSButton *button = sender; - MPFilterModeType toggledMode = [button tag]; - switch ([button state]) { - case NSOnState: - self.filterMode |= toggledMode; - break; - - case NSOffState: - self.filterMode ^= toggledMode; - break; - - default: - break; - } -} - (void)_columnDoubleClick:(id)sender { if(0 == [[self.entryArrayController arrangedObjects] count]) { @@ -766,30 +614,4 @@ NSString *const _MPTAbleSecurCellView = @"PasswordCell"; // TODO: Add more actions for new columns } -- (void)setFilterMode:(MPFilterModeType)newFilterMode { - if(_filterMode != newFilterMode) { - if(newFilterMode == MPFilterNone) { - newFilterMode = MPFilterTitles; - } - _filterMode = newFilterMode; - [self updateFilter]; - } -} - -- (BOOL)_shouldFilterTitles { - return (MPFilterNone != (self.filterMode & MPFilterTitles)); -} - -- (BOOL)_shouldFilterURLs { - return (MPFilterNone != (self.filterMode & MPFilterUrls)); -} - -- (BOOL)_shouldFilterUsernames { - return (MPFilterNone != (self.filterMode & MPFilterUsernames)); -} - -- (BOOL)_shouldFilterPasswords { - return (MPFilterNone != (self.filterMode & MPFilterPasswords)); -} - @end diff --git a/MacPass/MPGroupInspectorViewController.m b/MacPass/MPGroupInspectorViewController.m index bf9aa1d4..6287056a 100644 --- a/MacPass/MPGroupInspectorViewController.m +++ b/MacPass/MPGroupInspectorViewController.m @@ -53,7 +53,7 @@ views:views]]; [[self view] layoutSubtreeIfNeeded]; - copyAction copyBlock = ^void(NSTextField *textField) { + void(^copyBlock)(NSTextField *textField) = ^void(NSTextField *textField) { [[MPPasteBoardController defaultController] copyObjects:@[ textField.stringValue ]]; }; diff --git a/MacPass/MPInspectorViewController.m b/MacPass/MPInspectorViewController.m index 3217b6aa..9e50fcc9 100644 --- a/MacPass/MPInspectorViewController.m +++ b/MacPass/MPInspectorViewController.m @@ -27,7 +27,7 @@ typedef NS_ENUM(NSUInteger, MPContentTab) { MPEntryTab, MPGroupTab, - MPEmptyTab + MPEmptyTab, }; @interface MPInspectorViewController () { diff --git a/MacPass/MPOutlineDataSource.m b/MacPass/MPOutlineDataSource.m index f43001c7..1237da2c 100644 --- a/MacPass/MPOutlineDataSource.m +++ b/MacPass/MPOutlineDataSource.m @@ -27,9 +27,6 @@ #import "KPKGroup.h" #import "KPKEntry.h" #import "KPKUTIs.h" -#import "KPKEntry+TemplateCopy.h" -#import "KPKGroup+TemplateCopy.h" - #import "NSUUID+KeePassKit.h" @@ -146,11 +143,7 @@ KPKGroup *targetGroup = (KPKGroup *)targetItem; if(draggedGroup) { if(copyItem || (nil == self.localDraggedGroup) ) { - /* Add Copy to title */ - NSString *copyTemplate = NSLocalizedString(@"%@_COPY", ""); - /* If we copy, we need to update the uuid */ - draggedGroup.name = [NSString stringWithFormat:copyTemplate, draggedGroup.name]; - draggedGroup.uuid = [NSUUID UUID]; + draggedGroup = [draggedGroup copyWithName:nil options:0]; [targetGroup addGroup:draggedGroup atIndex:index]; [targetGroup.undoManager setActionName:NSLocalizedString(@"COPY_GROUP", "")]; return YES; @@ -166,10 +159,7 @@ } else if(draggedEntry) { if(copyItem || (nil == self.localDraggedEntry)) { - /* if we copy, we need to update the uuid */ - NSString *copyTemplate = NSLocalizedString(@"%@_COPY", ""); - draggedEntry.title = [NSString stringWithFormat:copyTemplate, draggedEntry.title]; - draggedEntry.uuid = [NSUUID UUID]; + draggedEntry = [draggedEntry copyWithTitle:nil options:0]; [targetGroup addEntry:draggedEntry atIndex:index]; [targetGroup.undoManager setActionName:NSLocalizedString(@"COPY_ENTRY", "")]; return YES; diff --git a/MacPass/MPOutlineViewController.h b/MacPass/MPOutlineViewController.h index 2db6eb9d..3d767782 100644 --- a/MacPass/MPOutlineViewController.h +++ b/MacPass/MPOutlineViewController.h @@ -25,7 +25,6 @@ APPKIT_EXTERN NSString *const MPOutlineViewDidChangeGroupSelection; - (void)createGroup:(id)sender; - (void)createEntry:(id)sender; -- (void)deleteNode:(id)sender; /** * Retrieves the current item for the current mouse location * @return Item under mouse. If the mouse isn't inside the view, nil is returned diff --git a/MacPass/MPOutlineViewController.m b/MacPass/MPOutlineViewController.m index 1b8d06e8..460e1f98 100644 --- a/MacPass/MPOutlineViewController.m +++ b/MacPass/MPOutlineViewController.m @@ -180,7 +180,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell"; [document createEntry:[self _clickedOrSelectedGroup]]; } -- (void)deleteNode:(id)sender { +- (void)delete:(id)sender { [[[self windowController] document] deleteGroup:[self _clickedOrSelectedGroup]]; } diff --git a/MacPass/TrashBar.xib b/MacPass/TrashBar.xib deleted file mode 100644 index eb742c7c..00000000 --- a/MacPass/TrashBar.xib +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MacPass/en.lproj/Localizable.strings b/MacPass/en.lproj/Localizable.strings index cb8c5be7..e01e872a 100644 Binary files a/MacPass/en.lproj/Localizable.strings and b/MacPass/en.lproj/Localizable.strings differ