aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2012-10-06 11:48:15 +0000
committerrowanbeentje <rowan@beent.je>2012-10-06 11:48:15 +0000
commitecb5c70566d1303288e4faf170bda40672a799e1 (patch)
tree2882fa5fd6f25eed9c754e810785f5834225b95f
parentada181f6fe5b010a5ab56030d16b35e92e58af10 (diff)
downloadsequelpro-ecb5c70566d1303288e4faf170bda40672a799e1.tar.gz
sequelpro-ecb5c70566d1303288e4faf170bda40672a799e1.tar.bz2
sequelpro-ecb5c70566d1303288e4faf170bda40672a799e1.zip
Change the connection screen interface, particularly relating to favourite editing on the connection screen (Issue #1339, Issue #1440):
- No longer save changes made to connection favourites as soon as the interface is updated - Alter the interfaace if favourites are editing, offering to save the changes either to the old connection favourite or to a new favourite - Add a "Test connection" button to verify changes before saving - Add a "Quick Connect" entry to the top of the connection view's favourites list so a blank form is always available - Use a custom highlight when editing favourites to show the favourite has changed but is still linked - Reduce the margin on the left-hand side of the connection favourites list to increase the available space - Alter favourite name generation, making it less aggressive when generating names from partial details (eg creating names of just "@") and removing the user - Alter key icon usage to correctly update the button appearance if an SSL or SSH key is selected
-rw-r--r--Interfaces/English.lproj/ConnectionView.xib463
-rw-r--r--Resources/English.lproj/ConnectionView.stringsbin42456 -> 42630 bytes
-rw-r--r--Resources/English.lproj/Localizable.stringsbin233322 -> 235592 bytes
-rw-r--r--Resources/Images/key-icon-alternate.pngbin0 -> 380 bytes
-rw-r--r--Resources/Images/key-icon-alternate@2x.pngbin0 -> 786 bytes
-rw-r--r--Resources/Images/key-icon.pngbin0 -> 264 bytes
-rw-r--r--Resources/Images/key-icon@2x.pngbin0 -> 694 bytes
-rw-r--r--Resources/Images/quick-connect-icon-white.pdfbin0 -> 4758 bytes
-rw-r--r--Resources/Images/quick-connect-icon.pdfbin0 -> 4788 bytes
-rw-r--r--Source/SPConnectionController.h25
-rw-r--r--Source/SPConnectionController.m581
-rw-r--r--Source/SPConnectionControllerDataSource.m36
-rw-r--r--Source/SPConnectionControllerDelegate.m220
-rw-r--r--Source/SPConnectionControllerInitializer.m37
-rw-r--r--Source/SPConnectionHandler.m61
-rw-r--r--Source/SPFavoriteTextFieldCell.h16
-rw-r--r--Source/SPFavoriteTextFieldCell.m208
-rw-r--r--Source/SPFavoritesOutlineView.m63
-rw-r--r--sequel-pro.xcodeproj/project.pbxproj24
19 files changed, 1079 insertions, 655 deletions
diff --git a/Interfaces/English.lproj/ConnectionView.xib b/Interfaces/English.lproj/ConnectionView.xib
index 4c0d4dc2..f657096a 100644
--- a/Interfaces/English.lproj/ConnectionView.xib
+++ b/Interfaces/English.lproj/ConnectionView.xib
@@ -12,7 +12,7 @@
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
- <integer value="5739"/>
+ <integer value="5743"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -65,6 +65,7 @@
</object>
<string key="NSFrame">{{0, 1}, {202, 22}}</string>
<reference key="NSSuperview" ref="551584428"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSImageCell" key="NSCell" id="147458525">
<int key="NSCellFlags">130560</int>
@@ -85,6 +86,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{61, -1}, {32, 25}}</string>
<reference key="NSSuperview" ref="551584428"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="953363291">
<int key="NSCellFlags">67239424</int>
@@ -113,6 +115,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{30, -1}, {32, 25}}</string>
<reference key="NSSuperview" ref="551584428"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="340161940">
<int key="NSCellFlags">67239424</int>
@@ -137,6 +140,7 @@
<int key="NSvFlags">292</int>
<string key="NSFrame">{{-1, -1}, {36, 25}}</string>
<reference key="NSSuperview" ref="551584428"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSReuseIdentifierKey">_NS:791</string>
<bool key="NSEnabled">YES</bool>
<object class="NSPopUpButtonCell" key="NSCell" id="970960222">
@@ -311,6 +315,7 @@
</object>
<string key="NSFrame">{{187, 1}, {15, 22}}</string>
<reference key="NSSuperview" ref="551584428"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSReuseIdentifierKey">_NS:2165</string>
<bool key="NSEnabled">YES</bool>
<object class="NSImageCell" key="NSCell" id="875077014">
@@ -341,8 +346,9 @@
<object class="NSTableView" id="1012579052">
<reference key="NSNextResponder" ref="233523429"/>
<int key="NSvFlags">4352</int>
- <string key="NSFrameSize">{202, 451}</string>
+ <string key="NSFrameSize">{202, 489}</string>
<reference key="NSSuperview" ref="233523429"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="_NSCornerView" key="NSCornerView">
<nil key="NSNextResponder"/>
@@ -438,9 +444,10 @@
<int key="NSTableViewGroupRowStyle">1</int>
</object>
</object>
- <string key="NSFrameSize">{202, 451}</string>
+ <string key="NSFrameSize">{202, 489}</string>
<reference key="NSSuperview" ref="524598165"/>
<reference key="NSNextKeyView" ref="1012579052"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<reference key="NSDocView" ref="1012579052"/>
<object class="NSColor" key="NSBGColor">
<int key="NSColorSpace">3</int>
@@ -468,9 +475,10 @@
<double key="NSPercent">0.99507391452789307</double>
</object>
</object>
- <string key="NSFrame">{{0, 23}, {202, 451}}</string>
+ <string key="NSFrame">{{0, 23}, {202, 489}}</string>
<reference key="NSSuperview" ref="551584428"/>
<reference key="NSNextKeyView" ref="233523429"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<int key="NSsFlags">133680</int>
<reference key="NSVScroller" ref="533108700"/>
<reference key="NSHScroller" ref="802793151"/>
@@ -478,8 +486,9 @@
<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
</object>
</object>
- <string key="NSFrameSize">{202, 475}</string>
+ <string key="NSFrameSize">{202, 513}</string>
<reference key="NSSuperview" ref="616749187"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
</object>
<object class="NSView" id="563806501">
<reference key="NSNextResponder" ref="616749187"/>
@@ -506,17 +515,99 @@
<int key="NSvFlags">301</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSCustomView" id="765073663">
+ <reference key="NSNextResponder" ref="735564334"/>
+ <int key="NSvFlags">-2147483358</int>
+ <object class="NSMutableArray" key="NSSubviews">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSButton" id="148626614">
+ <reference key="NSNextResponder" ref="765073663"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{158.5, 3}, {125, 28}}</string>
+ <reference key="NSSuperview" ref="765073663"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
+ <string key="NSReuseIdentifierKey">_NS:610</string>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="1020482049">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134348800</int>
+ <string key="NSContents">Save changes</string>
+ <reference key="NSSupport" ref="26"/>
+ <string key="NSCellIdentifier">_NS:610</string>
+ <reference key="NSControlView" ref="148626614"/>
+ <int key="NSButtonFlags">-2038284033</int>
+ <int key="NSButtonFlags2">268435585</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent">s</string>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ <object class="NSButton" id="463178943">
+ <reference key="NSNextResponder" ref="765073663"/>
+ <int key="NSvFlags">268</int>
+ <string key="NSFrame">{{15, 3}, {145, 28}}</string>
+ <reference key="NSSuperview" ref="765073663"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
+ <string key="NSReuseIdentifierKey">_NS:610</string>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="1027746126">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134348800</int>
+ <string key="NSContents">Add to Favorites</string>
+ <reference key="NSSupport" ref="26"/>
+ <string key="NSCellIdentifier">_NS:610</string>
+ <reference key="NSControlView" ref="463178943"/>
+ <int key="NSButtonFlags">-2038284033</int>
+ <int key="NSButtonFlags2">402653313</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent">a</string>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ <object class="NSButton" id="941479834">
+ <reference key="NSNextResponder" ref="765073663"/>
+ <int key="NSvFlags">265</int>
+ <string key="NSFrame">{{286, 3}, {145, 28}}</string>
+ <reference key="NSSuperview" ref="765073663"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
+ <string key="NSReuseIdentifierKey">_NS:610</string>
+ <bool key="NSEnabled">YES</bool>
+ <object class="NSButtonCell" key="NSCell" id="90221493">
+ <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags2">134348800</int>
+ <string key="NSContents">Test connection</string>
+ <reference key="NSSupport" ref="26"/>
+ <string key="NSCellIdentifier">_NS:610</string>
+ <reference key="NSControlView" ref="941479834"/>
+ <int key="NSButtonFlags">-2038284033</int>
+ <int key="NSButtonFlags2">129</int>
+ <string key="NSAlternateContents"/>
+ <string key="NSKeyEquivalent"/>
+ <int key="NSPeriodicDelay">200</int>
+ <int key="NSPeriodicInterval">25</int>
+ </object>
+ </object>
+ </object>
+ <string key="NSFrameSize">{446, 37}</string>
+ <reference key="NSSuperview" ref="735564334"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
+ <string key="NSReuseIdentifierKey">_NS:1109</string>
+ <string key="NSClassName">NSView</string>
+ </object>
<object class="NSTabView" id="134031646">
<reference key="NSNextResponder" ref="735564334"/>
<int key="NSvFlags">274</int>
- <string key="NSFrame">{{13, 25}, {420, 417}}</string>
+ <string key="NSFrame">{{13, 61}, {420, 417}}</string>
<reference key="NSSuperview" ref="735564334"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<object class="NSMutableArray" key="NSTabViewItems">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSTabViewItem" id="253369045">
<string key="NSIdentifier">1</string>
<object class="NSView" key="NSView" id="32802602">
- <reference key="NSNextResponder" ref="134031646"/>
+ <nil key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -836,9 +927,13 @@
<reference key="NSControlView" ref="839299955"/>
<int key="NSButtonFlags">-922992385</int>
<int key="NSButtonFlags2">34</int>
- <object class="NSCustomResource" key="NSNormalImage" id="22774617">
+ <object class="NSCustomResource" key="NSNormalImage" id="792471251">
<string key="NSClassName">NSImage</string>
- <string key="NSResourceName">KeyTemplate</string>
+ <string key="NSResourceName">key-icon</string>
+ </object>
+ <object class="NSCustomResource" key="NSAlternateImage" id="503225194">
+ <string key="NSClassName">NSImage</string>
+ <string key="NSResourceName">key-icon-alternate</string>
</object>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
@@ -898,7 +993,8 @@
<reference key="NSControlView" ref="945929172"/>
<int key="NSButtonFlags">-922992385</int>
<int key="NSButtonFlags2">34</int>
- <reference key="NSNormalImage" ref="22774617"/>
+ <reference key="NSNormalImage" ref="792471251"/>
+ <reference key="NSAlternateImage" ref="503225194"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
@@ -956,7 +1052,8 @@
<reference key="NSControlView" ref="586011242"/>
<int key="NSButtonFlags">-922992385</int>
<int key="NSButtonFlags2">34</int>
- <reference key="NSNormalImage" ref="22774617"/>
+ <reference key="NSNormalImage" ref="792471251"/>
+ <reference key="NSAlternateImage" ref="503225194"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
@@ -970,7 +1067,6 @@
</object>
</object>
<string key="NSFrame">{{10, 33}, {400, 371}}</string>
- <reference key="NSSuperview" ref="134031646"/>
</object>
<string key="NSLabel">Standard</string>
<reference key="NSColor" ref="644242225"/>
@@ -993,6 +1089,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{108, 11}, {251, 18}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="972347112">
<int key="NSCellFlags">67239424</int>
@@ -1015,6 +1112,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{110, 141}, {247, 22}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="279442436">
<int key="NSCellFlags">-1804468671</int>
@@ -1032,6 +1130,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{7, 143}, {98, 17}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="798396187">
<int key="NSCellFlags">68288064</int>
@@ -1048,6 +1147,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{110, 107}, {247, 22}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="251554254">
<int key="NSCellFlags">-1804468671</int>
@@ -1065,6 +1165,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{7, 109}, {98, 17}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="797213431">
<int key="NSCellFlags">68288064</int>
@@ -1081,6 +1182,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{110, 73}, {247, 22}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="185246669">
<int key="NSCellFlags">-1804468671</int>
@@ -1099,6 +1201,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{7, 75}, {98, 17}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="728524936">
<int key="NSCellFlags">68288064</int>
@@ -1115,6 +1218,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{110, 39}, {247, 22}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="299457759">
<int key="NSCellFlags">-1804468671</int>
@@ -1133,6 +1237,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{7, 41}, {98, 17}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="317867885">
<int key="NSCellFlags">68288064</int>
@@ -1149,6 +1254,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{110, 175}, {247, 22}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="684614893">
<int key="NSCellFlags">-1804468671</int>
@@ -1167,6 +1273,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{7, 177}, {98, 17}}</string>
<reference key="NSSuperview" ref="394302879"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="352725628">
<int key="NSCellFlags">68288064</int>
@@ -1181,6 +1288,7 @@
</object>
<string key="NSFrame">{{6, 164}, {377, 224}}</string>
<reference key="NSSuperview" ref="962671066"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSClassName">NSView</string>
</object>
<object class="NSCustomView" id="866600720">
@@ -1193,6 +1301,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{-3, 15}, {107, 17}}</string>
<reference key="NSSuperview" ref="866600720"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="730590428">
<int key="NSCellFlags">68288064</int>
@@ -1209,6 +1318,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{109, 13}, {220, 22}}</string>
<reference key="NSSuperview" ref="866600720"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="169093017">
<int key="NSCellFlags">-2073952703</int>
@@ -1231,6 +1341,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{328, 12}, {29, 24}}</string>
<reference key="NSSuperview" ref="866600720"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="308087760">
<int key="NSCellFlags">67239424</int>
@@ -1240,7 +1351,8 @@
<reference key="NSControlView" ref="680939705"/>
<int key="NSButtonFlags">-922992385</int>
<int key="NSButtonFlags2">34</int>
- <reference key="NSNormalImage" ref="22774617"/>
+ <reference key="NSNormalImage" ref="792471251"/>
+ <reference key="NSAlternateImage" ref="503225194"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
@@ -1252,6 +1364,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{-3, 49}, {107, 17}}</string>
<reference key="NSSuperview" ref="866600720"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="1025158673">
<int key="NSCellFlags">68288064</int>
@@ -1268,6 +1381,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{109, 47}, {220, 22}}</string>
<reference key="NSSuperview" ref="866600720"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="276609847">
<int key="NSCellFlags">-2073952703</int>
@@ -1290,6 +1404,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{328, 46}, {29, 24}}</string>
<reference key="NSSuperview" ref="866600720"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="559442548">
<int key="NSCellFlags">67239424</int>
@@ -1299,7 +1414,8 @@
<reference key="NSControlView" ref="988136593"/>
<int key="NSButtonFlags">-922992385</int>
<int key="NSButtonFlags2">34</int>
- <reference key="NSNormalImage" ref="22774617"/>
+ <reference key="NSNormalImage" ref="792471251"/>
+ <reference key="NSAlternateImage" ref="503225194"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
@@ -1311,6 +1427,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{-3, 83}, {107, 17}}</string>
<reference key="NSSuperview" ref="866600720"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="357553281">
<int key="NSCellFlags">68288064</int>
@@ -1327,6 +1444,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{109, 81}, {220, 22}}</string>
<reference key="NSSuperview" ref="866600720"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="575863174">
<int key="NSCellFlags">-2073952703</int>
@@ -1348,6 +1466,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{328, 80}, {29, 24}}</string>
<reference key="NSSuperview" ref="866600720"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="167444868">
<int key="NSCellFlags">67239424</int>
@@ -1357,7 +1476,8 @@
<reference key="NSControlView" ref="237955939"/>
<int key="NSButtonFlags">-922992385</int>
<int key="NSButtonFlags2">34</int>
- <reference key="NSNormalImage" ref="22774617"/>
+ <reference key="NSNormalImage" ref="792471251"/>
+ <reference key="NSAlternateImage" ref="503225194"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
@@ -1367,10 +1487,12 @@
</object>
<string key="NSFrame">{{6, 61}, {377, 104}}</string>
<reference key="NSSuperview" ref="962671066"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSClassName">NSView</string>
</object>
</object>
<string key="NSFrame">{{10, 33}, {400, 371}}</string>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
</object>
<string key="NSLabel">Socket</string>
<reference key="NSColor" ref="644242225"/>
@@ -1379,7 +1501,7 @@
<object class="NSTabViewItem" id="591192172">
<string key="NSIdentifier">Item 2</string>
<object class="NSView" key="NSView" id="159800861">
- <nil key="NSNextResponder"/>
+ <reference key="NSNextResponder" ref="134031646"/>
<int key="NSvFlags">256</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -1736,7 +1858,8 @@
<reference key="NSControlView" ref="183948302"/>
<int key="NSButtonFlags">-922992385</int>
<int key="NSButtonFlags2">34</int>
- <reference key="NSNormalImage" ref="22774617"/>
+ <reference key="NSNormalImage" ref="792471251"/>
+ <reference key="NSAlternateImage" ref="503225194"/>
<string key="NSAlternateContents"/>
<string key="NSKeyEquivalent"/>
<int key="NSPeriodicDelay">400</int>
@@ -1786,27 +1909,29 @@
</object>
</object>
<string key="NSFrame">{{10, 33}, {400, 371}}</string>
+ <reference key="NSSuperview" ref="134031646"/>
</object>
<string key="NSLabel">SSH</string>
<reference key="NSColor" ref="644242225"/>
<reference key="NSTabView" ref="134031646"/>
</object>
</object>
- <reference key="NSSelectedTabViewItem" ref="253369045"/>
+ <reference key="NSSelectedTabViewItem" ref="591192172"/>
<reference key="NSFont" ref="807120225"/>
<int key="NSTvFlags">0</int>
<bool key="NSAllowTruncatedLabels">YES</bool>
<bool key="NSDrawsBackground">YES</bool>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="32802602"/>
+ <reference ref="159800861"/>
</object>
</object>
<object class="NSButton" id="460592307">
<reference key="NSNextResponder" ref="735564334"/>
<int key="NSvFlags">289</int>
- <string key="NSFrame">{{285, -3}, {147, 32}}</string>
+ <string key="NSFrame">{{285, 33}, {147, 32}}</string>
<reference key="NSSuperview" ref="735564334"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="424756162">
<int key="NSCellFlags">67239424</int>
@@ -1822,32 +1947,13 @@
<int key="NSPeriodicInterval">25</int>
</object>
</object>
- <object class="NSButton" id="476973680">
- <reference key="NSNextResponder" ref="735564334"/>
- <int key="NSvFlags">289</int>
- <string key="NSFrame">{{93, -3}, {192, 32}}</string>
- <reference key="NSSuperview" ref="735564334"/>
- <bool key="NSEnabled">YES</bool>
- <object class="NSButtonCell" key="NSCell" id="220047154">
- <int key="NSCellFlags">67239424</int>
- <int key="NSCellFlags2">134217728</int>
- <string key="NSContents">Add to Favorites</string>
- <reference key="NSSupport" ref="807120225"/>
- <reference key="NSControlView" ref="476973680"/>
- <int key="NSButtonFlags">-2038284033</int>
- <int key="NSButtonFlags2">402653313</int>
- <string key="NSAlternateContents"/>
- <string key="NSKeyEquivalent">a</string>
- <int key="NSPeriodicDelay">200</int>
- <int key="NSPeriodicInterval">25</int>
- </object>
- </object>
<object class="NSProgressIndicator" id="575228526">
<reference key="NSNextResponder" ref="735564334"/>
<int key="NSvFlags">1316</int>
<object class="NSPSMatrix" key="NSDrawMatrix"/>
- <string key="NSFrame">{{20, 7}, {16, 16}}</string>
+ <string key="NSFrame">{{20, 43}, {16, 16}}</string>
<reference key="NSSuperview" ref="735564334"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<int key="NSpiFlags">28938</int>
<double key="NSMinValue">16</double>
<double key="NSMaxValue">100</double>
@@ -1855,8 +1961,9 @@
<object class="NSTextField" id="549907703">
<reference key="NSNextResponder" ref="735564334"/>
<int key="NSvFlags">-2147483356</int>
- <string key="NSFrame">{{41, 7}, {252, 17}}</string>
+ <string key="NSFrame">{{41, 43}, {252, 17}}</string>
<reference key="NSSuperview" ref="735564334"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="321846713">
<int key="NSCellFlags">68288064</int>
@@ -1871,11 +1978,12 @@
<object class="NSButton" id="990947983">
<reference key="NSNextResponder" ref="735564334"/>
<int key="NSvFlags">292</int>
- <string key="NSFrame">{{17, 1}, {25, 25}}</string>
+ <string key="NSFrame">{{15, 37}, {25, 25}}</string>
<reference key="NSSuperview" ref="735564334"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="757039715">
- <int key="NSCellFlags">67239424</int>
+ <int key="NSCellFlags">-2080244224</int>
<int key="NSCellFlags2">134217728</int>
<string key="NSContents"/>
<reference key="NSSupport" ref="807120225"/>
@@ -1889,19 +1997,22 @@
</object>
</object>
</object>
- <string key="NSFrame">{{116, 2}, {446, 436}}</string>
+ <string key="NSFrame">{{116, 5}, {446, 472}}</string>
<reference key="NSSuperview" ref="315390047"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSClassName">NSCustomView</string>
</object>
</object>
- <string key="NSFrameSize">{679, 442}</string>
+ <string key="NSFrameSize">{679, 480}</string>
<reference key="NSSuperview" ref="954788335"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSClassName">SPFlippedView</string>
</object>
</object>
- <string key="NSFrameSize">{679, 443}</string>
+ <string key="NSFrameSize">{679, 481}</string>
<reference key="NSSuperview" ref="1058735001"/>
<reference key="NSNextKeyView" ref="315390047"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<reference key="NSDocView" ref="315390047"/>
<reference key="NSBGColor" ref="644242225"/>
<int key="NScvFlags">4</int>
@@ -1909,12 +2020,12 @@
<object class="NSScroller" id="508899576">
<reference key="NSNextResponder" ref="1058735001"/>
<int key="NSvFlags">-2147483392</int>
- <string key="NSFrame">{{664, 0}, {15, 453}}</string>
+ <string key="NSFrame">{{664, 0}, {15, 477}}</string>
<reference key="NSSuperview" ref="1058735001"/>
<reference key="NSTarget" ref="1058735001"/>
<string key="NSAction">_doScroller:</string>
<double key="NSCurValue">1</double>
- <double key="NSPercent">0.99775278568267822</double>
+ <double key="NSPercent">0.99582463465553239</double>
</object>
<object class="NSScroller" id="108277656">
<reference key="NSNextResponder" ref="1058735001"/>
@@ -1927,9 +2038,10 @@
<double key="NSPercent">0.97838616371154785</double>
</object>
</object>
- <string key="NSFrameSize">{679, 443}</string>
+ <string key="NSFrameSize">{679, 481}</string>
<reference key="NSSuperview" ref="563806501"/>
<reference key="NSNextKeyView" ref="954788335"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<int key="NSsFlags">133680</int>
<reference key="NSVScroller" ref="508899576"/>
<reference key="NSHScroller" ref="108277656"/>
@@ -1938,8 +2050,9 @@
<object class="NSTextField" id="570492783">
<reference key="NSNextResponder" ref="563806501"/>
<int key="NSvFlags">266</int>
- <string key="NSFrame">{{17, 451}, {645, 17}}</string>
+ <string key="NSFrame">{{17, 489}, {645, 17}}</string>
<reference key="NSSuperview" ref="563806501"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="607446274">
<int key="NSCellFlags">68288064</int>
@@ -1956,19 +2069,22 @@
</object>
</object>
</object>
- <string key="NSFrame">{{203, 0}, {679, 475}}</string>
+ <string key="NSFrame">{{203, 0}, {679, 513}}</string>
<reference key="NSSuperview" ref="616749187"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
</object>
</object>
- <string key="NSFrameSize">{882, 475}</string>
+ <string key="NSFrame">{{0, -2}, {882, 513}}</string>
<reference key="NSSuperview" ref="733821228"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<bool key="NSIsVertical">YES</bool>
<int key="NSDividerStyle">2</int>
<string key="NSAutosaveName">DBViewSplitter</string>
</object>
</object>
- <string key="NSFrameSize">{882, 475}</string>
+ <string key="NSFrameSize">{882, 511}</string>
<reference key="NSSuperview"/>
+ <int key="NSViewLayerContentsRedrawPolicy">2</int>
<string key="NSClassName">SPFlippedView</string>
</object>
<object class="NSWindowTemplate" id="958272936">
@@ -2893,14 +3009,6 @@
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
- <string key="label">addToFavoritesButton</string>
- <reference key="source" ref="545410097"/>
- <reference key="destination" ref="476973680"/>
- </object>
- <int key="connectionID">5357</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="644973446"/>
<reference key="destination" ref="545410097"/>
@@ -4753,14 +4861,6 @@
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
- <string key="label">addFavoriteUsingCurrentDetails:</string>
- <reference key="source" ref="545410097"/>
- <reference key="destination" ref="476973680"/>
- </object>
- <int key="connectionID">5821</int>
- </object>
- <object class="IBConnectionRecord">
- <object class="IBActionConnection" key="connection">
<string key="label">exportFavorites:</string>
<reference key="source" ref="545410097"/>
<reference key="destination" ref="567127977"/>
@@ -4847,6 +4947,54 @@
</object>
<int key="connectionID">5861</int>
</object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">addFavoriteUsingCurrentDetails:</string>
+ <reference key="source" ref="545410097"/>
+ <reference key="destination" ref="463178943"/>
+ </object>
+ <int key="connectionID">5871</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">saveFavoriteButton</string>
+ <reference key="source" ref="545410097"/>
+ <reference key="destination" ref="148626614"/>
+ </object>
+ <int key="connectionID">5874</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">testConnectButton</string>
+ <reference key="source" ref="545410097"/>
+ <reference key="destination" ref="941479834"/>
+ </object>
+ <int key="connectionID">5875</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">saveFavorite:</string>
+ <reference key="source" ref="545410097"/>
+ <reference key="destination" ref="148626614"/>
+ </object>
+ <int key="connectionID">5880</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBActionConnection" key="connection">
+ <string key="label">initiateConnection:</string>
+ <reference key="source" ref="545410097"/>
+ <reference key="destination" ref="941479834"/>
+ </object>
+ <int key="connectionID">5881</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBOutletConnection" key="connection">
+ <string key="label">editButtonsView</string>
+ <reference key="source" ref="545410097"/>
+ <reference key="destination" ref="765073663"/>
+ </object>
+ <int key="connectionID">5882</int>
+ </object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -5169,7 +5317,7 @@
<reference ref="549907703"/>
<reference ref="990947983"/>
<reference ref="460592307"/>
- <reference ref="476973680"/>
+ <reference ref="765073663"/>
</object>
<reference key="parent" ref="315390047"/>
</object>
@@ -5194,15 +5342,6 @@
<reference key="parent" ref="735564334"/>
</object>
<object class="IBObjectRecord">
- <int key="objectID">5159</int>
- <reference key="object" ref="476973680"/>
- <object class="NSMutableArray" key="children">
- <bool key="EncodedWithXMLCoder">YES</bool>
- <reference ref="220047154"/>
- </object>
- <reference key="parent" ref="735564334"/>
- </object>
- <object class="IBObjectRecord">
<int key="objectID">5422</int>
<reference key="object" ref="575228526"/>
<reference key="parent" ref="735564334"/>
@@ -5236,11 +5375,6 @@
<reference key="parent" ref="549907703"/>
</object>
<object class="IBObjectRecord">
- <int key="objectID">5160</int>
- <reference key="object" ref="220047154"/>
- <reference key="parent" ref="476973680"/>
- </object>
- <object class="IBObjectRecord">
<int key="objectID">5158</int>
<reference key="object" ref="424756162"/>
<reference key="parent" ref="460592307"/>
@@ -6601,6 +6735,59 @@
<reference key="object" ref="875077014"/>
<reference key="parent" ref="250765522"/>
</object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5862</int>
+ <reference key="object" ref="765073663"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="148626614"/>
+ <reference ref="463178943"/>
+ <reference ref="941479834"/>
+ </object>
+ <reference key="parent" ref="735564334"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5869</int>
+ <reference key="object" ref="148626614"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1020482049"/>
+ </object>
+ <reference key="parent" ref="765073663"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5865</int>
+ <reference key="object" ref="463178943"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="1027746126"/>
+ </object>
+ <reference key="parent" ref="765073663"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5863</int>
+ <reference key="object" ref="941479834"/>
+ <object class="NSMutableArray" key="children">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference ref="90221493"/>
+ </object>
+ <reference key="parent" ref="765073663"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5864</int>
+ <reference key="object" ref="90221493"/>
+ <reference key="parent" ref="941479834"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5866</int>
+ <reference key="object" ref="1027746126"/>
+ <reference key="parent" ref="463178943"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">5870</int>
+ <reference key="object" ref="1020482049"/>
+ <reference key="parent" ref="148626614"/>
+ </object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
@@ -6636,10 +6823,6 @@
<string>5157.IBPluginDependency</string>
<string>5157.IBViewBoundsToFrameTransform</string>
<string>5158.IBPluginDependency</string>
- <string>5159.IBAttributePlaceholdersKey</string>
- <string>5159.IBPluginDependency</string>
- <string>5159.IBViewBoundsToFrameTransform</string>
- <string>5160.IBPluginDependency</string>
<string>5162.IBPluginDependency</string>
<string>5166.IBPluginDependency</string>
<string>5171.IBAttributePlaceholdersKey</string>
@@ -6915,6 +7098,16 @@
<string>5858.IBPluginDependency</string>
<string>5858.IBViewBoundsToFrameTransform</string>
<string>5859.IBPluginDependency</string>
+ <string>5862.IBPluginDependency</string>
+ <string>5862.IBViewBoundsToFrameTransform</string>
+ <string>5863.IBPluginDependency</string>
+ <string>5863.IBViewBoundsToFrameTransform</string>
+ <string>5864.IBPluginDependency</string>
+ <string>5865.IBPluginDependency</string>
+ <string>5865.IBViewBoundsToFrameTransform</string>
+ <string>5866.IBPluginDependency</string>
+ <string>5869.IBPluginDependency</string>
+ <string>5870.IBPluginDependency</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -6933,7 +7126,7 @@
<string>SPFavoritesOutlineView</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>SPTableTextFieldCell</string>
+ <string>SPFavoriteTextFieldCell</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSMutableDictionary">
<string key="NS.key.0">InitialTabViewItem</string>
@@ -6958,19 +7151,6 @@
<bytes key="NSTransformStruct">P4AAAL+AAABDjIAAwdgAAA</bytes>
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <object class="NSMutableDictionary">
- <string key="NS.key.0">ToolTip</string>
- <object class="IBToolTipAttribute" key="NS.object.0">
- <string key="name">ToolTip</string>
- <reference key="object" ref="476973680"/>
- <string key="toolTip">Add to Favorites (⌥⌘A)</string>
- </object>
- </object>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <object class="NSAffineTransform">
- <bytes key="NSTransformStruct">P4AAAL+AAABCsgAAwdgAAA</bytes>
- </object>
- <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSMutableDictionary">
@@ -7399,7 +7579,7 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
- <string>{{158, 366}, {882, 475}}</string>
+ <string>{{158, 330}, {882, 511}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>SPSplitView</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -7494,6 +7674,22 @@
<bytes key="NSTransformStruct">AUMRgABCkgAAA</bytes>
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <object class="NSAffineTransform">
+ <bytes key="NSTransformStruct">AUNNAABC+gAAA</bytes>
+ </object>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <object class="NSAffineTransform">
+ <bytes key="NSTransformStruct">P4AAAL+AAABDpIAAwmQAAA</bytes>
+ </object>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <object class="NSAffineTransform">
+ <bytes key="NSTransformStruct">P4AAAL+AAABB8AAAwkgAAA</bytes>
+ </object>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+ <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
</object>
</object>
<object class="NSMutableDictionary" key="unlocalizedProperties">
@@ -7512,7 +7708,7 @@
</object>
</object>
<nil key="sourceID"/>
- <int key="maxID">5861</int>
+ <int key="maxID">5882</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -7767,6 +7963,7 @@
<string>removeNode:</string>
<string>renameNode:</string>
<string>reverseSortFavorites:</string>
+ <string>saveFavorite:</string>
<string>showHelp:</string>
<string>sortFavorites:</string>
<string>updateFavoriteSelection:</string>
@@ -7794,6 +7991,7 @@
<string>id</string>
<string>id</string>
<string>id</string>
+ <string>id</string>
</object>
</object>
<object class="NSMutableDictionary" key="actionInfosByName">
@@ -7814,6 +8012,7 @@
<string>removeNode:</string>
<string>renameNode:</string>
<string>reverseSortFavorites:</string>
+ <string>saveFavorite:</string>
<string>showHelp:</string>
<string>sortFavorites:</string>
<string>updateFavoriteSelection:</string>
@@ -7879,6 +8078,10 @@
<string key="candidateClassName">NSMenuItem</string>
</object>
<object class="IBActionInfo">
+ <string key="name">saveFavorite:</string>
+ <string key="candidateClassName">id</string>
+ </object>
+ <object class="IBActionInfo">
<string key="name">showHelp:</string>
<string key="candidateClassName">id</string>
</object>
@@ -7904,7 +8107,6 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
- <string>addToFavoritesButton</string>
<string>connectButton</string>
<string>connectionDetailsScrollView</string>
<string>connectionInstructionsTextField</string>
@@ -7912,6 +8114,7 @@
<string>connectionSplitView</string>
<string>connectionView</string>
<string>delegate</string>
+ <string>editButtonsView</string>
<string>errorDetailText</string>
<string>errorDetailWindow</string>
<string>exportPanelAccessoryView</string>
@@ -7920,6 +8123,7 @@
<string>helpButton</string>
<string>progressIndicator</string>
<string>progressIndicatorText</string>
+ <string>saveFavoriteButton</string>
<string>socketConnectionFormContainer</string>
<string>socketConnectionSSLDetailsContainer</string>
<string>socketNameField</string>
@@ -7948,17 +8152,18 @@
<string>standardSSLCertificateButton</string>
<string>standardSSLKeyFileButton</string>
<string>standardUserField</string>
+ <string>testConnectButton</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSButton</string>
- <string>NSButton</string>
<string>NSScrollView</string>
<string>NSTextField</string>
<string>NSView</string>
<string>SPSplitView</string>
<string>NSView</string>
<string>id</string>
+ <string>NSView</string>
<string>NSTextView</string>
<string>NSWindow</string>
<string>NSView</string>
@@ -7967,6 +8172,7 @@
<string>NSButton</string>
<string>NSProgressIndicator</string>
<string>NSTextField</string>
+ <string>NSButton</string>
<string>NSView</string>
<string>NSView</string>
<string>NSTextField</string>
@@ -7995,13 +8201,13 @@
<string>NSButton</string>
<string>NSButton</string>
<string>NSTextField</string>
+ <string>NSButton</string>
</object>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
- <string>addToFavoritesButton</string>
<string>connectButton</string>
<string>connectionDetailsScrollView</string>
<string>connectionInstructionsTextField</string>
@@ -8009,6 +8215,7 @@
<string>connectionSplitView</string>
<string>connectionView</string>
<string>delegate</string>
+ <string>editButtonsView</string>
<string>errorDetailText</string>
<string>errorDetailWindow</string>
<string>exportPanelAccessoryView</string>
@@ -8017,6 +8224,7 @@
<string>helpButton</string>
<string>progressIndicator</string>
<string>progressIndicatorText</string>
+ <string>saveFavoriteButton</string>
<string>socketConnectionFormContainer</string>
<string>socketConnectionSSLDetailsContainer</string>
<string>socketNameField</string>
@@ -8045,14 +8253,11 @@
<string>standardSSLCertificateButton</string>
<string>standardSSLKeyFileButton</string>
<string>standardUserField</string>
+ <string>testConnectButton</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBToOneOutletInfo">
- <string key="name">addToFavoritesButton</string>
- <string key="candidateClassName">NSButton</string>
- </object>
- <object class="IBToOneOutletInfo">
<string key="name">connectButton</string>
<string key="candidateClassName">NSButton</string>
</object>
@@ -8081,6 +8286,10 @@
<string key="candidateClassName">id</string>
</object>
<object class="IBToOneOutletInfo">
+ <string key="name">editButtonsView</string>
+ <string key="candidateClassName">NSView</string>
+ </object>
+ <object class="IBToOneOutletInfo">
<string key="name">errorDetailText</string>
<string key="candidateClassName">NSTextView</string>
</object>
@@ -8113,6 +8322,10 @@
<string key="candidateClassName">NSTextField</string>
</object>
<object class="IBToOneOutletInfo">
+ <string key="name">saveFavoriteButton</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
+ <object class="IBToOneOutletInfo">
<string key="name">socketConnectionFormContainer</string>
<string key="candidateClassName">NSView</string>
</object>
@@ -8224,6 +8437,10 @@
<string key="name">standardUserField</string>
<string key="candidateClassName">NSTextField</string>
</object>
+ <object class="IBToOneOutletInfo">
+ <string key="name">testConnectButton</string>
+ <string key="candidateClassName">NSButton</string>
+ </object>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
@@ -8260,6 +8477,14 @@
</object>
</object>
<object class="IBPartialClassDescription">
+ <string key="className">SPFavoriteTextFieldCell</string>
+ <string key="superclassName">ImageAndTextCell</string>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">Source/SPFavoriteTextFieldCell.h</string>
+ </object>
+ </object>
+ <object class="IBPartialClassDescription">
<string key="className">SPFavoritesOutlineView</string>
<string key="superclassName">NSOutlineView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
@@ -8326,14 +8551,6 @@
<string key="minorKey">Source/SPSplitView.h</string>
</object>
</object>
- <object class="IBPartialClassDescription">
- <string key="className">SPTableTextFieldCell</string>
- <string key="superclassName">ImageAndTextCell</string>
- <object class="IBClassDescriptionSource" key="sourceIdentifier">
- <string key="majorKey">IBProjectSource</string>
- <string key="minorKey">Source/SPTableTextFieldCell.h</string>
- </object>
- </object>
</object>
<object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -9100,7 +9317,6 @@
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
- <string>KeyTemplate</string>
<string>NSMenuCheckmark</string>
<string>NSMenuMixedState</string>
<string>NSSwitch</string>
@@ -9109,10 +9325,11 @@
<string>button_add_folder</string>
<string>button_bar_handle</string>
<string>button_bar_spacer</string>
+ <string>key-icon</string>
+ <string>key-icon-alternate</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
- <string>{16, 8}</string>
<string>{11, 11}</string>
<string>{10, 3}</string>
<string>{15, 15}</string>
@@ -9121,6 +9338,8 @@
<string>{32, 23}</string>
<string>{15, 23}</string>
<string>{10, 23}</string>
+ <string>{16, 8}</string>
+ <string>{16, 8}</string>
</object>
</object>
</data>
diff --git a/Resources/English.lproj/ConnectionView.strings b/Resources/English.lproj/ConnectionView.strings
index b6ae4e8c..b1fb2824 100644
--- a/Resources/English.lproj/ConnectionView.strings
+++ b/Resources/English.lproj/ConnectionView.strings
Binary files differ
diff --git a/Resources/English.lproj/Localizable.strings b/Resources/English.lproj/Localizable.strings
index 8fd66cfd..42c07f9d 100644
--- a/Resources/English.lproj/Localizable.strings
+++ b/Resources/English.lproj/Localizable.strings
Binary files differ
diff --git a/Resources/Images/key-icon-alternate.png b/Resources/Images/key-icon-alternate.png
new file mode 100644
index 00000000..4176f58d
--- /dev/null
+++ b/Resources/Images/key-icon-alternate.png
Binary files differ
diff --git a/Resources/Images/key-icon-alternate@2x.png b/Resources/Images/key-icon-alternate@2x.png
new file mode 100644
index 00000000..1a0f68b8
--- /dev/null
+++ b/Resources/Images/key-icon-alternate@2x.png
Binary files differ
diff --git a/Resources/Images/key-icon.png b/Resources/Images/key-icon.png
new file mode 100644
index 00000000..9bd894a4
--- /dev/null
+++ b/Resources/Images/key-icon.png
Binary files differ
diff --git a/Resources/Images/key-icon@2x.png b/Resources/Images/key-icon@2x.png
new file mode 100644
index 00000000..e7a82660
--- /dev/null
+++ b/Resources/Images/key-icon@2x.png
Binary files differ
diff --git a/Resources/Images/quick-connect-icon-white.pdf b/Resources/Images/quick-connect-icon-white.pdf
new file mode 100644
index 00000000..090f4f08
--- /dev/null
+++ b/Resources/Images/quick-connect-icon-white.pdf
Binary files differ
diff --git a/Resources/Images/quick-connect-icon.pdf b/Resources/Images/quick-connect-icon.pdf
new file mode 100644
index 00000000..e9037f51
--- /dev/null
+++ b/Resources/Images/quick-connect-icon.pdf
Binary files differ
diff --git a/Source/SPConnectionController.h b/Source/SPConnectionController.h
index de517fdf..dda04343 100644
--- a/Source/SPConnectionController.h
+++ b/Source/SPConnectionController.h
@@ -42,7 +42,8 @@
SPSplitView
#ifndef SP_REFACTOR /* class decl */
,SPKeychain,
- SPFavoriteNode
+ SPFavoriteNode,
+ SPFavoriteTextFieldCell
#endif
;
@@ -64,6 +65,8 @@
BOOL cancellingConnection;
BOOL isConnecting;
+ BOOL isEditingConnection;
+ BOOL isTestingConnection;
// Standard details
NSInteger previousType;
@@ -141,25 +144,31 @@
IBOutlet NSButton *socketSSLCertificateButton;
IBOutlet NSButton *socketSSLCACertButton;
- IBOutlet NSButton *addToFavoritesButton;
IBOutlet NSButton *connectButton;
+ IBOutlet NSButton *testConnectButton;
IBOutlet NSButton *helpButton;
+ IBOutlet NSButton *saveFavoriteButton;
IBOutlet NSProgressIndicator *progressIndicator;
IBOutlet NSTextField *progressIndicatorText;
IBOutlet NSMenuItem *favoritesSortByMenuItem;
IBOutlet NSView *exportPanelAccessoryView;
-
- BOOL isEditing;
+ IBOutlet NSView *editButtonsView;
+
+ BOOL isEditingItemName;
BOOL reverseFavoritesSort;
BOOL initComplete;
BOOL mySQLConnectionCancelled;
- BOOL favoriteNameFieldWasTouched;
+ BOOL favoriteNameFieldWasAutogenerated;
#ifndef SP_REFACTOR /* ivars */
NSArray *draggedNodes;
NSImage *folderImage;
SPTreeNode *favoritesRoot;
+ SPTreeNode *quickConnectItem;
+
+ SPFavoriteTextFieldCell *quickConnectCell;
+
NSDictionary *currentFavorite;
SPFavoritesController *favoritesController;
SPFavoritesSortItem currentSortItem;
@@ -198,6 +207,7 @@
#endif
@property (readonly, assign) BOOL isConnecting;
+@property (readonly, assign) BOOL isEditingConnection;
// Connection processes
- (IBAction)initiateConnection:(id)sender;
@@ -211,18 +221,19 @@
- (IBAction)updateSSLInterface:(id)sender;
- (IBAction)updateKeyLocationFileVisibility:(id)sender;
- (void)updateSplitViewSize;
+
- (void)resizeTabViewToConnectionType:(NSUInteger)theType animating:(BOOL)animate;
+
- (IBAction)sortFavorites:(id)sender;
- (IBAction)reverseSortFavorites:(NSMenuItem *)sender;
-- (void)resizeTabViewToConnectionType:(NSUInteger)theType animating:(BOOL)animate;
-
// Favorites interaction
- (void)updateFavoriteSelection:(id)sender;
- (NSMutableDictionary *)selectedFavorite;
- (SPTreeNode *)selectedFavoriteNode;
- (NSArray *)selectedFavoriteNodes;
+- (IBAction)saveFavorite:(id)sender;
- (IBAction)addFavorite:(id)sender;
- (IBAction)addFavoriteUsingCurrentDetails:(id)sender;
- (IBAction)addGroup:(id)sender;
diff --git a/Source/SPConnectionController.m b/Source/SPConnectionController.m
index d6078f1d..a6ca5f75 100644
--- a/Source/SPConnectionController.m
+++ b/Source/SPConnectionController.m
@@ -31,6 +31,7 @@
// More info at <http://code.google.com/p/sequel-pro/>
#import "SPConnectionController.h"
+#import "SPConnectionHandler.h"
#import "SPDatabaseDocument.h"
#ifndef SP_REFACTOR /* headers */
@@ -67,6 +68,10 @@ static NSString *SPExportFavoritesFilename = @"SequelProFavorites.plist";
@interface SPConnectionController ()
+// Privately redeclare as read/write to get the synthesized setter
+@property (readwrite, assign) BOOL isEditingConnection;
+
+- (void)_saveCurrentDetailsCreatingNewFavorite:(BOOL)createNewFavorite;
- (BOOL)_checkHost;
#ifndef SP_REFACTOR
- (void)_sortFavorites;
@@ -83,13 +88,22 @@ static NSString *SPExportFavoritesFilename = @"SequelProFavorites.plist";
- (SPTreeNode *)_favoriteNodeForFavoriteID:(NSInteger)favoriteID;
- (NSString *)_stripInvalidCharactersFromString:(NSString *)subject;
-- (void)_updateFavoritePasswordsFromField:(NSControl *)control;
+- (NSString *)_generateNameForConnection;
+
+- (void)_startEditingConnection;
static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2, void *key);
#endif
@end
+@interface SPConnectionController (SPConnectionControllerDelegate)
+
+- (void)_stopEditingConnection;
+
+@end
+
+
@implementation SPConnectionController
@synthesize delegate;
@@ -125,6 +139,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
@synthesize connectionSSHKeychainItemAccount;
@synthesize isConnecting;
+@synthesize isEditingConnection;
#pragma mark -
#pragma mark Connection processes
@@ -143,6 +158,9 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
if (sender == favoritesOutlineView && [favoritesOutlineView clickedRow] <= 0) return;
#endif
+ // If triggered via the "Test Connection" button, set the state - otherwise clear it
+ isTestingConnection = (sender == testConnectButton);
+
// Ensure that host is not empty if this is a TCP/IP or SSH connection
if (([self type] == SPTCPIPConnection || [self type] == SPSSHTunnelConnection) && ![[self host] length]) {
SPBeginAlertSheet(NSLocalizedString(@"Insufficient connection details", @"insufficient details message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [dbDocument parentWindow], self, nil, nil, NSLocalizedString(@"Insufficient details provided to establish a connection. Please enter at least the hostname.", @"insufficient details informative message"));
@@ -212,9 +230,9 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
// Disable the favorites outline view to prevent further connections attempts
[favoritesOutlineView setEnabled:NO];
- [addToFavoritesButton setHidden:YES];
[helpButton setHidden:YES];
[connectButton setEnabled:NO];
+ [testConnectButton setEnabled:NO];
[progressIndicator startAnimation:self];
[progressIndicatorText setHidden:NO];
#endif
@@ -226,7 +244,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
// have been changed or not; if not, leave the mark in place and remove the password from the field
// for increased security.
#ifndef SP_REFACTOR
- if (connectionKeychainItemName) {
+ if (connectionKeychainItemName && !isTestingConnection) {
if ([[keychain getPasswordForName:connectionKeychainItemName account:connectionKeychainItemAccount] isEqualToString:[self password]]) {
[self setPassword:[[NSString string] stringByPaddingToLength:[[self password] length] withString:@"sp" startingAtIndex:0]];
@@ -240,7 +258,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
}
}
- if (connectionSSHKeychainItemName) {
+ if (connectionSSHKeychainItemName && !isTestingConnection) {
if ([[keychain getPasswordForName:connectionSSHKeychainItemName account:connectionSSHKeychainItemAccount] isEqualToString:[self sshPassword]]) {
[self setSshPassword:[[NSString string] stringByPaddingToLength:[[self sshPassword] length] withString:@"sp" startingAtIndex:0]];
[[sshSSHPasswordField undoManager] removeAllActionsWithTarget:sshSSHPasswordField];
@@ -302,10 +320,15 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
SPTreeNode *node = [self selectedFavoriteNode];
if (node) {
+ if (node == quickConnectItem) {
+ return;
+ }
+
// Only proceed to initiate a connection if a leaf node (i.e. a favorite and not a group) was double clicked.
if (![node isGroup]) {
[self initiateConnection:self];
}
+
// Otherwise start editing the group node's name
else {
[favoritesOutlineView editColumn:0 row:[favoritesOutlineView selectedRow] withEvent:nil select:YES];
@@ -325,6 +348,11 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
keySelectionPanel = [NSOpenPanel openPanel];
[keySelectionPanel setShowsHiddenFiles:[prefs boolForKey:SPHiddenKeyFileVisibilityKey]];
+ // If the button was toggled off, ensure editing is ended
+ if ([sender state] == NSOffState) {
+ [self _startEditingConnection];
+ }
+
// Switch details by sender.
// First, SSH keys:
if (sender == sshSSHKeyButton) {
@@ -402,6 +430,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
- (IBAction)updateSSLInterface:(id)sender
{
[self resizeTabViewToConnectionType:[self type] animating:YES];
+ [self _startEditingConnection];
}
/**
@@ -436,7 +465,10 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
- (void)resizeTabViewToConnectionType:(NSUInteger)theType animating:(BOOL)animate
{
NSRect frameRect, targetResizeRect;
- NSInteger additionalFormHeight = 55;
+
+ // Use a magic number which needs to be added to the form when calculating resizes -
+ // including the height of the button areas below.
+ NSInteger additionalFormHeight = 92;
frameRect = [connectionResizeContainer frame];
@@ -529,6 +561,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
currentFavorite = [fav copy];
[connectionResizeContainer setHidden:NO];
+ [self _stopEditingConnection];
// Set up the type, also storing it in the previous type store to prevent type "changes" triggering actions
NSUInteger connectionType = ([fav objectForKey:SPFavoriteTypeKey] ? [[fav objectForKey:SPFavoriteTypeKey] integerValue] : SPTCPIPConnection);
@@ -639,6 +672,14 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
}
/**
+ * Saves the current connection favorite.
+ */
+- (IBAction)saveFavorite:(id)sender
+{
+ [self _saveCurrentDetailsCreatingNewFavorite:NO];
+}
+
+/**
* Adds a new connection favorite.
*/
- (IBAction)addFavorite:(id)sender
@@ -687,7 +728,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
[[[[NSApp delegate] preferenceController] generalPreferencePane] updateDefaultFavoritePopup];
- favoriteNameFieldWasTouched = NO;
+ favoriteNameFieldWasAutogenerated = YES;
[favoritesOutlineView editColumn:0 row:[favoritesOutlineView selectedRow] withEvent:nil select:YES];
}
@@ -698,98 +739,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
*/
- (IBAction)addFavoriteUsingCurrentDetails:(id)sender
{
- NSString *thePassword, *theSSHPassword;
- NSNumber *favoriteid = [self _createNewFavoriteID];
- NSString *favoriteName = [[self name] length] ? [self name] : [NSString stringWithFormat:@"%@@%@", ([self user] && [[self user] length])?[self user] : @"anonymous", (([self type] == SPSocketConnection) ? @"localhost" : [self host])];
-
- if (![[self name] length] && [self database] && ![[self database] isEqualToString:@""]) {
- favoriteName = [NSString stringWithFormat:@"%@ %@", [self database], favoriteName];
- }
-
- // Ensure that host is not empty if this is a TCP/IP or SSH connection
- if (([self type] == SPTCPIPConnection || [self type] == SPSSHTunnelConnection) && ![[self host] length]) {
- SPBeginAlertSheet(NSLocalizedString(@"Insufficient connection details", @"insufficient details message"),
- NSLocalizedString(@"OK", @"OK button"), nil, nil, [dbDocument parentWindow], nil, nil, nil,
- NSLocalizedString(@"Insufficient details provided to establish a connection. Please provide at least a host.", @"insufficient details informative message"));
- return;
- }
-
- // If SSH is enabled, ensure that the SSH host is not nil
- if ([self type] == SPSSHTunnelConnection && ![[self sshHost] length]) {
- SPBeginAlertSheet(NSLocalizedString(@"Insufficient connection details", @"insufficient details message"),
- NSLocalizedString(@"OK", @"OK button"), nil, nil, [dbDocument parentWindow], nil, nil, nil,
- NSLocalizedString(@"Please enter the hostname for the SSH Tunnel, or disable the SSH Tunnel.", @"message of panel when ssh details are incomplete"));
- return;
- }
-
- // Ensure that a socket connection is not inadvertently used
- if (![self _checkHost]) return;
-
- // Construct the favorite details - cannot use only dictionaryWithObjectsAndKeys for possible nil values.
- NSMutableDictionary *newFavorite = [NSMutableDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithInteger:[self type]], SPFavoriteTypeKey,
- favoriteName, SPFavoriteNameKey,
- favoriteid, SPFavoriteIDKey,
- nil];
-
- // Standard details
- if ([self host]) [newFavorite setObject:[self host] forKey:SPFavoriteHostKey];
- if ([self socket]) [newFavorite setObject:[self socket] forKey:SPFavoriteSocketKey];
- if ([self user]) [newFavorite setObject:[self user] forKey:SPFavoriteUserKey];
- if ([self port]) [newFavorite setObject:[self port] forKey:SPFavoritePortKey];
- if ([self database]) [newFavorite setObject:[self database] forKey:SPFavoriteDatabaseKey];
-
- // SSL details
- if ([self useSSL]) [newFavorite setObject:[NSNumber numberWithInteger:[self useSSL]] forKey:SPFavoriteUseSSLKey];
- [newFavorite setObject:[NSNumber numberWithInteger:[self sslKeyFileLocationEnabled]] forKey:SPFavoriteSSLKeyFileLocationEnabledKey];
- if ([self sslKeyFileLocation]) [newFavorite setObject:[self sslKeyFileLocation] forKey:SPFavoriteSSLKeyFileLocationKey];
- [newFavorite setObject:[NSNumber numberWithInteger:[self sslCertificateFileLocationEnabled]] forKey:SPFavoriteSSLCertificateFileLocationEnabledKey];
- if ([self sslCertificateFileLocation]) [newFavorite setObject:[self sslCertificateFileLocation] forKey:SPFavoriteSSLCertificateFileLocationKey];
- [newFavorite setObject:[NSNumber numberWithInteger:[self sslCACertFileLocationEnabled]] forKey:SPFavoriteSSLCACertFileLocationEnabledKey];
- if ([self sslCACertFileLocation]) [newFavorite setObject:[self sslCACertFileLocation] forKey:SPFavoriteSSLCACertFileLocationKey];
-
- // SSH details
- if ([self sshHost]) [newFavorite setObject:[self sshHost] forKey:SPFavoriteSSHHostKey];
- if ([self sshUser]) [newFavorite setObject:[self sshUser] forKey:SPFavoriteSSHUserKey];
- if ([self sshPort]) [newFavorite setObject:[self sshPort] forKey:SPFavoriteSSHPortKey];
- [newFavorite setObject:[NSNumber numberWithInteger:[self sshKeyLocationEnabled]] forKey:SPFavoriteSSHKeyLocationEnabledKey];
- if ([self sshKeyLocation]) [newFavorite setObject:[self sshKeyLocation] forKey:SPFavoriteSSHKeyLocationKey];
-
- // Add the password to keychain as appropriate
- thePassword = [self password];
-
- if (mySQLConnection && connectionKeychainItemName) {
- thePassword = [keychain getPasswordForName:connectionKeychainItemName account:connectionKeychainItemAccount];
- }
-
- if (thePassword && (![thePassword isEqualToString:@""])) {
- [keychain addPassword:thePassword
- forName:[keychain nameForFavoriteName:favoriteName id:[NSString stringWithFormat:@"%lld", [favoriteid longLongValue]]]
- account:[keychain accountForUser:[self user] host:(([self type] == SPSocketConnection) ? @"localhost" : [self host]) database:[self database]]];
- }
-
- // Add the SSH password to keychain as appropriate
- theSSHPassword = [self sshPassword];
-
- if (mySQLConnection && connectionSSHKeychainItemName) {
- theSSHPassword = [keychain getPasswordForName:connectionSSHKeychainItemName account:connectionSSHKeychainItemAccount];
- }
-
- if (theSSHPassword && (![theSSHPassword isEqualToString:@""])) {
- [keychain addPassword:theSSHPassword
- forName:[keychain nameForSSHForFavoriteName:favoriteName id:[NSString stringWithFormat:@"%lld", [favoriteid longLongValue]]]
- account:[keychain accountForSSHUser:[self sshUser] sshHost:[self sshHost]]];
- }
-
- SPTreeNode *selectedNode = [self selectedFavoriteNode];
-
- SPTreeNode *node = [favoritesController addFavoriteNodeWithData:newFavorite asChildOfNode:[selectedNode isGroup] ? selectedNode : nil];
-
- [self _reloadFavoritesViewData];
- [self _selectNode:node];
-
- // Update the favorites popup button in the preferences
- [[[[NSApp delegate] preferenceController] generalPreferencePane] updateDefaultFavoritePopup];
+ [self _saveCurrentDetailsCreatingNewFavorite:YES];
}
/**
@@ -805,9 +755,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
[self _reloadFavoritesViewData];
[self _selectNode:node];
-
- isEditing = YES;
-
+
[favoritesOutlineView editColumn:0 row:[favoritesOutlineView selectedRow] withEvent:nil select:YES];
}
@@ -999,26 +947,9 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
- NSMutableDictionary *selectedFavorite = [self selectedFavorite];
- if (!selectedFavorite) return;
-
- id oldObject = [change objectForKey:NSKeyValueChangeOldKey];
- id newObject = [change objectForKey:NSKeyValueChangeNewKey];
-
- if (oldObject != newObject) {
- [selectedFavorite setObject:![newObject isNSNull] ? newObject : @"" forKey:keyPath];
-
- // Save the new data to disk
- [favoritesController saveFavorites];
-
- [self _reloadFavoritesViewData];
-
- if ([keyPath isEqualToString:SPFavoriteNameKey]) {
- [[NSNotificationCenter defaultCenter] postNotificationName:SPConnectionFavoritesChangedNotification object:self];
- }
- }
}
+
#pragma mark -
#pragma mark Sheet methods
@@ -1082,6 +1013,8 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
[self setSslCACertFileLocation:abbreviatedFileName];
}
+
+ [self _startEditingConnection];
}
/**
@@ -1119,15 +1052,9 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
if (returnCode == NSAlertAlternateReturn) {
[self setType:SPSocketConnection];
[self setHost:@""];
-#ifndef SP_REFACTOR
- [self _updateFavoritePasswordsFromField:standardSQLHostField];
-#endif
}
else {
[self setHost:@"127.0.0.1"];
-#ifndef SP_REFACTOR
- [self _updateFavoritePasswordsFromField:standardSQLHostField];
-#endif
}
}
@@ -1135,6 +1062,245 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
#pragma mark Private API
/**
+ * Take the current details and either save them to the currently selected
+ * favourite, or create a new connection favourite using them.
+ * If creating a new favourite, also select it and ensure the selected
+ * favourite is visible.
+ */
+- (void)_saveCurrentDetailsCreatingNewFavorite:(BOOL)createNewFavorite
+{
+
+ // Complete any active editing
+ if ([[connectionView window] firstResponder]) {
+ [[connectionView window] endEditingFor:[[connectionView window] firstResponder]];
+ }
+
+
+ // Ensure that host is not empty if this is a TCP/IP or SSH connection
+ if (([self type] == SPTCPIPConnection || [self type] == SPSSHTunnelConnection) && ![[self host] length]) {
+ SPBeginAlertSheet(NSLocalizedString(@"Insufficient connection details", @"insufficient details message"),
+ NSLocalizedString(@"OK", @"OK button"), nil, nil, [dbDocument parentWindow], nil, nil, nil,
+ NSLocalizedString(@"Insufficient details provided to establish a connection. Please provide at least a host.", @"insufficient details informative message"));
+ return;
+ }
+
+ // If SSH is enabled, ensure that the SSH host is not nil
+ if ([self type] == SPSSHTunnelConnection && ![[self sshHost] length]) {
+ SPBeginAlertSheet(NSLocalizedString(@"Insufficient connection details", @"insufficient details message"),
+ NSLocalizedString(@"OK", @"OK button"), nil, nil, [dbDocument parentWindow], nil, nil, nil,
+ NSLocalizedString(@"Please enter the hostname for the SSH Tunnel, or disable the SSH Tunnel.", @"message of panel when ssh details are incomplete"));
+ return;
+ }
+
+ // Ensure that a socket connection is not inadvertently used
+ if (![self _checkHost]) return;
+
+
+ // Set up the favourite, or get the mutable dictionary for the current favourite.
+ NSMutableDictionary *theFavorite;
+ if (createNewFavorite) {
+ theFavorite = [NSMutableDictionary dictionary];
+ [theFavorite setObject:[self _createNewFavoriteID] forKey:SPFavoriteIDKey];
+ } else {
+ if (!currentFavorite) {
+ [NSException raise:NSInternalInconsistencyException format:@"Tried to save a current favourite with no currentFavorite"];
+ }
+ theFavorite = [self selectedFavorite];
+ }
+
+ // Set the name - either taking the provided name, or generating one.
+ if ([[self name] length]) {
+ [theFavorite setObject:[self name] forKey:SPFavoriteNameKey];
+ } else {
+ NSString *favoriteName = [self _generateNameForConnection];
+ if (!favoriteName) {
+ favoriteName = NSLocalizedString(@"Untitled", @"Name for an untitled connection");
+ }
+ [theFavorite setObject:favoriteName forKey:SPFavoriteNameKey];
+ }
+
+ // Set standard details for the connection
+ [theFavorite setObject:[NSNumber numberWithInteger:[self type]] forKey:SPFavoriteTypeKey];
+ if ([self host]) {
+ [theFavorite setObject:[self host] forKey:SPFavoriteHostKey];
+ }
+ if ([self socket]) {
+ [theFavorite setObject:[self socket] forKey:SPFavoriteSocketKey];
+ }
+ if ([self user]) {
+ [theFavorite setObject:[self user] forKey:SPFavoriteUserKey];
+ }
+ if ([self port]) {
+ [theFavorite setObject:[self port] forKey:SPFavoritePortKey];
+ }
+ if ([self database]) {
+ [theFavorite setObject:[self database] forKey:SPFavoriteDatabaseKey];
+ }
+
+ // SSL details
+ if ([self useSSL]) {
+ [theFavorite setObject:[NSNumber numberWithInteger:[self useSSL]] forKey:SPFavoriteUseSSLKey];
+ }
+ [theFavorite setObject:[NSNumber numberWithInteger:[self sslKeyFileLocationEnabled]] forKey:SPFavoriteSSLKeyFileLocationEnabledKey];
+ if ([self sslKeyFileLocation]) {
+ [theFavorite setObject:[self sslKeyFileLocation] forKey:SPFavoriteSSLKeyFileLocationKey];
+ }
+ [theFavorite setObject:[NSNumber numberWithInteger:[self sslCertificateFileLocationEnabled]] forKey:SPFavoriteSSLCertificateFileLocationEnabledKey];
+ if ([self sslCertificateFileLocation]) {
+ [theFavorite setObject:[self sslCertificateFileLocation] forKey:SPFavoriteSSLCertificateFileLocationKey];
+ }
+ [theFavorite setObject:[NSNumber numberWithInteger:[self sslCACertFileLocationEnabled]] forKey:SPFavoriteSSLCACertFileLocationEnabledKey];
+ if ([self sslCACertFileLocation]) {
+ [theFavorite setObject:[self sslCACertFileLocation] forKey:SPFavoriteSSLCACertFileLocationKey];
+ }
+
+ // SSH details
+ if ([self sshHost]) {
+ [theFavorite setObject:[self sshHost] forKey:SPFavoriteSSHHostKey];
+ }
+ if ([self sshUser]) {
+ [theFavorite setObject:[self sshUser] forKey:SPFavoriteSSHUserKey];
+ }
+ if ([self sshPort]) {
+ [theFavorite setObject:[self sshPort] forKey:SPFavoriteSSHPortKey];
+ }
+ [theFavorite setObject:[NSNumber numberWithInteger:[self sshKeyLocationEnabled]] forKey:SPFavoriteSSHKeyLocationEnabledKey];
+ if ([self sshKeyLocation]) {
+ [theFavorite setObject:[self sshKeyLocation] forKey:SPFavoriteSSHKeyLocationKey];
+ }
+
+
+ /**
+ * Password handling for the SQL connection
+ */
+ NSString *oldKeychainName, *oldKeychainAccount, *newKeychainName, *newKeychainAccount;;
+ NSString *oldHostnameForPassword = ([[currentFavorite objectForKey:SPFavoriteTypeKey] integerValue] == SPSocketConnection) ? @"localhost" : [currentFavorite objectForKey:SPFavoriteHostKey];
+ NSString *newHostnameForPassword = ([self type] == SPSocketConnection) ? @"localhost" : [self host];
+
+ // Grab the password for this connection
+ // Add the password to keychain as appropriate
+ NSString *sqlPassword = [self password];
+ if (mySQLConnection && connectionKeychainItemName) {
+ sqlPassword = [keychain getPasswordForName:connectionKeychainItemName account:connectionKeychainItemAccount];
+ }
+
+ // If creating a new favourite, always add the password to the keychain if it's set
+ if (createNewFavorite && [sqlPassword length]) {
+ [keychain addPassword:sqlPassword
+ forName:[keychain nameForFavoriteName:[theFavorite objectForKey:SPFavoriteNameKey] id:[theFavorite objectForKey:SPFavoriteIDKey]]
+ account:[keychain accountForUser:[self user] host:newHostnameForPassword database:[self database]]];
+ }
+
+ // If not creating a new favourite...
+ if (!createNewFavorite) {
+
+ // Get the old keychain name and account strings
+ oldKeychainName = [keychain nameForFavoriteName:[currentFavorite objectForKey:SPFavoriteNameKey] id:[currentFavorite objectForKey:SPFavoriteIDKey]];
+ oldKeychainAccount = [keychain accountForUser:[currentFavorite objectForKey:SPFavoriteUserKey] host:oldHostnameForPassword database:[currentFavorite objectForKey:SPFavoriteDatabaseKey]];
+
+ // If there's no new password, remove the old item from the keychain
+ if (![sqlPassword length]) {
+ [keychain deletePasswordForName:oldKeychainName account:oldKeychainAccount];
+
+ // Otherwise, set up the new keychain name and account strings and create or edit the item
+ } else {
+ newKeychainName = [keychain nameForFavoriteName:[theFavorite objectForKey:SPFavoriteNameKey] id:[theFavorite objectForKey:SPFavoriteIDKey]];
+ newKeychainAccount = [keychain accountForUser:[self user] host:newHostnameForPassword database:[self database]];
+ if ([keychain passwordExistsForName:oldKeychainName account:oldKeychainAccount]) {
+ [keychain updateItemWithName:oldKeychainName account:oldKeychainAccount toName:newKeychainName account:newKeychainAccount password:sqlPassword];
+ } else {
+ [keychain addPassword:sqlPassword forName:newKeychainName account:newKeychainAccount];
+ }
+ }
+ }
+ sqlPassword = nil;
+
+
+ /**
+ * Password handling for the SSH connection
+ */
+ NSString *theSSHPassword = [self sshPassword];
+ if (mySQLConnection && connectionSSHKeychainItemName) {
+ theSSHPassword = [keychain getPasswordForName:connectionSSHKeychainItemName account:connectionSSHKeychainItemAccount];
+ }
+
+ // If creating a new favourite, always add the password if it's set
+ if (createNewFavorite && [theSSHPassword length]) {
+ [keychain addPassword:theSSHPassword
+ forName:[keychain nameForSSHForFavoriteName:[theFavorite objectForKey:SPFavoriteNameKey] id:[theFavorite objectForKey:SPFavoriteIDKey]]
+ account:[keychain accountForSSHUser:[self sshUser] sshHost:[self sshHost]]];
+ }
+
+ // If not creating a new favourite...
+ if (!createNewFavorite) {
+
+ // Get the old keychain name and account strings
+ oldKeychainName = [keychain nameForSSHForFavoriteName:[currentFavorite objectForKey:SPFavoriteNameKey] id:[currentFavorite objectForKey:SPFavoriteIDKey]];
+ oldKeychainAccount = [keychain accountForSSHUser:[currentFavorite objectForKey:SPFavoriteSSHUserKey] sshHost:[currentFavorite objectForKey:SPFavoriteSSHHostKey]];
+
+ // If there's no new password, remove the old item from the keychain
+ if (![theSSHPassword length]) {
+ [keychain deletePasswordForName:oldKeychainName account:oldKeychainAccount];
+
+ // Otherwise, set up the new keychain name and account strings and create or edit the item
+ } else {
+ newKeychainName = [keychain nameForSSHForFavoriteName:[theFavorite objectForKey:SPFavoriteNameKey] id:[theFavorite objectForKey:SPFavoriteIDKey]];
+ newKeychainAccount = [keychain accountForSSHUser:[self sshUser] sshHost:[self sshHost]];
+ if ([keychain passwordExistsForName:oldKeychainName account:oldKeychainAccount]) {
+ [keychain updateItemWithName:oldKeychainName account:oldKeychainAccount toName:newKeychainName account:newKeychainAccount password:theSSHPassword];
+ } else {
+ [keychain addPassword:theSSHPassword forName:newKeychainName account:newKeychainAccount];
+ }
+ }
+ }
+ theSSHPassword = nil;
+
+
+ /**
+ * Saving the connection
+ */
+
+ // If creating the connection, add to the favourites tree.
+ if (createNewFavorite) {
+ SPTreeNode *selectedNode = [self selectedFavoriteNode];
+ SPTreeNode *parentNode = nil;
+
+ // If the current node is a group node, create the favorite as a child of it
+ if ([selectedNode isGroup]) {
+ parentNode = selectedNode;
+
+ // Otherwise, create the new node as a sibling of the selected node if possible
+ } else if ([selectedNode parentNode] && [selectedNode parentNode] != favoritesRoot) {
+ parentNode = (SPTreeNode *)[selectedNode parentNode];
+ }
+
+ // Add the new node and select it
+ SPTreeNode *newNode = [favoritesController addFavoriteNodeWithData:theFavorite asChildOfNode:parentNode];
+ [self _reloadFavoritesViewData];
+ [self _selectNode:newNode];
+
+ // Update the favorites popup button in the preferences
+ [[[[NSApp delegate] preferenceController] generalPreferencePane] updateDefaultFavoritePopup];
+
+ // Otherwise, if editing the favourite, update it
+ } else {
+ [[[self selectedFavoriteNode] representedObject] setNodeFavorite:theFavorite];
+
+ // Save the new data to disk
+ [favoritesController saveFavorites];
+
+ [self _stopEditingConnection];
+
+ if (currentFavorite) [currentFavorite release], currentFavorite = nil;
+ currentFavorite = [theFavorite copy];
+
+ [self _reloadFavoritesViewData];
+ }
+
+ [[NSNotificationCenter defaultCenter] postNotificationName:SPConnectionFavoritesChangedNotification object:self];
+}
+
+/**
* Check the host field and ensure it isn't set to 'localhost' for non-socket connections.
*/
- (BOOL)_checkHost
@@ -1281,16 +1447,12 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
}
// Update the name for newly added favorites if not already touched by the user, by triggering a KVO update
- if (![[self name] length]) {
- [self setName:[NSString stringWithFormat:@"%@@%@",
- ([favorite objectForKey:SPFavoriteUserKey]) ? [favorite objectForKey:SPFavoriteUserKey] : @"",
- ((previousType == SPSocketConnection) ? @"localhost" :
- (([favorite objectForKey:SPFavoriteHostKey]) ? [favorite valueForKeyPath:SPFavoriteHostKey] : @""))
- ]];
+ if (![[self name] length] || favoriteNameFieldWasAutogenerated) {
+ NSString *favoriteName = [self _generateNameForConnection];
+ if (favoriteName) {
+ [self setName:favoriteName];
+ }
}
-
- // Trigger a password change in response to host changes
- [self _updateFavoritePasswordsFromField:nil];
}
/**
@@ -1350,13 +1512,12 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
[dbDocument setIsProcessing:NO];
// Reset the UI
- [addToFavoritesButton setHidden:NO];
- [addToFavoritesButton display];
[helpButton setHidden:NO];
[helpButton display];
[connectButton setTitle:NSLocalizedString(@"Connect", @"connect button")];
[connectButton setEnabled:YES];
[connectButton display];
+ [testConnectButton setEnabled:YES];
[progressIndicator stopAnimation:self];
[progressIndicator display];
[progressIndicatorText setHidden:YES];
@@ -1463,6 +1624,8 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
SPTreeNode *favoriteNode = nil;
if (!favoritesRoot) return favoriteNode;
+
+ if (!favoriteID) return quickConnectItem;
for (SPTreeNode *node in [favoritesRoot allChildLeafs])
{
@@ -1486,106 +1649,70 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
return [result stringByReplacingOccurrencesOfString:@"\n" withString:@""];
}
-#ifndef SP_REFACTOR
/**
- * Check all fields used in the keychain names against the old values for that
- * favorite, and update the keychain names to match if necessary.
- * If an (optional) recognised password field is supplied, that field is assumed
- * to have changed and is used to supply the new value.
+ * Generate a name for the current connection based on any other populated details.
+ * Currently uses the host and database fields.
+ * If a name cannot be generated because there are insufficient other details, returns nil.
*/
-- (void)_updateFavoritePasswordsFromField:(NSControl *)control
+- (NSString *)_generateNameForConnection
{
- if (!currentFavorite) return;
-
- NSDictionary *oldFavorite = currentFavorite;
- NSDictionary *newFavorite = [[[self selectedFavoriteNode] representedObject] nodeFavorite];
-
- NSString *passwordValue;
- NSString *oldKeychainName, *newKeychainName;
- NSString *oldKeychainAccount, *newKeychainAccount;
- NSString *oldHostnameForPassword = ([[oldFavorite objectForKey:SPFavoriteTypeKey] integerValue] == SPSocketConnection) ? @"localhost" : [oldFavorite objectForKey:SPFavoriteHostKey];
- NSString *newHostnameForPassword = ([[newFavorite objectForKey:SPFavoriteTypeKey] integerValue] == SPSocketConnection) ? @"localhost" : [newFavorite objectForKey:SPFavoriteHostKey];
-
- // SQL passwords are indexed by name, host, user and database. If any of these
- // have changed, or a standard password field has, alter the keychain item to match.
- if (![[oldFavorite objectForKey:SPFavoriteNameKey] isEqualToString:[newFavorite objectForKey:SPFavoriteNameKey]] ||
- ![oldHostnameForPassword isEqualToString:newHostnameForPassword] ||
- ![[oldFavorite objectForKey:SPFavoriteUserKey] isEqualToString:[newFavorite objectForKey:SPFavoriteUserKey]] ||
- ![[oldFavorite objectForKey:SPFavoriteDatabaseKey] isEqualToString:[newFavorite objectForKey:SPFavoriteDatabaseKey]] ||
- control == standardPasswordField || control == socketPasswordField || control == sshPasswordField)
- {
- // Determine the correct password field to read the password from, defaulting to standard
- if (control == socketPasswordField) {
- passwordValue = [socketPasswordField stringValue];
- }
- else if (control == sshPasswordField) {
- passwordValue = [sshPasswordField stringValue];
- }
- else {
- passwordValue = [standardPasswordField stringValue];
- }
-
- // Get the old keychain name and account strings
- oldKeychainName = [keychain nameForFavoriteName:[oldFavorite objectForKey:SPFavoriteNameKey] id:[newFavorite objectForKey:SPFavoriteIDKey]];
- oldKeychainAccount = [keychain accountForUser:[oldFavorite objectForKey:SPFavoriteUserKey] host:oldHostnameForPassword database:[oldFavorite objectForKey:SPFavoriteDatabaseKey]];
-
- // If there's no new password, remove the old item from the keychain
- if (![passwordValue length]) {
- [keychain deletePasswordForName:oldKeychainName account:oldKeychainAccount];
+ NSString *aName;
- // Otherwise, set up the new keychain name and account strings and create or edit the item
- } else {
- newKeychainName = [keychain nameForFavoriteName:[newFavorite objectForKey:SPFavoriteNameKey] id:[newFavorite objectForKey:SPFavoriteIDKey]];
- newKeychainAccount = [keychain accountForUser:[newFavorite objectForKey:SPFavoriteUserKey] host:newHostnameForPassword database:[newFavorite objectForKey:SPFavoriteDatabaseKey]];
- if ([keychain passwordExistsForName:oldKeychainName account:oldKeychainAccount]) {
- [keychain updateItemWithName:oldKeychainName account:oldKeychainAccount toName:newKeychainName account:newKeychainAccount password:passwordValue];
- } else {
- [keychain addPassword:passwordValue forName:newKeychainName account:newKeychainAccount];
- }
- }
-
- // Synch password changes
- [standardPasswordField setStringValue:passwordValue?passwordValue:@""];
- [socketPasswordField setStringValue:passwordValue?passwordValue:@""];
- [sshPasswordField setStringValue:passwordValue?passwordValue:@""];
-
- passwordValue = @"";
+ if ([self type] != SPSocketConnection && ![[self host] length]) {
+ return nil;
}
-
- // If SSH account/password details have changed, update the keychain to match
- if (![[oldFavorite objectForKey:SPFavoriteNameKey] isEqualToString:[newFavorite objectForKey:SPFavoriteNameKey]] ||
- ![[oldFavorite objectForKey:SPFavoriteSSHHostKey] isEqualToString:[newFavorite objectForKey:SPFavoriteSSHHostKey]] ||
- ![[oldFavorite objectForKey:SPFavoriteSSHUserKey] isEqualToString:[newFavorite objectForKey:SPFavoriteSSHUserKey]] ||
- control == sshSSHPasswordField)
- {
- // Get the old keychain name and account strings
- oldKeychainName = [keychain nameForSSHForFavoriteName:[oldFavorite objectForKey:SPFavoriteNameKey] id:[newFavorite objectForKey:SPFavoriteIDKey]];
- oldKeychainAccount = [keychain accountForSSHUser:[oldFavorite objectForKey:SPFavoriteSSHUserKey] sshHost:[oldFavorite objectForKey:SPFavoriteSSHHostKey]];
- // If there's no new password, delete the keychain item
- if (![[sshSSHPasswordField stringValue] length]) {
- [keychain deletePasswordForName:oldKeychainName account:oldKeychainAccount];
+ aName = ([self type] == SPSocketConnection) ? @"localhost" : [self host];
- // Otherwise, set up the new keychain name and account strings and create or update the keychain item
- } else {
- newKeychainName = [keychain nameForSSHForFavoriteName:[newFavorite objectForKey:SPFavoriteNameKey] id:[newFavorite objectForKey:SPFavoriteIDKey]];
- newKeychainAccount = [keychain accountForSSHUser:[newFavorite objectForKey:SPFavoriteSSHUserKey] sshHost:[newFavorite objectForKey:SPFavoriteSSHHostKey]];
- if ([keychain passwordExistsForName:oldKeychainName account:oldKeychainAccount]) {
- [keychain updateItemWithName:oldKeychainName account:oldKeychainAccount toName:newKeychainName account:newKeychainAccount password:[sshSSHPasswordField stringValue]];
- } else {
- [keychain addPassword:[sshSSHPasswordField stringValue] forName:newKeychainName account:newKeychainAccount];
- }
- }
+ if ([[self database] length]) {
+ aName = [NSString stringWithFormat:@"%@/%@", aName, [self database]];
}
-
- // Update the current favorite
- if (currentFavorite) [currentFavorite release], currentFavorite = nil;
-
- if ([[favoritesOutlineView selectedRowIndexes] count]) {
- currentFavorite = [[[[self selectedFavoriteNode] representedObject] nodeFavorite] copy];
+
+ return aName;
+}
+
+
+/**
+ * If editing is not already active, mark editing as starting, triggering UI updates
+ * to match.
+ */
+- (void)_startEditingConnection
+{
+
+ // If not connecting, hide the connection status text to reflect changes
+ if (!isConnecting) {
+ [progressIndicatorText setHidden:YES];
}
+
+ if (isEditingConnection) return;
+
+ // Fade and move the edit button area in
+ [editButtonsView setAlphaValue:0.0];
+ [editButtonsView setHidden:NO];
+ [editButtonsView setFrameOrigin:NSMakePoint([editButtonsView frame].origin.x, [editButtonsView frame].origin.y - 40)];
+ [[editButtonsView animator] setFrameOrigin:NSMakePoint([editButtonsView frame].origin.x, [editButtonsView frame].origin.y + 40)];
+ [[editButtonsView animator] setAlphaValue:1.0];
+
+ // Update the "Save" button state as appropriate
+ [saveFavoriteButton setEnabled:([self selectedFavorite] != nil)];
+
+ // Show the area to allow saving the changes
+ [self setIsEditingConnection:YES];
+ [favoritesOutlineView setNeedsDisplayInRect:[favoritesOutlineView rectOfRow:[favoritesOutlineView selectedRow]]];
+}
+
+/**
+ * If editing is active, mark editing as complete, triggering UI updates to match.
+ */
+- (void)_stopEditingConnection
+{
+ if (!isEditingConnection) return;
+
+ [editButtonsView setHidden:YES];
+ [progressIndicatorText setHidden:YES];
+
+ [self setIsEditingConnection:NO];
}
-#endif
#pragma mark -
@@ -1624,6 +1751,8 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2,
#ifndef SP_REFACTOR
[folderImage release], folderImage = nil;
+ [quickConnectItem release], quickConnectItem = nil;
+ [quickConnectCell release], quickConnectCell = nil;
#endif
for (id retainedObject in nibObjectsToRelease) [retainedObject release];
diff --git a/Source/SPConnectionControllerDataSource.m b/Source/SPConnectionControllerDataSource.m
index 86f6db49..d7f3d235 100644
--- a/Source/SPConnectionControllerDataSource.m
+++ b/Source/SPConnectionControllerDataSource.m
@@ -39,7 +39,6 @@
@interface SPConnectionController ()
- (void)_reloadFavoritesViewData;
-- (void)_updateFavoritePasswordsFromField:(NSControl *)control;
@end
@@ -47,16 +46,42 @@
#ifndef SP_REFACTOR
+/**
+ * Return the number of children for the specified item in the favourites tree.
+ * Note that to support the "Quick Connect" entry, the returned count is amended
+ * for the top level.
+ */
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
SPTreeNode *node = (item == nil ? favoritesRoot : (SPTreeNode *)item);
-
+
+ // If at the root, return the count plus one for the "Quick Connect" entry
+ if (!item) {
+ return [[node childNodes] count] + 1;
+ }
+
return [[node childNodes] count];
}
+/**
+ * Return the branch at the specified index of a supplied tree level.
+ * Note that to support the "Quick Connect" entry, children of the top level
+ * have their offsets amended.
+ */
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)childIndex ofItem:(id)item
{
+
+ // For the top level of the tree, return the "Quick Connect" child for position zero;
+ // amend all other positions to compensate for the faked position.
+ if (!item) {
+ if (childIndex == 0) {
+ return quickConnectItem;
+ }
+ childIndex--;
+ }
+
SPTreeNode *node = (item == nil ? favoritesRoot : (SPTreeNode *)item);
+
return NSArrayObjectAtIndex([node childNodes], childIndex);
}
@@ -83,11 +108,10 @@
SPTreeNode *node = [self selectedFavoriteNode];
if (![node isGroup]) {
+
// Updating the name triggers a KVO update
- [self setName:newName];
-
- // Update associated Keychain items
- [self _updateFavoritePasswordsFromField:nil];
+ [self setName:newName];
+ [self saveFavorite:self];
}
else {
[[node representedObject] setNodeName:newName];
diff --git a/Source/SPConnectionControllerDelegate.m b/Source/SPConnectionControllerDelegate.m
index 30b602cd..e18c43ab 100644
--- a/Source/SPConnectionControllerDelegate.m
+++ b/Source/SPConnectionControllerDelegate.m
@@ -43,19 +43,27 @@
#endif
static NSString *SPDatabaseImage = @"database-small";
+static NSString *SPQuickConnectImage = @"quick-connect-icon.pdf";
+static NSString *SPQuickConnectImageWhite = @"quick-connect-icon-white.pdf";
@interface SPConnectionController ()
+// Privately redeclare as read/write to get the synthesized setter
+@property (readwrite, assign) BOOL isEditingConnection;
+
- (void)_checkHost;
- (void)_sortFavorites;
- (void)_favoriteTypeDidChange;
- (void)_reloadFavoritesViewData;
-- (void)_updateFavoritePasswordsFromField:(NSControl *)control;
- (NSString *)_stripInvalidCharactersFromString:(NSString *)subject;
+- (void)_startEditingConnection;
+- (void)_stopEditingConnection;
- (void)_setNodeIsExpanded:(BOOL)expanded fromNotification:(NSNotification *)notification;
+- (NSString *)_generateNameForConnection;
+
@end
@implementation SPConnectionController (SPConnectionControllerDelegate)
@@ -88,25 +96,27 @@ static NSString *SPDatabaseImage = @"database-small";
return ([[(SPTreeNode *)item parentNode] parentNode] == nil);
}
+- (void)outlineViewSelectionIsChanging:(NSNotification *)notification
+{
+ if (isEditingConnection) {
+ [self _stopEditingConnection];
+ [[notification object] setNeedsDisplay:YES];
+ }
+}
+
- (void)outlineViewSelectionDidChange:(NSNotification *)notification
-{
+{
NSInteger selected = [favoritesOutlineView numberOfSelectedRows];
-
- if (selected == 1) {
- SPTreeNode *node = [self selectedFavoriteNode];
-
- [self updateFavoriteSelection:self];
+ if (isEditingConnection) {
+ [self _stopEditingConnection];
+ [[notification object] setNeedsDisplay:YES];
+ }
- if (![node isGroup]) {
- [addToFavoritesButton setEnabled:NO];
+ if (selected == 1) {
+ [self updateFavoriteSelection:self];
- favoriteNameFieldWasTouched = YES;
- }
- else {
- [addToFavoritesButton setEnabled:YES];
- }
-
+ favoriteNameFieldWasAutogenerated = NO;
[connectionResizeContainer setHidden:NO];
[connectionInstructionsTextField setStringValue:NSLocalizedString(@"Enter connection details below, or choose a favorite", @"enter connection details label")];
}
@@ -116,17 +126,58 @@ static NSString *SPDatabaseImage = @"database-small";
}
}
+- (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item
+{
+ if (item == quickConnectItem) {
+ return (NSCell *)quickConnectCell;
+ }
+
+ return [tableColumn dataCellForRow:[outlineView rowForItem:item]];
+}
+
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
SPTreeNode *node = (SPTreeNode *)item;
-
+
+ // Draw entries with the small system font by default
[(SPTableTextFieldCell *)cell setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
- [(SPTableTextFieldCell *)cell setImage:(![[node parentNode] parentNode]) ? nil : (![node isGroup]) ? [NSImage imageNamed:SPDatabaseImage] : folderImage];
+
+ // Set an image as appropriate; the quick connect image for that entry, no image for other
+ // top-level items, the folder image for group nodes, or the database image for other nodes.
+ if (![[node parentNode] parentNode]) {
+ if (node == quickConnectItem) {
+ if ([outlineView rowForItem:item] == [outlineView selectedRow]) {
+ [(SPTableTextFieldCell *)cell setImage:[NSImage imageNamed:SPQuickConnectImageWhite]];
+ } else {
+ [(SPTableTextFieldCell *)cell setImage:[NSImage imageNamed:SPQuickConnectImage]];
+ }
+ } else {
+ [(SPTableTextFieldCell *)cell setImage:nil];
+ }
+ } else {
+ if ([node isGroup]) {
+ [(SPTableTextFieldCell *)cell setImage:folderImage];
+ } else {
+ [(SPTableTextFieldCell *)cell setImage:[NSImage imageNamed:SPDatabaseImage]];
+ }
+ }
+
+ // If a favourite item is being edited, draw the text in bold to show state
+ if (isEditingConnection && ![node isGroup] && [outlineView rowForItem:item] == [outlineView selectedRow]) {
+ NSMutableAttributedString *editedCellString = [[cell attributedStringValue] mutableCopy];
+ [editedCellString addAttribute:NSForegroundColorAttributeName value:[NSColor colorWithDeviceWhite:0.25f alpha:1.f] range:NSMakeRange(0, [editedCellString length])];
+ [cell setAttributedStringValue:editedCellString];
+ [editedCellString release];
+ }
}
- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
{
- return ([[item parentNode] parentNode]) ? 17 : 22;
+ if (item == quickConnectItem) {
+ return 24.f;
+ }
+
+ return ([[item parentNode] parentNode]) ? 17.f : 22.f;
}
- (NSString *)outlineView:(NSOutlineView *)outlineView toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)tableColumn item:(id)item mouseLocation:(NSPoint)mouseLocation
@@ -170,8 +221,18 @@ static NSString *SPDatabaseImage = @"database-small";
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item
-{
- return ([[item parentNode] parentNode] != nil);
+{
+
+ // If this is a top level item, only allow the "Quick Connect" item to be selectable
+ if (![[item parentNode] parentNode]) {
+ if (item == quickConnectItem) {
+ return YES;
+ }
+ return NO;
+ }
+
+ // Otherwise allow all items to be selectable
+ return YES;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item
@@ -184,6 +245,11 @@ static NSString *SPDatabaseImage = @"database-small";
return ([[item parentNode] parentNode] != nil);
}
+- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
+{
+ return (item != quickConnectItem);
+}
+
- (void)outlineViewItemDidCollapse:(NSNotification *)notification
{
[self _setNodeIsExpanded:NO fromNotification:notification];
@@ -210,12 +276,12 @@ static NSString *SPDatabaseImage = @"database-small";
}
// If the user is in the process of changing a node's name, trigger a save and prevent dragging.
- if (isEditing) {
+ if (isEditingItemName) {
[favoritesController saveFavorites];
[self _reloadFavoritesViewData];
- isEditing = NO;
+ isEditingItemName = NO;
return NO;
}
@@ -350,77 +416,60 @@ static NSString *SPDatabaseImage = @"database-small";
#ifndef SP_REFACTOR
/**
- * Trap and control the 'name' field of the selected favorite. If the user pressed
- * 'Add Favorite' the 'name' field is set to 'New Favorite'. If the user did not
- * change the 'name' field or delete that field it will be set to user@host automatically.
+ * React to control text changes in the connection interface
*/
- (void)controlTextDidChange:(NSNotification *)notification
{
id field = [notification object];
-
+
+ // If a 'name' field was edited, and is now of zero length, trigger a replacement
+ // with a standard suggestion
if (((field == standardNameField) || (field == socketNameField) || (field == sshNameField)) && [self selectedFavoriteNode]) {
-
- favoriteNameFieldWasTouched = YES;
-
- NSString *favoriteName = [self _stripInvalidCharactersFromString:[field stringValue]];
-
- BOOL nameFieldIsEmpty = [favoriteName length] == 0;
-
- switch (previousType)
- {
- case SPTCPIPConnection:
- if (nameFieldIsEmpty || (!favoriteNameFieldWasTouched && (field == standardUserField || field == standardSQLHostField))) {
- [standardNameField setStringValue:[NSString stringWithFormat:@"%@@%@", [standardUserField stringValue], [standardSQLHostField stringValue]]];
- }
-
- break;
- case SPSocketConnection:
- if (nameFieldIsEmpty || (!favoriteNameFieldWasTouched && field == socketUserField)) {
- [socketNameField setStringValue:[NSString stringWithFormat:@"%@@localhost", [socketUserField stringValue]]];
- }
-
- break;
- case SPSSHTunnelConnection:
- if (nameFieldIsEmpty || (!favoriteNameFieldWasTouched && (field == sshUserField || field == sshSQLHostField))) {
- [sshNameField setStringValue:[NSString stringWithFormat:@"%@@%@", [sshUserField stringValue], [sshSQLHostField stringValue]]];
- }
-
- break;
+ if (![[self _stripInvalidCharactersFromString:[field stringValue]] length]) {
+ [self controlTextDidEndEditing:notification];
}
-
- // Trigger KVO update
- [self setName:favoriteName];
-
- // If name field is empty enable user@host update
- if (nameFieldIsEmpty) favoriteNameFieldWasTouched = NO;
+ }
+
+ [self _startEditingConnection];
+
+ if (favoriteNameFieldWasAutogenerated) {
+ [self setName:[self _generateNameForConnection]];
}
}
/**
- * When a host field finishes editing, ensure that it hasn't been set to "localhost"
- * to ensure that socket connections don't inadvertently occur.
+ * React to the end of control text changes in the connection interface.
*/
- (void)controlTextDidEndEditing:(NSNotification *)notification
{
- if ([notification object] == standardSQLHostField || [notification object] == sshSQLHostField) {
- [self _checkHost];
+ id field = [notification object];
+
+ // Handle updates to the 'name' field of the selected favourite. The favourite name should
+ // have leading or trailing spaces removed at the end of editing, and if it's left empty,
+ // should have a default name set.
+ if (((field == standardNameField) || (field == socketNameField) || (field == sshNameField)) && [self selectedFavoriteNode]) {
+
+ NSString *favoriteName = [self _stripInvalidCharactersFromString:[field stringValue]];
+
+ if (![favoriteName length]) {
+ favoriteName = [self _generateNameForConnection];
+ if (favoriteName) {
+ [self setName:favoriteName];
+ }
+
+ // Enable user@host update in reaction to other UI changes
+ favoriteNameFieldWasAutogenerated = YES;
+ } else if (![[field stringValue] isEqualToString:[self name]]) {
+ favoriteNameFieldWasAutogenerated = NO;
+ [self setName:favoriteName];
+ }
}
-}
-/**
- * Trap editing end notifications and use them to update the keychain password
- * appropriately when name, host, user, password or database changes.
- */
-- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
-{
- // Request a password refresh to keep keychain references in sync with favorites, but only if a favorite
- // is selected, meaning we're editing an existing one, not a new one.
- if (((id)control != (id)favoritesOutlineView) && ([self selectedFavoriteNode])) {
- [self _updateFavoritePasswordsFromField:control];
+ // When a host field finishes editing, ensure that it hasn't been set to "localhost" to
+ // ensure that socket connections don't inadvertently occur.
+ if (field == standardSQLHostField || field == sshSQLHostField) {
+ [self _checkHost];
}
-
- // Proceed with editing
- return YES;
}
#endif
@@ -442,19 +491,18 @@ static NSString *SPDatabaseImage = @"database-small";
NSInteger selectedTabView = [tabView indexOfTabViewItem:tabViewItem];
if (selectedTabView == previousType) return;
-
+
[self resizeTabViewToConnectionType:selectedTabView animating:YES];
// Update the host as appropriate
if ((selectedTabView != SPSocketConnection) && [[self host] isEqualToString:@"localhost"]) {
[self setHost:@""];
}
-
+
previousType = selectedTabView;
-
- // Enable the add to favorites button
- [addToFavoritesButton setEnabled:YES];
-
+
+ [self _startEditingConnection];
+
[self _favoriteTypeDidChange];
}
@@ -510,7 +558,11 @@ static NSString *SPDatabaseImage = @"database-small";
SPTreeNode *node = [self selectedFavoriteNode];
NSInteger selectedRows = [favoritesOutlineView numberOfSelectedRows];
-
+
+ if (node == quickConnectItem) {
+ return NO;
+ }
+
if ((action == @selector(sortFavorites:)) || (action == @selector(reverseSortFavorites:))) {
if ([[favoritesRoot allChildLeafs] count] < 2) return NO;
diff --git a/Source/SPConnectionControllerInitializer.m b/Source/SPConnectionControllerInitializer.m
index cee0770a..73ebcad8 100644
--- a/Source/SPConnectionControllerInitializer.m
+++ b/Source/SPConnectionControllerInitializer.m
@@ -33,6 +33,7 @@
#import "SPConnectionControllerInitializer.h"
#import "SPKeychain.h"
#import "SPFavoritesController.h"
+#import "SPFavoriteTextFieldCell.h"
#import "SPTreeNode.h"
#import "SPFavoriteNode.h"
#import "SPGroupNode.h"
@@ -78,13 +79,14 @@ static NSString *SPConnectionViewNibName = @"ConnectionView";
connectionSSHKeychainItemAccount = nil;
initComplete = NO;
- isEditing = NO;
+ isEditingItemName = NO;
isConnecting = NO;
+ isTestingConnection = NO;
sshTunnel = nil;
mySQLConnection = nil;
cancellingConnection = NO;
mySQLConnectionCancelled = NO;
- favoriteNameFieldWasTouched = YES;
+ favoriteNameFieldWasAutogenerated = NO;
[self loadNib];
[self registerForNotifications];
@@ -101,9 +103,8 @@ static NSString *SPConnectionViewNibName = @"ConnectionView";
// Generic folder image for use in the outline view's groups
folderImage = [[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)] retain];
-
[folderImage setSize:NSMakeSize(16, 16)];
-
+
// Set up a keychain instance and preferences reference, and create the initial favorites list
keychain = [[SPKeychain alloc] init];
prefs = [[NSUserDefaults standardUserDefaults] retain];
@@ -111,11 +112,20 @@ static NSString *SPConnectionViewNibName = @"ConnectionView";
// Create a reference to the favorites controller, forcing the data to be loaded from disk
// and the tree to be constructed.
favoritesController = [SPFavoritesController sharedFavoritesController];
-
+
// Tree references
favoritesRoot = [favoritesController favoritesTree];
currentFavorite = nil;
-
+
+ // Create the "Quick Connect" placeholder group
+ quickConnectItem = [[SPTreeNode treeNodeWithRepresentedObject:[SPGroupNode groupNodeWithName:[NSLocalizedString(@"Quick Connect", @"Quick connect item label") uppercaseString]]] retain];
+ [quickConnectItem setIsGroup:YES];
+
+ // Create a NSOutlineView cell for the Quick Connect group
+ quickConnectCell = [[SPFavoriteTextFieldCell alloc] init];
+ [quickConnectCell setDrawsDividerUnderCell:YES];
+ [quickConnectCell setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
+
// Update the UI
[self _reloadFavoritesViewData];
[self setUpFavoritesOutlineView];
@@ -290,13 +300,16 @@ static NSString *SPConnectionViewNibName = @"ConnectionView";
SPTreeNode *favorite = [self _favoriteNodeForFavoriteID:[prefs integerForKey:[prefs boolForKey:SPSelectLastFavoriteUsed] ? SPLastFavoriteID : SPDefaultFavorite]];
if (favorite) {
+
+ if (favorite == quickConnectItem) {
+ [self _selectNode:favorite];
+ } else {
+ NSNumber *typeNumber = [[[favorite representedObject] nodeFavorite] objectForKey:SPFavoriteTypeKey];
+ previousType = typeNumber ? [typeNumber integerValue] : SPTCPIPConnection;
- NSNumber *typeNumber = [[[favorite representedObject] nodeFavorite] objectForKey:SPFavoriteTypeKey];
-
- previousType = typeNumber ? [typeNumber integerValue] : SPTCPIPConnection;
-
- [self _selectNode:favorite];
- [self resizeTabViewToConnectionType:[[[[favorite representedObject] nodeFavorite] objectForKey:SPFavoriteTypeKey] integerValue] animating:NO];
+ [self _selectNode:favorite];
+ [self resizeTabViewToConnectionType:[[[[favorite representedObject] nodeFavorite] objectForKey:SPFavoriteTypeKey] integerValue] animating:NO];
+ }
[self _scrollToSelectedNode];
}
diff --git a/Source/SPConnectionHandler.m b/Source/SPConnectionHandler.m
index 5ae8d586..1a85bc50 100644
--- a/Source/SPConnectionHandler.m
+++ b/Source/SPConnectionHandler.m
@@ -45,8 +45,7 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
@interface SPConnectionController ()
- (void)_restoreConnectionInterface;
-
-- (void)_updateFavoritePasswordsFromField:(NSControl *)control;
+- (void)_showConnectionTestResult:(NSString *)resultString;
@end
@@ -58,7 +57,17 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
- (void)initiateMySQLConnection
{
#ifndef SP_REFACTOR
- [progressIndicatorText setStringValue:(sshTunnel) ? NSLocalizedString(@"MySQL connecting...", @"MySQL connecting very short status message") : NSLocalizedString(@"Connecting...", @"Generic connecting very short status message")];
+ if (isTestingConnection) {
+ if (sshTunnel) {
+ [progressIndicatorText setStringValue:NSLocalizedString(@"Testing MySQL...", @"MySQL connection test very short status message")];
+ } else {
+ [progressIndicatorText setStringValue:NSLocalizedString(@"Testing connection...", @"Connection test very short status message")];
+ }
+ } else if (sshTunnel) {
+ [progressIndicatorText setStringValue:NSLocalizedString(@"MySQL connecting...", @"MySQL connecting very short status message")];
+ } else {
+ [progressIndicatorText setStringValue:NSLocalizedString(@"Connecting...", @"Generic connecting very short status message")];
+ }
[progressIndicatorText display];
[connectButton setTitle:NSLocalizedString(@"Cancel", @"cancel button")];
@@ -200,7 +209,9 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
if ([self database] && ![[self database] isEqualToString:@""]) {
if (![mySQLConnection selectDatabase:[self database]]) {
- [[self onMainThread] failConnectionWithTitle:NSLocalizedString(@"Could not select database", @"message when database selection failed") errorMessage:[NSString stringWithFormat:NSLocalizedString(@"Connected to host, but unable to connect to database %@.\n\nBe sure that the database exists and that you have the necessary privileges.\n\nMySQL said: %@", @"message of panel when connection to db failed"), [self database], [mySQLConnection lastErrorMessage]] detail:nil rawErrorText:[mySQLConnection lastErrorMessage]];
+ if (!isTestingConnection) {
+ [[self onMainThread] failConnectionWithTitle:NSLocalizedString(@"Could not select database", @"message when database selection failed") errorMessage:[NSString stringWithFormat:NSLocalizedString(@"Connected to host, but unable to connect to database %@.\n\nBe sure that the database exists and that you have the necessary privileges.\n\nMySQL said: %@", @"message of panel when connection to db failed"), [self database], [mySQLConnection lastErrorMessage]] detail:nil rawErrorText:[mySQLConnection lastErrorMessage]];
+ }
// Tidy up
isConnecting = NO;
@@ -209,6 +220,10 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
[mySQLConnection release], mySQLConnection = nil;
[self _restoreConnectionInterface];
+ if (isTestingConnection) {
+ [self _showConnectionTestResult:NSLocalizedString(@"Invalid database", @"Invalid database very short status message")];
+ }
+
[pool release];
return;
@@ -228,7 +243,11 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
*/
- (void)initiateSSHTunnelConnection
{
- [progressIndicatorText setStringValue:NSLocalizedString(@"SSH connecting...", @"SSH connecting very short status message")];
+ if (isTestingConnection) {
+ [progressIndicatorText setStringValue:NSLocalizedString(@"Testing SSH...", @"SSH testing very short status message")];
+ } else {
+ [progressIndicatorText setStringValue:NSLocalizedString(@"SSH connecting...", @"SSH connecting very short status message")];
+ }
[progressIndicatorText display];
// Trim whitespace and newlines from the SSH host field before attempting to connect
@@ -266,9 +285,9 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
{
isConnecting = NO;
- // If the user hit cancel during the connection attempt, kill the connection once
- // established and reset the UI.
- if (mySQLConnectionCancelled) {
+ // If the user hit cancel during the connection attempt, or a test connection is
+ // occurring, kill the connection once established and reset the UI.
+ if (mySQLConnectionCancelled || isTestingConnection) {
if ([mySQLConnection isConnected]) {
[mySQLConnection disconnect];
[mySQLConnection release], mySQLConnection = nil;
@@ -278,7 +297,11 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
[self cancelConnection];
[self _restoreConnectionInterface];
-
+
+ if (isTestingConnection) {
+ [self _showConnectionTestResult:NSLocalizedString(@"Connection succeeded", @"Connection success very short status message")];
+ }
+
return;
}
@@ -296,7 +319,6 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
[connectButton display];
[progressIndicator stopAnimation:self];
[progressIndicatorText setHidden:YES];
- [addToFavoritesButton setHidden:NO];
#endif
// If SSL was enabled, check it was established correctly
@@ -418,9 +440,8 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
[progressIndicator display];
[progressIndicatorText setHidden:YES];
[progressIndicatorText display];
- [addToFavoritesButton setHidden:NO];
- [addToFavoritesButton display];
[connectButton setEnabled:YES];
+ [testConnectButton setEnabled:YES];
[dbDocument clearStatusIcon];
#endif
@@ -483,7 +504,6 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
// Change connection details
[self setPort:tunnelPort];
[self setHost:SPLocalhostAddress];
- [self _updateFavoritePasswordsFromField:standardSQLHostField];
#ifndef SP_REFACTOR
// Change to standard TCP/IP connection view
@@ -495,4 +515,19 @@ static NSString *SPLocalhostAddress = @"127.0.0.1";
}
}
+/**
+ * Display a connection test error or success message
+ */
+- (void)_showConnectionTestResult:(NSString *)resultString
+{
+ if (![NSThread isMainThread]) {
+ [[self onMainThread] _showConnectionTestResult:resultString];
+ }
+
+ [helpButton setHidden:NO];
+ [progressIndicator stopAnimation:self];
+ [progressIndicatorText setStringValue:resultString];
+ [progressIndicatorText setHidden:NO];
+}
+
@end
diff --git a/Source/SPFavoriteTextFieldCell.h b/Source/SPFavoriteTextFieldCell.h
index c006c9e7..84bee6ba 100644
--- a/Source/SPFavoriteTextFieldCell.h
+++ b/Source/SPFavoriteTextFieldCell.h
@@ -34,20 +34,10 @@
@interface SPFavoriteTextFieldCell : ImageAndTextCell
{
- NSString *favoriteName;
- NSString *favoriteHost;
-
- NSColor *mainStringColor;
- NSColor *subStringColor;
+ BOOL drawsDividerUnderCell;
}
-- (NSString *)favoriteName;
-- (void)setFavoriteName:(NSString *)name;
-
-- (NSString *)favoriteHost;
-- (void)setFavoriteHost:(NSString *)host;
-
-- (void)invertFontColors;
-- (void)restoreFontColors;
+- (BOOL)drawsDividerUnderCell;
+- (void)setDrawsDividerUnderCell:(BOOL)drawsDivider;
@end
diff --git a/Source/SPFavoriteTextFieldCell.m b/Source/SPFavoriteTextFieldCell.m
index e084d173..f9ebd280 100644
--- a/Source/SPFavoriteTextFieldCell.m
+++ b/Source/SPFavoriteTextFieldCell.m
@@ -32,17 +32,6 @@
#import "SPFavoriteTextFieldCell.h"
-#define FAVORITE_NAME_FONT_SIZE 12.0f
-
-@interface SPFavoriteTextFieldCell (PrivateAPI)
-
-- (NSAttributedString *)constructSubStringAttributedString;
-- (NSAttributedString *)attributedStringForFavoriteName;
-- (NSDictionary *)mainStringAttributedStringAttributes;
-- (NSDictionary *)subStringAttributedStringAttributes;
-
-@end
-
@implementation SPFavoriteTextFieldCell
/**
@@ -51,10 +40,7 @@
- (id)init
{
if ((self = [super init])) {
- mainStringColor = [NSColor blackColor];
- subStringColor = [NSColor grayColor];
- favoriteName = nil;
- favoriteHost = nil;
+ drawsDividerUnderCell = NO;
}
return self;
@@ -63,186 +49,64 @@
- (id)copyWithZone:(NSZone *)zone
{
SPFavoriteTextFieldCell *cell = (SPFavoriteTextFieldCell *)[super copyWithZone:zone];
-
- cell->favoriteName = nil;
- if (favoriteName) cell->favoriteName = [favoriteName copyWithZone:zone];
- cell->favoriteHost = nil;
- if (favoriteHost) cell->favoriteHost = [favoriteHost copyWithZone:zone];
+ cell->drawsDividerUnderCell = drawsDividerUnderCell;
return cell;
}
/**
- * Get the cell's favorite name.
- */
-- (NSString *)favoriteName
-{
- return favoriteName;
-}
-
-/**
- * Set the cell's favorite name to the supplied name.
+ * Returns whether this cell is set to draw a divider in the space directly below
+ * the cell (whatever currently populates that space).
*/
-- (void)setFavoriteName:(NSString *)name
+- (BOOL)drawsDividerUnderCell
{
- if (favoriteName != name) {
- [favoriteName release];
- favoriteName = [name retain];
- }
+ return drawsDividerUnderCell;
}
/**
- * Get the cell's favorite host.
+ * Set whether this cell should draw a divider in the space directly below
+ * the cell (whatever currently populates that space).
*/
-- (NSString *)favoriteHost
+- (void)setDrawsDividerUnderCell:(BOOL)drawsDivider
{
- return favoriteHost;
+ drawsDividerUnderCell = drawsDivider;
}
-/**
- * Set the cell's favorite host to the supplied name.
- */
-- (void)setFavoriteHost:(NSString *)host
-{
- if (favoriteHost != host) {
- [favoriteHost release];
- favoriteHost = [host retain];
- }
-}
+#pragma mark -
/**
- * Draws the actual cell.
+ * Draws the actual cell, with a divider if appropriate.
*/
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
- (([self isHighlighted]) && (![[self highlightColorWithFrame:cellFrame inView:controlView] isEqualTo:[NSColor secondarySelectedControlColor]])) ? [self invertFontColors] : [self restoreFontColors];
-
- // Construct and get the sub text attributed string
- NSAttributedString *mainString = [self attributedStringForFavoriteName];
- NSAttributedString *subString = [self constructSubStringAttributedString];
-
- NSRect subFrame = NSMakeRect(0.0f, 0.0f, [subString size].width, [subString size].height);
-
- // Total height of both strings with a 2 pixel separation space
- CGFloat totalHeight = [mainString size].height + [subString size].height + 1.0f;
-
- cellFrame.origin.y += (cellFrame.size.height - totalHeight) / 2.0f;
- cellFrame.origin.x += 10.0f; // Indent main string from image
-
- // Position the sub text's frame rect
- subFrame.origin.y = [mainString size].height + cellFrame.origin.y + 1.0f;
- subFrame.origin.x = cellFrame.origin.x;
-
- cellFrame.size.height = totalHeight;
-
- NSUInteger i;
- CGFloat maxWidth = cellFrame.size.width;
- CGFloat mainStringWidth = [mainString size].width;
- CGFloat subStringWidth = [subString size].width;
-
- // Set a right-padding
- maxWidth -= 10;
-
- if (maxWidth < mainStringWidth) {
- for (i = 0; i <= [mainString length]; i++) {
- if ([[mainString attributedSubstringFromRange:NSMakeRange(0, i)] size].width >= maxWidth && i >= 3) {
- mainString = [[[NSMutableAttributedString alloc] initWithString:[[[mainString attributedSubstringFromRange:NSMakeRange(0, i - 3)] string] stringByAppendingString:@"..."] attributes:[self mainStringAttributedStringAttributes]] autorelease];
- }
- }
- }
-
- if (maxWidth < subStringWidth) {
- for (i = 0; i <= [subString length]; i++) {
- if ([[subString attributedSubstringFromRange:NSMakeRange(0, i)] size].width >= maxWidth && i >= 3) {
- subString = [[[NSMutableAttributedString alloc] initWithString:[[[subString attributedSubstringFromRange:NSMakeRange(0, i - 3)] string] stringByAppendingString:@"..."] attributes:[self subStringAttributedStringAttributes]] autorelease];
- }
- }
- }
-
- [mainString drawInRect:cellFrame];
- [subString drawInRect:subFrame];
-}
+ [super drawInteriorWithFrame:cellFrame inView:controlView];
-- (NSSize)cellSize
-{
- NSSize cellSize = [super cellSize];
- NSAttributedString *mainString = [self attributedStringForFavoriteName];
- NSAttributedString *subString = [self constructSubStringAttributedString];
-
- // 15 := indention 10 from image to string plus 5 px padding
- CGFloat theWidth = MAX([mainString size].width, [subString size].width) + (([self image] != nil) ? [[self image] size].width : 0) + 15;
+ if (drawsDividerUnderCell) {
+ NSRect viewFrame = [controlView frame];
- CGFloat totalHeight = [mainString size].height + [subString size].height + 1.0f;
-
- cellSize.width = theWidth;
- cellSize.height = totalHeight + 13.0f;
- return cellSize;
-}
+ NSPoint startPoint = NSMakePoint(viewFrame.origin.x + 7.f, viewFrame.origin.y);
+ NSPoint endPoint = NSMakePoint(viewFrame.origin.x + viewFrame.size.width - 7.f, viewFrame.origin.y);
-/**
- * Inverts the displayed font colors when the cell is selected.
- */
-- (void)invertFontColors
-{
- mainStringColor = [NSColor whiteColor];
- subStringColor = [NSColor whiteColor];
-}
-
-/**
- * Restores the displayed font colors once the cell is no longer selected.
- */
-- (void)restoreFontColors
-{
- mainStringColor = [NSColor blackColor];
- subStringColor = [NSColor grayColor];
-}
-
-/**
- * Dealloc.
- */
-- (void)dealloc
-{
- [favoriteName release], favoriteName = nil;
- [favoriteHost release], favoriteHost = nil;
-
- [super dealloc];
-}
-
-@end
-
-@implementation SPFavoriteTextFieldCell (PrivateAPI)
-
-/**
- * Constructs the attributed string to be used as the cell's substring.
- */
-- (NSAttributedString *)constructSubStringAttributedString
-{
- return [[[NSAttributedString alloc] initWithString:favoriteHost attributes:[self subStringAttributedStringAttributes]] autorelease];
-}
-
-/**
- * Constructs the attributed string for the cell's favorite name.
- */
-- (NSAttributedString *)attributedStringForFavoriteName
-{
- return [[[NSAttributedString alloc] initWithString:favoriteName attributes:[self mainStringAttributedStringAttributes]] autorelease];
-}
-
-/**
- * Returns the attributes of the cell's main string.
- */
-- (NSDictionary *)mainStringAttributedStringAttributes
-{
- return [NSDictionary dictionaryWithObjectsAndKeys:mainStringColor, NSForegroundColorAttributeName, [NSFont systemFontOfSize:FAVORITE_NAME_FONT_SIZE], NSFontAttributeName, nil];
-}
+ if ([controlView isFlipped]) {
+ startPoint.y += cellFrame.size.height + 8.5f;
+ endPoint.y += cellFrame.size.height + 8.5f;
+ } else {
+ startPoint.y -= cellFrame.size.height + 8.5f;
+ endPoint.y -= cellFrame.size.height + 8.5f;
+ }
-/**
- * Returns the attributes of the cell's sub string.
- */
-- (NSDictionary *)subStringAttributedStringAttributes
-{
- return [NSDictionary dictionaryWithObjectsAndKeys:subStringColor, NSForegroundColorAttributeName, [NSFont systemFontOfSize:[NSFont smallSystemFontSize]], NSFontAttributeName, nil];
+ [NSGraphicsContext saveGraphicsState];
+ [[NSColor gridColor] set];
+ NSShadow *lineGlow = [[NSShadow alloc] init];
+ [lineGlow setShadowBlurRadius:1];
+ [lineGlow setShadowColor:[[NSColor controlLightHighlightColor] colorWithAlphaComponent:0.75f]];
+ [lineGlow setShadowOffset:NSMakeSize(0, -1)];
+ [lineGlow set];
+ [NSBezierPath strokeLineFromPoint:startPoint toPoint:endPoint];
+ [lineGlow release];
+ [NSGraphicsContext restoreGraphicsState];
+ }
}
-@end
+@end \ No newline at end of file
diff --git a/Source/SPFavoritesOutlineView.m b/Source/SPFavoritesOutlineView.m
index 883896ef..08880ec8 100644
--- a/Source/SPFavoritesOutlineView.m
+++ b/Source/SPFavoritesOutlineView.m
@@ -31,6 +31,9 @@
// More info at <http://code.google.com/p/sequel-pro/>
#import "SPFavoritesOutlineView.h"
+#import "SPConnectionControllerDelegate.h"
+
+static NSUInteger SPFavoritesOutlineViewUnindent = 14;
@implementation SPFavoritesOutlineView
@@ -88,4 +91,64 @@
}
}
+/**
+ * Don't reserve a gap for the disclosure triangles for top-level items. This involves reducing the
+ * padding - and increasing the width - of all rows to compensate.
+ */
+- (NSRect)frameOfCellAtColumn:(NSInteger)columnIndex row:(NSInteger)rowIndex
+{
+ NSRect superFrame = [super frameOfCellAtColumn:columnIndex row:rowIndex];
+
+ return NSMakeRect(superFrame.origin.x - SPFavoritesOutlineViewUnindent, superFrame.origin.y, superFrame.size.width + SPFavoritesOutlineViewUnindent, superFrame.size.height);
+}
+
+/**
+ * As no gap is reserved for the disclosure triangles at the top level, the frames for other
+ * disclosure items need to be similarly moved.
+ */
+- (NSRect)frameOfOutlineCellAtRow:(NSInteger)rowIndex
+{
+ NSRect superFrame = [super frameOfOutlineCellAtRow:rowIndex];
+
+ if (superFrame.origin.x > SPFavoritesOutlineViewUnindent) {
+ return NSMakeRect(superFrame.origin.x - SPFavoritesOutlineViewUnindent, superFrame.origin.y, superFrame.size.width, superFrame.size.height);
+ }
+
+ return superFrame;
+}
+
+
+/**
+ * If the delegate is a SPConnectionControllerDelegate, and editing is currently in
+ * progress, draw a custom highlight.
+ */
+- (void)highlightSelectionInClipRect:(NSRect)clipRect
+{
+
+ // Only proceed if a the delegate is a SPConnectionControllerDelegate and a favoruite being edited
+ if ([[self delegate] isKindOfClass:[SPConnectionController class]]
+ && [(SPConnectionController *)[self delegate] isEditingConnection]
+ && [(SPConnectionController *)[self delegate] selectedFavorite])
+ {
+
+ // Draw an editing dot instead of highlighting the whole row
+ NSRect rowRect = [self rectOfRow:[self selectedRow]];
+ float dotSize = rowRect.size.height / 1.9;
+ NSRect dotRect = NSMakeRect(9.f, rowRect.origin.y + ((rowRect.size.height - dotSize) / 2), dotSize, dotSize);
+ [NSGraphicsContext saveGraphicsState];
+
+ NSBezierPath *clipPath = [NSBezierPath bezierPath];
+ [clipPath appendBezierPathWithOvalInRect:dotRect];
+ [clipPath addClip];
+
+ NSGradient *dotGradient = [[[NSGradient alloc] initWithStartingColor:[NSColor colorWithDeviceRed:0.44f green:0.72f blue:0.92f alpha:1.f] endingColor:[NSColor colorWithDeviceRed:0.21f green:0.53f blue:0.82f alpha:1.f]] autorelease];
+ [dotGradient drawInRect:dotRect angle:90.f];
+
+ [NSGraphicsContext restoreGraphicsState];
+ return;
+ }
+
+ [super highlightSelectionInClipRect:clipRect];
+}
+
@end
diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj
index 9126c6a7..a666fe74 100644
--- a/sequel-pro.xcodeproj/project.pbxproj
+++ b/sequel-pro.xcodeproj/project.pbxproj
@@ -208,6 +208,10 @@
584095191107CB6600260CFD /* SPAlertSheets.m in Sources */ = {isa = PBXBuildFile; fileRef = 584095181107CB6600260CFD /* SPAlertSheets.m */; };
5841423F0F97E11000A34B47 /* NoodleLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5841423E0F97E11000A34B47 /* NoodleLineNumberView.m */; };
584192A1101E57BB0089807F /* NSMutableArray-MultipleSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 584192A0101E57BB0089807F /* NSMutableArray-MultipleSort.m */; };
+ 5843DA6C161FA35600EAA6D1 /* key-icon-alternate.png in Resources */ = {isa = PBXBuildFile; fileRef = 5843DA68161FA35600EAA6D1 /* key-icon-alternate.png */; };
+ 5843DA6D161FA35600EAA6D1 /* key-icon-alternate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5843DA69161FA35600EAA6D1 /* key-icon-alternate@2x.png */; };
+ 5843DA6E161FA35600EAA6D1 /* key-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 5843DA6A161FA35600EAA6D1 /* key-icon.png */; };
+ 5843DA6F161FA35600EAA6D1 /* key-icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5843DA6B161FA35600EAA6D1 /* key-icon@2x.png */; };
584754D3120A05910057631F /* GeneratePreviewForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = 584754D0120A05910057631F /* GeneratePreviewForURL.m */; };
584754D4120A05910057631F /* GenerateThumbnailForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = 584754D1120A05910057631F /* GenerateThumbnailForURL.m */; };
584754D5120A05910057631F /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 584754D2120A05910057631F /* main.c */; };
@@ -344,6 +348,8 @@
58DFC8E415C9F402003B4330 /* button_select_none.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 58DFC8E215C9F402003B4330 /* button_select_none.tiff */; };
58DFC91615CB3501003B4330 /* BGHUDButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 58DFC91515CB3501003B4330 /* BGHUDButtonCell.m */; };
58E205FC1234FE4F00A97059 /* KeyTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 58E205FB1234FE4F00A97059 /* KeyTemplate.pdf */; };
+ 58F48AA3161D03C6008536A1 /* quick-connect-icon.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 58F48AA2161D03C6008536A1 /* quick-connect-icon.pdf */; };
+ 58F48B2E161D08C0008536A1 /* quick-connect-icon-white.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 58F48B2D161D08C0008536A1 /* quick-connect-icon-white.pdf */; };
58FEF16D0F23D66600518E8E /* SPSQLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 58FEF16C0F23D66600518E8E /* SPSQLParser.m */; };
58FEF57E0F3B4E9700518E8E /* SPTableData.m in Sources */ = {isa = PBXBuildFile; fileRef = 58FEF57D0F3B4E9700518E8E /* SPTableData.m */; };
8D15AC340486D014006FF6A4 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */; };
@@ -923,6 +929,10 @@
5841423E0F97E11000A34B47 /* NoodleLineNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleLineNumberView.m; sourceTree = "<group>"; };
5841929F101E57BB0089807F /* NSMutableArray-MultipleSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray-MultipleSort.h"; sourceTree = "<group>"; };
584192A0101E57BB0089807F /* NSMutableArray-MultipleSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray-MultipleSort.m"; sourceTree = "<group>"; };
+ 5843DA68161FA35600EAA6D1 /* key-icon-alternate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "key-icon-alternate.png"; sourceTree = "<group>"; };
+ 5843DA69161FA35600EAA6D1 /* key-icon-alternate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "key-icon-alternate@2x.png"; sourceTree = "<group>"; };
+ 5843DA6A161FA35600EAA6D1 /* key-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "key-icon.png"; sourceTree = "<group>"; };
+ 5843DA6B161FA35600EAA6D1 /* key-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "key-icon@2x.png"; sourceTree = "<group>"; };
584754C2120A04560057631F /* Sequel Pro.qlgenerator */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Sequel Pro.qlgenerator"; sourceTree = BUILT_PRODUCTS_DIR; };
584754D0120A05910057631F /* GeneratePreviewForURL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratePreviewForURL.m; sourceTree = "<group>"; };
584754D1120A05910057631F /* GenerateThumbnailForURL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GenerateThumbnailForURL.m; sourceTree = "<group>"; };
@@ -1132,6 +1142,8 @@
58DFC91415CB3501003B4330 /* BGHUDButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BGHUDButtonCell.h; sourceTree = "<group>"; };
58DFC91515CB3501003B4330 /* BGHUDButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BGHUDButtonCell.m; sourceTree = "<group>"; };
58E205FB1234FE4F00A97059 /* KeyTemplate.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = KeyTemplate.pdf; sourceTree = "<group>"; };
+ 58F48AA2161D03C6008536A1 /* quick-connect-icon.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "quick-connect-icon.pdf"; sourceTree = "<group>"; };
+ 58F48B2D161D08C0008536A1 /* quick-connect-icon-white.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "quick-connect-icon-white.pdf"; sourceTree = "<group>"; };
58FEF16B0F23D66600518E8E /* SPSQLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPSQLParser.h; sourceTree = "<group>"; };
58FEF16C0F23D66600518E8E /* SPSQLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPSQLParser.m; sourceTree = "<group>"; };
58FEF57C0F3B4E9700518E8E /* SPTableData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPTableData.h; sourceTree = "<group>"; };
@@ -2145,12 +2157,18 @@
17E6419D0EF02036001BC333 /* grabber-horizontal.png */,
17E6419E0EF02036001BC333 /* grabber-vertical.png */,
17E6419F0EF02036001BC333 /* hideconsole.tiff */,
+ 5843DA68161FA35600EAA6D1 /* key-icon-alternate.png */,
+ 5843DA69161FA35600EAA6D1 /* key-icon-alternate@2x.png */,
+ 5843DA6A161FA35600EAA6D1 /* key-icon.png */,
+ 5843DA6B161FA35600EAA6D1 /* key-icon@2x.png */,
58E205FB1234FE4F00A97059 /* KeyTemplate.pdf */,
58D2E22D101222870063EF1D /* link-arrow.png */,
58D2E22B101222870063EF1D /* link-arrow-clicked.png */,
581068B51015411B0068C6E2 /* link-arrow-highlighted.png */,
58D2E22C101222870063EF1D /* link-arrow-highlighted-clicked.png */,
17E641A20EF02036001BC333 /* logo-48.png */,
+ 58F48AA2161D03C6008536A1 /* quick-connect-icon.pdf */,
+ 58F48B2D161D08C0008536A1 /* quick-connect-icon-white.pdf */,
17E641AE0EF02036001BC333 /* selectall.tiff */,
17E641AF0EF02036001BC333 /* selectnone.tiff */,
17E641B10EF02036001BC333 /* showconsole.tiff */,
@@ -3014,6 +3032,12 @@
58DFC0B215C728A5003B4330 /* button_add_folder.tiff in Resources */,
58DFC8E315C9F402003B4330 /* button_select_all.tiff in Resources */,
58DFC8E415C9F402003B4330 /* button_select_none.tiff in Resources */,
+ 58F48AA3161D03C6008536A1 /* quick-connect-icon.pdf in Resources */,
+ 58F48B2E161D08C0008536A1 /* quick-connect-icon-white.pdf in Resources */,
+ 5843DA6C161FA35600EAA6D1 /* key-icon-alternate.png in Resources */,
+ 5843DA6D161FA35600EAA6D1 /* key-icon-alternate@2x.png in Resources */,
+ 5843DA6E161FA35600EAA6D1 /* key-icon.png in Resources */,
+ 5843DA6F161FA35600EAA6D1 /* key-icon@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};