fixed #155 added Quicklook like preview for attachments

This commit is contained in:
michael starke
2014-03-19 22:57:06 +01:00
parent c460b2187a
commit 03d13e5b2f
27 changed files with 408 additions and 155 deletions

View File

@@ -73,7 +73,6 @@
4C25D58716CF0FAA00F6806C /* EntryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C25D58616CF0FAA00F6806C /* EntryView.xib */; };
4C2671AD17A7D8FC00F3A645 /* HNHColorWell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C2671AC17A7D8FC00F3A645 /* HNHColorWell.m */; };
4C26C33F18D8C92100CF1A1C /* MPTemporaryFileStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C26C33E18D8C92100CF1A1C /* MPTemporaryFileStorage.m */; };
4C26C34718D8C9C400CF1A1C /* KPKBinary+Quickook.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C26C34618D8C9C400CF1A1C /* KPKBinary+Quickook.m */; };
4C26C34B18D8D5A300CF1A1C /* MPPreviewViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C26C34918D8D5A300CF1A1C /* MPPreviewViewController.m */; };
4C26C34C18D8D5A300CF1A1C /* PreviewView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C26C34A18D8D5A300CF1A1C /* PreviewView.xib */; };
4C2724D71778FF1A00FD8456 /* NSUUID+KeePassKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C2724D61778FF1A00FD8456 /* NSUUID+KeePassKit.m */; };
@@ -205,6 +204,7 @@
4C888C9016EB6C91003D34A1 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4C888C8E16EB6C91003D34A1 /* Localizable.strings */; };
4C888C9316EB6F5E003D34A1 /* MPToolbarItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C888C9216EB6F5E003D34A1 /* MPToolbarItem.m */; };
4C888C9716EB754B003D34A1 /* MPActionHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C888C9616EB754B003D34A1 /* MPActionHelper.m */; };
4C88C66918D9F8D600F43852 /* MPTemporaryFileStorageCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C88C66818D9F8D600F43852 /* MPTemporaryFileStorageCenter.m */; };
4C89F521182F9FDD0069C73C /* NSString+Commands.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C89F520182F9FDD0069C73C /* NSString+Commands.m */; };
4C89F524182FB4740069C73C /* MPAutotypeCommand.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C89F523182FB4740069C73C /* MPAutotypeCommand.m */; };
4C8A173D1790AA41008B5C17 /* NSData+Keyfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C8A173C1790AA41008B5C17 /* NSData+Keyfile.m */; };
@@ -487,8 +487,6 @@
4C2671AC17A7D8FC00F3A645 /* HNHColorWell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HNHColorWell.m; sourceTree = "<group>"; };
4C26C33D18D8C92100CF1A1C /* MPTemporaryFileStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTemporaryFileStorage.h; sourceTree = "<group>"; };
4C26C33E18D8C92100CF1A1C /* MPTemporaryFileStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTemporaryFileStorage.m; sourceTree = "<group>"; };
4C26C34518D8C9C400CF1A1C /* KPKBinary+Quickook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KPKBinary+Quickook.h"; sourceTree = "<group>"; };
4C26C34618D8C9C400CF1A1C /* KPKBinary+Quickook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "KPKBinary+Quickook.m"; sourceTree = "<group>"; };
4C26C34818D8D5A300CF1A1C /* MPPreviewViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPPreviewViewController.h; sourceTree = "<group>"; };
4C26C34918D8D5A300CF1A1C /* MPPreviewViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPPreviewViewController.m; sourceTree = "<group>"; };
4C26C34A18D8D5A300CF1A1C /* PreviewView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PreviewView.xib; sourceTree = "<group>"; };
@@ -718,6 +716,8 @@
4C888C9216EB6F5E003D34A1 /* MPToolbarItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPToolbarItem.m; sourceTree = "<group>"; };
4C888C9516EB754B003D34A1 /* MPActionHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPActionHelper.h; sourceTree = "<group>"; };
4C888C9616EB754B003D34A1 /* MPActionHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPActionHelper.m; sourceTree = "<group>"; };
4C88C66718D9F8D600F43852 /* MPTemporaryFileStorageCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTemporaryFileStorageCenter.h; sourceTree = "<group>"; };
4C88C66818D9F8D600F43852 /* MPTemporaryFileStorageCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTemporaryFileStorageCenter.m; sourceTree = "<group>"; };
4C89F51F182F9FDD0069C73C /* NSString+Commands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Commands.h"; sourceTree = "<group>"; };
4C89F520182F9FDD0069C73C /* NSString+Commands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Commands.m"; sourceTree = "<group>"; };
4C89F522182FB4740069C73C /* MPAutotypeCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAutotypeCommand.h; sourceTree = "<group>"; };
@@ -997,8 +997,6 @@
4CC6DB7917D23719002C6091 /* KPKNode+IconImage.m */,
4CEED1C417D7BD0E007180F1 /* NSError+Messages.h */,
4CEED1C517D7BD0E007180F1 /* NSError+Messages.m */,
4C26C34518D8C9C400CF1A1C /* KPKBinary+Quickook.h */,
4C26C34618D8C9C400CF1A1C /* KPKBinary+Quickook.m */,
);
name = Categories;
sourceTree = "<group>";
@@ -1210,6 +1208,8 @@
4C3C4EAE18D7039300153127 /* MPValueTransformerHelper.m */,
4C26C33D18D8C92100CF1A1C /* MPTemporaryFileStorage.h */,
4C26C33E18D8C92100CF1A1C /* MPTemporaryFileStorage.m */,
4C88C66718D9F8D600F43852 /* MPTemporaryFileStorageCenter.h */,
4C88C66818D9F8D600F43852 /* MPTemporaryFileStorageCenter.m */,
);
name = Helper;
sourceTree = "<group>";
@@ -2217,6 +2217,7 @@
4C245B77176E1E3D0086100E /* DDNumber.m in Sources */,
4C245B78176E1E3D0086100E /* DDRange.m in Sources */,
4C3C4EA618D6FEA100153127 /* TTTJSONTransformer.m in Sources */,
4C88C66918D9F8D600F43852 /* MPTemporaryFileStorageCenter.m in Sources */,
4C245B79176E1E3D0086100E /* HTTPAuthenticationRequest.m in Sources */,
4C245B7A176E1E3D0086100E /* HTTPConnection.m in Sources */,
4C245B7B176E1E3D0086100E /* HTTPMessage.m in Sources */,
@@ -2265,7 +2266,6 @@
4C10412C178CDD44001B5239 /* NSDate+Humanized.m in Sources */,
4CD3ABBA178F71B50073F5C5 /* KPKTree.m in Sources */,
4CD3ABBF178F72610073F5C5 /* KPKEntry.m in Sources */,
4C26C34718D8C9C400CF1A1C /* KPKBinary+Quickook.m in Sources */,
4CD3ABC2178F72720073F5C5 /* KPKGroup.m in Sources */,
4C591B57178F897A0080B16B /* KPKBinary.m in Sources */,
4C0C59F118B17F10009C7B76 /* DDHotKeyUtilities.m in Sources */,

View File

@@ -112,6 +112,11 @@
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="FVA-Cn-g79"/>
<menuItem title="Quicklook" keyEquivalent="y" id="aVO-9F-Lwc">
<connections>
<action selector="toggleQuicklookPreview:" target="-1" id="LeI-cb-9vg"/>
</connections>
</menuItem>
<menuItem title="Lock" keyEquivalent="L" id="1261">
<modifierMask key="keyEquivalentModifierMask" control="YES"/>
<connections>

View File

@@ -168,7 +168,7 @@
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSActionTemplate" id="170"/>
</imageView>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="166">
<rect key="frame" x="41" y="10" width="126" height="17"/>
<rect key="frame" x="41" y="10" width="160" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="171">
<font key="font" metaFont="system"/>
@@ -176,47 +176,44 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="156">
<rect key="frame" x="213" y="8" width="32" height="19"/>
<popUpButton verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="42g-QS-XtW">
<rect key="frame" x="207" y="8" width="38" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="32" id="172"/>
<constraint firstAttribute="width" constant="38" id="2EY-Pv-ic4"/>
</constraints>
<buttonCell key="cell" type="roundRect" bezelStyle="roundedRect" image="NSRemoveTemplate" imagePosition="overlaps" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="173">
<popUpButtonCell key="cell" type="roundRect" bezelStyle="roundedRect" alignment="center" lineBreakMode="truncatingTail" borderStyle="border" imageScaling="proportionallyDown" inset="2" pullsDown="YES" altersStateOfSelectedItem="NO" id="nJc-UT-cas">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="cellTitle"/>
<string key="keyEquivalent" base64-UTF8="YES">
CA
</string>
</buttonCell>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="155">
<rect key="frame" x="173" y="8" width="32" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<constraints>
<constraint firstAttribute="width" constant="32" id="174"/>
</constraints>
<buttonCell key="cell" type="roundRect" bezelStyle="roundedRect" image="26_FileSaveTemplate" imagePosition="only" alignment="center" state="on" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="175">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="cellTitle"/>
</buttonCell>
</button>
<menu key="menu" title="OtherViews" id="sNS-o1-pD7">
<items>
<menuItem hidden="YES" id="lbx-U1-RCe">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Save" id="0ok-MC-QMP"/>
<menuItem title="Delete" id="bke-G2-oEf">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="Quicklook" id="NtM-y3-l4D">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items>
</menu>
</popUpButtonCell>
</popUpButton>
</subviews>
<constraints>
<constraint firstItem="167" firstAttribute="leading" secondItem="141" secondAttribute="leading" constant="3" id="157"/>
<constraint firstItem="167" firstAttribute="centerY" secondItem="166" secondAttribute="centerY" id="158"/>
<constraint firstItem="167" firstAttribute="centerY" secondItem="141" secondAttribute="centerY" id="159"/>
<constraint firstItem="166" firstAttribute="leading" secondItem="167" secondAttribute="trailing" constant="8" symbolic="YES" id="160"/>
<constraint firstItem="155" firstAttribute="baseline" secondItem="156" secondAttribute="baseline" id="161"/>
<constraint firstItem="155" firstAttribute="top" secondItem="166" secondAttribute="top" id="162"/>
<constraint firstItem="155" firstAttribute="leading" secondItem="166" secondAttribute="trailing" constant="8" symbolic="YES" id="163"/>
<constraint firstAttribute="trailing" secondItem="156" secondAttribute="trailing" constant="3" id="164"/>
<constraint firstItem="156" firstAttribute="leading" secondItem="155" secondAttribute="trailing" constant="8" symbolic="YES" id="165"/>
<constraint firstItem="42g-QS-XtW" firstAttribute="centerY" secondItem="166" secondAttribute="centerY" constant="0.5" id="04U-i0-gjS"/>
<constraint firstItem="42g-QS-XtW" firstAttribute="leading" secondItem="166" secondAttribute="trailing" constant="8" id="EEX-YD-llx"/>
<constraint firstAttribute="trailing" secondItem="42g-QS-XtW" secondAttribute="trailing" constant="3" id="vvP-2V-gwi"/>
</constraints>
<connections>
<outlet property="actionButton" destination="42g-QS-XtW" id="IEV-gn-6YI"/>
<outlet property="imageView" destination="167" id="244"/>
<outlet property="removeButton" destination="156" id="247"/>
<outlet property="saveButton" destination="155" id="246"/>
<outlet property="textField" destination="166" id="245"/>
</connections>
</tableCellView>
@@ -880,7 +877,6 @@ CA
</view>
</objects>
<resources>
<image name="26_FileSaveTemplate" width="16" height="16"/>
<image name="NSActionTemplate" width="14" height="14"/>
<image name="NSAddTemplate" width="8" height="8"/>
<image name="NSQuickLookTemplate" width="21" height="16"/>

View File

@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5053" systemVersion="13C64" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1080" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5053"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="MPIntegrationSettingsController">
<connections>
<outlet property="enableGlobalAutotypeCheckbutton" destination="tik-Ar-FJg" id="d2f-69-2BP"/>
<outlet property="enableQuicklookCheckbutton" destination="LNw-5t-TS4" id="NRN-7y-W0e"/>
<outlet property="enableServerCheckbutton" destination="2" id="17"/>
<outlet property="view" destination="1" id="18"/>
</connections>
@@ -15,11 +16,11 @@
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="1">
<rect key="frame" x="0.0" y="0.0" width="400" height="179"/>
<rect key="frame" x="0.0" y="0.0" width="400" height="281"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<box autoresizesSubviews="NO" verticalHuggingPriority="500" title="Keepass HTTP" borderType="line" translatesAutoresizingMaskIntoConstraints="NO" id="KbH-0Q-5Tw">
<rect key="frame" x="17" y="105" width="366" height="54"/>
<rect key="frame" x="17" y="207" width="366" height="54"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<view key="contentView">
<rect key="frame" x="1" y="1" width="364" height="38"/>
@@ -44,7 +45,7 @@
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</box>
<box autoresizesSubviews="NO" verticalHuggingPriority="500" title="Autotype" borderType="line" translatesAutoresizingMaskIntoConstraints="NO" id="P9N-HM-wER">
<rect key="frame" x="17" y="16" width="366" height="85"/>
<rect key="frame" x="17" y="118" width="366" height="85"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<view key="contentView">
<rect key="frame" x="1" y="1" width="364" height="69"/>
@@ -90,16 +91,56 @@
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</box>
<box autoresizesSubviews="NO" verticalHuggingPriority="500" title="Preview" borderType="line" translatesAutoresizingMaskIntoConstraints="NO" id="VVs-b5-cX9">
<rect key="frame" x="17" y="16" width="366" height="98"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<view key="contentView">
<rect key="frame" x="1" y="1" width="364" height="82"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button translatesAutoresizingMaskIntoConstraints="NO" id="LNw-5t-TS4">
<rect key="frame" x="16" y="56" width="183" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Enabel Quicklook Preview" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="ERs-ct-Eyx">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="V6l-R9-hIj">
<rect key="frame" x="16" y="22" width="322" height="28"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" controlSize="small" sendsActionOnEndEditing="YES" title="If enabled attached files will be copied to a tempoary location for preview and deleted after the preview is closed." id="WmI-IB-Aso">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</view>
<constraints>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="V6l-R9-hIj" secondAttribute="trailing" constant="26" id="6va-Ii-axg"/>
<constraint firstAttribute="bottom" secondItem="V6l-R9-hIj" secondAttribute="bottom" constant="19" id="W4Q-ec-J2U"/>
<constraint firstItem="LNw-5t-TS4" firstAttribute="leading" secondItem="VVs-b5-cX9" secondAttribute="leading" constant="16" id="dgd-Gt-Zxu"/>
<constraint firstItem="LNw-5t-TS4" firstAttribute="top" secondItem="VVs-b5-cX9" secondAttribute="top" constant="25" id="obp-WH-C6P"/>
<constraint firstItem="V6l-R9-hIj" firstAttribute="leading" secondItem="VVs-b5-cX9" secondAttribute="leading" constant="16" id="qDK-YA-moR"/>
<constraint firstItem="V6l-R9-hIj" firstAttribute="top" secondItem="LNw-5t-TS4" secondAttribute="bottom" constant="8" id="yiH-zj-kL4"/>
</constraints>
<color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
<color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</box>
</subviews>
<constraints>
<constraint firstAttribute="width" constant="400" id="19"/>
<constraint firstAttribute="trailing" secondItem="KbH-0Q-5Tw" secondAttribute="trailing" constant="20" symbolic="YES" id="0x4-nr-DuM"/>
<constraint firstItem="VVs-b5-cX9" firstAttribute="top" secondItem="P9N-HM-wER" secondAttribute="bottom" constant="8" id="VCX-JW-cBe"/>
<constraint firstItem="KbH-0Q-5Tw" firstAttribute="leading" secondItem="1" secondAttribute="leading" constant="20" symbolic="YES" id="dln-JS-u45"/>
<constraint firstItem="P9N-HM-wER" firstAttribute="leading" secondItem="KbH-0Q-5Tw" secondAttribute="leading" id="iZD-AQ-EeG"/>
<constraint firstItem="VVs-b5-cX9" firstAttribute="trailing" secondItem="P9N-HM-wER" secondAttribute="trailing" id="k9i-4T-WY0"/>
<constraint firstItem="KbH-0Q-5Tw" firstAttribute="top" secondItem="1" secondAttribute="top" constant="20" symbolic="YES" id="mtr-dI-3QM"/>
<constraint firstItem="P9N-HM-wER" firstAttribute="top" secondItem="KbH-0Q-5Tw" secondAttribute="bottom" constant="8" symbolic="YES" id="oFy-uk-HLJ"/>
<constraint firstItem="P9N-HM-wER" firstAttribute="trailing" secondItem="KbH-0Q-5Tw" secondAttribute="trailing" id="sIZ-ZD-A8K"/>
<constraint firstAttribute="bottom" secondItem="P9N-HM-wER" secondAttribute="bottom" constant="20" symbolic="YES" id="tUs-qA-SKq"/>
<constraint firstItem="VVs-b5-cX9" firstAttribute="leading" secondItem="P9N-HM-wER" secondAttribute="leading" id="z4a-9C-78h"/>
<constraint firstAttribute="bottom" secondItem="VVs-b5-cX9" secondAttribute="bottom" constant="20" id="zdK-YX-54I"/>
</constraints>
</customView>
</objects>

View File

@@ -1,15 +0,0 @@
//
// KPKBinary+Quickook.h
// MacPass
//
// Created by Michael Starke on 18/03/14.
// Copyright (c) 2014 HicknHack Software GmbH. All rights reserved.
//
#import "KPKBinary.h"
@interface KPKBinary (Quickook)
- (void)quicklock;
@end

View File

@@ -1,17 +0,0 @@
//
// KPKBinary+Quickook.m
// MacPass
//
// Created by Michael Starke on 18/03/14.
// Copyright (c) 2014 HicknHack Software GmbH. All rights reserved.
//
#import "KPKBinary+Quickook.h"
#import "MPTemporaryFileStorage.h"
@implementation KPKBinary (Quickook)
- (void)quicklock {
}
@end

View File

@@ -26,7 +26,8 @@ typedef NS_ENUM(NSUInteger, MPActionType) {
MPActionDatabaseSettings, // Show the settings for the database
MPActionEditTemplateGroup, // Edit the Template group
MPActionExportXML, // Exporte as XML
MPActionImportXML // Import form XML
MPActionImportXML, // Import form XML
MPActionToggleQuicklook
};
/**
* Helper to retrieve commonly used actions

View File

@@ -30,8 +30,9 @@
@(MPActionEmptyTrash): @"emptyTrash:",
@(MPActionDatabaseSettings): @"showDatabaseSettings:",
@(MPActionEditTemplateGroup): @"editTemplateGroup:",
@(MPActionExportXML): @"exportAsXML",
@(MPActionImportXML): @"importFromXMl",
@(MPActionExportXML): @"exportAsXML:",
@(MPActionImportXML): @"importFromXMl:",
@(MPActionToggleQuicklook): @"toggleQuicklookPreview:",
};
});
return actionDict;

View File

@@ -32,6 +32,8 @@
#import "MPAutotypeDaemon.h"
#import "MPDocumentWindowController.h"
#import "MPTemporaryFileStorageCenter.h"
#import "MPDocument.h"
#import "KPKCompositeKey.h"
@@ -123,6 +125,17 @@ NSString *const MPDidChangeStoredKeyFilesSettings = @"com.hicknhack.macpass.MPDi
}
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
if([[MPTemporaryFileStorageCenter defaultCenter] hasPendingStorages]) {
dispatch_async(dispatch_get_main_queue(), ^{
[[MPTemporaryFileStorageCenter defaultCenter] cleanupStorages];
[sender replyToApplicationShouldTerminate:YES];
});
return NSTerminateLater;
}
return NSTerminateNow;
}
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
_shouldOpenFile = YES;
NSURL *fileURL = [NSURL fileURLWithPath:filename];

View File

@@ -48,13 +48,7 @@
NSTableCellView *view;
if([selectedIndexes containsIndex:row]) {
MPSelectedAttachmentTableCellView *cellView = [tableView makeViewWithIdentifier:@"SelectedCell" owner:tableView];
[cellView.saveButton setTag:row];
[cellView.saveButton setAction:@selector(saveAttachment:)];
[cellView.saveButton setTarget:self.viewController];
[cellView.removeButton setTag:row];
[cellView.removeButton setAction:@selector(removeAttachment:)];
[cellView.removeButton setTarget:nil];
[cellView.removeButton setTarget:self.viewController];
[cellView.actionButton setMenu:[self allocateActionMenu]];
view = cellView;
}
else {
@@ -76,4 +70,25 @@
return view;
}
- (NSMenu *)allocateActionMenu {
NSMenu *menu = [[NSMenu alloc] init];
/* Image for Popup button */
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"" action:NULL keyEquivalent:@""];
[item setImage:[NSImage imageNamed:NSImageNameActionTemplate]];
[menu addItem:item];
/* Quicklook */
[menu addItemWithTitle:NSLocalizedString(@"PREVIEW", "") action:@selector(toggleQuicklookPreview:) keyEquivalent:@""];
/* Save */
item = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"SAVE", "") action:@selector(saveAttachment:) keyEquivalent:@""];
[item setTarget:self.viewController];
[menu addItem:item];
/* Remove */
[menu addItem:[NSMenuItem separatorItem]];
item = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"DELETE", "") action:@selector(removeAttachment:) keyEquivalent:@""];
[item setTarget:self.viewController];
[menu addItem:item];
return menu;
}
@end

View File

@@ -12,7 +12,6 @@
#import <Foundation/Foundation.h>
FOUNDATION_EXPORT NSString *const MPPasteBoardType;
FOUNDATION_EXPORT NSString *const MPErrorDomain;
FOUNDATION_EXPORT NSString *const MPLegacyDocumentUTI;
FOUNDATION_EXPORT NSString *const MPXMLDocumentUTI;

View File

@@ -9,6 +9,5 @@
#import "MPConstants.h"
NSString *const MPPasteBoardType = @"com.hicknhack.macpass.pasteboard";
NSString *const MPErrorDomain = @"com.hicknhack.macpass.error";
NSString *const MPLegacyDocumentUTI = @"com.hicknhack.macpass.kdb";
NSString *const MPXMLDocumentUTI = @"com.hicknhack.macpass.kdbx";

View File

@@ -43,6 +43,8 @@
#import "KPKTimeInfo.h"
#import "KPKAttribute.h"
#import "NSError+Messages.h"
NSString *const MPDocumentDidAddGroupNotification = @"com.hicknhack.macpass.MPDocumentDidAddGroupNotification";
NSString *const MPDocumentDidRevertNotifiation = @"com.hicknhack.macpass.MPDocumentDidRevertNotifiation";

View File

@@ -17,7 +17,7 @@
@class MPOutlineViewController;
@class MPToolbarDelegate;
@interface MPDocumentWindowController : NSWindowController <MPPasswordEditWindowDelegate, QLPreviewPanelDataSource, QLPreviewPanelDelegate>
@interface MPDocumentWindowController : NSWindowController <MPPasswordEditWindowDelegate>
@property (readonly, strong) MPPasswordInputController *passwordInputController;
@property (readonly, strong) MPEntryViewController *entryViewController;

View File

@@ -51,8 +51,6 @@ typedef void (^MPPasswordChangedBlock)(void);
@property (nonatomic, copy) MPPasswordChangedBlock passwordChangedBlock;
@property (strong) QLPreviewPanel *previewPanel;
@end
@implementation MPDocumentWindowController
@@ -439,38 +437,4 @@ typedef void (^MPPasswordChangedBlock)(void);
}
- (void)toggleQuicklookPreview:(id)sender {
if([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible]) {
[[QLPreviewPanel sharedPreviewPanel] orderOut:sender];
}
else {
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:sender];
}
}
#pragma mark -
#pragma mark QLPreviewDelegate
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel {
return YES;
}
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel {
self.previewPanel = panel;
[self.previewPanel setDataSource:self];
}
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel {
self.previewPanel = nil;
}
#pragma mark -
#pragma mark QLPreviewDataSource
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
return (self.previewPanel == panel ? 1 : 0);
}
- (id<QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
return [[NSURL alloc] initWithString:@"file:///test.txt"];
}
@end

View File

@@ -8,10 +8,12 @@
#import "MPViewController.h"
#import <Quartz/Quartz.h>
@class HNHRoundedSecureTextField;
@class MPDocument;
@interface MPEntryInspectorViewController : MPViewController <NSPopoverDelegate>
@interface MPEntryInspectorViewController : MPViewController <NSPopoverDelegate, QLPreviewPanelDelegate>
@property (weak) IBOutlet NSTextField *titleTextField;
@property (weak) IBOutlet NSTextField *usernameTextField;
@@ -57,7 +59,10 @@
- (IBAction)addWindowAssociation:(id)sender;
- (IBAction)removeWindowAssociation:(id)sender;
- (IBAction)toggleQuicklookPreview:(id)sender;
- (void)beginEditing;
- (void)endEditing;
@end

View File

@@ -16,6 +16,10 @@
#import "MPDocument.h"
#import "MPIconHelper.h"
#import "MPValueTransformerHelper.h"
#import "MPTemporaryFileStorage.h"
#import "MPTemporaryFileStorageCenter.h"
#import "MPActionHelper.h"
#import "MPSettingsHelper.h"
#import "KPKEntry.h"
#import "KPKBinary.h"
@@ -49,6 +53,7 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
@property (strong) NSPopover *activePopover;
@property (nonatomic, weak) KPKEntry *entry;
@property (strong) MPTemporaryFileStorage *quicklookStorage;
@end
@@ -128,7 +133,11 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
}
- (void)saveAttachment:(id)sender {
KPKBinary *binary = self.entry.binaries[[sender tag]];
NSInteger row = [self.attachmentTableView selectedRow];
if(row < 0) {
return; // No selection
}
KPKBinary *binary = self.entry.binaries[row];
NSSavePanel *savePanel = [NSSavePanel savePanel];
[savePanel setCanCreateDirectories:YES];
[savePanel setNameFieldStringValue:binary.name];
@@ -156,7 +165,11 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
}
- (void)removeAttachment:(id)sender {
KPKBinary *binary = self.entry.binaries[[sender tag]];
NSInteger row = [self.attachmentTableView selectedRow];
if(row < 0) {
return; // no selection
}
KPKBinary *binary = self.entry.binaries[row];
[self.entry removeBinary:binary];
}
@@ -172,7 +185,22 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
}
}
#pragma mark Editing
- (void)toggleQuicklookPreview:(id)sender {
if([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible]) {
QLPreviewPanel *panel = [QLPreviewPanel sharedPreviewPanel];
if([self acceptsPreviewPanelControl:nil]) {
[self _updatePreviewItemForPanel:panel];
[panel reloadData];
}
else {
[panel orderOut:sender];
}
}
else {
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:sender];
}
}
- (void)beginEditing {
[self _toggleEditing:YES];
@@ -181,6 +209,45 @@ typedef NS_ENUM(NSUInteger, MPEntryTab) {
[self _toggleEditing:NO];
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
switch([MPActionHelper typeForAction:[menuItem action]]) {
case MPActionToggleQuicklook: {
BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:kMPSettingsKeyEnableQuicklookPreview];
return enabled ? [self acceptsPreviewPanelControl:nil] : NO;
}
default:
return YES;
}
}
#pragma mark -
#pragma mark QLPreviewPanelDelegate
- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel {
if(self.activeTab == MPEntryTabFiles) {
return ([self.attachmentTableView selectedRow] != -1);
}
return NO;
}
- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel {
[self _updatePreviewItemForPanel:panel];
}
- (void)endPreviewPanelControl:(QLPreviewPanel *)panel {
MPTemporaryFileStorage *storage = (MPTemporaryFileStorage *)panel.dataSource;
[[MPTemporaryFileStorageCenter defaultCenter] unregisterStorage:storage];
}
- (void)_updatePreviewItemForPanel:(QLPreviewPanel *)panel {
NSInteger row = [self.attachmentTableView selectedRow];
NSAssert(row > -1, @"Row needs to be selected");
KPKBinary *binary = self.entry.binaries[row];
MPTemporaryFileStorage *oldStorage = (MPTemporaryFileStorage *)panel.dataSource;
[[MPTemporaryFileStorageCenter defaultCenter] unregisterStorage:oldStorage];
panel.dataSource = [[MPTemporaryFileStorageCenter defaultCenter] storageForBinary:binary];
}
#pragma mark -
#pragma mark Popovers

View File

@@ -13,5 +13,6 @@
@property (weak) IBOutlet NSButton *enableServerCheckbutton;
@property (weak) IBOutlet NSButton *enableGlobalAutotypeCheckbutton;
@property (weak) IBOutlet NSButton *enableQuicklookCheckbutton;
@end

View File

@@ -37,10 +37,12 @@
NSUserDefaultsController *defaultsController = [NSUserDefaultsController sharedUserDefaultsController];
NSString *serverKeyPath = [MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyEnableHttpServer];
NSString *globalAutotypeKeyPath = [MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyEnableGlobalAutotype];
NSString *quicklookKeyPath = [MPSettingsHelper defaultControllerPathForKey:kMPSettingsKeyEnableQuicklookPreview];
[self.enableServerCheckbutton bind:NSValueBinding toObject:defaultsController withKeyPath:serverKeyPath options:nil];
[self.enableServerCheckbutton setEnabled:NO];
[self.enableGlobalAutotypeCheckbutton bind:NSValueBinding toObject:defaultsController withKeyPath:globalAutotypeKeyPath options:nil];
[self.enableGlobalAutotypeCheckbutton setEnabled:NO];
[self.enableQuicklookCheckbutton bind:NSValueBinding toObject:defaultsController withKeyPath:quicklookKeyPath options:nil];
}
@end

View File

@@ -11,7 +11,6 @@
/* Simple View with an additional Button to add an Action to selected rows */
@interface MPSelectedAttachmentTableCellView : NSTableCellView
@property (nonatomic, weak) IBOutlet NSButton *saveButton;
@property (nonatomic, weak) IBOutlet NSButton *removeButton;
@property (nonatomic, weak) IBOutlet NSPopUpButton *actionButton;
@end

View File

@@ -10,4 +10,5 @@
@implementation MPSelectedAttachmentTableCellView
@end

View File

@@ -7,17 +7,17 @@
//
#import <Foundation/Foundation.h>
/**
* Instance to handle a temporary file storage. Quicklook support uses this as a means to vent attachments to the system
* After using the file, the storage is removed.
*/
#import <Quartz/Quartz.h>
@class KPKBinary;
@interface MPTemporaryFileStorage : NSObject
/**
* File Storage the Storage center vents on request. Use this to feed as datasource to QLPreviewPanels
*/
@interface MPTemporaryFileStorage : NSObject <QLPreviewPanelDataSource, QLPreviewItem>
- (instancetype)initWithBinary:(KPKBinary *)binary;
- (void)quicklook;
- (void)cleanup;
- (void)cleanupNow;
@end

View File

@@ -7,13 +7,17 @@
//
#import "MPTemporaryFileStorage.h"
#import "MPTemporaryFileStorageCenter.h"
#import "KPKBinary.h"
#import <QuickLook/QuickLook.h>
#import "NSError+Messages.h"
@interface MPTemporaryFileStorage ()
@property (strong) KPKBinary *binary;
@property (assign) BOOL loadScheduled;
@property (strong) NSURL *temporaryFileURL;
@end
@@ -23,28 +27,103 @@
self = [super init];
if(self) {
_binary = binary;
_loadScheduled = NO;
[[MPTemporaryFileStorageCenter defaultCenter] registerStorage:self];
}
return self;
}
- (void)quicklook {
- (void)dealloc {
NSLog(@"dealloc");
[self cleanup];
[[MPTemporaryFileStorageCenter defaultCenter] unregisterStorage:self];
}
NSString *fileName = [NSString stringWithFormat:@"%@_%@", [[NSProcessInfo processInfo] globallyUniqueString], self.binary.name];
NSURL *fileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:fileName]];
- (void)cleanupNow {
[self _cleanupBinary:YES];
}
NSError *error;
BOOL success = [self.binary.data writeToURL:fileURL options:0 error:&error];
- (void)cleanup {
[self _cleanupBinary:NO];
}
#pragma mark -
#pragma mark QLPreviewPanelDataSource
- (id<QLPreviewItem>)previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index {
if(!self.temporaryFileURL && !self.loadScheduled) {
self.loadScheduled = YES;
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(defaultQueue, ^{
BOOL success = [self _saveBinary:self.binary];
if(success){
dispatch_async(dispatch_get_main_queue(), ^{
[panel refreshCurrentPreviewItem];
});
}
});
}
return self;
}
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel {
return 1;
}
#pragma mark -
#pragma mark QLPreviewItem
- (NSURL *)previewItemURL {
return self.temporaryFileURL;
}
- (NSString *)previewItemTitle {
return self.binary.name;
}
#pragma mark -
#pragma mark Private
- (BOOL)_saveBinary:(KPKBinary *)binary {
if(!binary || !binary.data || !binary.name || [binary.name length] == 0) {
return NO;
}
NSString *fileName = [NSString stringWithFormat:@"%@_%@", [[NSProcessInfo processInfo] globallyUniqueString], binary.name];
self.temporaryFileURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:fileName]];
BOOL success = [binary.data writeToURL:self.temporaryFileURL options:0 error:0];
if(!success) {
if(error) {
[NSApp presentError:error];
self.temporaryFileURL = nil;
return NO;
}
return;
NSLog(@"Did write data to %@", [self.temporaryFileURL path]);
return YES;
}
- (void)_cleanupBinary:(BOOL)blockUntilDone {
if(!self.temporaryFileURL) {
return; // No URL to clean up
}
NSString *path = [self.temporaryFileURL path];
if(blockUntilDone) {
[MPTemporaryFileStorage _runCleanupForPath:path];
}
else {
dispatch_queue_t lowQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_async(lowQueue, ^{
[MPTemporaryFileStorage _runCleanupForPath:path];
});
}
self.temporaryFileURL = nil;
}
+ (void)_runCleanupForPath:(NSString *)path {
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"srm"];
[task setArguments:@[@"-m", fileName]];
[task setLaunchPath:@"/usr/bin/srm"];
[task setArguments:@[@"-m", path]];
[task launch];
[task waitUntilExit];
}
@end

View File

@@ -0,0 +1,25 @@
//
// MPTemporaryFileStorageCleaner.h
// MacPass
//
// Created by Michael Starke on 19/03/14.
// Copyright (c) 2014 HicknHack Software GmbH. All rights reserved.
//
#import <Foundation/Foundation.h>
@class MPTemporaryFileStorage;
@class KPKBinary;
@interface MPTemporaryFileStorageCenter : NSObject
+ (instancetype)defaultCenter;
- (BOOL)hasPendingStorages;
- (MPTemporaryFileStorage *)storageForBinary:(KPKBinary *)binary;
- (void)registerStorage:(MPTemporaryFileStorage *)storage;
- (void)unregisterStorage:(MPTemporaryFileStorage *)storage;
- (void)cleanupStorages;
@end

View File

@@ -0,0 +1,61 @@
//
// MPTemporaryFileStorageCleaner.m
// MacPass
//
// Created by Michael Starke on 19/03/14.
// Copyright (c) 2014 HicknHack Software GmbH. All rights reserved.
//
#import "MPTemporaryFileStorageCenter.h"
#import "MPTemporaryFileStorage.h"
@interface MPTemporaryFileStorageCenter () {
NSMutableArray *_storages;
}
@end
@implementation MPTemporaryFileStorageCenter
+ (instancetype)defaultCenter {
static MPTemporaryFileStorageCenter *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[MPTemporaryFileStorageCenter alloc] init];
});
return instance;
}
- (instancetype)init {
self = [super init];
if(self) {
_storages = [[NSMutableArray alloc] init];
}
return self;
}
- (BOOL)hasPendingStorages {
return [_storages count] > 0;
}
- (MPTemporaryFileStorage *)storageForBinary:(KPKBinary *)binary {
return [[MPTemporaryFileStorage alloc] initWithBinary:binary];
}
- (void)cleanupStorages {
for(MPTemporaryFileStorage *storage in _storages) {
[storage cleanupNow];
}
_storages = nil;
}
- (void)registerStorage:(MPTemporaryFileStorage *)storage {
[_storages addObject:storage];
}
- (void)unregisterStorage:(MPTemporaryFileStorage *)storage {
[storage cleanup];
[_storages removeObject:storage];
}
@end

View File

@@ -8,8 +8,12 @@
#import <Foundation/Foundation.h>
FOUNDATION_EXPORT NSString *const MPErrorDomain;
@interface NSError (Messages)
+ (NSError *)errorWithCode:(NSInteger)code description:(NSString *)description;
- (NSString *)descriptionForErrorCode;
@end

View File

@@ -7,11 +7,16 @@
//
#import "NSError+Messages.h"
#import "KPKErrors.h"
NSString *const MPErrorDomain = @"com.hicknhack.macpass.error";
@implementation NSError (Messages)
- (NSString *)descriptionForErrorCode {
return [NSString stringWithFormat:@"%@ (%ld)", [self localizedDescription], [self code] ];
}
+ (NSError *)errorWithCode:(NSInteger)code description:(NSString *)description {
return [[NSError alloc] initWithDomain:MPErrorDomain code:code userInfo:@{ NSLocalizedDescriptionKey: description }];
}
@end