From 9c06d1219c66acc043b5f13ab29379f60eb00350 Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Tue, 28 Jul 2009 01:02:40 +0000 Subject: Improve TablesList significantly: - If there are twenty or more tables, show a table quicksearch/filter at the top of the list, and update the rest of the code to match. This addresses issue #178. - Select tables and views alphabetically by user's current locale (instead of default MySQL "A B C a b c") - When adding or duplicating tables, insert them at the correct point - Fix a number of minor display bugs caused by incorrect interaction with the tables list caches --- Interfaces/English.lproj/DBView.xib | 772 ++++++++++------- Source/NSMutableArray-MultipleSort.h | 54 ++ Source/NSMutableArray-MultipleSort.m | 77 ++ Source/TableDocument.m | 1 - Source/TableDump.h | 1 - Source/TableDump.m | 9 +- Source/TableSource.m | 9 +- Source/TablesList.h | 20 +- Source/TablesList.m | 1549 ++++++++++++++++++++-------------- sequel-pro.xcodeproj/project.pbxproj | 6 + 10 files changed, 1575 insertions(+), 923 deletions(-) create mode 100644 Source/NSMutableArray-MultipleSort.h create mode 100644 Source/NSMutableArray-MultipleSort.m diff --git a/Interfaces/English.lproj/DBView.xib b/Interfaces/English.lproj/DBView.xib index 77286596..14b44c40 100644 --- a/Interfaces/English.lproj/DBView.xib +++ b/Interfaces/English.lproj/DBView.xib @@ -8,6 +8,7 @@ 353.00 YES + YES @@ -70,95 +71,124 @@ 274 YES - + 274 YES - - - 4370 + + + 288 YES - - - 2304 + + + 4370 YES - - - 4352 - {212, 381} - - - YES - - - -2147483392 - {{-26, 0}, {16, 17}} - - + + + 2304 + YES - - tables - 2.090000e+02 - 4.286900e+01 - 1.000000e+03 - - 75628032 - 0 - Tables - - LucidaGrande - 1.100000e+01 - 3100 - - - 3 - MC4zMzMzMzI5OQA - - - 6 - System - headerTextColor - - 3 - MAA - - - - - 337772096 - 272761856 - Text Cell - - - YES - - 6 - System - controlColor - - 3 - MC42NjY2NjY2OQA + + + 274 + + YES + + + 266 + {{5, 2}, {202, 19}} + + YES + + 343014976 + 268567552 + + + LucidaGrande + 1.100000e+01 + 3100 + + + YES + 1 + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + 130560 + 0 + search + _searchFieldSearch: + + + 138690815 + 0 + + 400 + 75 + + + 130560 + 0 + clear + + YES + + YES + + YES + AXDescription + NSAccessibilityEncodedAttributesValueType + + + YES + cancel + + + + + _searchFieldCancel: + + + 138690815 + 0 + + 400 + 75 + + 255 + CAAAAA - - 6 - System - controlTextColor - - - 3 - YES - YES - + {212, 26} + + NSView - 3.000000e+00 - 2.000000e+00 - + {212, 26} + + + + 6 System _sourceListBackgroundColor @@ -167,78 +197,218 @@ MC44MzkyMTU3IDAuODY2NjY2NjcgMC44OTgwMzkyMgA - + 4 + + + + 256 + {{-100, -100}, {15, 94}} + + + _doScroller: + 1.000000e+00 + 9.636363e-01 + + + + 256 + {{-100, -100}, {166, 15}} + + 1 + + _doScroller: + 5.060241e-01 + + + {212, 26} + + + 0 + + + + + + {212, 26} + + NSView + + + + 272 + + YES + + + 4370 + + YES + + + 2304 + + YES + + + 4352 + {212, 354} + + YES + + + -2147483392 + {{-26, 0}, {16, 17}} + + + YES + + tables + 2.090000e+02 + 4.286900e+01 + 1.000000e+03 + + 75628032 + 0 + Tables + + + 3 + MC4zMzMzMzI5OQA + + + 6 + System + headerTextColor + + + + + 337772096 + 272761856 + Text Cell + + + YES + + 6 + System + controlColor + + 3 + MC42NjY2NjY2OQA + + + + + 3 + YES + YES + + + + 3.000000e+00 + 2.000000e+00 + + 6 + System + _sourceListBackgroundColor + + 1 + MC44MzkyMTU3IDAuODY2NjY2NjcgMC44OTgwMzkyMgA + + + + 6 + System + gridColor + + 3 + MC41AA + + + 1.700000e+01 + 1514143744 + 2 + 15 + 0 + YES + 1 + + + {212, 354} + + + + 6 System - gridColor - - 3 - MC41AA - + controlBackgroundColor + - 1.700000e+01 - 1514143744 - 2 - 15 - 0 - YES - 1 + 4 + + + + -2147483392 + {{197, 0}, {15, 292}} + + + _doScroller: + 9.965870e-01 + + + + 256 + {{-100, -100}, {141, 11}} + + 257 + + _doScroller: + 9.904762e-01 - {212, 381} - - - - - - 6 - System - controlBackgroundColor - - - 4 - - - - -2147483392 - {{175, 1}, {15, 481}} - - - - _doScroller: - 9.979253e-01 - - - - 256 - {{-100, -100}, {141, 11}} - - - 257 - - _doScroller: - 9.904762e-01 + {212, 354} + + + 528 + + + + QSAAAEEgAABBmAAAQZgAAA - {212, 381} - - - - 528 - - - - QSAAAEEgAABBmAAAQZgAAA + {{0, 27}, {212, 354}} + + NSView {212, 381} - + 2 + + YES + + + + + + + + + + + + + + + + + 1 + NO {212, 381} - NSView @@ -261,7 +431,6 @@ 4352 {212, 145} - YES @@ -325,7 +494,6 @@ {212, 145} - @@ -336,7 +504,6 @@ -2147483392 {{-100, -100}, {15, 20}} - _doScroller: 9.473684e-01 @@ -346,7 +513,6 @@ 256 {{-100, -100}, {141, 11}} - 257 _doScroller: @@ -355,7 +521,6 @@ {212, 145} - 528 @@ -366,19 +531,17 @@ {{0, 382}, {212, 145}} - NSView {{0, 23}, {212, 527}} - 2 NO - - + + @@ -423,7 +586,6 @@ 268 {{-1, -1}, {32, 24}} - YES 67239424 @@ -448,7 +610,6 @@ 268 {{30, -1}, {32, 24}} - YES 71433792 @@ -558,7 +719,6 @@ 268 {{61, -1}, {32, 24}} - YES 67239424 @@ -583,7 +743,6 @@ 268 {{92, -1}, {32, 24}} - YES -2080244224 @@ -610,7 +769,6 @@ {212, 23} - YES YES NO @@ -619,7 +777,6 @@ {212, 550} - NSView @@ -632,7 +789,6 @@ 274 {{-7, -10}, {735, 564}} - YES @@ -702,15 +858,7 @@ Text Cell - - 6 - System - textBackgroundColor - - 3 - MQA - - + 3 @@ -3982,14 +4130,12 @@ 4352 {688, 454} - YES 256 {688, 17} - @@ -3997,7 +4143,6 @@ -2147483392 {{-26, 0}, {16, 17}} - YES @@ -4181,7 +4326,6 @@ {{1, 17}, {688, 454}} - @@ -4192,7 +4336,6 @@ -2147483392 {{674, 17}, {15, 453}} - _doScroller: 9.679487e-01 @@ -4202,7 +4345,6 @@ -2147483392 {{1, 470}, {688, 15}} - 1 _doScroller: @@ -4217,7 +4359,6 @@ {{1, 0}, {688, 17}} - @@ -4227,7 +4368,6 @@ {{6, 32}, {690, 472}} - 562 @@ -4242,7 +4382,6 @@ 292 {{6, 9}, {32, 25}} - YES -1543373312 @@ -4264,7 +4403,6 @@ 292 {{68, 9}, {32, 25}} - YES -2080244224 @@ -4286,7 +4424,6 @@ 292 {{37, 9}, {32, 25}} - YES -1543373312 @@ -4320,7 +4457,6 @@ {{100, 10}, {596, 23}} - YES 130560 @@ -4338,7 +4474,6 @@ 268 {{14, 515}, {347, 14}} - YES 68288064 @@ -4353,7 +4488,6 @@ {{10, 7}, {700, 544}} - Relations @@ -4373,20 +4507,17 @@ {{221, 0}, {723, 550}} - NSView {944, 550} - YES DBViewSplitter {944, 550} - {{0, 0}, {1920, 1178}} {780, 502} @@ -6019,7 +6150,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {3.40282e+38, 3.40282e+38} - + 256 YES @@ -6038,7 +6169,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{80, 10}, {171, 22}} - YES -2076049856 @@ -6104,7 +6234,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{29, 15}, {49, 14}} - YES 68288064 @@ -6119,12 +6248,10 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {{1, 1}, {266, 40}} - {{17, 231}, {268, 56}} - {0, 0} 67239424 @@ -6158,7 +6285,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{81, 40}, {170, 22}} - YES -2076049856 @@ -6244,7 +6370,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{81, 10}, {170, 22}} - YES -2076049856 @@ -6330,7 +6455,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{15, 45}, {64, 14}} - YES 68288064 @@ -6347,7 +6471,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{19, 15}, {59, 14}} - YES 68288064 @@ -6362,12 +6485,10 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {{1, 1}, {266, 71}} - {{17, 49}, {268, 87}} - {0, 0} 67239424 @@ -6401,7 +6522,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{80, 40}, {171, 22}} - YES -2076049856 @@ -6467,7 +6587,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{80, 10}, {171, 22}} - YES -2076049856 @@ -6533,7 +6652,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{41, 45}, {37, 14}} - YES 68288064 @@ -6550,7 +6668,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{29, 15}, {49, 14}} - YES 68288064 @@ -6565,12 +6682,10 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {{1, 1}, {266, 71}} - {{17, 140}, {268, 87}} - {0, 0} 67239424 @@ -6594,7 +6709,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{191, 13}, {96, 28}} - 1 YES @@ -6616,7 +6730,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 {{97, 13}, {96, 28}} - YES 67239424 @@ -6634,8 +6747,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {302, 307} - - {{0, 0}, {1440, 878}} {3.40282e+38, 3.40282e+38} @@ -12381,14 +12492,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 4681 - - - tableListView - - - - 4683 - toggleFilterField: @@ -13813,22 +13916,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 5938 - - - tableListSplitter - - - - 5939 - - - - delegate - - - - 5940 - tableInfoTable @@ -14353,6 +14440,46 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 6259 + + + tableListSplitter + + + + 6269 + + + + tableListFilterSplitView + + + + 6280 + + + + delegate + + + + 6283 + + + + listFilterField + + + + 6284 + + + + updateFilter: + + + + 6285 + @@ -19727,63 +19854,10 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 YES - + - - 4487 - - - YES - - - - - - 21 - - - YES - - - - - - - - 3916 - - - - - 3915 - - - - - 22 - - - YES - - - - - - 23 - - - YES - - - - - - 4015 - - - 6067 @@ -20266,6 +20340,122 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 + + 6265 + + + YES + + + + + + + 6266 + + + YES + + + + + + 6267 + + + YES + + + + + + 21 + + + YES + + + + + + + + 22 + + + YES + + + + + + 3915 + + + + + 3916 + + + + + 23 + + + YES + + + + + + 4015 + + + + + 6274 + + + YES + + + + + + + + 6277 + + + YES + + + + + + 6276 + + + + + 6275 + + + + + 6278 + + + YES + + + + + + 6279 + + + @@ -20791,8 +20981,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 4485.ImportedFromIB2 4486.CustomClassName 4486.IBPluginDependency - 4487.CustomClassName - 4487.IBPluginDependency 4488.IBPluginDependency 4503.IBPluginDependency 4504.IBPluginDependency @@ -21487,6 +21675,15 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 6242.IBPluginDependency 6249.IBPluginDependency 6253.IBPluginDependency + 6265.IBPluginDependency + 6266.IBPluginDependency + 6267.IBPluginDependency + 6274.IBPluginDependency + 6275.IBPluginDependency + 6276.IBPluginDependency + 6277.IBPluginDependency + 6278.IBPluginDependency + 6279.IBPluginDependency 654.IBPluginDependency 654.ImportedFromIB2 655.IBPluginDependency @@ -22322,8 +22519,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 ImageAndTextCell com.apple.InterfaceBuilder.CocoaPlugin - BWSplitView - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -22516,8 +22711,8 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{177, 306}, {944, 550}} - {{177, 306}, {944, 550}} + {{60, 298}, {944, 550}} + {{60, 298}, {944, 550}} {{62, 352}, {845, 504}} @@ -23256,6 +23451,15 @@ aGUgYWN0aXZlIHNlbGVjdGlvbiAo4oyl4oyYUik com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -23476,7 +23680,7 @@ Y2hhbmdlIHRoZSBvcmRlcg - 6259 + 6285 @@ -24429,7 +24633,6 @@ Y2hhbmdlIHRoZSBvcmRlcg tableContentInstance tableDataInstance tableDocumentInstance - tableListView tableSourceInstance tableWindow tablesListInstance @@ -24488,7 +24691,6 @@ Y2hhbmdlIHRoZSBvcmRlcg id id id - id @@ -24609,6 +24811,7 @@ Y2hhbmdlIHRoZSBvcmRlcg renameTable: togglePaneCollapse: truncateTable: + updateFilter: updateTables: @@ -24622,6 +24825,7 @@ Y2hhbmdlIHRoZSBvcmRlcg id id id + id @@ -24639,6 +24843,7 @@ Y2hhbmdlIHRoZSBvcmRlcg duplicateTableContextMenuItem duplicateTableMenuItem extendedTableInfoInstance + listFilterField removeTableContextMenuItem removeTableMenuItem renameTableButton @@ -24653,6 +24858,7 @@ Y2hhbmdlIHRoZSBvcmRlcg tableDumpInstance tableEncodingButton tableInfoCollapseButton + tableListFilterSplitView tableListSplitView tableNameField tableRenameField @@ -24679,6 +24885,7 @@ Y2hhbmdlIHRoZSBvcmRlcg NSMenuItem NSMenuItem id + NSSearchField NSMenuItem NSMenuItem id @@ -24694,6 +24901,7 @@ Y2hhbmdlIHRoZSBvcmRlcg id NSButton NSSplitView + NSSplitView id id id diff --git a/Source/NSMutableArray-MultipleSort.h b/Source/NSMutableArray-MultipleSort.h new file mode 100644 index 00000000..91c8f3f2 --- /dev/null +++ b/Source/NSMutableArray-MultipleSort.h @@ -0,0 +1,54 @@ +// +// NSMutableArray-MultipleSort.h +// iContractor +// +// Created by Jeff LaMarche on 1/16/09. +// Copyright 2009 Jeff LaMarche. All rights reserved. +// + +// This category on NSMutableArray implements a shell sort based on the old NeXT example +// SortingInAction. It is functionally identical to sortArrayUsingSelector: except that +// it will sort other paired arrays based on the comparison values of the original array +// this is for use in paired array situations, such as when you use one array to store +// keys and another array to store values. This is a variadic method, so you can sort +// as many paired arrays as you have. + +// This source may be used, free of charge, for any purposes. commercial or non- +// commercial. There is no attribution requirement, nor any need to distribute +// your source code. If you do redistribute the source code, you must +// leave the original header comments, but you may add additional ones. + + +// Stride factor defines the size of the shell sort loop's stride. It can be tweaked +// for performance, though 3 seems to be a good general purpose value +#define STRIDE_FACTOR 3 + +#import + +// This compare method was taken from the GNUStep project. GNUStep is +// licensed under the LGPL, which allows such use. +static inline NSComparisonResult compare(id elem1, id elem2, void* context) +{ + NSComparisonResult (*imp)(id, SEL, id); + + if (context == 0) { + [NSException raise: NSInvalidArgumentException + format: @"compare null selector given"]; + } + + imp = (NSComparisonResult (*)(id, SEL, id)) + [elem1 methodForSelector: context]; + + if (imp == NULL) { + [NSException raise: NSGenericException + format: @"invalid selector passed to compare"]; + } + + return (*imp)(elem1, context, elem2); +} + +@interface NSMutableArray(MultipleSort) + +// Takes a comparator and a nil-terminated list of paired arrays +- (void)sortArrayUsingSelector:(SEL)comparator withPairedMutableArrays:(NSMutableArray *)array1, ...; +@end diff --git a/Source/NSMutableArray-MultipleSort.m b/Source/NSMutableArray-MultipleSort.m new file mode 100644 index 00000000..f98732b7 --- /dev/null +++ b/Source/NSMutableArray-MultipleSort.m @@ -0,0 +1,77 @@ +// +// NSMutableArray-MultipleSort.m +// iContractor +// +// Created by Jeff LaMarche on 1/16/09. +// Copyright 2009 Jeff LaMarche Consulting. All rights reserved. +// +// This source may be used, free of charge, for any purposes. commercial or non- +// commercial. There is no attribution requirement, nor any need to distribute +// your source code. If you do redistribute the source code, you must +// leave the original header comments, but you may add additional ones. + +#import "NSMutableArray-MultipleSort.h" + +@implementation NSMutableArray(MultipleSort) +- (void)sortArrayUsingSelector:(SEL)comparator withPairedMutableArrays:(NSMutableArray *)array1, ... +{ + unsigned int stride = 1; + BOOL found = NO; + unsigned int count = [self count]; + unsigned int d; + + while (stride <= count) + stride = stride * STRIDE_FACTOR + 1; + + while (stride > (STRIDE_FACTOR - 1)) { + stride = stride / STRIDE_FACTOR; + for (unsigned int c = stride; c < count; c++) { + found = NO; + if (stride > c) break; + + d = c - stride; + while (!found) { + id a = [self objectAtIndex: d + stride]; + id b = [self objectAtIndex: d]; + + NSComparisonResult result = (*compare)(a, b, (void *)comparator); + + if (result < 0) { + [a retain]; + [self replaceObjectAtIndex: d + stride withObject: b]; + [self replaceObjectAtIndex: d withObject: a]; + + id eachObject; + va_list argumentList; + if (array1) { + id a1 = [array1 objectAtIndex:d+stride]; + id b1 = [array1 objectAtIndex:d]; + [a1 retain]; + [array1 replaceObjectAtIndex: d + stride withObject:b1]; + [array1 replaceObjectAtIndex: d withObject: a1]; + [a1 release]; + va_start(argumentList, array1); + while (eachObject = va_arg(argumentList, id)) { + id ax = [eachObject objectAtIndex:d+stride]; + id bx = [eachObject objectAtIndex:d]; + [ax retain]; + [eachObject replaceObjectAtIndex: d + stride withObject:bx]; + [eachObject replaceObjectAtIndex: d withObject: ax]; + [ax release]; + } + va_end(argumentList); + } + + [a release]; + + if (stride > d) + break; + + d -= stride; + } else + found = YES; + } + } + } +} +@end \ No newline at end of file diff --git a/Source/TableDocument.m b/Source/TableDocument.m index 7970d0aa..07b6b42b 100644 --- a/Source/TableDocument.m +++ b/Source/TableDocument.m @@ -116,7 +116,6 @@ // Hide the tabs in the tab view (we only show them to allow switching tabs in interface builder) [tableTabView setTabViewType:NSNoTabsNoBorder]; - [tableListSplitter setDividerStyle:NSSplitViewDividerStyleThin]; // Add the icon accessory view to the title bar NSView *windowFrame = [[tableWindow contentView] superview]; diff --git a/Source/TableDump.h b/Source/TableDump.h index e0ee2c59..bb4c0284 100644 --- a/Source/TableDump.h +++ b/Source/TableDump.h @@ -37,7 +37,6 @@ IBOutlet id customQueryInstance; IBOutlet id tableWindow; - IBOutlet id tableListView; IBOutlet id exportDumpView; IBOutlet id exportCSVView; diff --git a/Source/TableDump.m b/Source/TableDump.m index 3edf0619..34ffe262 100644 --- a/Source/TableDump.m +++ b/Source/TableDump.m @@ -379,8 +379,8 @@ } - (IBAction)changeTable:(id)sender -{ - [tableListView selectRowIndexes:[NSIndexSet indexSetWithIndex:[[tablesListInstance tables] indexOfObject:[fieldMappingPopup titleOfSelectedItem]]] byExtendingSelection:NO]; +{ + [tablesListInstance selectTableOrViewWithName:[fieldMappingPopup titleOfSelectedItem]]; //set up tableView currentRow = 0; @@ -603,12 +603,9 @@ [fieldMappingPopup selectItemAtIndex:0]; } - int indexOfFirstTable = [[tablesListInstance tables] indexOfObject:[fieldMappingPopup titleOfSelectedItem]]; - - if( indexOfFirstTable == NSNotFound ){ + if( ![tablesListInstance selectTableOrViewWithName:[fieldMappingPopup titleOfSelectedItem]] ) { [errors appendString:[NSString stringWithFormat:NSLocalizedString(@"[ERROR] %@\n", @"error text when trying to import csv data, but we have no tables in the db"), @"Can't import CSV data into a database without any tables!"]]; } else { - [tableListView selectRowIndexes:[NSIndexSet indexSetWithIndex:indexOfFirstTable] byExtendingSelection:NO]; //set up tableView currentRow = 0; diff --git a/Source/TableSource.m b/Source/TableSource.m index 7fb0cdfd..48d1d75d 100644 --- a/Source/TableSource.m +++ b/Source/TableSource.m @@ -49,7 +49,12 @@ loads aTable, put it in an array, update the tableViewColumns and reload the tab // Check whether a save of the current row is required. if ( ![self saveRowOnDeselect] ) return; - selectedTable = aTable; + if (selectedTable) [selectedTable release]; + if (aTable == nil) { + selectedTable = nil; + } else { + selectedTable = [[NSString alloc] initWithString:aTable]; + } [tableSourceView deselectAll:self]; [indexView deselectAll:self]; @@ -1342,6 +1347,7 @@ traps enter and esc and make/cancel editing without entering next row currentlyEditingRow = -1; defaultValues = nil; + selectedTable = nil; prefs = [NSUserDefaults standardUserDefaults]; } @@ -1363,6 +1369,7 @@ traps enter and esc and make/cancel editing without entering next row [oldRow release]; [enumFields release]; if (defaultValues) [defaultValues release]; + if (selectedTable) [selectedTable release]; [super dealloc]; } diff --git a/Source/TablesList.h b/Source/TablesList.h index 6210f9e7..68578010 100644 --- a/Source/TablesList.h +++ b/Source/TablesList.h @@ -40,6 +40,7 @@ enum sp_table_types @interface NSObject (NSSplitView) - (NSView *)collapsibleSubview; - (IBAction)toggleCollapse:(id)sender; +- (BOOL)collapsibleSubviewIsCollapsed; - (void)setCollapsibleSubviewCollapsed:(BOOL)flag; @end @@ -74,8 +75,11 @@ enum sp_table_types IBOutlet id truncateTableButton; IBOutlet id truncateTableContextButton; IBOutlet NSSplitView *tableListSplitView; + IBOutlet NSSplitView *tableListFilterSplitView; IBOutlet NSButton *tableInfoCollapseButton; - + + IBOutlet NSSearchField *listFilterField; + IBOutlet NSMenuItem *removeTableMenuItem; IBOutlet NSMenuItem *duplicateTableMenuItem; IBOutlet NSMenuItem *renameTableMenuItem; @@ -89,7 +93,13 @@ enum sp_table_types IBOutlet NSMenuItem *separatorTableContextMenuItem; NSMutableArray *tables; + NSMutableArray *filteredTables; NSMutableArray *tableTypes; + NSMutableArray *filteredTableTypes; + int selectedTableType; + NSString *selectedTableName; + BOOL isTableListFiltered; + BOOL tableListContainsViews; BOOL structureLoaded, contentLoaded, statusLoaded, alertSheetOpened; } @@ -112,6 +122,7 @@ enum sp_table_types - (void)setConnection:(MCPConnection *)theConnection; - (void)truncateTable; - (void)doPerformQueryService:(NSString *)query; +- (void)updateSelection; // Getters - (NSString *)tableName; @@ -133,4 +144,11 @@ enum sp_table_types - (void)setStatusRequiresReload:(BOOL)reload; - (BOOL)selectTableOrViewWithName:(NSString *)theName; +// Table list filter interaction +- (void) showFilter; +- (void) hideFilter; +- (void) clearFilter; +- (IBAction) updateFilter:(id)sender; +- (void) selectTableAtIndex:(NSNumber *)rowIndex; + @end diff --git a/Source/TablesList.m b/Source/TablesList.m index a8781128..35240e46 100644 --- a/Source/TablesList.m +++ b/Source/TablesList.m @@ -34,6 +34,7 @@ #import "SPArrayAdditions.h" #import "RegexKitLite.h" #import "SPDatabaseData.h" +#import "NSMutableArray-MultipleSort.h" @implementation TablesList @@ -47,20 +48,24 @@ MCPResult *theResult; NSArray *resultRow; int i; - BOOL containsViews = NO; - NSString *selectedTable = nil; + NSString *previousSelectedTable = nil; NSInteger selectedRowIndex; selectedRowIndex = [tablesListView selectedRow]; - if(selectedRowIndex > 0 && [tables count] && selectedRowIndex < [tables count]){ - selectedTable = [NSString stringWithString:[tables objectAtIndex:selectedRowIndex]]; + if (selectedTableName) previousSelectedTable = [[NSString alloc] initWithString:selectedTableName]; + if (isTableListFiltered) { + if (filteredTables) [filteredTables release]; + filteredTables = tables; + if (filteredTableTypes) [filteredTableTypes release]; + filteredTableTypes = tableTypes; + isTableListFiltered = NO; } + tableListContainsViews = NO; [tablesListView deselectAll:self]; [tables removeAllObjects]; [tableTypes removeAllObjects]; - [tableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_NONE]]; if ([tableDocumentInstance database]) { @@ -82,12 +87,15 @@ [tables addObject:[resultRow objectAtIndex:0]]; if ([[resultRow objectAtIndex:1] isEqualToString:@"VIEW"]) { [tableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_VIEW]]; - containsViews = YES; + tableListContainsViews = YES; } else { [tableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_TABLE]]; } } } + + // Reorder the tables in alphabetical order + [tables sortArrayUsingSelector:@selector(localizedCompare:) withPairedMutableArrays:tableTypes, nil]; /* grab the procedures and functions * @@ -118,7 +126,7 @@ [tables addObject:NSArrayObjectAtIndex(resultRow, 3)]; if( [NSArrayObjectAtIndex(resultRow, 4) isEqualToString:@"PROCEDURE"] ) { [tableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_PROC]]; - } else { + } else { [tableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_FUNC]]; } } @@ -180,17 +188,38 @@ [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self]; } - if (containsViews) { + // Add the table headers even if no tables were found + if (tableListContainsViews) { [tables insertObject:NSLocalizedString(@"TABLES & VIEWS",@"header for table & views list") atIndex:0]; } else { [tables insertObject:NSLocalizedString(@"TABLES",@"header for table list") atIndex:0]; } + [tableTypes insertObject:[NSNumber numberWithInt:SP_TABLETYPE_NONE] atIndex:0]; [tablesListView reloadData]; // if the previous selected table still exists, select it - if( selectedTable != nil && [tables indexOfObject:selectedTable] < [tables count]) { - [tablesListView selectRowIndexes:[NSIndexSet indexSetWithIndex:[tables indexOfObject:selectedTable]] byExtendingSelection:NO]; + if( previousSelectedTable != nil && [tables indexOfObject:previousSelectedTable] < [tables count]) { + int itemToReselect = [tables indexOfObject:previousSelectedTable]; + [tablesListView selectRowIndexes:[NSIndexSet indexSetWithIndex:itemToReselect] byExtendingSelection:NO]; + if (selectedTableName) [selectedTableName release]; + selectedTableName = [[NSString alloc] initWithString:[tables objectAtIndex:itemToReselect]]; + selectedTableType = [[tableTypes objectAtIndex:itemToReselect] intValue]; + } else { + selectedTableName = nil; + selectedTableType = SP_TABLETYPE_NONE; + } + + // Determine whether or not to show the list filter based on the number of tables, and clear it + [self clearFilter]; + if ([tables count] > 20) [self showFilter]; + else [self hideFilter]; + + // Set the filter placeholder text + if ([tableDocumentInstance database]) { + if ([theResult numOfRows]) [[listFilterField cell] setPlaceholderString:NSLocalizedString(@"Filter tables, views, procs & funcs", @"Filter placeholder when all tables types are present")]; + else if (tableListContainsViews) [[listFilterField cell] setPlaceholderString:NSLocalizedString(@"Filter tables and views", @"Filter placeholder when tables and views are present")]; + else [[listFilterField cell] setPlaceholderString:NSLocalizedString(@"Filter the list of tables", @"Filter placeholder when only tables are present")]; } } @@ -254,11 +283,35 @@ [mySQLConnection queryString:createStatement]; if ([[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { - // Table creation was successful - [tables insertObject:tableName atIndex:1]; - [tableTypes insertObject:[NSNumber numberWithInt:SP_TABLETYPE_TABLE] atIndex:1]; - [tablesListView reloadData]; - [tablesListView selectRow:1 byExtendingSelection:NO]; + + // Table creation was successful - insert the new item into the tables list and select it. + int addItemAtIndex = NSNotFound; + for (int i = 0; i < [tables count]; i++) { + int tableType = [[tableTypes objectAtIndex:i] intValue]; + if (tableType == SP_TABLETYPE_NONE) continue; + if (tableType == SP_TABLETYPE_PROC || tableType == SP_TABLETYPE_FUNC) { + addItemAtIndex = i - 1; + break; + } + if ([tableName localizedCompare:[tables objectAtIndex:i]] == NSOrderedAscending) { + addItemAtIndex = i; + break; + } + } + if (addItemAtIndex == NSNotFound) { + [tables addObject:tableName]; + [tableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_TABLE]]; + } else { + [tables insertObject:tableName atIndex:addItemAtIndex]; + [tableTypes insertObject:[NSNumber numberWithInt:SP_TABLETYPE_TABLE] atIndex:addItemAtIndex]; + } + + // Set the selected table name and type, and then use updateFilter to update the filter list and selection. + if (selectedTableName) [selectedTableName release]; + selectedTableName = [[NSString alloc] initWithString:tableName]; + selectedTableType = SP_TABLETYPE_TABLE; + [self updateFilter:self]; + [tablesListView scrollRowToVisible:[tablesListView selectedRow]]; NSInteger selectedIndex = [tabView indexOfTabViewItem:[tabView selectedTabViewItem]]; @@ -299,8 +352,6 @@ [NSString stringWithFormat:NSLocalizedString(@"Couldn't add table %@.\nMySQL said: %@", @"message of panel when table cannot be created with the given name"), tableName, [mySQLConnection getLastErrorMessage]]); - [tableTypes removeObjectAtIndex:([tableTypes count] - 1)]; - [tables removeObjectAtIndex:([tables count] - 1)]; [tablesListView reloadData]; } @@ -342,25 +393,25 @@ unsigned currentIndex = [indexes lastIndex]; if ([tablesListView numberOfSelectedRows] == 1) { - if([[tableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_VIEW) + if([[filteredTableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_VIEW) tblTypes = NSLocalizedString(@"view", @"view"); - else if([[tableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_TABLE) + else if([[filteredTableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_TABLE) tblTypes = NSLocalizedString(@"table", @"table"); - else if([[tableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_PROC) + else if([[filteredTableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_PROC) tblTypes = NSLocalizedString(@"procedure", @"procedure"); - else if([[tableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_FUNC) + else if([[filteredTableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_FUNC) tblTypes = NSLocalizedString(@"function", @"function"); - [alert setMessageText:[NSString stringWithFormat:NSLocalizedString(@"Delete %@ '%@'?", @"delete table/view message"), tblTypes, [tables objectAtIndex:[tablesListView selectedRow]]]]; - [alert setInformativeText:[NSString stringWithFormat:NSLocalizedString(@"Are you sure you want to delete the %@ '%@'. This operation cannot be undone.", @"delete table/view informative message"), tblTypes, [tables objectAtIndex:[tablesListView selectedRow]]]]; + [alert setMessageText:[NSString stringWithFormat:NSLocalizedString(@"Delete %@ '%@'?", @"delete table/view message"), tblTypes, [filteredTables objectAtIndex:[tablesListView selectedRow]]]]; + [alert setInformativeText:[NSString stringWithFormat:NSLocalizedString(@"Are you sure you want to delete the %@ '%@'. This operation cannot be undone.", @"delete table/view informative message"), tblTypes, [filteredTables objectAtIndex:[tablesListView selectedRow]]]]; } else { BOOL areTableTypeEqual = YES; - int lastType = [[tableTypes objectAtIndex:currentIndex] intValue]; + int lastType = [[filteredTableTypes objectAtIndex:currentIndex] intValue]; while (currentIndex != NSNotFound) { - if([[tableTypes objectAtIndex:currentIndex] intValue]!=lastType) + if([[filteredTableTypes objectAtIndex:currentIndex] intValue]!=lastType) { areTableTypeEqual = NO; break; @@ -415,7 +466,7 @@ [tableWindow endEditingFor:nil]; // Detect table type: table or view - tblType = [[tableTypes objectAtIndex:[tablesListView selectedRow]] intValue]; + tblType = [[filteredTableTypes objectAtIndex:[tablesListView selectedRow]] intValue]; switch (tblType){ case SP_TABLETYPE_TABLE: @@ -439,7 +490,7 @@ [copyTableMessageField setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Duplicate %@ '%@' to:", @"duplicate object message"), tableType, [self tableName]]]; //open copyTableSheet - [copyTableNameField setStringValue:[NSString stringWithFormat:@"%@_copy", [tables objectAtIndex:[tablesListView selectedRow]]]]; + [copyTableNameField setStringValue:[NSString stringWithFormat:@"%@_copy", [filteredTables objectAtIndex:[tablesListView selectedRow]]]]; [copyTableContentSwitch setState:NSOffState]; [NSApp beginSheet:copyTableSheet @@ -463,7 +514,7 @@ //get table/view structure queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW CREATE %@ %@", [tableType uppercaseString], - [[tables objectAtIndex:[tablesListView selectedRow]] backtickQuotedString] + [[filteredTables objectAtIndex:[tablesListView selectedRow]] backtickQuotedString] ]]; if ( ![queryResult numOfRows] ) { @@ -492,10 +543,10 @@ { // get the create syntax MCPResult *theResult; - if([self tableType] == SP_TABLETYPE_PROC) - theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW CREATE PROCEDURE %@", [[tables objectAtIndex:[tablesListView selectedRow]] backtickQuotedString]]]; + if(selectedTableType == SP_TABLETYPE_PROC) + theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW CREATE PROCEDURE %@", [selectedTableName backtickQuotedString]]]; else if([self tableType] == SP_TABLETYPE_FUNC) - theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW CREATE FUNCTION %@", [[tables objectAtIndex:[tablesListView selectedRow]] backtickQuotedString]]]; + theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW CREATE FUNCTION %@", [selectedTableName backtickQuotedString]]]; else return; @@ -503,7 +554,7 @@ if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { if ([mySQLConnection isConnected]) { NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, - [NSString stringWithFormat:NSLocalizedString(@"An error occured while retrieving the create syntax for '%@'.\nMySQL said: %@", @"message of panel when create syntax cannot be retrieved"), [tables objectAtIndex:[tablesListView selectedRow]], [mySQLConnection getLastErrorMessage]]); + [NSString stringWithFormat:NSLocalizedString(@"An error occured while retrieving the create syntax for '%@'.\nMySQL said: %@", @"message of panel when create syntax cannot be retrieved"), selectedTableName, [mySQLConnection getLastErrorMessage]]); } return; } @@ -535,7 +586,7 @@ [mySQLConnection queryString:[NSString stringWithFormat: @"INSERT INTO %@ SELECT * FROM %@", [[copyTableNameField stringValue] backtickQuotedString], - [[tables objectAtIndex:[tablesListView selectedRow]] backtickQuotedString] + [selectedTableName backtickQuotedString] ]]; if ( ![[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) { @@ -553,13 +604,41 @@ ); } } + + // Insert the new item into the tables list and select it. + int addItemAtIndex = NSNotFound; + for (int i = 0; i < [tables count]; i++) { + int tableType = [[tableTypes objectAtIndex:i] intValue]; + if (tableType == SP_TABLETYPE_NONE) continue; + if ((tableType == SP_TABLETYPE_VIEW || tableType == SP_TABLETYPE_TABLE) + && (tblType == SP_TABLETYPE_PROC || tblType == SP_TABLETYPE_FUNC)) { + continue; + } + if ((tableType == SP_TABLETYPE_PROC || tableType == SP_TABLETYPE_FUNC) + && (tblType == SP_TABLETYPE_VIEW || tblType == SP_TABLETYPE_TABLE)) { + addItemAtIndex = i - 1; + break; + } + if ([[copyTableNameField stringValue] localizedCompare:[tables objectAtIndex:i]] == NSOrderedAscending) { + addItemAtIndex = i; + break; + } + } + if (addItemAtIndex == NSNotFound) { + [tables addObject:[copyTableNameField stringValue]]; + [tableTypes addObject:[NSNumber numberWithInt:tblType]]; + } else { + [tables insertObject:[copyTableNameField stringValue] atIndex:addItemAtIndex]; + [tableTypes insertObject:[NSNumber numberWithInt:tblType] atIndex:addItemAtIndex]; + } - [tables insertObject:[copyTableNameField stringValue] atIndex:[tablesListView selectedRow]+1]; - [tableTypes insertObject:[NSNumber numberWithInt:tblType] atIndex:[tablesListView selectedRow]+1]; - [tablesListView selectRow:[tablesListView selectedRow]+1 byExtendingSelection:NO]; - [self updateTables:self]; + // Set the selected table name and type, and use updateFilter to update the filter list and selection + if (selectedTableName) [selectedTableName release]; + selectedTableName = [[NSString alloc] initWithString:[copyTableNameField stringValue]]; + selectedTableType = tblType; + [self updateFilter:self]; + [self updateSelection]; [tablesListView scrollRowToVisible:[tablesListView selectedRow]]; - } } } @@ -622,9 +701,14 @@ } else { // If there was no error, rename the table in our list and reload the table view's data - [tables replaceObjectAtIndex:[tablesListView selectedRow] withObject:[tableRenameField stringValue]]; - + if (isTableListFiltered) { + [tables replaceObjectAtIndex:[tables indexOfObject:[self tableName]] withObject:[tableRenameField stringValue]]; + } + [filteredTables replaceObjectAtIndex:[tablesListView selectedRow] withObject:[tableRenameField stringValue]]; + if (selectedTableName) [selectedTableName release]; + selectedTableName = [[NSString alloc] initWithString:[tableRenameField stringValue]]; [tablesListView reloadData]; + [self updateSelection]; } } else { // procedures and functions can only be renamed if one creates the new one and delete the old one @@ -664,11 +748,18 @@ NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Couldn't rename '%@'.\nMySQL said: %@", @"message of panel when an item cannot be renamed"), [self tableName], [mySQLConnection getLastErrorMessage]]); } else { - [tables replaceObjectAtIndex:[tablesListView selectedRow] withObject:[tableRenameField stringValue]]; + if (isTableListFiltered) { + [tables replaceObjectAtIndex:[tables indexOfObject:[self tableName]] withObject:[tableRenameField stringValue]]; + } + [filteredTables replaceObjectAtIndex:[tablesListView selectedRow] withObject:[tableRenameField stringValue]]; + if (selectedTableName) [selectedTableName release]; + selectedTableName = [[NSString alloc] initWithString:[tableRenameField stringValue]]; [tablesListView reloadData]; + [self updateSelection]; } } - // set window title + + // Set window title [tableWindow setTitle:[NSString stringWithFormat:@"(MySQL %@) %@/%@/%@", [tableDocumentInstance mySQLVersion], [tableDocumentInstance name], [tableDocumentInstance database], [tableRenameField stringValue]]]; } @@ -694,8 +785,8 @@ [[buttons objectAtIndex:1] setKeyEquivalent:@"\r"]; if ([tablesListView numberOfSelectedRows] == 1) { - [alert setMessageText:[NSString stringWithFormat:NSLocalizedString(@"Truncate table '%@'?", @"truncate table message"), [tables objectAtIndex:[tablesListView selectedRow]]]]; - [alert setInformativeText:[NSString stringWithFormat:NSLocalizedString(@"Are you sure you want to delete ALL records in the table '%@'. This operation cannot be undone.", @"truncate table informative message"), [tables objectAtIndex:[tablesListView selectedRow]]]]; + [alert setMessageText:[NSString stringWithFormat:NSLocalizedString(@"Truncate table '%@'?", @"truncate table message"), [filteredTables objectAtIndex:[tablesListView selectedRow]]]]; + [alert setInformativeText:[NSString stringWithFormat:NSLocalizedString(@"Are you sure you want to delete ALL records in the table '%@'. This operation cannot be undone.", @"truncate table informative message"), [filteredTables objectAtIndex:[tablesListView selectedRow]]]]; } else { [alert setMessageText:NSLocalizedString(@"Truncate selected tables?", @"truncate tables message")]; @@ -764,28 +855,33 @@ while (currentIndex != NSNotFound) { - if([[tableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_VIEW) { + if([[filteredTableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_VIEW) { [mySQLConnection queryString: [NSString stringWithFormat: @"DROP VIEW %@", - [[tables objectAtIndex:currentIndex] backtickQuotedString] + [[filteredTables objectAtIndex:currentIndex] backtickQuotedString] ]]; - } else if([[tableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_TABLE) { + } else if([[filteredTableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_TABLE) { [mySQLConnection queryString: [NSString stringWithFormat: @"DROP TABLE %@", - [[tables objectAtIndex:currentIndex] backtickQuotedString] + [[filteredTables objectAtIndex:currentIndex] backtickQuotedString] ]]; - } else if([[tableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_PROC) { + } else if([[filteredTableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_PROC) { [mySQLConnection queryString: [NSString stringWithFormat: @"DROP PROCEDURE %@", - [[tables objectAtIndex:currentIndex] backtickQuotedString] + [[filteredTables objectAtIndex:currentIndex] backtickQuotedString] ]]; - } else if([[tableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_FUNC) { + } else if([[filteredTableTypes objectAtIndex:currentIndex] intValue] == SP_TABLETYPE_FUNC) { [mySQLConnection queryString: [NSString stringWithFormat: @"DROP FUNCTION %@", - [[tables objectAtIndex:currentIndex] backtickQuotedString] + [[filteredTables objectAtIndex:currentIndex] backtickQuotedString] ]]; } if ( [[mySQLConnection getLastErrorMessage] isEqualTo:@""] ) { //dropped table with success - [tables removeObjectAtIndex:currentIndex]; - [tableTypes removeObjectAtIndex:currentIndex]; + if (isTableListFiltered) { + int unfilteredIndex = [tables indexOfObject:[filteredTables objectAtIndex:currentIndex]]; + [tables removeObjectAtIndex:unfilteredIndex]; + [tableTypes removeObjectAtIndex:unfilteredIndex]; + } + [filteredTables removeObjectAtIndex:currentIndex]; + [filteredTableTypes removeObjectAtIndex:currentIndex]; } else { //couldn't drop table error = TRUE; @@ -795,6 +891,15 @@ // get next index (beginning from the end) currentIndex = [indexes indexLessThanIndex:currentIndex]; } + + // Remove the isolated "current selection" item for filtered lists if appropriate + if (isTableListFiltered && [filteredTables count] > 1 + && [[filteredTableTypes objectAtIndex:[filteredTableTypes count]-1] intValue] == SP_TABLETYPE_NONE + && [[filteredTables objectAtIndex:[filteredTables count]-1] isEqualToString:NSLocalizedString(@"CURRENT SELECTION",@"header for current selection in filtered list")]) + { + [filteredTables removeLastObject]; + [filteredTableTypes removeLastObject]; + } [tablesListView reloadData]; @@ -822,13 +927,13 @@ while (currentIndex != NSNotFound) { - [mySQLConnection queryString:[NSString stringWithFormat: @"TRUNCATE TABLE %@", [[tables objectAtIndex:currentIndex] backtickQuotedString]]]; + [mySQLConnection queryString:[NSString stringWithFormat: @"TRUNCATE TABLE %@", [[filteredTables objectAtIndex:currentIndex] backtickQuotedString]]]; // Couldn't truncate table if (![[mySQLConnection getLastErrorMessage] isEqualTo:@""]) { NSBeginAlertSheet(NSLocalizedString(@"Error truncating table", @"error truncating table message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, - [NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to truncate the table '%@'.\n\nMySQL said: %@", @"error truncating table informative message"), [tables objectAtIndex:currentIndex], [mySQLConnection getLastErrorMessage]]); + [NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to truncate the table '%@'.\n\nMySQL said: %@", @"error truncating table informative message"), [filteredTables objectAtIndex:currentIndex], [mySQLConnection getLastErrorMessage]]); } // Get next index (beginning from the end) @@ -898,644 +1003,690 @@ } } -#pragma mark Getter methods - /** - * Returns the currently selected table or nil if no table or mulitple tables are selected + * Updates the current table selection. Triggered most times tableViewSelectionDidChange: + * fires, and also as a result of certain table actions. */ -- (NSString *)tableName +- (void)updateSelection { - if ( [tablesListView numberOfSelectedRows] == 1 ) { - return [tables objectAtIndex:[tablesListView selectedRow]]; - } else if ([tablesListView numberOfSelectedRows] > 1) { - return @""; - } else { - return nil; - } -} + if ( [tablesListView numberOfSelectedRows] == 1 && [[filteredTables objectAtIndex:[tablesListView selectedRow]] length] ) { -/* - * Returns the currently selected table type, or -1 if no table or multiple tables are selected - */ -- (int) tableType -{ - if ( [tablesListView numberOfSelectedRows] == 1 ) { - return [[tableTypes objectAtIndex:[tablesListView selectedRow]] intValue]; - } else if ([tablesListView numberOfSelectedRows] > 1) { - return -1; - } else { - return -1; - } -} + // Update the selected table name and type + if (selectedTableName) [selectedTableName release]; + selectedTableName = [[NSString alloc] initWithString:[filteredTables objectAtIndex:[tablesListView selectedRow]]]; + selectedTableType = [[filteredTableTypes objectAtIndex:[tablesListView selectedRow]] intValue]; + + // Remove the "current selection" item for filtered lists if appropriate + if (isTableListFiltered && [tablesListView selectedRow] < [filteredTables count] - 2 && [filteredTables count] > 2 + && [[filteredTableTypes objectAtIndex:[filteredTableTypes count]-2] intValue] == SP_TABLETYPE_NONE + && [[filteredTables objectAtIndex:[filteredTables count]-2] isEqualToString:NSLocalizedString(@"CURRENT SELECTION",@"header for current selection in filtered list")]) + { + [filteredTables removeObjectsInRange:NSMakeRange([filteredTables count]-2, 2)]; + [filteredTableTypes removeObjectsInRange:NSMakeRange([filteredTableTypes count]-2, 2)]; + [tablesListView reloadData]; + } + + // Reset the table information caches + [tableDataInstance resetAllData]; -/** - * Database tables accessor - */ -- (NSArray *)tables -{ - return tables; -} + [separatorTableMenuItem setHidden:NO]; + [separatorTableContextMenuItem setHidden:NO]; -/** - * Database tables accessors for a given table type - */ -- (NSArray *)allTableAndViewNames -{ - NSMutableArray *returnArray = [NSMutableArray array]; - int i; - int cnt = [[self tables] count]; - for(i=0; i Table items + // according to the table types + NSMenu *tableSubMenu = [[[NSApp mainMenu] itemAtIndex:5] submenu]; + + if(selectedTableType == SP_TABLETYPE_VIEW) + { + // Change mainMenu > Table > ... according to table type + [[tableSubMenu itemAtIndex:0] setTitle:NSLocalizedString(@"Copy Create View Syntax", @"copy create view syntax menu item")]; + [[tableSubMenu itemAtIndex:1] setTitle:NSLocalizedString(@"Show Create View Syntax", @"show create view syntax menu item")]; + [[tableSubMenu itemAtIndex:2] setHidden:NO]; // divider + [[tableSubMenu itemAtIndex:3] setHidden:NO]; + [[tableSubMenu itemAtIndex:3] setTitle:NSLocalizedString(@"Check View", @"check view menu item")]; + [[tableSubMenu itemAtIndex:4] setHidden:YES]; // repair + [[tableSubMenu itemAtIndex:5] setHidden:YES]; // divider + [[tableSubMenu itemAtIndex:6] setHidden:YES]; // analyse + [[tableSubMenu itemAtIndex:7] setHidden:YES]; // optimize + [[tableSubMenu itemAtIndex:8] setHidden:NO]; + [[tableSubMenu itemAtIndex:8] setTitle:NSLocalizedString(@"Flush View", @"flush view menu item")]; + [[tableSubMenu itemAtIndex:9] setHidden:YES]; // checksum -/** - * Returns YES if table status has already been loaded - */ -- (BOOL)statusLoaded -{ - return statusLoaded; -} + [renameTableMenuItem setHidden:NO]; // we don't have to check the mysql version + [renameTableMenuItem setTitle:NSLocalizedString(@"Rename View...", @"rename view menu title")]; + [duplicateTableMenuItem setHidden:NO]; + [duplicateTableMenuItem setTitle:NSLocalizedString(@"Duplicate View...", @"duplicate view menu title")]; + [truncateTableButton setHidden:YES]; + [removeTableMenuItem setTitle:NSLocalizedString(@"Remove View", @"remove view menu title")]; -#pragma mark Setter methods + [renameTableContextMenuItem setHidden:NO]; // we don't have to check the mysql version + [renameTableContextMenuItem setTitle:NSLocalizedString(@"Rename View...", @"rename view menu title")]; + [duplicateTableContextMenuItem setHidden:NO]; + [duplicateTableContextMenuItem setTitle:NSLocalizedString(@"Duplicate View...", @"duplicate view menu title")]; + [truncateTableContextButton setHidden:YES]; + [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove View", @"remove view menu title")]; + } + else if(selectedTableType == SP_TABLETYPE_TABLE) { + [[tableSubMenu itemAtIndex:0] setTitle:NSLocalizedString(@"Copy Create Table Syntax", @"copy create table syntax menu item")]; + [[tableSubMenu itemAtIndex:1] setTitle:NSLocalizedString(@"Show Create Table Syntax", @"show create table syntax menu item")]; + [[tableSubMenu itemAtIndex:2] setHidden:NO]; // divider + [[tableSubMenu itemAtIndex:3] setHidden:NO]; + [[tableSubMenu itemAtIndex:3] setTitle:NSLocalizedString(@"Check Table", @"check table menu item")]; + [[tableSubMenu itemAtIndex:4] setHidden:NO]; + [[tableSubMenu itemAtIndex:5] setHidden:NO]; // divider + [[tableSubMenu itemAtIndex:6] setHidden:NO]; + [[tableSubMenu itemAtIndex:7] setHidden:NO]; + [[tableSubMenu itemAtIndex:8] setHidden:NO]; + [[tableSubMenu itemAtIndex:8] setTitle:NSLocalizedString(@"Flush Table", @"flush table menu item")]; + [[tableSubMenu itemAtIndex:9] setHidden:NO]; -/** - * Mark the content table for refresh when it's next switched to - */ -- (void)setContentRequiresReload:(BOOL)reload -{ - contentLoaded = !reload; + [renameTableMenuItem setHidden:NO]; + [renameTableMenuItem setTitle:NSLocalizedString(@"Rename Table...", @"rename table menu title")]; + [duplicateTableMenuItem setHidden:NO]; + [duplicateTableMenuItem setTitle:NSLocalizedString(@"Duplicate Table...", @"duplicate table menu title")]; + [truncateTableButton setHidden:NO]; + [truncateTableButton setTitle:NSLocalizedString(@"Truncate Table", @"truncate table menu title")]; + [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Table", @"remove table menu title")]; + + [renameTableContextMenuItem setHidden:NO]; + [renameTableContextMenuItem setTitle:NSLocalizedString(@"Rename Table...", @"rename table menu title")]; + [duplicateTableContextMenuItem setHidden:NO]; + [duplicateTableContextMenuItem setTitle:NSLocalizedString(@"Duplicate Table...", @"duplicate table menu title")]; + [truncateTableContextButton setHidden:NO]; + [truncateTableContextButton setTitle:NSLocalizedString(@"Truncate Table", @"truncate table menu title")]; + [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Table", @"remove table menu title")]; + + } + else if(selectedTableType == SP_TABLETYPE_PROC) { + [[tableSubMenu itemAtIndex:0] setTitle:NSLocalizedString(@"Copy Create Procedure Syntax", @"copy create proc syntax menu item")]; + [[tableSubMenu itemAtIndex:1] setTitle:NSLocalizedString(@"Show Create Procedure Syntax", @"show create proc syntax menu item")]; + [[tableSubMenu itemAtIndex:2] setHidden:YES]; // divider + [[tableSubMenu itemAtIndex:3] setHidden:YES]; // copy columns + [[tableSubMenu itemAtIndex:4] setHidden:YES]; // divider + [[tableSubMenu itemAtIndex:5] setHidden:YES]; + [[tableSubMenu itemAtIndex:6] setHidden:YES]; + [[tableSubMenu itemAtIndex:7] setHidden:YES]; // divider + [[tableSubMenu itemAtIndex:8] setHidden:YES]; + [[tableSubMenu itemAtIndex:9] setHidden:YES]; + + [renameTableMenuItem setHidden:NO]; + [renameTableMenuItem setTitle:NSLocalizedString(@"Rename Procedure...", @"rename proc menu title")]; + [duplicateTableMenuItem setHidden:NO]; + [duplicateTableMenuItem setTitle:NSLocalizedString(@"Duplicate Procedure...", @"duplicate proc menu title")]; + [truncateTableButton setHidden:YES]; + [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Procedure", @"remove proc menu title")]; + + [renameTableContextMenuItem setHidden:NO]; + [renameTableContextMenuItem setTitle:NSLocalizedString(@"Rename Procedure...", @"rename proc menu title")]; + [duplicateTableContextMenuItem setHidden:NO]; + [duplicateTableContextMenuItem setTitle:NSLocalizedString(@"Duplicate Procedure...", @"duplicate proc menu title")]; + [truncateTableContextButton setHidden:YES]; + [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Procedure", @"remove proc menu title")]; + + } + else if(selectedTableType == SP_TABLETYPE_FUNC) { + [[tableSubMenu itemAtIndex:0] setTitle:NSLocalizedString(@"Copy Create Function Syntax", @"copy create func syntax menu item")]; + [[tableSubMenu itemAtIndex:1] setTitle:NSLocalizedString(@"Show Create Function Syntax", @"show create func syntax menu item")]; + [[tableSubMenu itemAtIndex:2] setHidden:YES]; // divider + [[tableSubMenu itemAtIndex:3] setHidden:YES]; // copy columns + [[tableSubMenu itemAtIndex:4] setHidden:YES]; // divider + [[tableSubMenu itemAtIndex:5] setHidden:YES]; + [[tableSubMenu itemAtIndex:6] setHidden:YES]; + [[tableSubMenu itemAtIndex:7] setHidden:YES]; // divider + [[tableSubMenu itemAtIndex:8] setHidden:YES]; + [[tableSubMenu itemAtIndex:9] setHidden:YES]; + + [renameTableMenuItem setHidden:NO]; + [renameTableMenuItem setTitle:NSLocalizedString(@"Rename Function...", @"rename func menu title")]; + [duplicateTableMenuItem setHidden:NO]; + [duplicateTableMenuItem setTitle:NSLocalizedString(@"Duplicate Function...", @"duplicate func menu title")]; + [truncateTableButton setHidden:YES]; + [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Function", @"remove func menu title")]; + + [renameTableContextMenuItem setHidden:NO]; + [renameTableContextMenuItem setTitle:NSLocalizedString(@"Rename Function...", @"rename func menu title")]; + [duplicateTableContextMenuItem setHidden:NO]; + [duplicateTableContextMenuItem setTitle:NSLocalizedString(@"Duplicate Function...", @"duplicate func menu title")]; + [truncateTableContextButton setHidden:YES]; + [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Function", @"remove func menu title")]; + + } + // set window title + [tableWindow setTitle:[NSString stringWithFormat:@"(MySQL %@) %@/%@/%@", [tableDocumentInstance mySQLVersion], + [tableDocumentInstance name], [tableDocumentInstance database], selectedTableName]]; + + // Update the "Show Create Syntax" window if it's already opened + // according to the selected table/view/proc/func + if([[tableDocumentInstance getCreateTableSyntaxWindow] isVisible]) + [tableDocumentInstance showCreateTableSyntax:self]; + + } else { + NSIndexSet *indexes = [tablesListView selectedRowIndexes]; + + // Update the selected table name and type + if (selectedTableName) [selectedTableName release]; + if ([indexes count]) { + selectedTableName = [[NSString alloc] initWithString:@""]; + } else { + selectedTableName = nil; + } + selectedTableType = SP_TABLETYPE_NONE; + + [tableSourceInstance loadTable:nil]; + [tableContentInstance loadTable:nil]; + [extendedTableInfoInstance loadTable:nil]; + structureLoaded = NO; + contentLoaded = NO; + statusLoaded = NO; + + // Set gear menu items Remove/Duplicate table/view according to the table types + // if at least one item is selected + if([indexes count]) { + unsigned int currentIndex = [indexes lastIndex]; + BOOL areTableTypeEqual = YES; + int lastType = [[filteredTableTypes objectAtIndex:currentIndex] intValue]; + while (currentIndex != NSNotFound) + { + if ([[filteredTableTypes objectAtIndex:currentIndex] intValue] != lastType) + { + areTableTypeEqual = NO; + break; + } + currentIndex = [indexes indexLessThanIndex:currentIndex]; + } + if (areTableTypeEqual) + { + switch (lastType) { + case SP_TABLETYPE_TABLE: + [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Tables", @"remove tables menu title")]; + [truncateTableButton setTitle:NSLocalizedString(@"Truncate Tables", @"truncate tables menu item")]; + [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Tables", @"remove tables menu title")]; + [truncateTableContextButton setTitle:NSLocalizedString(@"Truncate Tables", @"truncate tables menu item")]; + [truncateTableButton setHidden:NO]; + [truncateTableContextButton setHidden:NO]; + break; + case SP_TABLETYPE_VIEW: + [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Views", @"remove views menu title")]; + [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Views", @"remove views menu title")]; + [truncateTableButton setHidden:YES]; + [truncateTableContextButton setHidden:YES]; + break; + case SP_TABLETYPE_PROC: + [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Procedures", @"remove procedures menu title")]; + [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Procedures", @"remove procedures menu title")]; + [truncateTableButton setHidden:YES]; + [truncateTableContextButton setHidden:YES]; + break; + case SP_TABLETYPE_FUNC: + [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Functions", @"remove functions menu title")]; + [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Functions", @"remove functions menu title")]; + [truncateTableButton setHidden:YES]; + [truncateTableContextButton setHidden:YES]; + break; + } + + } else { + [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Items", @"remove items menu title")]; + [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Items", @"remove items menu title")]; + [truncateTableButton setHidden:YES]; + [truncateTableContextButton setHidden:YES]; + } + } + [renameTableContextMenuItem setHidden:YES]; + [duplicateTableContextMenuItem setHidden:YES]; + [separatorTableContextMenuItem setHidden:YES]; + + [renameTableMenuItem setHidden:YES]; + [duplicateTableMenuItem setHidden:YES]; + [separatorTableMenuItem setHidden:YES]; + [separatorTableContextMenuItem setHidden:YES]; + + // set window title + [tableWindow setTitle:[NSString stringWithFormat:@"(MySQL %@) %@/%@", [tableDocumentInstance mySQLVersion], + [tableDocumentInstance name], [tableDocumentInstance database]]]; + } } +#pragma mark Getter methods + /** - * Mark the exteded table info for refresh when it's next switched to + * Returns the currently selected table or nil if no table or mulitple tables are selected */ -- (void)setStatusRequiresReload:(BOOL)reload +- (NSString *)tableName { - statusLoaded = !reload; + return selectedTableName; +} + +/* + * Returns the currently selected table type, or -1 if no table or multiple tables are selected + */ +- (int) tableType +{ + return selectedTableType; } /** - * Select a table or view using the provided name; returns YES if the - * supplied name could be selected, or NO if not. + * Database tables accessor */ -- (BOOL)selectTableOrViewWithName:(NSString *)theName +- (NSArray *)tables { - int i, tableType; - int itemIndex = NSNotFound; - int caseInsensitiveItemIndex = NSNotFound; + return tables; +} - // Loop through the tables/views to find the desired item - for (i = 0; i < [tables count]; i++) { - tableType = [[tableTypes objectAtIndex:i] intValue]; - if (tableType != SP_TABLETYPE_TABLE && tableType != SP_TABLETYPE_VIEW) continue; - if ([[tables objectAtIndex:i] isEqualToString:theName]) { - itemIndex = i; - break; - } - if ([[tables objectAtIndex:i] compare:theName options:NSCaseInsensitiveSearch|NSLiteralSearch] == NSOrderedSame) - caseInsensitiveItemIndex = i; +/** + * Database tables accessors for a given table type + */ +- (NSArray *)allTableAndViewNames +{ + NSMutableArray *returnArray = [NSMutableArray array]; + int i; + int cnt = [[self tables] count]; + for(i=0; i Table items - // according to the table types - NSMenu *tableSubMenu = [[[NSApp mainMenu] itemAtIndex:5] submenu]; - - if([[tableTypes objectAtIndex:[tablesListView selectedRow]] intValue] == SP_TABLETYPE_VIEW) - { - // Change mainMenu > Table > ... according to table type - [[tableSubMenu itemAtIndex:0] setTitle:NSLocalizedString(@"Copy Create View Syntax", @"copy create view syntax menu item")]; - [[tableSubMenu itemAtIndex:1] setTitle:NSLocalizedString(@"Show Create View Syntax", @"show create view syntax menu item")]; - [[tableSubMenu itemAtIndex:2] setHidden:NO]; // divider - [[tableSubMenu itemAtIndex:3] setHidden:NO]; - [[tableSubMenu itemAtIndex:3] setTitle:NSLocalizedString(@"Check View", @"check view menu item")]; - [[tableSubMenu itemAtIndex:4] setHidden:YES]; // repair - [[tableSubMenu itemAtIndex:5] setHidden:YES]; // divider - [[tableSubMenu itemAtIndex:6] setHidden:YES]; // analyse - [[tableSubMenu itemAtIndex:7] setHidden:YES]; // optimize - [[tableSubMenu itemAtIndex:8] setHidden:NO]; - [[tableSubMenu itemAtIndex:8] setTitle:NSLocalizedString(@"Flush View", @"flush view menu item")]; - [[tableSubMenu itemAtIndex:9] setHidden:YES]; // checksum - - [renameTableMenuItem setHidden:NO]; // we don't have to check the mysql version - [renameTableMenuItem setTitle:NSLocalizedString(@"Rename View...", @"rename view menu title")]; - [duplicateTableMenuItem setHidden:NO]; - [duplicateTableMenuItem setTitle:NSLocalizedString(@"Duplicate View...", @"duplicate view menu title")]; - [truncateTableButton setHidden:YES]; - [removeTableMenuItem setTitle:NSLocalizedString(@"Remove View", @"remove view menu title")]; - - [renameTableContextMenuItem setHidden:NO]; // we don't have to check the mysql version - [renameTableContextMenuItem setTitle:NSLocalizedString(@"Rename View...", @"rename view menu title")]; - [duplicateTableContextMenuItem setHidden:NO]; - [duplicateTableContextMenuItem setTitle:NSLocalizedString(@"Duplicate View...", @"duplicate view menu title")]; - [truncateTableContextButton setHidden:YES]; - [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove View", @"remove view menu title")]; - } - else if([[tableTypes objectAtIndex:[tablesListView selectedRow]] intValue] == SP_TABLETYPE_TABLE) { - [[tableSubMenu itemAtIndex:0] setTitle:NSLocalizedString(@"Copy Create Table Syntax", @"copy create table syntax menu item")]; - [[tableSubMenu itemAtIndex:1] setTitle:NSLocalizedString(@"Show Create Table Syntax", @"show create table syntax menu item")]; - [[tableSubMenu itemAtIndex:2] setHidden:NO]; // divider - [[tableSubMenu itemAtIndex:3] setHidden:NO]; - [[tableSubMenu itemAtIndex:3] setTitle:NSLocalizedString(@"Check Table", @"check table menu item")]; - [[tableSubMenu itemAtIndex:4] setHidden:NO]; - [[tableSubMenu itemAtIndex:5] setHidden:NO]; // divider - [[tableSubMenu itemAtIndex:6] setHidden:NO]; - [[tableSubMenu itemAtIndex:7] setHidden:NO]; - [[tableSubMenu itemAtIndex:8] setHidden:NO]; - [[tableSubMenu itemAtIndex:8] setTitle:NSLocalizedString(@"Flush Table", @"flush table menu item")]; - [[tableSubMenu itemAtIndex:9] setHidden:NO]; - - [renameTableMenuItem setHidden:NO]; - [renameTableMenuItem setTitle:NSLocalizedString(@"Rename Table...", @"rename table menu title")]; - [duplicateTableMenuItem setHidden:NO]; - [duplicateTableMenuItem setTitle:NSLocalizedString(@"Duplicate Table...", @"duplicate table menu title")]; - [truncateTableButton setHidden:NO]; - [truncateTableButton setTitle:NSLocalizedString(@"Truncate Table", @"truncate table menu title")]; - [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Table", @"remove table menu title")]; - - [renameTableContextMenuItem setHidden:NO]; - [renameTableContextMenuItem setTitle:NSLocalizedString(@"Rename Table...", @"rename table menu title")]; - [duplicateTableContextMenuItem setHidden:NO]; - [duplicateTableContextMenuItem setTitle:NSLocalizedString(@"Duplicate Table...", @"duplicate table menu title")]; - [truncateTableContextButton setHidden:NO]; - [truncateTableContextButton setTitle:NSLocalizedString(@"Truncate Table", @"truncate table menu title")]; - [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Table", @"remove table menu title")]; +#pragma mark Datasource methods - } - else if([[tableTypes objectAtIndex:[tablesListView selectedRow]] intValue] == SP_TABLETYPE_PROC) { - [[tableSubMenu itemAtIndex:0] setTitle:NSLocalizedString(@"Copy Create Procedure Syntax", @"copy create proc syntax menu item")]; - [[tableSubMenu itemAtIndex:1] setTitle:NSLocalizedString(@"Show Create Procedure Syntax", @"show create proc syntax menu item")]; - [[tableSubMenu itemAtIndex:2] setHidden:YES]; // divider - [[tableSubMenu itemAtIndex:3] setHidden:YES]; // copy columns - [[tableSubMenu itemAtIndex:4] setHidden:YES]; // divider - [[tableSubMenu itemAtIndex:5] setHidden:YES]; - [[tableSubMenu itemAtIndex:6] setHidden:YES]; - [[tableSubMenu itemAtIndex:7] setHidden:YES]; // divider - [[tableSubMenu itemAtIndex:8] setHidden:YES]; - [[tableSubMenu itemAtIndex:9] setHidden:YES]; - - [renameTableMenuItem setHidden:NO]; - [renameTableMenuItem setTitle:NSLocalizedString(@"Rename Procedure...", @"rename proc menu title")]; - [duplicateTableMenuItem setHidden:NO]; - [duplicateTableMenuItem setTitle:NSLocalizedString(@"Duplicate Procedure...", @"duplicate proc menu title")]; - [truncateTableButton setHidden:YES]; - [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Procedure", @"remove proc menu title")]; +/** + * Returns the number of tables in the current database. + */ +- (int)numberOfRowsInTableView:(NSTableView *)aTableView +{ + return [filteredTables count]; +} - [renameTableContextMenuItem setHidden:NO]; - [renameTableContextMenuItem setTitle:NSLocalizedString(@"Rename Procedure...", @"rename proc menu title")]; - [duplicateTableContextMenuItem setHidden:NO]; - [duplicateTableContextMenuItem setTitle:NSLocalizedString(@"Duplicate Procedure...", @"duplicate proc menu title")]; - [truncateTableContextButton setHidden:YES]; - [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Procedure", @"remove proc menu title")]; +/** + * Returns the table names to be displayed in the tables list table view. + */ +- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex +{ + return [filteredTables objectAtIndex:rowIndex]; +} - } - else if([[tableTypes objectAtIndex:[tablesListView selectedRow]] intValue] == SP_TABLETYPE_FUNC) { - [[tableSubMenu itemAtIndex:0] setTitle:NSLocalizedString(@"Copy Create Function Syntax", @"copy create func syntax menu item")]; - [[tableSubMenu itemAtIndex:1] setTitle:NSLocalizedString(@"Show Create Function Syntax", @"show create func syntax menu item")]; - [[tableSubMenu itemAtIndex:2] setHidden:YES]; // divider - [[tableSubMenu itemAtIndex:3] setHidden:YES]; // copy columns - [[tableSubMenu itemAtIndex:4] setHidden:YES]; // divider - [[tableSubMenu itemAtIndex:5] setHidden:YES]; - [[tableSubMenu itemAtIndex:6] setHidden:YES]; - [[tableSubMenu itemAtIndex:7] setHidden:YES]; // divider - [[tableSubMenu itemAtIndex:8] setHidden:YES]; - [[tableSubMenu itemAtIndex:9] setHidden:YES]; - - [renameTableMenuItem setHidden:NO]; - [renameTableMenuItem setTitle:NSLocalizedString(@"Rename Function...", @"rename func menu title")]; - [duplicateTableMenuItem setHidden:NO]; - [duplicateTableMenuItem setTitle:NSLocalizedString(@"Duplicate Function...", @"duplicate func menu title")]; - [truncateTableButton setHidden:YES]; - [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Function", @"remove func menu title")]; +/** + * Renames a table (in tables-array and mysql-db). + */ +- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex +{ + if ([selectedTableName isEqualToString:anObject]) { + // No changes in table name + } + else if ([anObject isEqualToString:@""]) { + // Table has no name + alertSheetOpened = YES; + NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, + @selector(sheetDidEnd:returnCode:contextInfo:), nil, @"addRow", NSLocalizedString(@"Empty names are not allowed.", @"message of panel when no name is given for an item")); + } + else { + if(selectedTableType == SP_TABLETYPE_VIEW || selectedTableType == SP_TABLETYPE_TABLE) + { + [mySQLConnection queryString:[NSString stringWithFormat:@"RENAME TABLE %@ TO %@", [selectedTableName backtickQuotedString], [anObject backtickQuotedString]]]; + } + else + { + // procedures and functions can only be renamed if one creates the new one and delete the old one + // get the create syntax + NSString *tableType; + switch (selectedTableType){ + case SP_TABLETYPE_PROC: + tableType = @"PROCEDURE"; + break; + case SP_TABLETYPE_FUNC: + tableType = @"FUNCTION"; + break; + } + MCPResult *theResult; + if (selectedTableType == SP_TABLETYPE_PROC) + theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW CREATE PROCEDURE %@", [selectedTableName backtickQuotedString]]]; + else if(selectedTableType == SP_TABLETYPE_FUNC) + theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW CREATE FUNCTION %@", [selectedTableName backtickQuotedString]]]; + else + return; - [renameTableContextMenuItem setHidden:NO]; - [renameTableContextMenuItem setTitle:NSLocalizedString(@"Rename Function...", @"rename func menu title")]; - [duplicateTableContextMenuItem setHidden:NO]; - [duplicateTableContextMenuItem setTitle:NSLocalizedString(@"Duplicate Function...", @"duplicate func menu title")]; - [truncateTableContextButton setHidden:YES]; - [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Function", @"remove func menu title")]; + // Check for errors, only displaying if the connection hasn't been terminated + if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { + if ([mySQLConnection isConnected]) { + NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), + NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, + [NSString stringWithFormat:NSLocalizedString(@"An error occured while retrieving create syntax for '%@'.\n\nMySQL said: %@", @"message of panel when create syntax cannot be retrieved"), selectedTableName, [mySQLConnection getLastErrorMessage]]); - } - // set window title - [tableWindow setTitle:[NSString stringWithFormat:@"(MySQL %@) %@/%@/%@", [tableDocumentInstance mySQLVersion], - [tableDocumentInstance name], [tableDocumentInstance database], [tables objectAtIndex:[tablesListView selectedRow]]]]; + } + return; + } - // Update the "Show Create Syntax" window if it's already opened - // according to the selected table/view/proc/func - if([[tableDocumentInstance getCreateTableSyntaxWindow] isVisible]) - [tableDocumentInstance showCreateTableSyntax:self]; + id tableSyntax = [[theResult fetchRowAsArray] objectAtIndex:2]; - } else { - [tableSourceInstance loadTable:nil]; - [tableContentInstance loadTable:nil]; - [extendedTableInfoInstance loadTable:nil]; - structureLoaded = NO; - contentLoaded = NO; - statusLoaded = NO; + if ([tableSyntax isKindOfClass:[NSData class]]) + tableSyntax = [[[NSString alloc] initWithData:tableSyntax encoding:[mySQLConnection encoding]] autorelease]; - // Set gear menu items Remove/Duplicate table/view according to the table types - // if at least one item is selected - NSIndexSet *indexes = [tablesListView selectedRowIndexes]; - if([indexes count]) { - unsigned int currentIndex = [indexes lastIndex]; - BOOL areTableTypeEqual = YES; - int lastType = [[tableTypes objectAtIndex:currentIndex] intValue]; - while (currentIndex != NSNotFound) - { - if([[tableTypes objectAtIndex:currentIndex] intValue]!=lastType) - { - areTableTypeEqual = NO; - break; + // replace the old name by the new one and drop the old one + [mySQLConnection queryString:[tableSyntax stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat:@"(?<=%@ )(`[^`]+?`)", tableType] withString:[anObject backtickQuotedString]]]; + if ([[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { + if ([mySQLConnection isConnected]) { + [mySQLConnection queryString: [NSString stringWithFormat: @"DROP %@ %@", tableType, [[tables objectAtIndex:rowIndex] backtickQuotedString]]]; } - currentIndex = [indexes indexLessThanIndex:currentIndex]; } - if(areTableTypeEqual) - { - switch(lastType) { - case SP_TABLETYPE_TABLE: - [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Tables", @"remove tables menu title")]; - [truncateTableButton setTitle:NSLocalizedString(@"Truncate Tables", @"truncate tables menu item")]; - [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Tables", @"remove tables menu title")]; - [truncateTableContextButton setTitle:NSLocalizedString(@"Truncate Tables", @"truncate tables menu item")]; - [truncateTableButton setHidden:NO]; - [truncateTableContextButton setHidden:NO]; - break; - case SP_TABLETYPE_VIEW: - [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Views", @"remove views menu title")]; - [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Views", @"remove views menu title")]; - [truncateTableButton setHidden:YES]; - [truncateTableContextButton setHidden:YES]; - break; - case SP_TABLETYPE_PROC: - [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Procedures", @"remove procedures menu title")]; - [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Procedures", @"remove procedures menu title")]; - [truncateTableButton setHidden:YES]; - [truncateTableContextButton setHidden:YES]; - break; - case SP_TABLETYPE_FUNC: - [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Functions", @"remove functions menu title")]; - [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Functions", @"remove functions menu title")]; - [truncateTableButton setHidden:YES]; - [truncateTableContextButton setHidden:YES]; - break; - } + } + + if ([[mySQLConnection getLastErrorMessage] isEqualToString:@""]) { + // Renamed with success + if (isTableListFiltered) { + int unfilteredIndex = [tables indexOfObject:[filteredTables objectAtIndex:rowIndex]]; + [tables replaceObjectAtIndex:unfilteredIndex withObject:anObject]; + } + [filteredTables replaceObjectAtIndex:rowIndex withObject:anObject]; + if (selectedTableName) [selectedTableName release]; + selectedTableName = [[NSString alloc] initWithString:anObject]; - } else { - [removeTableMenuItem setTitle:NSLocalizedString(@"Remove Items", @"remove items menu title")]; - [removeTableContextMenuItem setTitle:NSLocalizedString(@"Remove Items", @"remove items menu title")]; - [truncateTableButton setHidden:YES]; - [truncateTableContextButton setHidden:YES]; + if(selectedTableType == SP_TABLETYPE_FUNC || selectedTableType == SP_TABLETYPE_PROC) + return; + NSInteger selectedIndex = [tabView indexOfTabViewItem:[tabView selectedTabViewItem]]; + + if (selectedIndex == 0) { + [tableSourceInstance loadTable:anObject]; + structureLoaded = YES; + contentLoaded = NO; + statusLoaded = NO; + } + else if (selectedIndex == 1) { + [tableContentInstance loadTable:anObject]; + structureLoaded = NO; + contentLoaded = YES; + statusLoaded = NO; + } + else if (selectedIndex == 3) { + [extendedTableInfoInstance loadTable:anObject]; + structureLoaded = NO; + contentLoaded = NO; + statusLoaded = YES; + } + else { + statusLoaded = NO; + structureLoaded = NO; + contentLoaded = NO; } + + // Set window title + [tableWindow setTitle:[NSString stringWithFormat:@"(MySQL %@) %@/%@/%@", [tableDocumentInstance mySQLVersion], + [tableDocumentInstance name], [tableDocumentInstance database], anObject]]; + } + else { + // Error while renaming + alertSheetOpened = YES; + NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, + @selector(sheetDidEnd:returnCode:contextInfo:), nil, @"addRow", + [NSString stringWithFormat:NSLocalizedString(@"Couldn't rename '%@'.\nMySQL said: %@", @"message of panel when an item cannot be renamed"), + anObject, [mySQLConnection getLastErrorMessage]]); } - [renameTableContextMenuItem setHidden:YES]; - [duplicateTableContextMenuItem setHidden:YES]; - [separatorTableContextMenuItem setHidden:YES]; + } +} - [renameTableMenuItem setHidden:YES]; - [duplicateTableMenuItem setHidden:YES]; - [separatorTableMenuItem setHidden:YES]; - [separatorTableContextMenuItem setHidden:YES]; - // set window title - [tableWindow setTitle:[NSString stringWithFormat:@"(MySQL %@) %@/%@", [tableDocumentInstance mySQLVersion], - [tableDocumentInstance name], [tableDocumentInstance database]]]; +#pragma mark TableView delegate methods + +/** + * Traps enter and esc and edit/cancel without entering next row + */ +- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command +{ + if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertNewline:)] ) { + //save current line + [[control window] makeFirstResponder:control]; + return TRUE; + + } else if ( [[control window] methodForSelector:command] == [[control window] methodForSelector:@selector(_cancelKey:)] || + [textView methodForSelector:command] == [textView methodForSelector:@selector(complete:)] ) { + + //abort editing + [control abortEditing]; + + return TRUE; + } else{ + return FALSE; + } +} + +/** + * Table view delegate method + */ +- (BOOL)selectionShouldChangeInTableView:(NSTableView *)aTableView +{ + // End editing (otherwise problems when user hits reload button) + [tableWindow endEditingFor:nil]; + + if ( alertSheetOpened ) { + return NO; + } + + // We have to be sure that TableSource and TableContent have finished editing + if ( ![tableSourceInstance saveRowOnDeselect] || ![tableContentInstance saveRowOnDeselect] ) { + return NO; + } else { + return YES; + } +} + +/** + * Loads a table in content or source view (if tab selected) + */ +- (void)tableViewSelectionDidChange:(NSNotification *)aNotification +{ + + // Perform no action if the selected table hasn't actually changed - reselection etc + if ([tablesListView numberOfSelectedRows] == 1 + && [[filteredTables objectAtIndex:[tablesListView selectedRow]] length] + && [selectedTableName isEqualToString:[filteredTables objectAtIndex:[tablesListView selectedRow]]] + && selectedTableType == [[filteredTableTypes objectAtIndex:[tablesListView selectedRow]] intValue]) + { + return; } + + [self updateSelection]; } /** @@ -1544,9 +1695,9 @@ - (BOOL)tableView:(NSTableView *)aTableView shouldSelectRow:(int)rowIndex { //return (rowIndex != 0); - if( [tableTypes count] == 0 ) + if( [filteredTableTypes count] == 0 ) return (rowIndex != 0 ); - return ([[tableTypes objectAtIndex:rowIndex] intValue] != SP_TABLETYPE_NONE ); + return ([[filteredTableTypes objectAtIndex:rowIndex] intValue] != SP_TABLETYPE_NONE ); } /** @@ -1555,9 +1706,9 @@ - (BOOL)tableView:(NSTableView *)aTableView isGroupRow:(int)rowIndex { //return (row == 0); - if( [tableTypes count] == 0 ) + if( [filteredTableTypes count] == 0 ) return (rowIndex == 0 ); - return ([[tableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_NONE ); + return ([[filteredTableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_NONE ); } /** @@ -1566,17 +1717,17 @@ - (void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex { if (rowIndex > 0 && [[aTableColumn identifier] isEqualToString:@"tables"]) { - if ([[tableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_VIEW) { + if ([[filteredTableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_VIEW) { [(ImageAndTextCell*)aCell setImage:[NSImage imageNamed:@"table-view-small"]]; - } else if ([[tableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_TABLE) { + } else if ([[filteredTableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_TABLE) { [(ImageAndTextCell*)aCell setImage:[NSImage imageNamed:@"table-small"]]; - } else if ([[tableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_PROC) { + } else if ([[filteredTableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_PROC) { [(ImageAndTextCell*)aCell setImage:[NSImage imageNamed:@"proc-small"]]; - } else if ([[tableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_FUNC) { + } else if ([[filteredTableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_FUNC) { [(ImageAndTextCell*)aCell setImage:[NSImage imageNamed:@"func-small"]]; } - if ([[tableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_NONE) { + if ([[filteredTableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_NONE) { [(ImageAndTextCell*)aCell setImage:nil]; [(ImageAndTextCell*)aCell setIndentationLevel:0]; } else { @@ -1608,17 +1759,17 @@ ([self tableType] == SP_TABLETYPE_TABLE || [self tableType] == SP_TABLETYPE_VIEW) ) { if ( ([tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 0) && !structureLoaded ) { - [tableSourceInstance loadTable:[tables objectAtIndex:[tablesListView selectedRow]]]; + [tableSourceInstance loadTable:selectedTableName]; structureLoaded = YES; } if ( ([tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 1) && !contentLoaded ) { - [tableContentInstance loadTable:[tables objectAtIndex:[tablesListView selectedRow]]]; + [tableContentInstance loadTable:selectedTableName]; contentLoaded = YES; } if ( ([tabView indexOfTabViewItem:[tabView selectedTabViewItem]] == 3) && !statusLoaded ) { - [extendedTableInfoInstance loadTable:[tables objectAtIndex:[tablesListView selectedRow]]]; + [extendedTableInfoInstance loadTable:selectedTableName]; statusLoaded = YES; } } @@ -1649,6 +1800,125 @@ return [super validateMenuItem:menuItem]; } +#pragma mark Table list filter interaction + +/** + * Show the filter box if it's currently hidden. Use a delay to ensure + * action is executed on first load. + */ +- (void) showFilter +{ + if ([tableListFilterSplitView collapsibleSubviewIsCollapsed]) + [tableListFilterSplitView performSelector:@selector(toggleCollapse:) withObject:nil afterDelay:0.0]; +} + +/** + * Hide the filter box if it's currently shown. Use a delay to ensure + * action is executed on first load. + */ +- (void) hideFilter +{ + if (![tableListFilterSplitView collapsibleSubviewIsCollapsed]) + [tableListFilterSplitView performSelector:@selector(toggleCollapse:) withObject:nil afterDelay:0.0]; +} + +/** + * Clear the current content of the filter box + */ +- (void) clearFilter +{ + [listFilterField setStringValue:@""]; +} + +/** + * Update the filter search. + */ +- (IBAction) updateFilter:(id)sender +{ + if ([[listFilterField stringValue] length]) { + if (isTableListFiltered) { + [filteredTables release]; + [filteredTableTypes release]; + } + filteredTables = [[NSMutableArray alloc] init]; + filteredTableTypes = [[NSMutableArray alloc] init]; + + int i, lastTableType = NSNotFound, tableType; + NSRange substringRange; + for (i = 0; i < [tables count]; i++) { + tableType = [[tableTypes objectAtIndex:i] intValue]; + if (tableType == SP_TABLETYPE_NONE) continue; + substringRange = [[tables objectAtIndex:i] rangeOfString:[listFilterField stringValue] options:NSCaseInsensitiveSearch]; + if (substringRange.location == NSNotFound) continue; + + // Add a title if necessary + if ((tableType == SP_TABLETYPE_TABLE || tableType == SP_TABLETYPE_VIEW) && lastTableType == NSNotFound) + { + if (tableListContainsViews) { + [filteredTables addObject:NSLocalizedString(@"TABLES & VIEWS",@"header for table & views list")]; + } else { + [filteredTables addObject:NSLocalizedString(@"TABLES",@"header for table list")]; + } + [filteredTableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_NONE]]; + } else if ((tableType == SP_TABLETYPE_PROC || tableType == SP_TABLETYPE_FUNC) + && (lastTableType == NSNotFound || lastTableType == SP_TABLETYPE_TABLE || lastTableType == SP_TABLETYPE_VIEW)) + { + [filteredTables addObject:NSLocalizedString(@"PROCS & FUNCS",@"header for procs & funcs list")]; + [filteredTableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_NONE]]; + } + lastTableType = tableType; + + // Add the item + [filteredTables addObject:[tables objectAtIndex:i]]; + [filteredTableTypes addObject:[tableTypes objectAtIndex:i]]; + } + + // Add a "no matches" title if nothing matches the current filter settings + if (![filteredTables count]) { + [filteredTables addObject:NSLocalizedString(@"NO MATCHES",@"header for no matches in filtered list")]; + [filteredTableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_NONE]]; + } + + // If the currently selected table isn't present in the filter list, add it as a special entry + if (selectedTableName && [filteredTables indexOfObject:selectedTableName] == NSNotFound) { + [filteredTables addObject:NSLocalizedString(@"CURRENT SELECTION",@"header for current selection in filtered list")]; + [filteredTableTypes addObject:[NSNumber numberWithInt:SP_TABLETYPE_NONE]]; + [filteredTables addObject:selectedTableName]; + [filteredTableTypes addObject:[NSNumber numberWithInt:selectedTableType]]; + } + +// [self performSelector:@selector(selectTableAtIndex:) withObject:[NSNumber numberWithInt:[filteredTables indexOfObject:selectedTableName]] afterDelay:0.0]; + isTableListFiltered = YES; + } else if (isTableListFiltered) { + isTableListFiltered = NO; + [filteredTables release]; + filteredTables = tables; + [filteredTableTypes release]; + filteredTableTypes = tableTypes; + if (selectedTableName) { +// [self performSelector:@selector(selectTableAtIndex:) withObject:[NSNumber numberWithInt:[tables indexOfObject:selectedTableName]] afterDelay:0.0]; + } + } + + // Reselect correct row and reload the table view display + if ([tablesListView numberOfRows] < [filteredTables count]) [tablesListView noteNumberOfRowsChanged]; + if (selectedTableName) [tablesListView selectRowIndexes:[NSIndexSet indexSetWithIndex:[filteredTables indexOfObject:selectedTableName]] byExtendingSelection:NO]; + [tablesListView reloadData]; +} + +/** + * Select the supplied row index; added for convenience to allow + * use with performSelector:withObject:afterDelay: for re-selection. + */ +- (void) selectTableAtIndex:(NSNumber *)rowIndex +{ +// int rowIndex = [rowIndex intValue]; +// if (rowIndex == NSNotFound || rowIndex > [filteredTables count] || [[filteredTableTypes objectAtIndex:rowIndex] intValue] == SP_TABLETYPE_NONE) +// return; +// +// [tablesListView selectRowIndexes:[NSIndexSet indexSetWithIndex:rowIndex] byExtendingSelection:NO]; +} + #pragma mark Other /** @@ -1658,10 +1928,16 @@ { if ((self = [super init])) { tables = [[NSMutableArray alloc] init]; + filteredTables = tables; tableTypes = [[NSMutableArray alloc] init]; + filteredTableTypes = tableTypes; structureLoaded = NO; contentLoaded = NO; statusLoaded = NO; + isTableListFiltered = NO; + tableListContainsViews = NO; + selectedTableType = SP_TABLETYPE_NONE; + selectedTableName = nil; [tables addObject:NSLocalizedString(@"TABLES",@"header for table list")]; } @@ -1682,6 +1958,14 @@ [[tableListSplitView collapsibleSubview] setFrameSize:NSMakeSize([tableListSplitView collapsibleSubview].frame.size.width, 0)]; [tableListSplitView setCollapsibleSubviewCollapsed:YES]; } + + // Start the table filter list collapsed + if ([tableListFilterSplitView collapsibleSubview]) { + [tableListFilterSplitView setValue:[NSNumber numberWithFloat:[tableListFilterSplitView collapsibleSubview].frame.size.height] forKey:@"uncollapsedSize"]; + [[tableListFilterSplitView collapsibleSubview] setFrameSize:NSMakeSize([tableListFilterSplitView collapsibleSubview].frame.size.width, 0)]; + [tableListFilterSplitView setCollapsibleSubviewCollapsed:YES]; + } + } /** @@ -1689,8 +1973,11 @@ */ - (void)dealloc { - [tables release], tables = nil; - [tableTypes release], tableTypes = nil; + [tables release]; + [tableTypes release]; + if (isTableListFiltered && filteredTables) [filteredTables release]; + if (isTableListFiltered && filteredTableTypes) [filteredTableTypes release]; + if (selectedTableName) [selectedTableName release]; [super dealloc]; } diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index 9af19ca1..05809064 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -133,6 +133,7 @@ 5822C9B51000DB2400DCC3D6 /* SPConnectionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5822C9B41000DB2400DCC3D6 /* SPConnectionController.m */; }; 5822CAE110011C8000DCC3D6 /* ConnectionView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5822CADF10011C8000DCC3D6 /* ConnectionView.xib */; }; 5841423F0F97E11000A34B47 /* NoodleLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5841423E0F97E11000A34B47 /* NoodleLineNumberView.m */; }; + 584192A1101E57BB0089807F /* NSMutableArray-MultipleSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 584192A0101E57BB0089807F /* NSMutableArray-MultipleSort.m */; }; 584F5F8F0F50ACD800036517 /* table-view-small.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 584F5F8E0F50ACD800036517 /* table-view-small.tiff */; }; 586F457B0FDB269E00B428D7 /* RegexKitLite.m in Sources */ = {isa = PBXBuildFile; fileRef = 296DC8AB0F909194002A3258 /* RegexKitLite.m */; }; 586F457E0FDB280100B428D7 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 296DC8BE0F9091DF002A3258 /* libicucore.dylib */; }; @@ -480,6 +481,8 @@ 5822CAE010011C8000DCC3D6 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/ConnectionView.xib; sourceTree = ""; }; 5841423D0F97E11000A34B47 /* NoodleLineNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleLineNumberView.h; sourceTree = ""; }; 5841423E0F97E11000A34B47 /* NoodleLineNumberView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoodleLineNumberView.m; sourceTree = ""; }; + 5841929F101E57BB0089807F /* NSMutableArray-MultipleSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableArray-MultipleSort.h"; sourceTree = ""; }; + 584192A0101E57BB0089807F /* NSMutableArray-MultipleSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableArray-MultipleSort.m"; sourceTree = ""; }; 584F5F8E0F50ACD800036517 /* table-view-small.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "table-view-small.tiff"; sourceTree = ""; }; 586F432A0FD74CFC00B428D7 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/SSHQuestionDialog.xib; sourceTree = ""; }; 588593F30F7AEC9500ED0E67 /* package-application.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "package-application.sh"; sourceTree = ""; }; @@ -1175,6 +1178,8 @@ children = ( B52460D30F8EF92300171639 /* SPArrayAdditions.h */, B52460D40F8EF92300171639 /* SPArrayAdditions.m */, + 5841929F101E57BB0089807F /* NSMutableArray-MultipleSort.h */, + 584192A0101E57BB0089807F /* NSMutableArray-MultipleSort.m */, 1789343A0F30C1DD0097539A /* SPStringAdditions.h */, 1789343B0F30C1DD0097539A /* SPStringAdditions.m */, B52460D50F8EF92300171639 /* SPTextViewAdditions.h */, @@ -1581,6 +1586,7 @@ BC9F0881100FCF2C00A80D32 /* SPFieldEditorController.m in Sources */, 58D2E229101222670063EF1D /* SPTextAndLinkCell.m in Sources */, BC05F1C5101241DF008A97F8 /* AMIndeterminateProgressIndicatorCell.m in Sources */, + 584192A1101E57BB0089807F /* NSMutableArray-MultipleSort.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; -- cgit v1.2.3