Started support for file attachments

This commit is contained in:
michael starke
2013-06-16 00:57:44 +02:00
parent 091bb384fe
commit cbbf55e0c5
7 changed files with 978 additions and 87 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -133,10 +133,6 @@ NSString *const _toggleFilterUsernameButton = @"SearchUsername";
NSTableColumn *passwordColumn = [self.entryTable tableColumns][3]; NSTableColumn *passwordColumn = [self.entryTable tableColumns][3];
NSTableColumn *urlColumn = [self.entryTable tableColumns][4]; NSTableColumn *urlColumn = [self.entryTable tableColumns][4];
for(NSTableColumn *column in [self.entryTable tableColumns]) {
[column setHeaderCell:[[HNHTableHeaderCell alloc] init]];
}
[parentColumn setIdentifier:MPEntryTableParentColumnIdentifier]; [parentColumn setIdentifier:MPEntryTableParentColumnIdentifier];
[titleColumn setIdentifier:MPEntryTableTitleColumnIdentifier]; [titleColumn setIdentifier:MPEntryTableTitleColumnIdentifier];

View File

@@ -14,7 +14,7 @@
@class HNHGradientView; @class HNHGradientView;
@class MPDocumentWindowController; @class MPDocumentWindowController;
@interface MPInspectorViewController : MPViewController @interface MPInspectorViewController : MPViewController <NSTableViewDelegate>
@property (assign) IBOutlet MPPopupImageView *itemImageView; @property (assign) IBOutlet MPPopupImageView *itemImageView;
@property (assign) IBOutlet NSTextField *itemNameTextfield; @property (assign) IBOutlet NSTextField *itemNameTextfield;
@@ -24,7 +24,10 @@
@property (assign) IBOutlet NSTextField *URLTextField; @property (assign) IBOutlet NSTextField *URLTextField;
@property (assign) IBOutlet NSTextField *passwordTextField; @property (assign) IBOutlet NSTextField *passwordTextField;
@property (assign) IBOutlet NSTextField *titleOrNameLabel; @property (assign) IBOutlet NSTextField *titleOrNameLabel;
@property (assign) IBOutlet NSTextField *notesTextField;
@property (assign) IBOutlet HNHGradientView *bottomBar; @property (assign) IBOutlet HNHGradientView *bottomBar;
@property (assign) IBOutlet NSTextField *infoTextField;
@property (assign) IBOutlet NSTableView *attachmentTableView;
- (void)closeActivePopup:(id)sender; - (void)closeActivePopup:(id)sender;
/* Seperate call to ensure alle registered objects are in place */ /* Seperate call to ensure alle registered objects are in place */

View File

@@ -18,6 +18,7 @@
#import "MPOutlineViewController.h" #import "MPOutlineViewController.h"
#import "MPOutlineViewDelegate.h" #import "MPOutlineViewDelegate.h"
#import "KdbLib.h" #import "KdbLib.h"
#import "Kdb4Node.h"
#import "KdbGroup+Undo.h" #import "KdbGroup+Undo.h"
#import "KdbEntry+Undo.h" #import "KdbEntry+Undo.h"
#import "HNHGradientView.h" #import "HNHGradientView.h"
@@ -32,6 +33,9 @@
@property (assign, nonatomic) BOOL showsEntry; @property (assign, nonatomic) BOOL showsEntry;
@property (retain) NSPopover *activePopover; @property (retain) NSPopover *activePopover;
@property (assign) IBOutlet NSButton *generatePasswordButton; @property (assign) IBOutlet NSButton *generatePasswordButton;
@property (nonatomic, assign) NSDate *modificationDate;
@property (nonatomic, assign) NSDate *creationDate;
@property (retain, nonatomic) NSArrayController *attachmentController;
@end @end
@@ -47,21 +51,27 @@
_selectedEntry = nil; _selectedEntry = nil;
_selectedGroup = nil; _selectedGroup = nil;
_showsEntry = NO; _showsEntry = NO;
_attachmentController = [[NSArrayController alloc] init];
} }
return self; return self;
} }
- (void)dealloc { - (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self]; [[NSNotificationCenter defaultCenter] removeObserver:self];
[_attachmentController release];
[_activePopover release]; [_activePopover release];
[super dealloc]; [super dealloc];
} }
- (void)didLoadView { - (void)didLoadView {
[[self.itemImageView cell] setBackgroundStyle:NSBackgroundStyleRaised]; [[self.itemImageView cell] setBackgroundStyle:NSBackgroundStyleRaised];
[self.itemImageView setTarget:self]; [self.itemImageView setTarget:self];
[_bottomBar setBorderType:HNHBorderTop]; [_bottomBar setBorderType:HNHBorderTop];
[[_infoTextField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[_attachmentTableView setDelegate:self];
[_attachmentTableView bind:NSContentBinding toObject:_attachmentController withKeyPath:@"arrangedObjects" options:nil];
[_attachmentTableView setHidden:YES];
[self _clearContent]; [self _clearContent];
} }
@@ -79,6 +89,28 @@
object:windowController.outlineViewController.outlineDelegate]; object:windowController.outlineViewController.outlineDelegate];
} }
- (void)_updateInfoString {
NSDate *modificationDate;
NSDate *creationDate;
if(_showsEntry) {
modificationDate = self.selectedEntry.lastModificationTime;
creationDate = self.selectedEntry.creationTime;
}
else {
modificationDate = self.selectedGroup.lastModificationTime;
creationDate = self.selectedGroup.creationTime;
}
[self.infoTextField setStringValue:[NSString stringWithFormat:@"created: %@ modified: %@", creationDate, modificationDate]];
}
- (void)setModificationDate:(NSDate *)modificationDate {
[self _updateInfoString];
}
- (void)setCreationDate:(NSDate *)creationDate {
[self _updateInfoString];
}
- (void)_updateContent { - (void)_updateContent {
if(self.showsEntry && self.selectedEntry) { if(self.showsEntry && self.selectedEntry) {
[self _showEntry]; [self _showEntry];
@@ -89,9 +121,14 @@
else { else {
[self _clearContent]; [self _clearContent];
} }
[self _updateAttachments];
} }
- (void)_showEntry { - (void)_showEntry {
[self bind:@"modificationDate" toObject:self.selectedEntry withKeyPath:@"lastModificationTime" options:nil];
[self bind:@"creationDate" toObject:self.selectedEntry withKeyPath:@"creationTime" options:nil];
[self.itemNameTextfield bind:NSValueBinding toObject:self.selectedEntry withKeyPath:MPEntryTitleUndoableKey options:nil]; [self.itemNameTextfield bind:NSValueBinding toObject:self.selectedEntry withKeyPath:MPEntryTitleUndoableKey options:nil];
[self.itemImageView setImage:[MPIconHelper icon:(MPIconType)self.selectedEntry.image ]]; [self.itemImageView setImage:[MPIconHelper icon:(MPIconType)self.selectedEntry.image ]];
[self.passwordTextField bind:NSValueBinding toObject:self.selectedEntry withKeyPath:MPEntryPasswordUndoableKey options:nil]; [self.passwordTextField bind:NSValueBinding toObject:self.selectedEntry withKeyPath:MPEntryPasswordUndoableKey options:nil];
@@ -99,11 +136,15 @@
[self.titleOrNameLabel setStringValue:NSLocalizedString(@"TITLE",@"")]; [self.titleOrNameLabel setStringValue:NSLocalizedString(@"TITLE",@"")];
[self.titleTextField bind:NSValueBinding toObject:self.selectedEntry withKeyPath:MPEntryTitleUndoableKey options:nil]; [self.titleTextField bind:NSValueBinding toObject:self.selectedEntry withKeyPath:MPEntryTitleUndoableKey options:nil];
[self.URLTextField bind:NSValueBinding toObject:self.selectedEntry withKeyPath:MPEntryUrlUndoableKey options:nil]; [self.URLTextField bind:NSValueBinding toObject:self.selectedEntry withKeyPath:MPEntryUrlUndoableKey options:nil];
[self.notesTextField bind:NSValueBinding toObject:self.selectedEntry withKeyPath:MPEntryNotesUndoableKey options:nil];
[self _setInputEnabled:YES]; [self _setInputEnabled:YES];
} }
- (void)_showGroup { - (void)_showGroup {
[self bind:@"modificationDate" toObject:self.selectedGroup withKeyPath:@"lastModificationTime" options:nil];
[self bind:@"creationDate" toObject:self.selectedGroup withKeyPath:@"creationTime" options:nil];
[self.itemNameTextfield bind:NSValueBinding toObject:self.selectedGroup withKeyPath:MPGroupNameUndoableKey options:nil]; [self.itemNameTextfield bind:NSValueBinding toObject:self.selectedGroup withKeyPath:MPGroupNameUndoableKey options:nil];
[self.itemImageView setImage:[MPIconHelper icon:(MPIconType)self.selectedGroup.image ]]; [self.itemImageView setImage:[MPIconHelper icon:(MPIconType)self.selectedGroup.image ]];
[self.titleOrNameLabel setStringValue:NSLocalizedString(@"NAME",@"")]; [self.titleOrNameLabel setStringValue:NSLocalizedString(@"NAME",@"")];
@@ -118,6 +159,7 @@
[self.passwordTextField setStringValue:@""]; [self.passwordTextField setStringValue:@""];
[self.usernameTextField setStringValue:@""]; [self.usernameTextField setStringValue:@""];
[self.URLTextField setStringValue:@""]; [self.URLTextField setStringValue:@""];
[self.notesTextField setStringValue:@""];
[self _setInputEnabled:YES]; [self _setInputEnabled:YES];
} }
@@ -131,6 +173,7 @@
[self.usernameTextField unbind:NSValueBinding]; [self.usernameTextField unbind:NSValueBinding];
[self.titleTextField unbind:NSValueBinding]; [self.titleTextField unbind:NSValueBinding];
[self.URLTextField unbind:NSValueBinding]; [self.URLTextField unbind:NSValueBinding];
[self.notesTextField unbind:NSValueBinding];
[self.itemNameTextfield setStringValue:NSLocalizedString(@"INSPECTOR_NO_SELECTION", @"No item selected in inspector")]; [self.itemNameTextfield setStringValue:NSLocalizedString(@"INSPECTOR_NO_SELECTION", @"No item selected in inspector")];
[self.itemImageView setImage:[NSImage imageNamed:NSImageNameActionTemplate]]; [self.itemImageView setImage:[NSImage imageNamed:NSImageNameActionTemplate]];
@@ -140,6 +183,7 @@
[self.usernameTextField setStringValue:@""]; [self.usernameTextField setStringValue:@""];
[self.titleTextField setStringValue:@""]; [self.titleTextField setStringValue:@""];
[self.URLTextField setStringValue:@""]; [self.URLTextField setStringValue:@""];
[self.notesTextField setStringValue:@""];
} }
@@ -156,9 +200,23 @@
[self.usernameTextField setEnabled:enabled]; [self.usernameTextField setEnabled:enabled];
[self.URLTextField setEnabled:enabled]; [self.URLTextField setEnabled:enabled];
[self.generatePasswordButton setEnabled:enabled]; [self.generatePasswordButton setEnabled:enabled];
[self.notesTextField setEditable:enabled];
} }
- (void)_updateAttachments {
if(self.selectedEntry && self.showsEntry) {
if([self.selectedEntry isKindOfClass:[Kdb4Entry class]]) {
[self.attachmentController bind:NSContentArrayBinding toObject:self.selectedEntry withKeyPath:@"binaries" options:nil];
}
}
else {
[self.attachmentController unbind:NSContentArrayBinding];
[self.attachmentController setContent:nil];
}
[self.attachmentTableView setHidden:(0 == [[self.attachmentController arrangedObjects] count])];
}
#pragma mark Actions #pragma mark Actions
- (void)_showImagePopup:(id)sender { - (void)_showImagePopup:(id)sender {
@@ -212,4 +270,15 @@
[self _updateContent]; [self _updateContent];
} }
} }
#pragma mark NSTableViewDelegate
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
NSTableCellView *tableCellView = [tableView makeViewWithIdentifier:[tableColumn identifier] owner:tableView];
BinaryRef *binaryRef = [self.attachmentController arrangedObjects][row];
[tableCellView.textField bind:NSValueBinding toObject:binaryRef withKeyPath:@"key" options:nil];
[[tableCellView.textField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[[tableCellView.imageView cell] setBackgroundStyle:NSBackgroundStyleLight];
return tableCellView;
}
@end @end

View File

@@ -80,6 +80,7 @@
MPDocument *document = [[[outlineView window] windowController] document]; MPDocument *document = [[[outlineView window] windowController] document];
KdbGroup *rootGroup = [document root]; KdbGroup *rootGroup = [document root];
KdbEntry *draggedEntry = [rootGroup entryForUUID:uuid]; KdbEntry *draggedEntry = [rootGroup entryForUUID:uuid];
[uuid release];
if(draggedEntry) { if(draggedEntry) {
if(draggedEntry.parent != target && index == NSOutlineViewDropOnItemIndex) { if(draggedEntry.parent != target && index == NSOutlineViewDropOnItemIndex) {
[document moveEntry:draggedEntry toGroup:target index:index]; [document moveEntry:draggedEntry toGroup:target index:index];

View File

@@ -44,28 +44,37 @@
if(self.showOverlay && [self isEnabled]) { if(self.showOverlay && [self isEnabled]) {
[[NSGraphicsContext currentContext] saveGraphicsState]; [[NSGraphicsContext currentContext] saveGraphicsState];
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:[self bounds] xRadius:4 yRadius:4];
[[NSColor colorWithCalibratedWhite:0 alpha:0.2] set];
[[NSBezierPath bezierPathWithRoundedRect:[self bounds] xRadius:4 yRadius:4] fill];
NSShadow *shadow = [[NSShadow alloc] init]; NSShadow *shadow = [[NSShadow alloc] init];
[shadow setShadowBlurRadius:2]; [shadow setShadowBlurRadius:6];
[shadow setShadowOffset:NSMakeSize(0, -1)]; [shadow setShadowOffset:NSMakeSize(0, 0)];
[shadow setShadowColor:[NSColor colorWithCalibratedWhite:0 alpha:0.5]]; [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.2 alpha:1]];
[shadow set]; [shadow set];
NSBezierPath *triangle = [NSBezierPath bezierPath]; [path addClip];
NSPoint left = NSMakePoint([self bounds].size.width - MPTRIANGLE_OFFSET - MPTRIANGLE_WIDTH, MPTRIANGLE_OFFSET + MPTRIANGLE_HEIGHT); [[NSColor colorWithCalibratedWhite:1 alpha:0.2] setFill];
NSPoint right = NSMakePoint(left.x + MPTRIANGLE_WIDTH, left.y); [path fill];
NSPoint bottom = NSMakePoint(left.x + 0.5 * MPTRIANGLE_WIDTH, MPTRIANGLE_OFFSET); NSBezierPath *strokePath = [NSBezierPath bezierPathWithRoundedRect:NSInsetRect([self bounds], -3, -3) xRadius:4 yRadius:4];
[strokePath setLineWidth:6];
[triangle moveToPoint:left]; [strokePath stroke];
[triangle lineToPoint:right]; // [shadow setShadowBlurRadius:2];
[triangle lineToPoint:bottom]; // [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0 alpha:0.5]];
[triangle closePath]; // [shadow setShadowOffset:NSMakeSize(0, -1)];
// [shadow set];
[[NSColor whiteColor] set]; //
[triangle fill]; // NSBezierPath *triangle = [NSBezierPath bezierPath];
// NSPoint left = NSMakePoint([self bounds].size.width - MPTRIANGLE_OFFSET - MPTRIANGLE_WIDTH, MPTRIANGLE_OFFSET + MPTRIANGLE_HEIGHT);
// NSPoint right = NSMakePoint(left.x + MPTRIANGLE_WIDTH, left.y);
// NSPoint bottom = NSMakePoint(left.x + 0.5 * MPTRIANGLE_WIDTH, MPTRIANGLE_OFFSET);
//
// [triangle moveToPoint:left];
// [triangle lineToPoint:right];
// [triangle lineToPoint:bottom];
// [triangle closePath];
//
// [[NSColor whiteColor] set];
// [triangle fill];
[shadow release]; [shadow release];
[[NSGraphicsContext currentContext] restoreGraphicsState]; [[NSGraphicsContext currentContext] restoreGraphicsState];

View File

@@ -48,7 +48,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>219</string> <string>322</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string> <string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>