aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPCharsetCollationHelper.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPCharsetCollationHelper.m')
-rw-r--r--Source/SPCharsetCollationHelper.m275
1 files changed, 275 insertions, 0 deletions
diff --git a/Source/SPCharsetCollationHelper.m b/Source/SPCharsetCollationHelper.m
new file mode 100644
index 00000000..c642c835
--- /dev/null
+++ b/Source/SPCharsetCollationHelper.m
@@ -0,0 +1,275 @@
+//
+// $Id$
+//
+// SPCharsetCollationHelper.h
+// sequel-pro
+//
+// Created by Max Lohrmann on March 20, 2013.
+// Copyright (c) 2013 Max Lohrmann. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "SPCharsetCollationHelper.h"
+
+#import "SPServerSupport.h"
+#import "SPDatabaseData.h"
+
+@interface SPCharsetCollationHelper (Hidden)
+
+- (void)charsetButtonClicked:(id)sender;
+- (void)collationButtonClicked:(id)sender;
+- (void)refreshCharsets;
+- (void)refreshCollations;
+
+@end
+
+
+@implementation SPCharsetCollationHelper
+
+@synthesize databaseData;
+@synthesize serverSupport;
+@synthesize promoteUTF8;
+@synthesize defaultCharset;
+@synthesize defaultCollation;
+@synthesize selectedCharset;
+@synthesize selectedCollation;
+@synthesize defaultCharsetFormatString;
+@synthesize _oldCharset;
+
+- (id)initWithCharsetButton:(NSPopUpButton *)aCharsetButton CollationButton:(NSPopUpButton *)aCollationButton
+{
+ NSAssert((aCharsetButton != nil),@"aCharsetButton != nil");
+ NSAssert((aCollationButton != nil),@"aCollationButton != nil");
+
+ self = [super init];
+ if (self != nil) {
+ [self setPromoteUTF8:YES];
+ [self setDefaultCharsetFormatString:NSLocalizedString(@"Default (%@)",@"Charset Dropdown : Default item ($1 = name)")];
+ charsetButton = aCharsetButton;
+ collationButton = aCollationButton;
+ //connect the charset button with ourselves
+ [charsetButton setTarget:self];
+ [charsetButton setAction:@selector(charsetButtonClicked:)];
+ //connect the collation button with ourselves
+ [collationButton setTarget:self];
+ [collationButton setAction:@selector(collationButtonClicked:)];
+ }
+ return self;
+}
+
+- (void)charsetButtonClicked:(id)sender {
+ if(!_enabled)
+ return;
+
+ //update selectedCharset
+ if(defaultCharset && [charsetButton indexOfSelectedItem] == 0) {
+ //this is the default item, which means nil for selectedCollation
+ [self setSelectedCharset:nil];
+ }
+ else {
+ //this is an actual item
+ NSString *charsetId = [[charsetButton selectedItem] representedObject];
+ [self setSelectedCharset:charsetId];
+ }
+
+ //update collations if there actually was a change in charset
+ if((selectedCharset == nil && _oldCharset == nil) || (selectedCharset && [selectedCharset isEqualToString:_oldCharset])) {
+ //same charset. (NOP - just for readability of the if statement)
+ }
+ else {
+ //reset the selected collation. that was only valid as long as the same charset was selected
+ [self setSelectedCollation:nil];
+ [self refreshCollations];
+ [self set_oldCharset:selectedCharset];
+ }
+
+}
+
+- (void)collationButtonClicked:(id)sender {
+ if(!_enabled)
+ return;
+
+ //update selectedCollation
+ if([collationButton indexOfSelectedItem] == 0) {
+ //this is the default item, which means nil for selectedCollation
+ [self setSelectedCollation:nil];
+ }
+ else {
+ //this is an actual item
+ [self setSelectedCollation:[collationButton titleOfSelectedItem]];
+ }
+
+}
+
+- (void)refreshCharsets {
+ //reset
+ [charsetButton removeAllItems];
+
+ // Retrieve the server-supported encodings and add them to the menu
+ NSArray *encodings = [databaseData getDatabaseCharacterSetEncodings];
+
+ [charsetButton setEnabled:NO];
+
+ NSMenuItem *selectedRef = nil;
+
+ if (([encodings count] > 0) && [serverSupport supportsPost41CharacterSetHandling]) {
+
+ for (NSDictionary *encoding in encodings)
+ {
+ NSString *charsetId = [encoding objectForKey:@"CHARACTER_SET_NAME"];
+ NSString *description = [encoding objectForKey:@"DESCRIPTION"];
+ NSString *menuItemTitle = (![description length]) ? charsetId : [NSString stringWithFormat:@"%@ (%@)", description, charsetId];
+
+ NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:menuItemTitle action:NULL keyEquivalent:@""];
+ [menuItem setRepresentedObject:charsetId];
+
+ //store the menu item that we want to select (we'll do that when the list is stable)
+ if(selectedCharset && [charsetId isEqualToString:selectedCharset])
+ selectedRef = menuItem;
+
+ // If the UTF8 entry has been encountered, promote it to the top of the list
+ if (promoteUTF8 && [charsetId isEqualToString:@"utf8"]) {
+ [[charsetButton menu] insertItem:[menuItem autorelease] atIndex:0];
+ //only add a separator if there actually are more items other than utf8 (might not be true for mysql forks)
+ if([encodings count] > 1)
+ [[charsetButton menu] insertItem:[NSMenuItem separatorItem] atIndex:1];
+ }
+ else {
+ [[charsetButton menu] addItem:[menuItem autorelease]];
+ }
+
+ }
+
+ [charsetButton setEnabled:YES];
+ }
+
+ // Populate the table encoding popup button with a default menu item (if set)
+ // This is down here so it is put even before the utf8 item.
+ if(defaultCharset) {
+ NSMenuItem *defaultItem = [[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:defaultCharsetFormatString,defaultCharset] action:NULL keyEquivalent:@""];
+ [defaultItem setRepresentedObject:defaultCharset];
+ [[charsetButton menu] insertItem:[defaultItem autorelease] atIndex:0];
+ if([encodings count] > 0)
+ [[charsetButton menu] insertItem:[NSMenuItem separatorItem] atIndex: 1];
+ }
+
+ //inserting items can have strange effects on the lists selectedItem, so we reset that.
+ [charsetButton selectItemAtIndex:0];
+
+ //honor selectedCharset
+ if(selectedRef)
+ [charsetButton selectItem:selectedRef];
+
+ //reload the collations for the selected charset
+ [self refreshCollations];
+}
+
+- (void)refreshCollations {
+ NSString *fmtStrDefaultId = NSLocalizedString(@"Default (%@)",@"Collation Dropdown : Default ($1 = collation name)");
+ NSString *fmtStrDefaultUnknown = NSLocalizedString(@"Default",@"Collation Dropdown : Default (unknown)"); // MySQL < 4.1.0
+
+ //throw out all items
+ [collationButton removeAllItems];
+ //we'll enable that later if the user can actually change the selection.
+ [collationButton setEnabled:NO];
+
+ //add the unknown default item - we will remove that once we have a real default,
+ //which can come from two sources:
+ // a) it was explicitly set in defaultCollation (only applies when defaultCharset == selectedCharset)
+ // b) the server told us which was the default
+ //if neither works (old mysql / forks ?) we at least have the dummy default.
+ [collationButton addItemWithTitle:fmtStrDefaultUnknown];
+
+ //if the server actually has support for charsets & collations we will now get a list of all collations
+ //for the current charset. Even if the default charset is kept by the user he can change the default collation
+ //so we search in that case, too.
+ if(![serverSupport supportsPost41CharacterSetHandling])
+ return;
+
+ //get the charset id
+ NSString *charsetId = [[charsetButton selectedItem] representedObject];
+
+ //now let's get the list of collations for the selected charset id
+ NSArray *applicableCollations = [databaseData getDatabaseCollationsForEncoding:charsetId];
+
+ //got something?
+ if (![applicableCollations count])
+ return;
+
+ //add a separator
+ [[collationButton menu] addItem:[NSMenuItem separatorItem]];
+
+ //if this is the defaultCharset and we have a defaultCollation use that instead
+ BOOL useGivenDefaultCollation = (defaultCharset && defaultCollation && [charsetId isEqualToString:defaultCharset]);
+
+ if(useGivenDefaultCollation) {
+ NSString *userDefaultCollateTitle = [NSString stringWithFormat:fmtStrDefaultId,defaultCollation];
+ //remove the dummy default item.
+ [collationButton removeItemAtIndex:0];
+ //add it to the top of the list
+ [collationButton insertItemWithTitle:userDefaultCollateTitle atIndex:0];
+ }
+
+ //add the real items
+ for (NSDictionary *collation in applicableCollations)
+ {
+ NSString *collationName = [collation objectForKey:@"COLLATION_NAME"];
+ [collationButton addItemWithTitle:collationName];
+
+ //is this the default collation for this charset (and we didn't override it)?
+ if(!useGivenDefaultCollation && [[collation objectForKey:@"IS_DEFAULT"] isEqualToString:@"Yes"]) {
+ NSString *defaultCollateTitle = [NSString stringWithFormat:fmtStrDefaultId,collationName];
+ //remove the dummy default item.
+ [collationButton removeItemAtIndex:0];
+ //add it to the top of the list
+ [collationButton insertItemWithTitle:defaultCollateTitle atIndex:0];
+ }
+ }
+ //reset selection to first item (it may moved when adding the default item)
+ [collationButton selectItemAtIndex:0];
+
+ //honor selectedCollation
+ if(selectedCollation)
+ [collationButton selectItemWithTitle:selectedCollation];
+
+ //yay, now there is actually something not the Default item, so we can enable the button
+ [collationButton setEnabled:YES];
+}
+
+- (BOOL)enabled {
+ return _enabled;
+}
+
+- (void)setEnabled:(BOOL)value {
+
+ if(value == YES) {
+ NSAssert((databaseData != nil),@"No valid SPDatabaseData object given!");
+ NSAssert((serverSupport != nil),@"No valid SPServerSupport object given!");
+ [self set_oldCharset:selectedCharset]; //initialise to the initial selected charset
+ [self refreshCharsets];
+ }
+ _enabled = value;
+}
+
+@end