aboutsummaryrefslogtreecommitdiffstats
path: root/TableContent.m
diff options
context:
space:
mode:
authorstuconnolly <stuart02@gmail.com>2008-12-10 16:52:52 +0000
committerstuconnolly <stuart02@gmail.com>2008-12-10 16:52:52 +0000
commitfab9a6506cd04ec8f840c98772a80c44a79c74a7 (patch)
tree3cd483487bef381c934717f10df71d306c7eaf97 /TableContent.m
parent4c3b208fad0572d8d1a79bba1bd1b8147fd0f8a6 (diff)
downloadsequelpro-fab9a6506cd04ec8f840c98772a80c44a79c74a7.tar.gz
sequelpro-fab9a6506cd04ec8f840c98772a80c44a79c74a7.tar.bz2
sequelpro-fab9a6506cd04ec8f840c98772a80c44a79c74a7.zip
MERGED r262:266 from branches/stuart02 to trunk to include new project structure.
Diffstat (limited to 'TableContent.m')
-rw-r--r--TableContent.m2018
1 files changed, 0 insertions, 2018 deletions
diff --git a/TableContent.m b/TableContent.m
deleted file mode 100644
index 1aa939f2..00000000
--- a/TableContent.m
+++ /dev/null
@@ -1,2018 +0,0 @@
-//
-// TableDocument.h
-// sequel-pro
-//
-// Created by lorenz textor (lorenz@textor.ch) on Wed May 01 2002.
-// Copyright (c) 2002-2003 Lorenz Textor. All rights reserved.
-//
-// Forked by Abhi Beckert (abhibeckert.com) 2008-04-04
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-// More info at <http://code.google.com/p/sequel-pro/>
-
-#import "TableContent.h"
-#import "TableDocument.h"
-#import "TablesList.h"
-#import "TableSource.h"
-#import "CMImageView.h"
-
-
-@implementation TableContent
-
-- (id)init
-{
- if (![super init])
- return nil;
-
- fullResult = [[NSMutableArray alloc] init];
- filteredResult = [[NSMutableArray alloc] init];
- oldRow = [[NSMutableDictionary alloc] init];
- selectedTable = nil;
- sortField = nil;
- areShowingAllRows = false;
-
- return self;
-}
-
-- (void)awakeFromNib
-{
-}
-
-/*
- Loads aTable, retrieving column information and updating the tableViewColumns before
- reloading table data into the fullResults array and redrawing the table.
- */
-- (void)loadTable:(NSString *)aTable
-{
- int i;
- NSNumber *colWidth;
- NSArray *theColumns;
- NSTableColumn *theCol;
- NSString *query;
- CMMCPResult *queryResult;
- BOOL preserveCurrentView = [aTable isEqualToString:selectedTable];
- NSString *preservedFilterField = nil, *preservedFilterComparison, *preservedFilterValue;
-
- // Clear the selection, and abort the reload if the user is still editing a row
- [tableContentView deselectAll:self];
- if ( isEditingRow )
- return;
-
- // Store the newly selected table name
- selectedTable = aTable;
-
- // Reset table key store for use in argumentForRow:
- if ( keys )
- keys = nil;
-
- // Restore the table content view to the top left
- [tableContentView scrollRowToVisible:0];
- [tableContentView scrollColumnToVisible:0];
-
- // If no table has been supplied, reset the view to a blank table and disabled elements
- if ( [aTable isEqualToString:@""] || !aTable )
- {
-
- // Empty the table and stored data arrays
- theColumns = [tableContentView tableColumns];
- while ([theColumns count]) {
- [tableContentView removeTableColumn:[theColumns objectAtIndex:0]];
- }
- [fullResult removeAllObjects];
- [filteredResult removeAllObjects];
- [tableContentView reloadData];
- areShowingAllRows = YES;
- [countText setStringValue:@""];
-
- // Empty and disable filter options
- [fieldField setEnabled:NO];
- [fieldField removeAllItems];
- [fieldField addItemWithTitle:NSLocalizedString(@"field", @"popup menuitem for field (showing only if disabled)")];
- [compareField setEnabled:NO];
- [compareField removeAllItems];
- [compareField addItemWithTitle:NSLocalizedString(@"is", @"popup menuitem for field IS value")];
- [argumentField setEnabled:NO];
- [argumentField setStringValue:@""];
- [filterButton setEnabled:NO];
-
- // Empty and disable the limit field
- [limitRowsField setStringValue:@""];
- [limitRowsText setStringValue:NSLocalizedString(@"No limit", @"text showing that the result isn't limited")];
- [limitRowsField setEnabled:NO];
- [limitRowsButton setEnabled:NO];
- [limitRowsStepper setEnabled:NO];
-
- // Disable table action buttons
- [addButton setEnabled:NO];
- [copyButton setEnabled:NO];
- [removeButton setEnabled:NO];
-
- return;
- }
-
- // Post a notification that a query will be performed
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:self];
-
-
- // Make a fast query to get fieldNames and fieldTypes for this table. This is used to decide whether to preserve the
- // current filter/sort settings, and also used when grabbing all the data as part of the fieldListForQuery method.
- queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT * FROM `%@` LIMIT 0", selectedTable]];
- if ( queryResult == nil ) {
- NSLog(@"Loading table columns for %@ failed", aTable);
- return;
- }
- fieldNames = [[queryResult fetchFieldNames] retain];
- fieldTypes = [[queryResult fetchTypesAsArray] retain];
-
- // Retrieve the number of rows in the table and initially mark all as being visible.
- numRows = [self getNumberOfRows];
- areShowingAllRows = YES;
-
- // Remove existing columns from the table
- theColumns = [tableContentView tableColumns];
- while ([theColumns count]) {
- [tableContentView removeTableColumn:[theColumns objectAtIndex:0]];
- }
-
- // Add the new columns to the table
- for ( i = 0 ; i < [fieldNames count] ; i++ ) {
-
- // Set up the column
- theCol = [[NSTableColumn alloc] initWithIdentifier:[fieldNames objectAtIndex:i]];
- [theCol setEditable:YES];
- if ( [theCol respondsToSelector:@selector(setResizingMask:)] ) {
- // Mac OS X 10.4+
- [theCol setResizingMask:NSTableColumnUserResizingMask];
- } else {
- // Mac OS X pre-10.4
- [theCol setResizable:YES];
- }
- [[theCol headerCell] setStringValue:[fieldNames objectAtIndex:i]];
-
- // Set up the data cell depending on the column type
- NSComboBoxCell *dataCell;
- if ( [[tableSourceInstance enumFields] objectForKey:[fieldNames objectAtIndex:i]] )
- {
- dataCell = [[[NSComboBoxCell alloc] initTextCell:@""] autorelease];
- [dataCell setButtonBordered:NO];
- [dataCell setBezeled:NO];
- [dataCell setDrawsBackground:NO];
- [dataCell setCompletes:YES];
- [dataCell setControlSize:NSSmallControlSize];
- [dataCell addItemWithObjectValue:@"NULL"];
- [dataCell addItemsWithObjectValues:[[tableSourceInstance enumFields] objectForKey:[fieldNames objectAtIndex:i]]];
- }
- else
- {
- dataCell = [[[NSTextFieldCell alloc] initTextCell:@""] autorelease];
- }
- [dataCell setEditable:YES];
-
- if ( [dataCell respondsToSelector:@selector(setLineBreakMode:)] ) {
- // Mac OS X 10.4+
- [dataCell setLineBreakMode:NSLineBreakByTruncatingTail];
- }
-
- // Set the data cell font according to the preferences
- if ( [prefs boolForKey:@"useMonospacedFonts"] )
- {
- [dataCell setFont:[NSFont fontWithName:@"Monaco" size:10]];
- }
- else
- {
- [dataCell setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
- }
-
- // Assign the data cell
- [theCol setDataCell:dataCell];
-
- // Set the width of this column to saved value if exists
- colWidth = [[[[prefs objectForKey:@"tableColumnWidths"] objectForKey:[NSString stringWithFormat:@"%@@%@", [tableDocumentInstance database], [tableDocumentInstance host]]] objectForKey:[tablesListInstance table]] objectForKey:[fieldNames objectAtIndex:i]];
- if ( colWidth )
- {
- [theCol setWidth:[colWidth floatValue]];
- }
-
- // Add the column to the table
- [tableContentView addTableColumn:theCol];
- [theCol release];
- }
-
- // If the table has been reloaded and the previously selected sort column is still present, reselect it.
- if (preserveCurrentView && [fieldNames containsObject:sortField])
- {
- theCol = [tableContentView tableColumnWithIdentifier:sortField];
- [tableContentView setHighlightedTableColumn:theCol];
- if ( isDesc ) {
- [tableContentView setIndicatorImage:[NSImage imageNamed:@"NSDescendingSortIndicator"] inTableColumn:theCol];
- } else {
- [tableContentView setIndicatorImage:[NSImage imageNamed:@"NSAscendingSortIndicator"] inTableColumn:theCol];
- }
- }
-
- // Otherwise, clear sorting
- else
- {
- sortField = nil;
- isDesc = NO;
- }
-
- // Preserve the stored filter settings if appropriate
- if (preserveCurrentView && [fieldField isEnabled])
- {
- preservedFilterField = [NSString stringWithString:[[fieldField selectedItem] title]];
- preservedFilterComparison = [NSString stringWithString:[[compareField selectedItem] title]];
- preservedFilterValue = [NSString stringWithString:[argumentField stringValue]];
- }
-
- // Enable and initialize filter fields (with tags for position of menu item and field position)
- [fieldField setEnabled:YES];
- [fieldField removeAllItems];
- [fieldField addItemsWithTitles:fieldNames];
- for ( i = 0 ; i < [fieldField numberOfItems] ; i++ ) {
- [[fieldField itemAtIndex:i] setTag:i];
- }
- [compareField setEnabled:YES];
- [self setCompareTypes:self];
- [argumentField setEnabled:YES];
- [argumentField setStringValue:@""];
- [filterButton setEnabled:YES];
-
- // Restore preserved filter settings if appropriate and valid
- if (preserveCurrentView && preservedFilterField != nil && [fieldField itemWithTitle:preservedFilterField])
- {
- [fieldField selectItemWithTitle:preservedFilterField];
- [self setCompareTypes:self];
- }
- if (preserveCurrentView && preservedFilterField != nil
- && [fieldField itemWithTitle:preservedFilterField]
- && [compareField itemWithTitle:preservedFilterComparison])
- {
- [compareField selectItemWithTitle:preservedFilterComparison];
- [argumentField setStringValue:preservedFilterValue];
- areShowingAllRows = NO;
- }
-
- // Enable or disable the limit fields according to preference setting
- if ( [prefs boolForKey:@"limitRows"] )
- {
-
- // Attempt to preserve the limit value if it's still valid
- if (!preserveCurrentView || [limitRowsField intValue] < 1 || [limitRowsField intValue] >= numRows) {
- [limitRowsField setStringValue:@"1"];
- }
- [limitRowsField setEnabled:YES];
- [limitRowsButton setEnabled:YES];
- [limitRowsStepper setEnabled:YES];
- [limitRowsText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Limited to %d rows starting with row", @"text showing the number of rows the result is limited to"),
- [prefs integerForKey:@"limitRowsValue"]]];
- if ([prefs integerForKey:@"limitRowsValue"] < numRows)
- areShowingAllRows = NO;
- }
- else
- {
- [limitRowsField setEnabled:NO];
- [limitRowsButton setEnabled:NO];
- [limitRowsStepper setEnabled:NO];
- [limitRowsField setStringValue:@""];
- [limitRowsText setStringValue:NSLocalizedString(@"No limit", @"text showing that the result isn't limited")];
- }
-
- // Enable the table buttons
- [addButton setEnabled:YES];
- [copyButton setEnabled:YES];
- [removeButton setEnabled:YES];
-
-
- // Perform the data query and store the result as an array containing a dictionary per result row
- query = [NSString stringWithFormat:@"SELECT %@ FROM `%@`", [self fieldListForQuery], selectedTable];
- if ( sortField )
- {
- query = [NSString stringWithFormat:@"%@ ORDER BY `%@`", query, sortField];
- if ( isDesc )
- query = [query stringByAppendingString:@" DESC"];
- }
- if ( [prefs boolForKey:@"limitRows"] )
- {
- if ( [limitRowsField intValue] <= 0 )
- {
- [limitRowsField setStringValue:@"1"];
- }
- query = [query stringByAppendingString:
- [NSString stringWithFormat:@" LIMIT %d,%d",
- [limitRowsField intValue]-1, [prefs integerForKey:@"limitRowsValue"]]];
- }
- queryResult = [mySQLConnection queryString:query];
- if ( queryResult == nil ) {
- NSLog(@"Loading table data for %@ failed, query string was: %@", aTable, query);
- return;
- }
- [fullResult setArray:[self fetchResultAsArray:queryResult]];
-
- // Apply any filtering and update the row count
- if ( !areShowingAllRows ) {
- [self filterTable:self];
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows of %d selected", @"text showing how many rows are in the filtered result"), [filteredResult count], numRows]];
- } else {
- [filteredResult setArray:fullResult];
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows in table", @"text showing how many rows are in the result"), numRows]];
- }
-
- // Reload the table data.
- [tableContentView reloadData];
-
- // Post the notification that the query is finished
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
-}
-
-/*
- Reloads the current table data, performing a new SQL query. Now attempts to preserve sort order, filters, and viewport.
- */
-- (IBAction)reloadTable:(id)sender
-{
- // Store the current viewport location
- NSRect viewRect = [tableContentView visibleRect];
-
- [self loadTable:selectedTable];
-
- // Restore the viewport
- [tableContentView scrollRectToVisible:viewRect];
-}
-
-- (IBAction)reloadTableValues:(id)sender
-/*
- reload the table values without reconfiguring the tableView (with filter and limit if set)
- */
-{
- NSString *queryString;
- CMMCPResult *queryResult;
-
- //query started
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:self];
-
- //enable or disable limit fields
- if ( [prefs boolForKey:@"limitRows"] ) {
- [limitRowsField setEnabled:YES];
- [limitRowsButton setEnabled:YES];
- [limitRowsStepper setEnabled:YES];
- [limitRowsText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Limited to %d rows starting with row", @"text showing the number of rows the result is limited to"),
- [prefs integerForKey:@"limitRowsValue"]]];
- } else {
- [limitRowsField setEnabled:NO];
- [limitRowsButton setEnabled:NO];
- [limitRowsStepper setEnabled:NO];
- [limitRowsText setStringValue:NSLocalizedString(@"No limit", @"text showing that the result isn't limited")];
- [limitRowsField setStringValue:@""];
- }
-
- // queryString = [@"SELECT * FROM " stringByAppendingString:selectedTable];
- queryString = [NSString stringWithFormat:@"SELECT %@ FROM `%@`", [self fieldListForQuery], selectedTable];
- if ( sortField ) {
- queryString = [NSString stringWithFormat:@"%@ ORDER BY `%@`", queryString, sortField];
- // queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@" ORDER BY `%@`", sortField]];
- if ( isDesc )
- queryString = [queryString stringByAppendingString:@" DESC"];
- }
- if ( [prefs boolForKey:@"limitRows"] ) {
- if ( [limitRowsField intValue] <= 0 ) {
- [limitRowsField setStringValue:@"1"];
- }
- queryString = [queryString stringByAppendingString:
- [NSString stringWithFormat:@" LIMIT %d,%d",
- [limitRowsField intValue]-1, [prefs integerForKey:@"limitRowsValue"]]];
- [limitRowsField selectText:self];
- }
- queryResult = [mySQLConnection queryString:queryString];
- // [fullResult setArray:[[self fetchResultAsArray:queryResult] retain]];
- [fullResult setArray:[self fetchResultAsArray:queryResult]];
- numRows = [self getNumberOfRows];
- if ( !areShowingAllRows ) {
- [self filterTable:self];
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows of %d selected", @"text showing how many rows are in the filtered result"), [filteredResult count], numRows]];
- } else {
- [filteredResult setArray:fullResult];
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows in table", @"text showing how many rows are in the result"), numRows]];
- }
- [tableContentView reloadData];
-
- //query finished
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
-}
-
-/**
- * filter the table with arguments given by the user
- */
-- (IBAction)filterTable:(id)sender
-{
- CMMCPResult *theResult;
- int tag = [[compareField selectedItem] tag];
- NSString *compareOperator = @"";
- NSMutableString *argument = [[NSMutableString alloc] initWithString:[argumentField stringValue]];
- NSString *queryString;
- int i;
-
- // Update negative limits
- if ( [limitRowsField intValue] <= 0 ) {
- [limitRowsField setStringValue:@"1"];
- }
-
- // If the filter field is empty, the limit field is at 1, and the selected filter is not looking
- // for NULLs or NOT NULLs, then don't allow filtering.
- if (([argument length] == 0) && (![[[compareField selectedItem] title] hasSuffix:@"NULL"]) && (![prefs boolForKey:@"limitRows"] || [limitRowsField intValue] == 1)) {
- [argument release];
- [self showAll:sender];
- return;
- }
-
- //query started
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:self];
-
- BOOL doQuote = YES;
- BOOL ignoreArgument = NO;
-
- // Start building the query string
- queryString = [NSString stringWithFormat:@"SELECT %@ FROM `%@`",
- [self fieldListForQuery], selectedTable];
-
- // Add filter if appropriate
- if (([argument length] > 0) || [[[compareField selectedItem] title] hasSuffix:@"NULL"]) {
- if ( ![compareType isEqualToString:@""] ) {
- if ( [compareType isEqualToString:@"string"] ) {
- //string comparision
- switch ( tag ) {
- case 0:
- compareOperator = @"LIKE";
- break;
- case 1:
- compareOperator = @"NOT LIKE";
- break;
- case 2:
- compareOperator = @"LIKE";
- [argument setString:[[@"%" stringByAppendingString:argument] stringByAppendingString:@"%"]];
- break;
- case 3:
- compareOperator = @"NOT LIKE";
- [argument setString:[[@"%" stringByAppendingString:argument] stringByAppendingString:@"%"]];
- break;
- case 4:
- compareOperator = @"IN";
- doQuote = NO;
- [argument setString:[[@"(" stringByAppendingString:argument] stringByAppendingString:@")"]];
- break;
- case 5:
- compareOperator = @"IS NULL";
- doQuote = NO;
- ignoreArgument = YES;
- break;
- case 6:
- compareOperator = @"IS NOT NULL";
- doQuote = NO;
- ignoreArgument = YES;
- break;
- }
- } else if ( [compareType isEqualToString:@"number"] ) {
- //number comparision
- switch ( tag ) {
- case 0:
- compareOperator = @"=";
- break;
- case 1:
- compareOperator = @"!=";
- break;
- case 2:
- compareOperator = @">";
- break;
- case 3:
- compareOperator = @"<";
- break;
- case 4:
- compareOperator = @">=";
- break;
- case 5:
- compareOperator = @"<=";
- break;
- case 6:
- compareOperator = @"IN";
- doQuote = NO;
- [argument setString:[[@"(" stringByAppendingString:argument] stringByAppendingString:@")"]];
- break;
- case 7:
- compareOperator = @"IS NULL";
- doQuote = NO;
- ignoreArgument = YES;
- break;
- case 8:
- compareOperator = @"IS NOT NULL";
- doQuote = NO;
- ignoreArgument = YES;
- break;
- }
- } else if ( [compareType isEqualToString:@"date"] ) {
- //date comparision
- switch ( tag ) {
- case 0:
- compareOperator = @"=";
- break;
- case 1:
- compareOperator = @"!=";
- break;
- case 2:
- compareOperator = @"<";
- break;
- case 3:
- compareOperator = @">";
- break;
- case 4:
- compareOperator = @"<=";
- break;
- case 5:
- compareOperator = @">=";
- break;
- case 6:
- compareOperator = @"IS NULL";
- doQuote = NO;
- ignoreArgument = YES;
- break;
- case 7:
- compareOperator = @"IS NOT NULL";
- doQuote = NO;
- ignoreArgument = YES;
- break;
- }
- } else {
- doQuote = NO;
- ignoreArgument = YES;
- NSLog(@"ERROR: unknown compare type %@", compareType);
- }
-
- if (doQuote) {
- //escape special characters
- for ( i = 0 ; i < [argument length] ; i++ ) {
- if ( [argument characterAtIndex:i] == '\\' ) {
- [argument insertString:@"\\" atIndex:i];
- i++;
- }
- }
- [argument setString:[mySQLConnection prepareString:argument]];
- queryString = [NSString stringWithFormat:@"%@ WHERE `%@` %@ \"%@\"",
- queryString, [fieldField titleOfSelectedItem], compareOperator, argument];
- } else {
- queryString = [NSString stringWithFormat:@"%@ WHERE `%@` %@ %@",
- queryString, [fieldField titleOfSelectedItem],
- compareOperator, (ignoreArgument) ? @"" : argument];
- }
- }
- }
-
- // Add sorting details if appropriate
- if ( sortField ) {
- queryString = [NSString stringWithFormat:@"%@ ORDER BY `%@`", queryString, sortField];
- if ( isDesc )
- queryString = [queryString stringByAppendingString:@" DESC"];
- }
-
- // LIMIT if appropriate
- if ( [prefs boolForKey:@"limitRows"] ) {
- queryString = [NSString stringWithFormat:@"%@ LIMIT %d,%d", queryString,
- [limitRowsField intValue]-1, [prefs integerForKey:@"limitRowsValue"]];
- }
-
- theResult = [mySQLConnection queryString:queryString];
- [filteredResult setArray:[self fetchResultAsArray:theResult]];
-
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows of %d selected", @"text showing how many rows are in the filtered result"), [filteredResult count], numRows]];
-
- // Reset the table view
- [tableContentView scrollPoint:NSMakePoint(0.0, 0.0)];
- [tableContentView reloadData];
- areShowingAllRows = NO;
-
- //query finished
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
- [argument release];
-}
-
-/**
- * reload tableView with all results shown (no new mysql-query, it uses simply the fullResult array)
- */
-- (IBAction)showAll:(id)sender
-{
- [filteredResult setArray:fullResult];
- [tableContentView reloadData];
- areShowingAllRows = YES;
-
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows in table", @"text showing how many rows are in the result"), numRows]];
-}
-
-/**
- * Enables or disables the filter input field based on the selected filter type.
- */
-- (IBAction)toggleFilterField:(id)sender
-{
- // If the user is filtering for NULLs then disabled the filter field, otherwise enable it.
- [argumentField setEnabled:(![[[compareField selectedItem] title] hasSuffix:@"NULL"])];
-}
-
-
-//edit methods
-- (IBAction)addRow:(id)sender
-/*
- adds an empty row to the table-array and goes into edit mode
- */
-{
- NSMutableDictionary *newRow = [NSMutableDictionary dictionary];
- int i;
-
- if ( ![self selectionShouldChangeInTableView:nil] )
- return;
-
- for ( i = 0 ; i < [fieldNames count] ; i++ ) {
- // [newRow setObject:[prefs stringForKey:@"nullValue"] forKey:[fieldNames objectAtIndex:i]];
- [newRow setObject:[tableSourceInstance defaultValueForField:[fieldNames objectAtIndex:i]]
- forKey:[fieldNames objectAtIndex:i]];
- }
- [filteredResult addObject:newRow];
-
- isEditingRow = YES;
- isEditingNewRow = YES;
- [tableContentView reloadData];
- [tableContentView selectRow:[tableContentView numberOfRows]-1 byExtendingSelection:NO];
- if ( [multipleLineEditingButton state] == NSOffState )
- [tableContentView editColumn:0 row:[tableContentView numberOfRows]-1 withEvent:nil select:YES];
-}
-
-- (IBAction)copyRow:(id)sender
-/*
- copies a row of the table-array and goes into edit mode
- */
-{
- NSMutableDictionary *tempRow;
- CMMCPResult *queryResult;
- NSDictionary *row;
- int i;
-
- if ( ![self selectionShouldChangeInTableView:nil] )
- return;
- if ( [tableContentView numberOfSelectedRows] < 1 )
- return;
- if ( [tableContentView numberOfSelectedRows] > 1 ) {
- NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, NSLocalizedString(@"You can only copy single rows.", @"message of panel when trying to copy multiple rows"));
- return;
- }
-
- //copy row
- tempRow = [NSMutableDictionary dictionaryWithDictionary:[filteredResult objectAtIndex:[tableContentView selectedRow]]];
- [filteredResult insertObject:tempRow atIndex:[tableContentView selectedRow]+1];
- isEditingRow = YES;
- isEditingNewRow = YES;
- //set autoincrement fields to NULL
- queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM `%@`", selectedTable]];
- if ([queryResult numOfRows]) [queryResult dataSeek:0];
- for ( i = 0 ; i < [queryResult numOfRows] ; i++ ) {
- row = [queryResult fetchRowAsDictionary];
- if ( [[row objectForKey:@"Extra"] isEqualToString:@"auto_increment"] ) {
- [tempRow setObject:[prefs stringForKey:@"nullValue"] forKey:[row objectForKey:@"Field"]];
- }
- }
- //select row and go in edit mode
- [tableContentView reloadData];
- [tableContentView selectRow:[tableContentView selectedRow]+1 byExtendingSelection:NO];
- if ( [multipleLineEditingButton state] == NSOffState )
- [tableContentView editColumn:0 row:[tableContentView selectedRow] withEvent:nil select:YES];
-}
-
-- (IBAction)removeRow:(id)sender
-/*
- asks user if he really wants to delete the selected rows
- */
-{
- if ( ![self selectionShouldChangeInTableView:nil] )
- return;
- if ( ![tableContentView numberOfSelectedRows] )
- return;
- /*
- if ( ([tableContentView numberOfSelectedRows] == [self numberOfRowsInTableView:tableContentView]) &&
- areShowingAllRows &&
- (![prefs boolForKey:@"limitRows"] || ([tableContentView numberOfSelectedRows] < [prefs integerForKey:@"limitRowsValue"])) ) {
- */
- if ( ([tableContentView numberOfSelectedRows] == [tableContentView numberOfRows]) &&
- (([prefs boolForKey:@"limitRows"] && [tableContentView numberOfSelectedRows] == [self fetchNumberOfRows]) ||
- (![prefs boolForKey:@"limitRows"] && [tableContentView numberOfSelectedRows] == [self getNumberOfRows])) ) {
- NSBeginAlertSheet(NSLocalizedString(@"Warning", @"warning"), NSLocalizedString(@"Delete", @"delete button"), NSLocalizedString(@"Cancel", @"cancel button"), nil, tableWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:),
- nil, @"removeallrows", NSLocalizedString(@"Do you really want to delete all rows?", @"message of panel asking for confirmation for deleting all rows"));
- } else if ( [tableContentView numberOfSelectedRows] == 1 ) {
- NSBeginAlertSheet(NSLocalizedString(@"Warning", @"warning"), NSLocalizedString(@"Delete", @"delete button"), NSLocalizedString(@"Cancel", @"cancel button"), nil, tableWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:),
- nil, @"removerow", NSLocalizedString(@"Do you really want to delete the selected row?", @"message of panel asking for confirmation for deleting the selected row"));
- } else {
- NSBeginAlertSheet(NSLocalizedString(@"Warning", @"warning"), NSLocalizedString(@"Delete", @"delete button"), NSLocalizedString(@"Cancel", @"cancel button"), nil, tableWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:),
- nil, @"removerow",
- [NSString stringWithFormat:NSLocalizedString(@"Do you really want to delete the selected %d rows?", @"message of panel asking for confirmation for deleting the selected rows"), [tableContentView numberOfSelectedRows]]);
- }
-}
-
-
-//editSheet methods
-- (IBAction)closeEditSheet:(id)sender
-{
- [NSApp stopModalWithCode:[sender tag]];
-}
-
-- (IBAction)openEditSheet:(id)sender
-/*
- loads a file into the editSheet
- */
-{
- NSOpenPanel *panel = [NSOpenPanel openPanel];
-
- if ( [panel runModal] == NSOKButton ) {
- NSString *fileName = [panel filename];
-
- // free old data
- if ( editData != nil ) {
- [editData release];
- }
-
- // load new data/images
- editData = [[NSData alloc] initWithContentsOfFile:fileName];
- NSImage *image = [[[NSImage alloc] initByReferencingFile:fileName] autorelease];
- NSString *contents = [[NSString stringWithContentsOfFile:fileName] autorelease];
-
- // set the image preview, string contents and hex representation
- [editImage setImage:image];
- [editTextView setString:contents];
- [hexTextView setString:[self dataToHex:editData]];
- }
-}
-
-- (IBAction)saveEditSheet:(id)sender
-/*
- saves a file containing the content of the editSheet
- */
-{
- NSSavePanel *panel = [NSSavePanel savePanel];
-
- if ( [panel runModal] == NSOKButton ) {
- NSString *fileName = [panel filename];
- NSString *data;
-
- if ( [editData isKindOfClass:[NSData class]] ) {
- data = editData;
- } else {
- data = [editData description];
- }
- if ( [editData respondsToSelector:@selector(writeToFile:atomically:encoding:error:)] ) {
- // mac os 10.4 or later
- [editData writeToFile:fileName atomically:YES encoding:[CMMCPConnection encodingForMySQLEncoding:[(NSString *)[tableDocumentInstance encoding] UTF8String]] error:NULL];
- } else {
- // mac os pre 10.4
- [editData writeToFile:fileName atomically:YES];
- }
- }
-}
-
-- (IBAction)dropImage:(id)sender
-/*
- invoked when user drag&drops image on imageView
- */
-{
- // load new data/images
- if (nil != editData)
- {
- [editData release];
- }
- editData = [[[NSData alloc] initWithContentsOfFile:[sender draggedFilePath]] retain];
- NSString *contents = [NSString stringWithContentsOfFile:[sender draggedFilePath]];
-
- // set the string contents and hex representation
- [editTextView setString:contents];
- [hexTextView setString:[self dataToHex:editData]];
-}
-
-- (void)textDidChange:(NSNotification *)notification
-/*
- invoked when the user changes the string in the editSheet
- */
-{
- // clear the image and hex (since i doubt someone can "type" a gif)
- [editImage setImage:nil];
- [hexTextView setString:@""];
-
- // free old data
- if ( editData != nil ) {
- [editData release];
- }
-
- // set edit data to text
- editData = [[editTextView string] retain];
-}
-
-- (NSString *)dataToHex:(NSData *)data
-/*
- returns the hex representation of the given data
- */
-{
- unsigned i;
- unsigned totalLength = [data length];
- int bytesPerLine = 16;
- NSMutableString *retVal = [NSMutableString string];
- unsigned char *nodisplay = "\t\n\r\f";
-
- // get the length of the longest location
- int longest = [(NSString *)[NSString stringWithFormat:@"%X", totalLength - ( totalLength % bytesPerLine )] length];
-
- for ( i = 0; i < totalLength; i += bytesPerLine ) {
- int j;
- NSMutableString *hex = [[NSMutableString alloc] initWithCapacity:(3 * bytesPerLine - 1)];
- NSMutableString *location = [[NSMutableString alloc] initWithCapacity:(longest + 2)];
- NSMutableString *chars = [[NSMutableString alloc] init];
- unsigned char *buffer;
- int buffLength = bytesPerLine;
-
- // add hex value of location
- [location appendString:[NSString stringWithFormat:@"%X", i]];
-
- // pad it
- while( longest > [location length] ) {
- [location insertString:@"0" atIndex:0];
- }
-
- // get the chars from the NSData obj
- if ( i + buffLength >= totalLength ) {
- buffLength = totalLength - i;
- }
- buffer = (unsigned char*) malloc( sizeof( unsigned char ) * buffLength );
- NSRange range = { i, buffLength };
- [data getBytes:buffer range:range];
-
- // build the hex string
- for ( j = 0; j < buffLength; j++ ) {
- unsigned char byte = *(buffer + j);
- if ( byte < 16 ) {
- [hex appendString:@"0"];
- }
- [hex appendString:[NSString stringWithFormat:@"%X", byte]];
- [hex appendString:@" "];
-
- // if the char is undisplayable, replace it with "."
- unsigned char current;
- int count = 0;
- while ( ( current = *(nodisplay + count++) ) > 0 ) {
- if ( current == byte ) {
- *(buffer + j) = '.';
- break;
- }
- }
- }
-
- // add padding to missing hex values.
- for ( j = 0; j < bytesPerLine - buffLength; j++ ) {
- [hex appendString:@" "];
- }
-
- // remove extra ghost characters
- [chars appendString:[NSString stringWithCString:buffer]];
- if ( [chars length] > bytesPerLine ) {
- [chars deleteCharactersInRange:NSMakeRange( bytesPerLine, [chars length] - bytesPerLine )];
- }
-
- // build line
- [retVal appendString:location];
- [retVal appendString:@" "];
- [retVal appendString:hex];
- [retVal appendString:@" "];
- [retVal appendString:chars];
- [retVal appendString:@"\n"];
-
- // clean up
- [hex release];
- [chars release];
- [location release];
- free( buffer );
- }
-
- return retVal;
-}
-
-//getter methods
-- (NSArray *)currentResult
-/*
- returns the current result (as shown in table content view) as array, the first object containing the field names as array, the following objects containing the rows as array
- */
-{
- NSArray *tableColumns;
- NSEnumerator *enumerator;
- id tableColumn;
- NSMutableArray *currentResult = [NSMutableArray array];
- NSMutableArray *tempRow = [NSMutableArray array];
- int i;
-
- //load table if not already done
- if ( ![tablesListInstance contentLoaded] ) {
- [self loadTable:(NSString *)[tablesListInstance table]];
- }
-
- tableColumns = [tableContentView tableColumns];
- enumerator = [tableColumns objectEnumerator];
-
- //set field names as first line
- while ( (tableColumn = [enumerator nextObject]) ) {
- [tempRow addObject:[[tableColumn headerCell] stringValue]];
- }
- [currentResult addObject:[NSArray arrayWithArray:tempRow]];
-
- //add rows
- for ( i = 0 ; i < [self numberOfRowsInTableView:nil] ; i++) {
- [tempRow removeAllObjects];
- enumerator = [tableColumns objectEnumerator];
- while ( (tableColumn = [enumerator nextObject]) ) {
- [tempRow addObject:[self tableView:nil objectValueForTableColumn:tableColumn row:i]];
- }
- [currentResult addObject:[NSArray arrayWithArray:tempRow]];
- }
- return currentResult;
-}
-
-
-//additional methods
-- (void)setConnection:(CMMCPConnection *)theConnection
-/*
- sets the connection (received from TableDocument) and makes things that have to be done only once
- */
-{
- mySQLConnection = theConnection;
-
- [tableContentView setVerticalMotionCanBeginDrag:NO];
-
- prefs = [[NSUserDefaults standardUserDefaults] retain];
- if ( [prefs boolForKey:@"useMonospacedFonts"] ) {
- [argumentField setFont:[NSFont fontWithName:@"Monaco" size:10]];
- [limitRowsField setFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]];
- [editTextView setFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]];
- } else {
- [editTextView setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
- [limitRowsField setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
- [argumentField setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
- }
- [hexTextView setFont:[NSFont fontWithName:@"Monaco" size:[NSFont smallSystemFontSize]]];
- [limitRowsStepper setEnabled:NO];
- if ( [prefs boolForKey:@"limitRows"] ) {
- [limitRowsText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"Limited to %d rows starting with row", @"text showing the number of rows the result is limited to"),
- [prefs integerForKey:@"limitRowsValue"]]];
- } else {
- [limitRowsText setStringValue:NSLocalizedString(@"No limit", @"text showing that the result isn't limited")];
- [limitRowsField setStringValue:@""];
- }
-}
-
-/**
- * Sets the compare types for the filter and the appropriate formatter for the textField
- */
-- (IBAction)setCompareTypes:(id)sender
-{
- NSArray *stringFields = [NSArray arrayWithObjects:@"varstring", @"string", @"tinyblob", @"blob", @"mediumblob", @"longblob", @"set", @"enum", nil];
- NSArray *stringTypes = [NSArray arrayWithObjects:NSLocalizedString(@"is", @"popup menuitem for field IS value"), NSLocalizedString(@"is not", @"popup menuitem for field IS NOT value"), NSLocalizedString(@"contains", @"popup menuitem for field CONTAINS value"), NSLocalizedString(@"contains not", @"popup menuitem for field CONTAINS NOT value"), @"IN", nil];
- NSArray *numberFields = [NSArray arrayWithObjects:@"tiny", @"short", @"long", @"int24", @"longlong", @"decimal", @"float", @"double", nil];
- NSArray *numberTypes = [NSArray arrayWithObjects:@"=", @"≠", @">", @"<", @"≥", @"≤", @"IN", nil];
- NSArray *dateFields = [NSArray arrayWithObjects:@"timestamp", @"date", @"time", @"datetime", @"year", nil];
- NSArray *dateTypes = [NSArray arrayWithObjects:NSLocalizedString(@"is", @"popup menuitem for field IS value"), NSLocalizedString(@"is not", @"popup menuitem for field IS NOT value"), NSLocalizedString(@"older than", @"popup menuitem for field OLDER THAN value"), NSLocalizedString(@"younger than", @"popup menuitem for field YOUNGER THAN value"), NSLocalizedString(@"older than or equal to", @"popup menuitem for field OLDER THAN OR EQUAL TO value"), NSLocalizedString(@"younger than or equal to", @"popup menuitem for field YOUNGER THAN OR EQUAL TO value"), nil];
- NSString *fieldType = [NSString stringWithString:[fieldTypes objectAtIndex:[[fieldField selectedItem] tag]]];
-
- int i;
-
- [compareField removeAllItems];
-
- // Why do we get "string" for enum fields? (error in framework?)
- if ( [stringFields containsObject:fieldType] ) {
- [compareField addItemsWithTitles:stringTypes];
- compareType = @"string";
- // [argumentField setFormatter:nil];
- } else if ( [numberFields containsObject:fieldType] ) {
- [compareField addItemsWithTitles:numberTypes];
- compareType = @"number";
- // [argumentField setFormatter:numberFormatter];
- } else if ( [dateFields containsObject:fieldType] ) {
- [compareField addItemsWithTitles:dateTypes];
- compareType = @"date";
- /*
- if ([fieldType isEqualToString:@"timestamp"]) {
- [argumentField setFormatter:[[NSDateFormatter alloc]
- initWithDateFormat:@"%Y-%m-%d %H:%M:%S" allowNaturalLanguage:YES]];
- }
- if ([fieldType isEqualToString:@"datetime"]) {
- [argumentField setFormatter:[[NSDateFormatter alloc] initWithDateFormat:@"%Y-%m-%d %H:%M:%S" allowNaturalLanguage:YES]];
- }
- if ([fieldType isEqualToString:@"date"]) {
- [argumentField setFormatter:[[NSDateFormatter alloc] initWithDateFormat:@"%Y-%m-%d" allowNaturalLanguage:YES]];
- }
- if ([fieldType isEqualToString:@"time"]) {
- [argumentField setFormatter:[[NSDateFormatter alloc] initWithDateFormat:@"%H:%M:%S" allowNaturalLanguage:YES]];
- }
- if ([fieldType isEqualToString:@"year"]) {
- [argumentField setFormatter:[[NSDateFormatter alloc] initWithDateFormat:@"%Y" allowNaturalLanguage:YES]];
- }
- */
- } else {
- NSLog(@"ERROR: unknown type for comparision: %@", fieldType);
- }
-
- // Add IS NULL and IS NOT NULL as they should always be available
- [compareField addItemWithTitle:@"IS NULL"];
- [compareField addItemWithTitle:@"IS NOT NULL"];
-
- for ( i = 0 ; i < [compareField numberOfItems] ; i++ ) {
- [[compareField itemAtIndex:i] setTag:i];
- }
-
- // Update the argumentField enabled state
- [self toggleFilterField:self];
-
- // set focus on argumentField
- [argumentField selectText:self];
-}
-
-- (IBAction)stepLimitRows:(id)sender
-/*
- steps the start row up or down (+/- limitRowsValue)
- */
-{
- if ( [limitRowsStepper intValue] > 0 ) {
- [limitRowsField setIntValue:[limitRowsField intValue]+[prefs integerForKey:@"limitRowsValue"]];
- } else {
- if ( ([limitRowsField intValue]-[prefs integerForKey:@"limitRowsValue"]) < 1 ) {
- [limitRowsField setIntValue:1];
- } else {
- [limitRowsField setIntValue:[limitRowsField intValue]-[prefs integerForKey:@"limitRowsValue"]];
- }
- }
- [limitRowsStepper setIntValue:0];
-}
-
-- (NSArray *)fetchResultAsArray:(CMMCPResult *)theResult
-/*
- fetches the result as an array with a dictionary for each row in it
- */
-{
- NSMutableArray *tempResult = [NSMutableArray array];
- NSDictionary *tempRow;
- NSMutableDictionary *modifiedRow = [NSMutableDictionary dictionary];
- NSEnumerator *enumerator;
- id key;
- int i,j;
-
- if ([theResult numOfRows]) [theResult dataSeek:0];
- for ( i = 0 ; i < [theResult numOfRows] ; i++ ) {
- tempRow = [theResult fetchRowAsDictionary];
- enumerator = [tempRow keyEnumerator];
- while ( key = [enumerator nextObject] ) {
- if ( [[tempRow objectForKey:key] isMemberOfClass:[NSNull class]] ) {
- [modifiedRow setObject:[prefs stringForKey:@"nullValue"] forKey:key];
- /*
- //NSData objects now decoded in tableView:objectValueForTableColumn:row
- //object in result remains a NSData object
- } else if ( [[tempRow objectForKey:key] isKindOfClass:[NSData class]] ) {
- [modifiedRow setObject:[[NSString alloc] initWithData:[tempRow objectForKey:key] encoding:[mySQLConnection encoding]]
- forKey:key];
- */
- } else {
- [modifiedRow setObject:[tempRow objectForKey:key] forKey:key];
- }
- //add values for hidden blob and text fields
- if ( [prefs boolForKey:@"dontShowBlob"] ) {
- for ( j = 0 ; j < [fieldTypes count] ; j++ ) {
- if ( [self isBlobOrText:[fieldTypes objectAtIndex:j]] ) {
- [modifiedRow setObject:NSLocalizedString(@"- blob or text -", @"value shown for hidden blob and text fields") forKey:[fieldNames objectAtIndex:j]];
- }
- }
- }
- }
- [tempResult addObject:[NSMutableDictionary dictionaryWithDictionary:modifiedRow]];
- }
- return tempResult;
-}
-
-- (BOOL)addRowToDB
-/*
- tries to write row to mysql-db
- returns YES if row written to db, otherwies NO
- returns YES if no row is beeing edited and nothing has to be written to db
- */
-{
- int rowIndex = [tableContentView selectedRow];
- NSMutableArray *fieldValues = [[NSMutableArray alloc] init];
- NSMutableString *queryString;
- NSString *query;
- CMMCPResult *queryResult;
- id rowObject;
- NSMutableString *rowValue = [NSMutableString string];
- NSString *currentTime = [[NSDate date] descriptionWithCalendarFormat:@"%H:%M:%S" timeZone:nil locale:nil];
- int i;
-
- if ( !isEditingRow || rowIndex == -1) {
- [fieldValues release];
- return YES;
- }
-
- //get field values
- for ( i=0 ; i < [fieldNames count] ; i++) {
- rowObject = [[filteredResult objectAtIndex:rowIndex] objectForKey:[fieldNames objectAtIndex:i]];
- //convert the object to a string (here we can add special treatment for date-, number- and data-fields)
- if ( [[rowObject description] isEqualToString:[prefs stringForKey:@"nullValue"]] ||
- ([rowObject isMemberOfClass:[NSString class]] && [[rowObject description] isEqualToString:@""]) ) {
- //NULL when user entered the nullValue string defined in the prefs or when a number field isn't set
- // problem: when a number isn't set, sequel-pro enters 0
- // -> second if argument isn't necessary!
- [rowValue setString:@"NULL"];
- } else {
- if ( [rowObject isKindOfClass:[NSCalendarDate class]] ) {
- // [rowValue setString:[NSString stringWithFormat:@"\"%@\"", [mySQLConnection prepareString:[rowObject description]]]];
- [rowValue setString:[NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[rowObject description]]]];
- } else if ( [rowObject isKindOfClass:[NSNumber class]] ) {
- [rowValue setString:[rowObject stringValue]];
- } else if ( [rowObject isKindOfClass:[NSData class]] ) {
- [rowValue setString:[NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:rowObject]]];
- } else {
- // [rowValue setString:[NSString stringWithFormat:@"\"%@\"", [mySQLConnection prepareString:[rowObject description]]]];
- if ( [[rowObject description] isEqualToString:@"CURRENT_TIMESTAMP"] ) {
- [rowValue setString:@"CURRENT_TIMESTAMP"];
- } else {
- [rowValue setString:[NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[rowObject description]]]];
- }
- }
- }
- //escape special characters -> now escaped by framework
- /*
- for ( j = 0 ; j < [rowValue length] ; j++ ) {
- if ( [rowValue characterAtIndex:j] == '\\' ) {
- [rowValue insertString:@"\\" atIndex:j];
- j++;
- } else if ( [rowValue characterAtIndex:j] == '"' ) {
- [rowValue insertString:@"\\" atIndex:j];
- j++;
- }
- }
- */
- [fieldValues addObject:[NSString stringWithString:rowValue]];
- }
-
- if ( isEditingNewRow ) {
- //INSERT syntax
- queryString = [NSString stringWithFormat:@"INSERT INTO `%@` (`%@`) VALUES (%@)",
- selectedTable, [fieldNames componentsJoinedByString:@"`,`"], [fieldValues componentsJoinedByString:@","]];
- } else {
- //UPDATE syntax
- queryString = [NSMutableString stringWithFormat:@"UPDATE `%@` SET ", selectedTable];
- for ( i = 0 ; i < [fieldNames count] ; i++ ) {
- if ( i > 0 ) {
- [queryString appendString:@", "];
- }
- [queryString appendString:[NSString stringWithFormat:@"`%@`=%@",
- [fieldNames objectAtIndex:i], [fieldValues objectAtIndex:i]]];
- }
- [fieldValues release];
- [queryString appendString:[NSString stringWithFormat:@" WHERE %@", [self argumentForRow:-2]]];
- }
- [mySQLConnection queryString:queryString];
-
- //NSLog( @"%@", queryString );
-
- if ( ![mySQLConnection affectedRows] ) {
- //no rows changed
- if ( [prefs boolForKey:@"showError"] ) {
- NSBeginAlertSheet(NSLocalizedString(@"Warning", @"warning"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil,
- NSLocalizedString(@"The row was not written to the MySQL database. You probably haven't changed anything.\nReload the table to be sure that the row exists and use a primary key for your table.\n(This error can be turned off in the preferences.)", @"message of panel when no rows have been affected after writing to the db"));
- } else {
- NSBeep();
- }
- [filteredResult replaceObjectAtIndex:rowIndex withObject:[NSMutableDictionary dictionaryWithDictionary:oldRow]];
- isEditingRow = NO;
- isEditingNewRow = NO;
- [tableDocumentInstance showErrorInConsole:[NSString stringWithFormat:NSLocalizedString(@"/* WARNING %@ No rows have been affected */\n", @"warning shown in the console when no rows have been affected after writing to the db"), currentTime]];
- return YES;
- } else if ( [[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) {
- //added new row with success
- isEditingRow = NO;
- if ( isEditingNewRow ) {
- if ( [prefs boolForKey:@"reloadAfterAdding"] ) {
- [self reloadTableValues:self];
- // if ( sortField )
- [tableContentView deselectAll:self];
- } else {
- //set insertId for fields with auto_increment
- queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM `%@`", selectedTable]];
- if ([queryResult numOfRows]) [queryResult dataSeek:0];
- for ( i = 0 ; i < [queryResult numOfRows] ; i++ ) {
- rowObject = [queryResult fetchRowAsDictionary];
- if ( [[rowObject objectForKey:@"Extra"] isEqualToString:@"auto_increment"] ) {
- [[filteredResult objectAtIndex:rowIndex] setObject:[NSNumber numberWithLong:[mySQLConnection insertId]]
- forKey:[rowObject objectForKey:@"Field"]];
- }
- }
- [fullResult addObject:[filteredResult objectAtIndex:rowIndex]];
- }
- isEditingNewRow = NO;
- } else {
- //updated row with success
- if ( [prefs boolForKey:@"reloadAfterEditing"] ) {
- [self reloadTableValues:self];
- // if ( sortField )
- [tableContentView deselectAll:self];
- } else {
- // query = [@"SELECT * FROM " stringByAppendingString:selectedTable];
- query = [NSString stringWithFormat:@"SELECT %@ FROM `%@`", [self fieldListForQuery], selectedTable];
- if ( sortField ) {
- // query = [query stringByAppendingString:[NSString stringWithFormat:@" ORDER BY `%@`", sortField]];
- query = [NSString stringWithFormat:@"%@ ORDER BY `%@`", query, sortField];
- if ( isDesc )
- query = [query stringByAppendingString:@" DESC"];
- }
- if ( [prefs boolForKey:@"limitRows"] ) {
- if ( [limitRowsField intValue] <= 0 ) {
- [limitRowsField setStringValue:@"1"];
- }
- query = [query stringByAppendingString:
- [NSString stringWithFormat:@" LIMIT %d,%d",
- [limitRowsField intValue]-1, [prefs integerForKey:@"limitRowsValue"]]];
- }
- queryResult = [mySQLConnection queryString:query];
- // [fullResult setArray:[[self fetchResultAsArray:queryResult] retain]];
- [fullResult setArray:[self fetchResultAsArray:queryResult]];
- }
- }
- return YES;
- } else {
- //error in mysql-query
- NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), NSLocalizedString(@"Cancel", @"cancel button"), nil, tableWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:), nil, @"addrow",
- [NSString stringWithFormat:NSLocalizedString(@"Couldn't write row.\nMySQL said: %@", @"message of panel when error while adding row to db"), [mySQLConnection getLastErrorMessage]]);
- return NO;
- }
-}
-
-- (NSString *)argumentForRow:(int)row
-/*
- returns the WHERE argument to identify a row
- if row is -2, it uses the oldRow
- if there is one, it uses the primary key, otherwise uses all fields as argument and sets LIMIT to 1
- */
-{
- CMMCPResult *theResult;
- NSDictionary *theRow;
- id tempValue;
- NSMutableString *value = [NSMutableString string];
- NSMutableString *argument = [NSMutableString string];
- int i,j;
- NSEnumerator *enumerator;
- id type;
- BOOL blob = NO;
- NSArray *numberFields = [NSArray arrayWithObjects:@"tiny", @"short", @"long", @"int24", @"longlong", @"decimal", @"float", @"double", nil];
-
- if ( row == -1 )
- return @"";
-
- //get primary key if there is one
- /*
- theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW INDEX FROM `%@`", selectedTable]];
- if ([theResult numOfRows]) [theResult dataSeek:0];
- for ( i = 0 ; i < [theResult numOfRows] ; i++ ) {
- theRow = [theResult fetchRowAsDictionary];
- if ( [[theRow objectForKey:@"Key_name"] isEqualToString:@"PRIMARY"] ) {
- [keys addObject:[theRow objectForKey:@"Column_name"]];
- }
- }
- */
- if ( !keys ) {
- setLimit = NO;
- keys = [[NSMutableArray alloc] init];
- theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM `%@`", selectedTable]];
- if ([theResult numOfRows]) [theResult dataSeek:0];
- for ( i = 0 ; i < [theResult numOfRows] ; i++ ) {
- theRow = [theResult fetchRowAsDictionary];
- if ( [[theRow objectForKey:@"Key"] isEqualToString:@"PRI"] ) {
- [keys addObject:[theRow objectForKey:@"Field"]];
- }
- }
- }
-
- if ( ![keys count] ) {
- //if there is no primary key, take all fields as argument
- //here we have a problem when dontShowBlob == YES (we don't have the right values to use in the WHERE statement)
- [keys setArray:fieldNames];
- setLimit = YES;
- enumerator = [fieldTypes objectEnumerator];
- while ( (type = [enumerator nextObject]) ) {
- if ( [self isBlobOrText:type] ) {
- blob = YES;
- }
- }
- if ( [prefs boolForKey:@"dontShowBlob"] && blob ) {
- NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil,
- NSLocalizedString(@"You can't hide blob and text fields when working with tables without index.", @"message of panel when trying to edit tables without index and with hidden blob/text fields"));
- [keys removeAllObjects];
- [tableContentView deselectAll:self];
- return @"";
- }
- }
- for ( i = 0 ; i < [keys count] ; i++ ) {
- if ( i )
- [argument appendString:@" AND "];
- if ( row >= 0 ) {
- //use selected row
- tempValue = [[filteredResult objectAtIndex:row] objectForKey:[keys objectAtIndex:i]];
- } else {
- //use oldRow
- tempValue = [oldRow objectForKey:[keys objectAtIndex:i]];
- }
- if ( [tempValue isKindOfClass:[NSData class]] ) {
- [value setString:[[NSString alloc] initWithData:tempValue encoding:[mySQLConnection encoding]]];
- } else {
- [value setString:[tempValue description]];
- }
-
- if ( [value isEqualToString:[prefs stringForKey:@"nullValue"]] ) {
- [value setString:@"NULL"];
- } else {
- //escape special characters (in WHERE statement!)
- for ( j = 0 ; j < [value length] ; j++ ) {
- if ( [value characterAtIndex:j] == '\\' ) {
- [value insertString:@"\\" atIndex:j];
- j++;
- }
- }
- [value setString:[mySQLConnection prepareString:value]];
- for ( j = 0 ; j < [value length] ; j++ ) {
- if ( [value characterAtIndex:j] == '%' ||
- [value characterAtIndex:j] == '_' ) {
- [value insertString:@"\\" atIndex:j];
- j++;
- }
- }
- // [value setString:[NSString stringWithFormat:@"\"%@\"", value]];
- [value setString:[NSString stringWithFormat:@"'%@'", value]];
- }
- if ( [value isEqualToString:@"NULL"] ) {
- [argument appendString:[NSString stringWithFormat:@"`%@` IS NULL", [keys objectAtIndex:i]]];
- } else {
- if ( [numberFields containsObject:[fieldTypes objectAtIndex:[fieldNames indexOfObject:[keys objectAtIndex:i]]]] ) {
- [argument appendString:[NSString stringWithFormat:@"`%@` = %@", [keys objectAtIndex:i], value]];
- } else {
- [argument appendString:[NSString stringWithFormat:@"`%@` LIKE %@", [keys objectAtIndex:i], value]];
- }
- }
- }
- if ( setLimit )
- [argument appendString:@" LIMIT 1"];
- return argument;
-}
-
-- (BOOL)isBlobOrText:(NSString *)fieldType
-/*
- returns YES if fieldType is some kind of blob or text. afaik the type of this fields is always blob, but better we test it...
- it would be nice to know if it is blob or text, but mysql doesn't want to tell it...
- */
-{
- if ( [fieldType isEqualToString:@"tinyblob"] || [fieldType isEqualToString:@"blob"] ||
- [fieldType isEqualToString:@"mediumblob"] || [fieldType isEqualToString:@"longblob"] ) {
- return YES;
- } else {
- return NO;
- }
-}
-
-- (NSString *)fieldListForQuery
-/*
- returns * if dontShowBlob == NO
- returns a comma-separated list of all fields which aren't of type blob or text if dontShowBlob == YES
- */
-{
- int i;
- NSMutableArray *fields = [NSMutableArray array];
-
- if ( [prefs boolForKey:@"dontShowBlob"] ) {
- for ( i = 0 ; i < [fieldTypes count] ; i++ ) {
- if ( ![self isBlobOrText:[fieldTypes objectAtIndex:i]] ) {
- [fields addObject:[fieldNames objectAtIndex:i]];
- }
- }
- if ( [fields count] == 0 ) {
- return [NSString stringWithFormat:@"`%@`", [fieldNames objectAtIndex:0]];
- } else {
- return [NSString stringWithFormat:@"`%@`", [fields componentsJoinedByString:@"`,`"]];
- }
- } else {
- return @"*";
- }
-}
-
-- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(NSString *)contextInfo
-/*
- if contextInfo == addrow: remain in edit-mode if user hits OK, otherwise cancel editing
- if contextInfo == removerow: removes row if user hits OK
- */
-{
- NSEnumerator *enumerator = [tableContentView selectedRowEnumerator];
- NSNumber *index;
- NSMutableArray *tempArray = [NSMutableArray array];
- NSMutableArray *tempResult = [NSMutableArray array];
- NSString *queryString;
- CMMCPResult *queryResult;
- int i, errors;
-
- [sheet orderOut:self];
-
- if ( [contextInfo isEqualToString:@"addrow"] ) {
- if ( returnCode == NSAlertDefaultReturn ) {
- //problem: reenter edit mode doesn't function
- [tableContentView editColumn:0 row:[tableContentView selectedRow] withEvent:nil select:YES];
- } else {
- if ( !isEditingNewRow ) {
- [filteredResult replaceObjectAtIndex:[tableContentView selectedRow]
- withObject:[NSMutableDictionary dictionaryWithDictionary:oldRow]];
- isEditingRow = NO;
- } else {
- [filteredResult removeObjectAtIndex:[tableContentView selectedRow]];
- isEditingRow = NO;
- isEditingNewRow = NO;
- }
- }
- [tableContentView reloadData];
- } else if ( [contextInfo isEqualToString:@"removeallrows"] ) {
- if ( returnCode == NSAlertDefaultReturn ) {
- /*
- if ( ([tableContentView numberOfSelectedRows] == [self numberOfRowsInTableView:tableContentView]) &&
- areShowingAllRows &&
- ([tableContentView numberOfSelectedRows] < [prefs integerForKey:@"limitRowsValue"]) ) {
- */
- [mySQLConnection queryString:[NSString stringWithFormat:@"DELETE FROM `%@`", selectedTable]];
- if ( [[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) {
- [self reloadTable:self];
- } else {
- NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil,
- [NSString stringWithFormat:NSLocalizedString(@"Couldn't remove rows.\nMySQL said: %@", @"message of panel when field cannot be removed"),
- [mySQLConnection getLastErrorMessage]]);
- }
- }
- } else if ( [contextInfo isEqualToString:@"removerow"] ) {
- if ( returnCode == NSAlertDefaultReturn ) {
- errors = 0;
-
- while ( (index = [enumerator nextObject]) ) {
- [mySQLConnection queryString:[NSString stringWithFormat:@"DELETE FROM `%@` WHERE %@",
- selectedTable, [self argumentForRow:[index intValue]]]];
- if ( ![mySQLConnection affectedRows] ) {
- //no rows deleted
- errors++;
- } else if ( [[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) {
- //rows deleted with success
- [tempArray addObject:index];
- } else {
- //error in mysql-query
- errors++;
- }
- }
-
- if ( errors ) {
- NSBeginAlertSheet(NSLocalizedString(@"Warning", @"warning"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"%d rows have not been removed. Reload the table to be sure that the rows exist and use a primary key for your table.", @"message of panel when not all selected fields have been deleted"), errors]);
- }
-
- //do deleting (after enumerating)
- if ( [prefs boolForKey:@"reloadAfterRemoving"] ) {
- [self reloadTableValues:self];
- } else {
- for ( i = 0 ; i < [filteredResult count] ; i++ ) {
- if ( ![tempArray containsObject:[NSNumber numberWithInt:i]] )
- [tempResult addObject:[filteredResult objectAtIndex:i]];
- }
- [filteredResult setArray:tempResult];
- numRows = [self getNumberOfRows];
- if ( !areShowingAllRows ) {
- // queryString = [@"SELECT * FROM " stringByAppendingString:selectedTable];
- queryString = [NSString stringWithFormat:@"SELECT %@ FROM `%@`", [self fieldListForQuery], selectedTable];
- if ( sortField ) {
- // queryString = [queryString stringByAppendingString:[NSString stringWithFormat:@" ORDER BY `%@`", sortField]];
- queryString = [NSString stringWithFormat:@"%@ ORDER BY `%@`", queryString, sortField];
- if ( isDesc )
- queryString = [queryString stringByAppendingString:@" DESC"];
- }
- if ( [prefs boolForKey:@"limitRows"] ) {
- if ( [limitRowsField intValue] <= 0 ) {
- [limitRowsField setStringValue:@"1"];
- }
- queryString = [queryString stringByAppendingString:
- [NSString stringWithFormat:@" LIMIT %d,%d",
- [limitRowsField intValue]-1, [prefs integerForKey:@"limitRowsValue"]]];
- }
- queryResult = [mySQLConnection queryString:queryString];
- // [fullResult setArray:[[self fetchResultAsArray:queryResult] retain]];
- [fullResult setArray:[self fetchResultAsArray:queryResult]];
- [tableContentView reloadData];
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows of %d selected", @"text showing how many rows are in the filtered result"),
- [filteredResult count], numRows]];
- } else {
- [fullResult setArray:filteredResult];
- [tableContentView reloadData];
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows in table", @"text showing how many rows are in the result"), numRows]];
- }
- }
- [tableContentView deselectAll:self];
- }
- }
-}
-
-- (int)getNumberOfRows
-/*
- returns the number of rows in the selected table
- queries the number from mysql if enabled in prefs and result is limited, otherwise just return the fullResult count
- */
-{
- if ( [prefs boolForKey:@"limitRows"] && [prefs boolForKey:@"fetchRowCount"] ) {
- numRows = [self fetchNumberOfRows];
- } else {
- numRows = [fullResult count];
- }
- return numRows;
-}
-
-- (int)fetchNumberOfRows
-/*
- fetches the number of rows in the selected table using a "SELECT COUNT(*)" query and return it
- */
-{
- return [[[[mySQLConnection queryString:[NSString stringWithFormat:@"SELECT COUNT(*) FROM `%@`", selectedTable]] fetchRowAsArray] objectAtIndex:0] intValue];
-}
-
-
-//tableView datasource methods
-- (int)numberOfRowsInTableView:(NSTableView *)aTableView
-{
- return [filteredResult count];
-}
-
-- (id)tableView:(NSTableView *)aTableView
-objectValueForTableColumn:(NSTableColumn *)aTableColumn
- row:(int)rowIndex
-{
- id theRow, theValue;
-
- theRow = [filteredResult objectAtIndex:rowIndex];
- theValue = [theRow objectForKey:[aTableColumn identifier]];
-
- if ( [theValue isKindOfClass:[NSData class]] ) {
- theValue = [[NSString alloc] initWithData:theValue encoding:[mySQLConnection encoding]];
- //show only first 50 characters to speed up interface (but return everything when this method is used to return the current result)
- // if ( ([theValue length] > 100) && aTableView ) {
- }
-
-// if ( ([(NSString *)theValue length] > 100) && aTableView ) {
-// theValue = [NSString stringWithFormat:@"%@(...)", [theValue substringToIndex:100]];
-// }
-
- return theValue;
-}
-
-- (void)tableView:(NSTableView *)aTableView
- setObjectValue:(id)anObject
- forTableColumn:(NSTableColumn *)aTableColumn
- row:(int)rowIndex
-{
- if ( !isEditingRow ) {
- [oldRow setDictionary:[filteredResult objectAtIndex:rowIndex]];
- isEditingRow = YES;
- }
- if ( anObject ) {
- [[filteredResult objectAtIndex:rowIndex] setObject:anObject forKey:[aTableColumn identifier]];
- } else {
- [[filteredResult objectAtIndex:rowIndex] setObject:@"" forKey:[aTableColumn identifier]];
- }
-}
-
-#pragma mark -
-#pragma mark tableView delegate methods
-
-- (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)tableColumn
-/*
- sorts the tableView by the clicked column
- if clicked twice, order is descending
- */
-{
- NSString *queryString;
- CMMCPResult *queryResult;
-
- if ( [selectedTable isEqualToString:@""] || !selectedTable )
- return;
- if ( ![self selectionShouldChangeInTableView:nil] )
- return;
-
- //query started
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:self];
-
- //sets order descending if a header is clicked twice
- if ( [[tableColumn identifier] isEqualTo:sortField] ) {
- if ( isDesc ) {
- isDesc = NO;
- } else {
- isDesc = YES;
- }
- } else {
- isDesc = NO;
- [tableContentView setIndicatorImage:nil inTableColumn:[tableContentView tableColumnWithIdentifier:sortField]];
- }
- sortField = [tableColumn identifier];
-
- //make queryString and perform query
- queryString = [NSString stringWithFormat:@"SELECT %@ FROM `%@` ORDER BY `%@`", [self fieldListForQuery],
- selectedTable, sortField];
- if ( isDesc )
- queryString = [queryString stringByAppendingString:@" DESC"];
- if ( [prefs boolForKey:@"limitRows"] ) {
- if ( [limitRowsField intValue] <= 0 ) {
- [limitRowsField setStringValue:@"1"];
- }
- queryString = [queryString stringByAppendingString:
- [NSString stringWithFormat:@" LIMIT %d,%d",
- [limitRowsField intValue]-1, [prefs integerForKey:@"limitRowsValue"]]];
- }
- queryResult = [mySQLConnection queryString:queryString];
-
- // [fullResult setArray:[[self fetchResultAsArray:queryResult] retain]];
- [fullResult setArray:[self fetchResultAsArray:queryResult]];
-
- if ( ![[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) {
- NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil,
- [NSString stringWithFormat:NSLocalizedString(@"Couldn't sort table. MySQL said: %@", @"message of panel when sorting of table failed"), [mySQLConnection getLastErrorMessage]]);
- return;
- }
-
- //sets highlight and indicatorImage
- [tableContentView setHighlightedTableColumn:tableColumn];
- if ( isDesc ) {
- [tableContentView setIndicatorImage:[NSImage imageNamed:@"NSDescendingSortIndicator"] inTableColumn:tableColumn];
- } else {
- [tableContentView setIndicatorImage:[NSImage imageNamed:@"NSAscendingSortIndicator"] inTableColumn:tableColumn];
- }
-
- //query finished
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
-
- //if filter is activated filters the result, otherwise shows fullResult
- if ( !areShowingAllRows ) {
- [self filterTable:self];
- } else {
- [filteredResult setArray:fullResult];
- [tableContentView reloadData];
- }
-}
-
-- (BOOL)selectionShouldChangeInTableView:(NSTableView *)aTableView
-{
- /*
- int row = [tableContentView editedRow];
- int column = [tableContentView editedColumn];
- NSTableColumn *tableColumn;
- NSCell *cell;
-
- if ( row != -1 ) {
- tableColumn = [[tableContentView tableColumns] objectAtIndex:column];
- cell = [tableColumn dataCellForRow:row];
- [cell endEditing:[tableContentView currentEditor]];
- }
- */
- //end editing (otherwise problems when user hits reload button)
- [tableWindow endEditingFor:nil];
-
- return [self addRowToDB];
-}
-
-- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
-{
- // Check our notification object is our table content view
- if ([aNotification object] != tableContentView)
- return;
-
- if ( [tableContentView numberOfSelectedRows] > 0 ) {
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d of %d rows selected", @"Text showing how many rows are selected"), [tableContentView numberOfSelectedRows], [tableContentView numberOfRows]]];
- } else {
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows", @"Text showing how many rows are in the result"), [tableContentView numberOfRows]]];
- }
-}
-
-- (void)tableViewSelectionIsChanging:(NSNotification *)aNotification
-{
- // Check our notification object is our table content view
- if ([aNotification object] != tableContentView)
- return;
-
- if ( [tableContentView numberOfSelectedRows] > 0 ) {
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d of %d rows selected", @"Text showing how many rows are selected"), [tableContentView numberOfSelectedRows], [tableContentView numberOfRows]]];
- } else {
- [countText setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%d rows", @"Text showing how many rows are in the result"), [tableContentView numberOfRows]]];
- }
-}
-
-
-- (void)tableViewColumnDidResize:(NSNotification *)aNotification
-/*
- saves the new column size in the preferences
- */
-{
- // sometimes the column has no identifier. I can't figure out what is causing it, so we just skip over this item
- if (![[[aNotification userInfo] objectForKey:@"NSTableColumn"] identifier])
- return;
-
- NSMutableDictionary *tableColumnWidths;
- NSString *database = [NSString stringWithFormat:@"%@@%@", [tableDocumentInstance database], [tableDocumentInstance host]];
- NSString *table = (NSString *)[tablesListInstance table];
-
- // get tableColumnWidths object
- if ( [prefs objectForKey:@"tableColumnWidths"] != nil ) {
- tableColumnWidths = [NSMutableDictionary dictionaryWithDictionary:[prefs objectForKey:@"tableColumnWidths"]];
- } else {
- tableColumnWidths = [NSMutableDictionary dictionary];
- }
- // get database object
- if ( [tableColumnWidths objectForKey:database] == nil ) {
- [tableColumnWidths setObject:[NSMutableDictionary dictionary] forKey:database];
- } else {
- [tableColumnWidths setObject:[[tableColumnWidths objectForKey:database] mutableCopy] forKey:database];
- }
- // get table object
- if ( [[tableColumnWidths objectForKey:database] objectForKey:table] == nil ) {
- [[tableColumnWidths objectForKey:database] setObject:[NSMutableDictionary dictionary] forKey:table];
- } else {
- [[tableColumnWidths objectForKey:database] setObject:[[[tableColumnWidths objectForKey:database] objectForKey:table] mutableCopy] forKey:table];
- }
- // save column size
- [[[tableColumnWidths objectForKey:database] objectForKey:table] setObject:[NSNumber numberWithFloat:[[[aNotification userInfo] objectForKey:@"NSTableColumn"] width]] forKey:[[[aNotification userInfo] objectForKey:@"NSTableColumn"] identifier]];
- [prefs setObject:tableColumnWidths forKey:@"tableColumnWidths"];
-}
-
-- (BOOL)tableView:(NSTableView *)aTableView shouldEditTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
-/*
- opens sheet if multipleLineEditingButton is clicked or field is a hidden blob or text field
- */
-{
- NSEnumerator *enumerator;
- id type;
- BOOL blob = NO;
- NSDictionary *tempRow;
- NSMutableDictionary *modifiedRow = [NSMutableDictionary dictionary];
- id key;
- int code;
- NSString *query;
- CMMCPResult *tempResult;
- id theValue;
- BOOL columnIsBlob = NO;
- // int i;
- // NSArray *columns = [aTableView tableColumns];
-
- if ( [prefs boolForKey:@"dontShowBlob"] && !isEditingRow ) {
- //get all row values if dontShowBlob == YES and table contains blob or text field and isEditingRow = NO
- enumerator = [fieldTypes objectEnumerator];
- while ( (type = [enumerator nextObject]) ) {
- if ( [self isBlobOrText:type] ) {
- blob = YES;
- }
- }
-
- if ( blob ) {
- query = [NSString stringWithFormat:@"SELECT * FROM `%@` WHERE %@",
- selectedTable, [self argumentForRow:[tableContentView selectedRow]]];
- tempResult = [mySQLConnection queryString:query];
- if ( ![tempResult numOfRows] ) {
- NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil,
- NSLocalizedString(@"Couldn't load the row. Reload the table to be sure that the row exists and use a primary key for your table.", @"message of panel when loading of row failed"));
- return NO;
- }
- tempRow = [tempResult fetchRowAsDictionary];
- enumerator = [tempRow keyEnumerator];
- while ( key = [enumerator nextObject] ) {
- if ( [[tempRow objectForKey:key] isMemberOfClass:[NSNull class]] ) {
- [modifiedRow setObject:[prefs stringForKey:@"nullValue"] forKey:key];
- } else {
- [modifiedRow setObject:[tempRow objectForKey:key] forKey:key];
- }
- }
- [filteredResult replaceObjectAtIndex:rowIndex
- withObject:[NSMutableDictionary dictionaryWithDictionary:modifiedRow]];
- [tableContentView reloadData];
- }
- }
-
- /*
- // find the column we're trying to edit
- for ( i = 0; i < [columns count]; i++ ) {
- if ( [columns objectAtIndex:i] == aTableColumn ) {
- // this flag will let us determine if we should "force" multi-line edit.
- columnIsBlob = [self isBlobOrText:[fieldTypes objectAtIndex:i]];
- break;
- }
- }
- */
- //is the column a blob field -> if YES force sheet editing
- if ( [self isBlobOrText:[fieldTypes objectAtIndex:[fieldNames indexOfObject:[aTableColumn identifier]]]] ) {
- columnIsBlob = YES;
- }
-
- if ( [multipleLineEditingButton state] == NSOnState || columnIsBlob ) {
- theValue = [[filteredResult objectAtIndex:rowIndex] objectForKey:[aTableColumn identifier]];
- NSImage *image = nil;
- editData = [theValue retain];
-
- if ( [theValue isKindOfClass:[NSData class]] ) {
- image = [[NSImage alloc] initWithData:theValue];
- [hexTextView setString:[self dataToHex:theValue]];
- /*
- // update displayed font to monospace
- NSFont *font = [NSFont fontWithName:@"Courier" size:12.0f];
- NSRange hexRange = { 0, [[hexTextView string] length] - 1 };
- [hexTextView setFont:font range:hexRange];
- */
- theValue = [[NSString alloc] initWithData:theValue encoding:[mySQLConnection encoding]];
- } else {
- [hexTextView setString:@""];
- theValue = [theValue description];
- }
-
- [editImage setImage:image];
- [editTextView setString:theValue];
- [editTextView setSelectedRange:NSMakeRange(0,[[editTextView string] length])];
- //different sheets for date (with up/down arrows), number and text
- [NSApp beginSheet:editSheet
- modalForWindow:tableWindow modalDelegate:self
- didEndSelector:nil contextInfo:nil];
- code = [NSApp runModalForWindow:editSheet];
-
- [NSApp endSheet:editSheet];
- [editSheet orderOut:nil];
-
- if ( code ) {
- if ( !isEditingRow ) {
- [oldRow setDictionary:[filteredResult objectAtIndex:rowIndex]];
- isEditingRow = YES;
- }
-
- [[filteredResult objectAtIndex:rowIndex] setObject:[editData copy]
- forKey:[aTableColumn identifier]];
-
- // clean up
- [editImage setImage:nil];
- [editTextView setString:@""];
- [hexTextView setString:@""];
- if ( editData ) {
- [editData release];
- }
- }
- return NO;
- } else {
- return YES;
- }
-}
-
-- (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray*)rows
- toPasteboard:(NSPasteboard*)pboard
-/*
- enable drag from tableview
- */
-{
- if ( tableView == tableContentView )
- {
- NSString *tmp = [tableContentView draggedRowsAsTabString:rows];
-
- if ( nil != tmp )
- {
- [pboard declareTypes:[NSArray arrayWithObjects: NSTabularTextPboardType,
- NSStringPboardType, nil]
- owner:nil];
-
- [pboard setString:tmp forType:NSStringPboardType];
- [pboard setString:tmp forType:NSTabularTextPboardType];
- return YES;
- }
- }
- return NO;
-}
-
-#pragma mark -
-
-- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command
-/*
- traps enter and esc an make/cancel editing without entering next row
- */
-{
- int row, column, i;
-
- row = [tableContentView editedRow];
- column = [tableContentView editedColumn];
-
- if ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertNewline:)] ||
- [textView methodForSelector:command] == [textView methodForSelector:@selector(insertTab:)] ) //trap enter and tab
- {
- //save current line
- [[control window] makeFirstResponder:control];
- if ( column == ( [tableContentView numberOfColumns] - 1 ) ) {
- [self addRowToDB];
- /*
- if ( [self addRowToDB] &&
- ( [textView methodForSelector:command] == [textView methodForSelector:@selector(insertTab:)] ) &&
- !(sortField && ([prefs boolForKey:@"reloadAfterAdding"] || [prefs boolForKey:@"reloadAfterEditing"])) ) {
- //get in edit-mode of next row if user hit tab (and result isn't sorted and reloaded)
- if ( row < ([tableContentView numberOfRows] - 1) ) {
- [tableContentView selectRow:row+1 byExtendingSelection:NO];
- [tableContentView editColumn:0 row:row+1 withEvent:nil select:YES];
- } else {
- [tableContentView selectRow:0 byExtendingSelection:NO];
- [tableContentView editColumn:0 row:0 withEvent:nil select:YES];
- }
- }
- */
- } else {
- //check if next column is a blob column
- i = 1;
- while ( [self isBlobOrText:[fieldTypes objectAtIndex:[fieldNames indexOfObject:[[[tableContentView tableColumns] objectAtIndex:column+i] identifier]]]] ) {
- i++;
- if ( (column+i) >= [tableContentView numberOfColumns] ) {
- //there is no other column after the blob column
- [self addRowToDB];
- return TRUE;
- }
- }
- //edit the column after the blob column
- [tableContentView editColumn:column+i row:row withEvent:nil select:YES];
- }
- return TRUE;
- }
- else if ( [[control window] methodForSelector:command] == [[control window] methodForSelector:@selector(_cancelKey:)] ||
- [textView methodForSelector:command] == [textView methodForSelector:@selector(complete:)] ) //trap esc
- {
- //abort editing
- [control abortEditing];
- if ( isEditingRow && !isEditingNewRow ) {
- isEditingRow = NO;
- [filteredResult replaceObjectAtIndex:row withObject:[NSMutableDictionary dictionaryWithDictionary:oldRow]];
- } else if ( isEditingNewRow ) {
- isEditingRow = NO;
- isEditingNewRow = NO;
- [filteredResult removeObjectAtIndex:row];
- [tableContentView reloadData];
- }
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-
-//textView delegate methods
-- (BOOL)textView:(NSTextView *)aTextView doCommandBySelector:(SEL)aSelector
-/*
- traps enter and return key and closes editSheet instead of inserting a linebreak when user hits return
- */
-{
- if ( aTextView == editTextView ) {
- if ( [aTextView methodForSelector:aSelector] == [aTextView methodForSelector:@selector(insertNewline:)] &&
- [[[NSApp currentEvent] characters] isEqualToString:@"\003"] )
- {
- [NSApp stopModalWithCode:1];
- return YES;
- } else {
- return NO;
- }
- }
- return NO;
-}
-
-
-//last but not least
-
-- (void)dealloc
-{
- // NSLog(@"TableContent dealloc");
-
- [editData release];
- [fullResult release];
- [filteredResult release];
- [keys release];
- [oldRow release];
- [fieldNames release];
- [fieldTypes release];
- [compareType release];
- [sortField release];
- [prefs release];
-
- [super dealloc];
-}
-
-@end