mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-14 11:42:30 +00:00
240 lines
8.3 KiB
Objective-C
240 lines
8.3 KiB
Objective-C
//
|
|
// MPInspectorTabViewController.m
|
|
// MacPass
|
|
//
|
|
// Created by Michael Starke on 05.03.13.
|
|
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
//
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
#import "MPInspectorViewController.h"
|
|
#import "MPDatePickingViewController.h"
|
|
#import "MPDocument.h"
|
|
#import "MPEntryInspectorViewController.h"
|
|
#import "MPGroupInspectorViewController.h"
|
|
#import "MPIconHelper.h"
|
|
#import "MPIconSelectViewController.h"
|
|
#import "MPIconImageView.h"
|
|
#import "MPNotifications.h"
|
|
#import "MPPluginDataViewController.h"
|
|
#import "MPPasteBoardController.h"
|
|
|
|
#import "KeePassKit/KeePassKit.h"
|
|
|
|
#import "KPKNode+IconImage.h"
|
|
|
|
typedef NS_ENUM(NSUInteger, MPContentTab) {
|
|
MPEntryTab,
|
|
MPGroupTab,
|
|
MPEmptyTab,
|
|
};
|
|
|
|
@interface MPInspectorViewController ()
|
|
|
|
@property (strong) MPEntryInspectorViewController *entryViewController;
|
|
@property (strong) MPGroupInspectorViewController *groupViewController;
|
|
|
|
@property (strong) NSPopover *popover;
|
|
@property (copy) NSString *expiryDateText;
|
|
|
|
@property (nonatomic, assign) NSUInteger activeTab;
|
|
@property (weak) IBOutlet NSTabView *tabView;
|
|
@property (weak) IBOutlet NSSplitView *splitView;
|
|
@property (unsafe_unretained) IBOutlet HNHUITextView *notesTextView;
|
|
|
|
@property BOOL didPushHistory;
|
|
|
|
@end
|
|
|
|
@implementation MPInspectorViewController
|
|
|
|
- (NSString *)nibName {
|
|
return @"InspectorView";
|
|
}
|
|
|
|
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
|
|
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
|
if (self) {
|
|
self.activeTab = MPEmptyTab;
|
|
self.entryViewController = [[MPEntryInspectorViewController alloc] init];
|
|
self.groupViewController = [[MPGroupInspectorViewController alloc] init];
|
|
self.didPushHistory = NO;
|
|
/* subviewcontrollers will notify us about a change so we can handle the history pushing */
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
}
|
|
|
|
- (NSResponder *)reconmendedFirstResponder {
|
|
return self.view;
|
|
}
|
|
|
|
- (void)awakeFromNib {
|
|
self.noSelectionInfo.cell.backgroundStyle = NSBackgroundStyleRaised;
|
|
self.itemImageView.cell.backgroundStyle = NSBackgroundStyleRaised;
|
|
[self.tabView bind:NSSelectedIndexBinding toObject:self withKeyPath:NSStringFromSelector(@selector(activeTab)) options:nil];
|
|
|
|
NSView *entryView = self.entryViewController.view;
|
|
NSView *groupView = self.groupViewController.view;
|
|
|
|
|
|
NSTabViewItem *entryTabItem = [self.tabView tabViewItemAtIndex:MPEntryTab];
|
|
NSView *entryTabView = entryTabItem.view;
|
|
[entryTabView addSubview:entryView];
|
|
NSDictionary *views = NSDictionaryOfVariableBindings(entryView, groupView);
|
|
[entryTabView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[entryView]|" options:0 metrics:nil views:views]];
|
|
[entryTabView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[entryView]|" options:0 metrics:nil views:views]];
|
|
entryTabItem.initialFirstResponder = entryTabView;
|
|
|
|
NSTabViewItem *groupTabItem = [self.tabView tabViewItemAtIndex:MPGroupTab];
|
|
NSView *groupTabView = groupTabItem.view;
|
|
[groupTabView addSubview:groupView];
|
|
[groupTabView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[groupView]|" options:0 metrics:nil views:views]];
|
|
[groupTabView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[groupView]|" options:0 metrics:nil views:views]];
|
|
groupTabItem.initialFirstResponder = groupView;
|
|
|
|
[self.view layout];}
|
|
|
|
- (void)registerNotificationsForDocument:(MPDocument *)document {
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(_didChangeCurrentItem:)
|
|
name:MPDocumentCurrentItemChangedNotification
|
|
object:document];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(_willChangeModelProperty:)
|
|
name:MPDocumentWillChangeModelPropertyNotification
|
|
object:document];
|
|
|
|
self.entryViewController.observer = document;
|
|
self.itemImageView.modelChangeObserver = document;
|
|
self.observer = document;
|
|
|
|
[self.entryViewController registerNotificationsForDocument:document];
|
|
[self.groupViewController registerNotificationsForDocument:document];
|
|
}
|
|
|
|
#pragma mark - Properties
|
|
- (void)setActiveTab:(NSUInteger)activeTab {
|
|
if(_activeTab != activeTab) {
|
|
_activeTab = activeTab;
|
|
}
|
|
}
|
|
|
|
#pragma mark - TextViewDelegate
|
|
- (BOOL)textView:(NSTextView *)textView performAction:(SEL)action {
|
|
if(action == @selector(copy:)) {
|
|
MPPasteboardOverlayInfoType info = MPPasteboardOverlayInfoCustom;
|
|
NSMutableString *selectedString = [[NSMutableString alloc] initWithCapacity:MAX(1,textView.string.length)];
|
|
NSString *string = textView.string;
|
|
for(NSValue *rangeValue in textView.selectedRanges) {
|
|
if(rangeValue.rangeValue.length != 0) {
|
|
[selectedString appendString:[string substringWithRange:rangeValue.rangeValue]];
|
|
}
|
|
}
|
|
NSString *name = @"";
|
|
if(selectedString.length == 0) {
|
|
return YES;
|
|
}
|
|
if(textView == self.notesTextView) {
|
|
name = NSLocalizedString(@"NOTES", "Displayed name when notes or part of notes was copied");
|
|
}
|
|
[[MPPasteBoardController defaultController] copyObjects:@[selectedString] overlayInfo:info name:name atView:self.view];
|
|
return NO;
|
|
}
|
|
return YES;
|
|
}
|
|
#pragma mark - Popup
|
|
- (IBAction)pickIcon:(id)sender {
|
|
NSAssert([sender isKindOfClass:NSView.class], @"");
|
|
[self _popupViewController:[[MPIconSelectViewController alloc] init] atView:sender];
|
|
}
|
|
|
|
- (IBAction)pickExpiryDate:(id)sender {
|
|
NSAssert([sender isKindOfClass:NSView.class], @"");
|
|
[self _popupViewController:[[MPDatePickingViewController alloc] init] atView:sender];
|
|
}
|
|
|
|
- (IBAction)showPluginData:(id)sender {
|
|
NSAssert([sender isKindOfClass:NSView.class], @"");
|
|
[self _popupViewController:[[MPPluginDataViewController alloc] init] atView:sender];
|
|
}
|
|
|
|
- (void)_popupViewController:(MPViewController *)vc atView:(NSView *)view {
|
|
if(self.popover) {
|
|
return; // Popover still active, abort
|
|
}
|
|
self.popover = [[NSPopover alloc] init];
|
|
self.popover.delegate = self;
|
|
self.popover.behavior = NSPopoverBehaviorTransient;
|
|
vc.representedObject = self.representedObject;
|
|
vc.observer = self.windowController.document;
|
|
self.popover.contentViewController = vc;
|
|
[self.popover showRelativeToRect:NSZeroRect ofView:view preferredEdge:NSMinYEdge];
|
|
}
|
|
|
|
|
|
#pragma mark - NSPopover Delegate
|
|
|
|
- (void)popoverDidClose:(NSNotification *)notification {
|
|
/* clear out the popover */
|
|
self.popover = nil;
|
|
}
|
|
|
|
#pragma mark - MPDocument Notifications
|
|
- (void)_willChangeModelProperty:(NSNotification *)notification {
|
|
/* TODO use uuids for pushed item? */
|
|
if(self.didPushHistory) {
|
|
return;
|
|
}
|
|
KPKEntry *entry = [self.representedObject asEntry];
|
|
if(entry) {
|
|
[entry pushHistory];
|
|
self.didPushHistory = YES;
|
|
}
|
|
}
|
|
|
|
- (void)_didChangeCurrentItem:(NSNotification *)notification {
|
|
MPDocument *document = notification.object;
|
|
KPKNode *node = document.selectedNodes.count == 1 ? document.selectedNodes.firstObject : nil;
|
|
if(node.asGroup) {
|
|
self.activeTab = MPGroupTab;
|
|
}
|
|
else if(node.asEntry) {
|
|
self.activeTab = MPEntryTab;
|
|
}
|
|
else {
|
|
self.activeTab = MPEmptyTab;
|
|
}
|
|
self.didPushHistory = NO;
|
|
|
|
/* manually commit editing on any active editors */
|
|
[self commitEditing];
|
|
[self.entryViewController commitEditing];
|
|
[self.groupViewController commitEditing];
|
|
|
|
self.representedObject = node;
|
|
self.itemImageView.node = node;
|
|
self.entryViewController.representedObject = node.asEntry;
|
|
self.groupViewController.representedObject = node.asGroup;
|
|
|
|
}
|
|
|
|
@end
|