diff options
-rw-r--r-- | Resources/English.lproj/sequel-pro-print-template.html | 19 | ||||
-rw-r--r-- | Resources/sequel-pro-table-info-print-template.html | 149 | ||||
-rw-r--r-- | Source/SPConstants.h | 1 | ||||
-rw-r--r-- | Source/SPConstants.m | 1 | ||||
-rw-r--r-- | Source/SPExtendedTableInfo.h | 1 | ||||
-rw-r--r-- | Source/SPExtendedTableInfo.m | 66 | ||||
-rw-r--r-- | Source/SPPrintController.h | 5 | ||||
-rw-r--r-- | Source/SPPrintController.m | 154 | ||||
-rw-r--r-- | Source/TableDocument.m | 4 | ||||
-rw-r--r-- | Source/TableSource.m | 46 | ||||
-rw-r--r-- | sequel-pro.xcodeproj/project.pbxproj | 4 |
11 files changed, 353 insertions, 97 deletions
diff --git a/Resources/English.lproj/sequel-pro-print-template.html b/Resources/English.lproj/sequel-pro-print-template.html index 6265a3f8..ba8b31fa 100644 --- a/Resources/English.lproj/sequel-pro-print-template.html +++ b/Resources/English.lproj/sequel-pro-print-template.html @@ -1,5 +1,5 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html dir="ltr" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml" lang="en"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Sequel Pro</title> @@ -7,7 +7,7 @@ <style type="text/css" media="all"> html { - font-size: 82%; + font-size: 12px; } .nowrap { @@ -25,19 +25,16 @@ } h1 { - font-size: 14px; + font-size: 16px; } h2 { - font-size: 11px; - } - - table, th, td { - border: 0.1em solid #000000; + font-size: 14px; } table { width: 100%; + border: 1px solid #CCCCCC; border-collapse: collapse; border-spacing: 0; } @@ -50,10 +47,12 @@ text-align: left; font-weight: bold; background-color: #E5E5E5; + border: 1px solid #CCCCCC; } td { font-family: {{font}}; + border: {{gridlines}}; } tr > td { @@ -69,7 +68,7 @@ } code { - font-family: Monaco; + font-family: Courier; } </style> </head> @@ -84,7 +83,7 @@ <br /> </p> - <h2>{{title}}</h2> + <h2>{{heading}}</h2> <table class="data"> <thead> diff --git a/Resources/sequel-pro-table-info-print-template.html b/Resources/sequel-pro-table-info-print-template.html new file mode 100644 index 00000000..30198ec2 --- /dev/null +++ b/Resources/sequel-pro-table-info-print-template.html @@ -0,0 +1,149 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head> + <title>Sequel Pro</title> + + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + + <style type="text/css" media="all"> + html { + font-size: 12px; + } + + .nowrap { + white-space: nowrap; + } + + div.nowrap { + margin: 0; + padding: 0; + } + + body, table, th, td { + background-color: #FFFFFF; + color: #000000; + } + + h1 { + font-size: 16px; + } + + h2 { + font-size: 14px; + } + + table, th, td { + width: 300px; + border: none; + border-style: hidden; + border-collapse: collapse; + border-spacing: 0; + } + + th, td { + padding: 0.2em; + } + + th { + text-align: left; + font-weight: bold; + } + + td { + width: 500px; + } + + pre { + font-family: {{font}}; + } + </style> +</head> + +<body> + <h1>{{c.table}}</h1> + + <p> + <strong>Connection:</strong> {{c.username}}{% if c.username %}@{% /if %}{{c.hostname}}{% if c.port %}:{% /if %}{{c.port}}/{{c.database}}<br /> + <strong>Generated on:</strong> {% now | date_format: "dd MMM yyyy 'at' HH:mm:ss" %} by {{c.version}}<br /> + </p> + + <h2>{{heading}}</h2> + + <table> + <tr> + <th scope="row">Type: </th> + <td>{{i.type}}</td> + </tr> + + <tr> + <th scope="row">Encoding: </th> + <td>{{i.encoding}}</td> + </tr> + + <tr> + <th scope="row">Collation: </th> + <td>{{i.collation}}</td> + </tr> + + <tr> + <th scope="row">Create at: </th> + <td>{{i.createdAt}}</td> + </tr> + + <tr> + <th scope="row">Updated at: </th> + <td>{{i.updatedAt}}</td> + </tr> + + <tr> + <th scope="row">Number of rows: </th> + <td>{{i.rowNumber}}</td> + </tr> + + <tr> + <th scope="row">Row format: </th> + <td>{{i.rowFormat}}</td> + </tr> + + <tr> + <th scope="row">Avg. row length: </th> + <td>{{i.rowAvgLength}}</td> + </tr> + + <tr> + <th scope="row">Auto increment: </th> + <td>{{i.rowAutoIncrement}}</td> + </tr> + + <tr> + <th scope="row">Data size: </th> + <td>{{i.dataSize}}</td> + </tr> + + <tr> + <th scope="row">Max data size: </th> + <td>{{i.maxDataSize}}</td> + </tr> + + <tr> + <th scope="row">Index size: </th> + <td>{{i.indexSize}}</td> + </tr> + + <tr> + <th scope="row">Free data size: </th> + <td>{{i.sizeFree}}</td> + </tr> + </table> + + {% if i.comments.length > 0 %} + <h2>Comments</h2> + + <p><em>{{i.comments}}</em></p> + {% /if %} + + <h2>Create Syntax</h2> + + <pre>{{i.createSyntax}}</pre> +</body> +</html> diff --git a/Source/SPConstants.h b/Source/SPConstants.h index c8342a5f..a7409ebc 100644 --- a/Source/SPConstants.h +++ b/Source/SPConstants.h @@ -73,6 +73,7 @@ extern NSString *SPFileExtensionSQL; // Filenames extern NSString *SPHTMLPrintTemplate; +extern NSString *SPHTMLTableInfoPrintTemplate; extern NSString *SPHTMLHelpTemplate; diff --git a/Source/SPConstants.m b/Source/SPConstants.m index a395e11a..7db91664 100644 --- a/Source/SPConstants.m +++ b/Source/SPConstants.m @@ -42,6 +42,7 @@ NSString *SPFileExtensionSQL = @"sql"; // Filenames NSString *SPHTMLPrintTemplate = @"sequel-pro-print-template"; +NSString *SPHTMLTableInfoPrintTemplate = @"sequel-pro-table-info-print-template"; NSString *SPHTMLHelpTemplate = @"sequel-pro-mysql-help-template"; // Preference key constants diff --git a/Source/SPExtendedTableInfo.h b/Source/SPExtendedTableInfo.h index 4c9d1f07..aef1a6c4 100644 --- a/Source/SPExtendedTableInfo.h +++ b/Source/SPExtendedTableInfo.h @@ -73,6 +73,7 @@ // Others - (void)loadTable:(NSString *)table; +- (NSDictionary *)tableInformationForPrinting; // Task interaction - (void)startDocumentTaskForTab:(NSNotification *)aNotification; diff --git a/Source/SPExtendedTableInfo.m b/Source/SPExtendedTableInfo.m index d13de4a7..852b1007 100644 --- a/Source/SPExtendedTableInfo.m +++ b/Source/SPExtendedTableInfo.m @@ -36,7 +36,7 @@ @interface SPExtendedTableInfo (PrivateAPI) -- (NSString *)_formatValueWithKey:(NSString *)key inDictionary:(NSDictionary *)statusDict withLabel:(NSString *)label; +- (NSString *)_formatValueWithKey:(NSString *)key inDictionary:(NSDictionary *)statusDict; @end @@ -236,7 +236,9 @@ [tableCreateSyntaxTextView setEditable:YES]; [tableCreateSyntaxTextView shouldChangeTextInRange:NSMakeRange(0, [[tableCreateSyntaxTextView string] length]) replacementString:@""]; [tableCreateSyntaxTextView setString:@""]; + NSString *createViewSyntax = [[tableDataInstance tableCreateSyntax] createViewSyntaxPrettifier]; + [tableCreateSyntaxTextView shouldChangeTextInRange:NSMakeRange(0, 0) replacementString:createViewSyntax]; [tableCreateSyntaxTextView insertText:createViewSyntax]; [tableCreateSyntaxTextView didChangeText]; @@ -327,20 +329,20 @@ [tableCollationPopUpButton addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")]; } - [tableCreatedAt setStringValue:[self _formatValueWithKey:@"Create_time" inDictionary:statusFields withLabel:@"Created at"]]; - [tableUpdatedAt setStringValue:[self _formatValueWithKey:@"Update_time" inDictionary:statusFields withLabel:@"Updated at"]]; + [tableCreatedAt setStringValue:[NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Created at: ", @"table info created at label"), [self _formatValueWithKey:@"Create_time" inDictionary:statusFields]]]; + [tableUpdatedAt setStringValue:[NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Updated at: ", @"table info updated at label"), [self _formatValueWithKey:@"Update_time" inDictionary:statusFields]]]; // Set row values - [tableRowNumber setStringValue:[self _formatValueWithKey:@"Rows" inDictionary:statusFields withLabel:@"Number of rows"]]; - [tableRowFormat setStringValue:[self _formatValueWithKey:@"Row_format" inDictionary:statusFields withLabel:@"Row format"]]; - [tableRowAvgLength setStringValue:[self _formatValueWithKey:@"Avg_row_length" inDictionary:statusFields withLabel:@"Avg. row length"]]; - [tableRowAutoIncrement setStringValue:[self _formatValueWithKey:@"Auto_increment" inDictionary:statusFields withLabel:@"Auto increment"]]; + [tableRowNumber setStringValue:[NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Number of rows: ", @"table info number of rows label"), [self _formatValueWithKey:@"Rows" inDictionary:statusFields]]]; + [tableRowFormat setStringValue:[NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Row format: ", @"table info row format label"), [self _formatValueWithKey:@"Row_format" inDictionary:statusFields]]]; + [tableRowAvgLength setStringValue:[NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Avg. row length: ", @"table info average row length label"), [self _formatValueWithKey:@"Avg_row_length" inDictionary:statusFields]]]; + [tableRowAutoIncrement setStringValue:[self _formatValueWithKey:@"Auto_increment" inDictionary:statusFields]]; // Set size values - [tableDataSize setStringValue:[self _formatValueWithKey:@"Data_length" inDictionary:statusFields withLabel:@"Data size"]]; - [tableMaxDataSize setStringValue:[self _formatValueWithKey:@"Max_data_length" inDictionary:statusFields withLabel:@"Max data size"]]; - [tableIndexSize setStringValue:[self _formatValueWithKey:@"Index_length" inDictionary:statusFields withLabel:@"Index size"]]; - [tableSizeFree setStringValue:[self _formatValueWithKey:@"Data_free" inDictionary:statusFields withLabel:@"Free data size"]]; + [tableDataSize setStringValue:[NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Data size: ", @"table info data size label"), [self _formatValueWithKey:@"Data_length" inDictionary:statusFields]]]; + [tableMaxDataSize setStringValue:[NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Max data size: ", @"table info max data size label"), [self _formatValueWithKey:@"Max_data_length" inDictionary:statusFields]]]; + [tableIndexSize setStringValue:[NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Index size: ", @"table info index size label"), [self _formatValueWithKey:@"Index_length" inDictionary:statusFields]]]; + [tableSizeFree setStringValue:[NSString stringWithFormat:@"%@%@", NSLocalizedString(@"Free data size: ", @"table info free data size label"), [self _formatValueWithKey:@"Data_free" inDictionary:statusFields]]]; // Set comments [tableCommentsTextView setEditable:YES]; @@ -366,6 +368,35 @@ } /** + * + */ +- (NSDictionary *)tableInformationForPrinting +{ + NSMutableDictionary *tableInfo = [NSMutableDictionary dictionary]; + NSDictionary *statusFields = [tableDataInstance statusValues]; + + [tableInfo setObject:[tableTypePopUpButton titleOfSelectedItem] forKey:@"type"]; + [tableInfo setObject:[tableEncodingPopUpButton titleOfSelectedItem] forKey:@"encoding"]; + [tableInfo setObject:[tableCollationPopUpButton titleOfSelectedItem] forKey:@"collation"]; + + [tableInfo setObject:[self _formatValueWithKey:@"Create_time" inDictionary:statusFields] forKey:@"createdAt"]; + [tableInfo setObject:[self _formatValueWithKey:@"Update_time" inDictionary:statusFields] forKey:@"updatedAt"]; + [tableInfo setObject:[self _formatValueWithKey:@"Rows" inDictionary:statusFields] forKey:@"rowNumber"]; + [tableInfo setObject:[self _formatValueWithKey:@"Row_format" inDictionary:statusFields] forKey:@"rowFormat"]; + [tableInfo setObject:[self _formatValueWithKey:@"Avg_row_length" inDictionary:statusFields] forKey:@"rowAvgLength"]; + [tableInfo setObject:[self _formatValueWithKey:@"Auto_increment" inDictionary:statusFields] forKey:@"rowAutoIncrement"]; + [tableInfo setObject:[self _formatValueWithKey:@"Data_length" inDictionary:statusFields] forKey:@"dataSize"]; + [tableInfo setObject:[self _formatValueWithKey:@"Max_data_length" inDictionary:statusFields] forKey:@"maxDataSize"]; + [tableInfo setObject:[self _formatValueWithKey:@"Index_length" inDictionary:statusFields] forKey:@"indexSize"]; + [tableInfo setObject:[self _formatValueWithKey:@"Data_free" inDictionary:statusFields] forKey:@"sizeFree"]; + + [tableInfo setObject:[tableCommentsTextView string] forKey:@"comments"]; + [tableInfo setObject:[tableCreateSyntaxTextView string] forKey:@"createSyntax"]; + + return tableInfo; +} + +/** * NSTextView delegate. Used to change the selected table's comment. */ - (void)textDidEndEditing:(NSNotification *)notification @@ -404,8 +435,7 @@ - (void)startDocumentTaskForTab:(NSNotification *)aNotification { // Only proceed if this view is selected. - if (![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableInfo]) - return; + if (![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableInfo]) return; [tableTypePopUpButton setEnabled:NO]; [tableEncodingPopUpButton setEnabled:NO]; @@ -419,13 +449,11 @@ - (void)endDocumentTaskForTab:(NSNotification *)aNotification { // Only proceed if this view is selected. - if (![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableInfo]) - return; + if (![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableInfo]) return; NSDictionary *statusFields = [tableDataInstance statusValues]; - if (!selectedTable || ![selectedTable length] || [[statusFields objectForKey:@"Engine"] isEqualToString:@"View"]) - return; + if (!selectedTable || ![selectedTable length] || [[statusFields objectForKey:@"Engine"] isEqualToString:@"View"]) return; // If we are viewing tables in the information_schema database, then disable all controls that cause table // changes as these tables are not modifiable by anyone. @@ -469,7 +497,7 @@ /** * Format and returns the value within the info dictionary with the associated key. */ -- (NSString *)_formatValueWithKey:(NSString *)key inDictionary:(NSDictionary *)infoDict withLabel:(NSString *)label +- (NSString *)_formatValueWithKey:(NSString *)key inDictionary:(NSDictionary *)infoDict { NSString *value = [infoDict objectForKey:key]; @@ -521,7 +549,7 @@ return ([value length] > 0) ? value : NSLocalizedString(@"Not available", @"not available label"); } else { - return [NSString stringWithFormat:@"%@: %@", label, ([value length] > 0) ? value : NSLocalizedString(@"Not available", @"not available label")]; + return ([value length] > 0) ? value : NSLocalizedString(@"Not available", @"not available label"); } } diff --git a/Source/SPPrintController.h b/Source/SPPrintController.h index 8fd1acf8..17b78e35 100644 --- a/Source/SPPrintController.h +++ b/Source/SPPrintController.h @@ -27,7 +27,10 @@ @interface TableDocument (SPPrintController) -- (NSString *)generateHTMLforPrinting; +- (NSString *)generateHTMLForPrinting; +- (NSString *)generateTableInfoHTMLForPrinting; + - (NSArray *)columnNames; +- (NSMutableDictionary *)connectionInformation; @end diff --git a/Source/SPPrintController.m b/Source/SPPrintController.m index 718a203b..f890ad01 100644 --- a/Source/SPPrintController.m +++ b/Source/SPPrintController.m @@ -33,6 +33,7 @@ #import "MGTemplateEngine.h" #import "ICUTemplateMatcher.h" #import "SPConnectionController.h" +#import "SPExtendedTableInfo.h" @implementation TableDocument (SPPrintController) @@ -44,13 +45,28 @@ // Because we need the webFrame loaded (for preview), we've moved the actual printing here NSPrintInfo *printInfo = [self printInfo]; + NSSize paperSize = [printInfo paperSize]; + NSRect printableRect = [printInfo imageablePageBounds]; + + // Calculate page margins + CGFloat marginL = printableRect.origin.x; + CGFloat marginR = paperSize.width - (printableRect.origin.x + printableRect.size.width); + CGFloat marginB = printableRect.origin.y; + CGFloat marginT = paperSize.height - (printableRect.origin.y + printableRect.size.height); + + // Make sure margins are symetric and positive + CGFloat marginLR = MAX(0, MAX(marginL, marginR)); + CGFloat marginTB = MAX(0, MAX(marginT, marginB)); + + // Set the margins + [printInfo setLeftMargin:marginLR]; + [printInfo setRightMargin:marginLR]; + [printInfo setTopMargin:marginTB]; + [printInfo setBottomMargin:marginTB]; + [printInfo setHorizontalPagination:NSFitPagination]; [printInfo setVerticalPagination:NSAutoPagination]; [printInfo setVerticallyCentered:NO]; - [printInfo setTopMargin:30]; - [printInfo setBottomMargin:30]; - [printInfo setLeftMargin:10]; - [printInfo setRightMargin:10]; NSPrintOperation *op = [NSPrintOperation printOperationWithView:[[[printWebView mainFrame] frameView] documentView] printInfo:printInfo]; @@ -81,46 +97,23 @@ */ - (IBAction)printDocument:(id)sender { - [[printWebView mainFrame] loadHTMLString:[self generateHTMLforPrinting] baseURL:nil]; + [[printWebView mainFrame] loadHTMLString:([tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]] == 3) ? [self generateTableInfoHTMLForPrinting] :[self generateHTMLForPrinting] baseURL:nil]; } /** * Generates the HTML for the current view that is being printed. */ -- (NSString *)generateHTMLforPrinting +- (NSString *)generateHTMLForPrinting { // Set up template engine with your chosen matcher MGTemplateEngine *engine = [MGTemplateEngine templateEngine]; [engine setMatcher:[ICUTemplateMatcher matcherWithTemplateEngine:engine]]; - NSString *versionForPrint = [NSString stringWithFormat:@"%@ %@ (build %@)", - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"], - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"], - [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] - ]; - - NSMutableDictionary *connection = [[NSMutableDictionary alloc] init]; - - if ([[self user] length]) { - [connection setValue:[self user] forKey:@"username"]; - } - - if ([[self table] length]) { - [connection setValue:[self table] forKey:@"table"]; - } - - - if ([connectionController port] && [[connectionController port] length]) { - [connection setValue:[connectionController port] forKey:@"port"]; - } + NSMutableDictionary *connection = [self connectionInformation]; - [connection setValue:[self host] forKey:@"hostname"]; - [connection setValue:selectedDatabase forKey:@"database"]; - [connection setValue:versionForPrint forKey:@"version"]; - - NSString *title = @""; + NSString *heading = @""; NSArray *rows, *indexes, *indexColumns = nil; NSArray *columns = [self columnNames]; @@ -133,18 +126,16 @@ if ([[tableSource objectForKey:@"structure"] count] > 1) { - title = @"Table Structure"; + heading = NSLocalizedString(@"Table Structure", @"table structure print heading"); rows = [[NSArray alloc] initWithArray: [[tableSource objectForKey:@"structure"] objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableSource objectForKey:@"structure"] count] - 1)] - ] + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableSource objectForKey:@"structure"] count] - 1)]] ]; indexes = [[NSArray alloc] initWithArray: [[tableSource objectForKey:@"indexes"] objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableSource objectForKey:@"indexes"] count] - 1)] - ] + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableSource objectForKey:@"indexes"] count] - 1)]] ]; indexColumns = [[tableSource objectForKey:@"indexes"] objectAtIndex:0]; @@ -157,12 +148,11 @@ else if ([tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]] == 1) { if ([[tableContentInstance currentResult] count] > 1) { - title = @"Table Content"; + heading = NSLocalizedString(@"Table Content", @"table content print heading"); rows = [[NSArray alloc] initWithArray: [[tableContentInstance currentDataResult] objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableContentInstance currentResult] count] - 1)] - ] + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[tableContentInstance currentResult] count] - 1)]] ]; [connection setValue:[tableContentInstance usedQuery] forKey:@"query"]; @@ -172,12 +162,11 @@ else if ([tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]] == 2) { if ([[customQueryInstance currentResult] count] > 1) { - title = @"Query Result"; + heading = NSLocalizedString(@"Query Result", @"query result print heading"); rows = [[NSArray alloc] initWithArray: [[customQueryInstance currentResult] objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[customQueryInstance currentResult] count] - 1)] - ] + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, [[customQueryInstance currentResult] count] - 1)]] ]; [connection setValue:[customQueryInstance usedQuery] forKey:@"query"]; @@ -187,33 +176,54 @@ else if ([tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]] == 4) { if ([[tableRelationsInstance relationDataForPrinting] count] > 1) { - title = @"Table Relations"; + heading = NSLocalizedString(@"Table Relations", @"table relations print heading"); NSArray *data = [tableRelationsInstance relationDataForPrinting]; rows = [[NSArray alloc] initWithArray: [data objectsAtIndexes: - [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, ([data count] - 1))] - ] + [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, ([data count] - 1))]] ]; } } [engine setObject:connection forKey:@"c"]; - [printData setObject:title forKey:@"title"]; + [printData setObject:heading forKey:@"heading"]; [printData setObject:columns forKey:@"columns"]; [printData setObject:rows forKey:@"rows"]; [printData setObject:([prefs boolForKey:SPUseMonospacedFonts]) ? SPDefaultMonospacedFontName : @"Lucida Grande" forKey:@"font"]; - - [connection release]; - + [printData setObject:([prefs boolForKey:SPDisplayTableViewVerticalGridlines]) ? @"1px solid #CCCCCC" : @"none" forKey:@"gridlines"]; + if (rows) [rows release]; // Process the template and display the results. - NSString *result = [engine processTemplateInFileAtPath:[[NSBundle mainBundle] pathForResource:SPHTMLPrintTemplate ofType:@"html"] withVariables:printData]; + return [engine processTemplateInFileAtPath:[[NSBundle mainBundle] pathForResource:SPHTMLPrintTemplate ofType:@"html"] withVariables:printData]; +} + +/** + * Generates the HTML for the table information view that is to be printed. + */ +- (NSString *)generateTableInfoHTMLForPrinting +{ + // Set up template engine with your chosen matcher + MGTemplateEngine *engine = [MGTemplateEngine templateEngine]; + + [engine setMatcher:[ICUTemplateMatcher matcherWithTemplateEngine:engine]]; - return result; + NSMutableDictionary *connection = [self connectionInformation]; + NSMutableDictionary *printData = [NSMutableDictionary dictionary]; + + NSString *heading = NSLocalizedString(@"Table Information", @"table information print heading"); + + [engine setObject:connection forKey:@"c"]; + [engine setObject:[extendedTableInfoInstance tableInformationForPrinting] forKey:@"i"]; + + [printData setObject:heading forKey:@"heading"]; + [printData setObject:[[NSUnarchiver unarchiveObjectWithData:[prefs objectForKey:SPCustomQueryEditorFont]] fontName] forKey:@"font"]; + + // Process the template and display the results. + return [engine processTemplateInFileAtPath:[[NSBundle mainBundle] pathForResource:SPHTMLTableInfoPrintTemplate ofType:@"html"] withVariables:printData]; } /** @@ -225,25 +235,25 @@ // Table source view if ([tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]] == 0 - && [[tableSourceInstance tableSourceForPrinting] count] > 0 ) { + && [[tableSourceInstance tableSourceForPrinting] count] > 0) { columns = [[NSArray alloc] initWithArray:[[[tableSourceInstance tableSourceForPrinting] objectForKey:@"structure"] objectAtIndex:0] copyItems:YES]; } // Table content view else if ([tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]] == 1 - && [[tableContentInstance currentResult] count] > 0 ) { + && [[tableContentInstance currentResult] count] > 0) { columns = [[NSArray alloc] initWithArray:[[tableContentInstance currentResult] objectAtIndex:0] copyItems:YES]; } // Custom query view else if ([tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]] == 2 - && [[customQueryInstance currentResult] count] > 0 ) { + && [[customQueryInstance currentResult] count] > 0) { columns = [[NSArray alloc] initWithArray:[[customQueryInstance currentResult] objectAtIndex:0] copyItems:YES]; } // Table relations view else if ([tableTabView indexOfTabViewItem:[tableTabView selectedTabViewItem]] == 4 - && [[tableRelationsInstance relationDataForPrinting] count] > 0 ) { + && [[tableRelationsInstance relationDataForPrinting] count] > 0) { columns = [[NSArray alloc] initWithArray:[[tableRelationsInstance relationDataForPrinting] objectAtIndex:0] copyItems:YES]; } @@ -253,4 +263,38 @@ return columns; } +/** + * Generates a dictionary of connection information that is used for printing. + */ +- (NSMutableDictionary *)connectionInformation +{ + NSString *versionForPrint = [NSString stringWithFormat:@"%@ %@ (%@ %@)", + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"], + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"], + NSLocalizedString(@"build", @"build label"), + [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] + ]; + + NSMutableDictionary *connection = [NSMutableDictionary dictionary]; + + if ([[self user] length]) { + [connection setValue:[self user] forKey:@"username"]; + } + + if ([[self table] length]) { + [connection setValue:[self table] forKey:@"table"]; + } + + + if ([connectionController port] && [[connectionController port] length]) { + [connection setValue:[connectionController port] forKey:@"port"]; + } + + [connection setValue:[self host] forKey:@"hostname"]; + [connection setValue:selectedDatabase forKey:@"database"]; + [connection setValue:versionForPrint forKey:@"version"]; + + return connection; +} + @end diff --git a/Source/TableDocument.m b/Source/TableDocument.m index 6d082a59..b32cc2bb 100644 --- a/Source/TableDocument.m +++ b/Source/TableDocument.m @@ -2993,9 +2993,7 @@ } if ([menuItem action] == @selector(printDocument:)) { - return (((([self database] != nil) && - ([[tablesListInstance valueForKeyPath:@"tablesListView"] numberOfSelectedRows] == 1)) || - ([tableWindow firstResponder] == customQueryInstance))); + return (([self database] != nil) && ([[tablesListInstance valueForKeyPath:@"tablesListView"] numberOfSelectedRows] == 1)); } if ([menuItem action] == @selector(chooseEncoding:)) { diff --git a/Source/TableSource.m b/Source/TableSource.m index 05eb0c53..e6d2d170 100644 --- a/Source/TableSource.m +++ b/Source/TableSource.m @@ -1123,10 +1123,12 @@ returns a dictionary containing enum/set field names as key and possible values */ - (NSDictionary *)tableSourceForPrinting { - NSInteger i; + NSInteger i, j; NSMutableArray *tempResult = [NSMutableArray array]; NSMutableArray *tempResult2 = [NSMutableArray array]; + NSString *nullValue = [prefs stringForKey:SPNullValue]; + MCPResult *structureQueryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@", [selectedTable backtickQuotedString]]]; MCPResult *indexesQueryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW INDEXES FROM %@", [selectedTable backtickQuotedString]]]; @@ -1138,24 +1140,52 @@ returns a dictionary containing enum/set field names as key and possible values [tempResult addObject:[structureQueryResult fetchFieldNames]]; - NSMutableArray *temp = [[[indexesQueryResult fetchFieldNames] mutableCopy] autorelease]; + NSMutableArray *temp = [[indexesQueryResult fetchFieldNames] mutableCopy]; // Remove the 'table' column [temp removeObjectAtIndex:0]; [tempResult2 addObject:temp]; - for (i = 0 ; i < [structureQueryResult numOfRows]; i++) { - [tempResult addObject:[structureQueryResult fetchRowAsArray]]; + [temp release]; + + for (i = 0; i < [structureQueryResult numOfRows]; i++) { + NSMutableArray *row = [[structureQueryResult fetchRowAsArray] mutableCopy]; + + // For every NULL value replace it with the user's NULL value placeholder so we can actually print it + for (j = 0; j < [row count]; j++) + { + if ([[row objectAtIndex:j] isNSNull]) { + + // Replace the NULL instance with an escaped version of the user's placeholder + [row replaceObjectAtIndex:j withObject:(NSString *)CFXMLCreateStringByEscapingEntities(NULL, ((CFStringRef)nullValue), NULL)]; + } + } + + [tempResult addObject:row]; + + [row release]; } - for (i = 0 ; i < [indexesQueryResult numOfRows]; i++) { - NSMutableArray *index = [[[indexesQueryResult fetchRowAsArray] mutableCopy] autorelease]; + for (i = 0; i < [indexesQueryResult numOfRows]; i++) { + NSMutableArray *index = [[indexesQueryResult fetchRowAsArray] mutableCopy]; // Remove the 'table' column values [index removeObjectAtIndex:0]; + // For every NULL value replace it with the user's NULL value placeholder so we can actually print it + for (j = 0; j < [index count]; j++) + { + if ([[index objectAtIndex:j] isNSNull]) { + + // Replace the NULL instance with an escaped version of the user's placeholder + [index replaceObjectAtIndex:j withObject:(NSString *)CFXMLCreateStringByEscapingEntities(NULL, ((CFStringRef)nullValue), NULL)]; + } + } + [tempResult2 addObject:index]; + + [index release]; } return [NSDictionary dictionaryWithObjectsAndKeys:tempResult, @"structure", tempResult2, @"indexes", nil]; @@ -1271,8 +1301,7 @@ Begin a drag and drop operation from the table - copy a single dragged row to th */ - (BOOL)tableView:(NSTableView *)aTableView writeRowsWithIndexes:(NSIndexSet *)rows toPasteboard:(NSPasteboard*)pboard { - - //make sure that the drag operation is started from the right table view + // Make sure that the drag operation is started from the right table view if (aTableView != tableSourceView) return NO; // Check whether a save of the current field row is required. @@ -1285,7 +1314,6 @@ Begin a drag and drop operation from the table - copy a single dragged row to th } else { return NO; } - } /* diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index d159d629..7954e81a 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -61,6 +61,7 @@ 17CC97F710B4AC6C0034CD7A /* AboutPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = 17CC97F510B4AC6C0034CD7A /* AboutPanel.xib */; }; 17CC993B10B4C9C80034CD7A /* License.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 17CC993A10B4C9C80034CD7A /* License.rtf */; }; 17E090E811498FC9007FC1B4 /* SPPrintController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17E090E711498FC9007FC1B4 /* SPPrintController.m */; }; + 17E0937E114AE154007FC1B4 /* sequel-pro-table-info-print-template.html in Resources */ = {isa = PBXBuildFile; fileRef = 17E0937D114AE154007FC1B4 /* sequel-pro-table-info-print-template.html */; }; 17E641460EF01EB5001BC333 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 17E641440EF01EB5001BC333 /* main.m */; }; 17E641560EF01EF6001BC333 /* CustomQuery.m in Sources */ = {isa = PBXBuildFile; fileRef = 17E641490EF01EF6001BC333 /* CustomQuery.m */; }; 17E641570EF01EF6001BC333 /* SPAppController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17E6414B0EF01EF6001BC333 /* SPAppController.m */; }; @@ -413,6 +414,7 @@ 17DA04EA0FC1A7DA00D66140 /* Unit Tests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Unit Tests-Info.plist"; sourceTree = "<group>"; }; 17E090E611498FC9007FC1B4 /* SPPrintController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPPrintController.h; sourceTree = "<group>"; }; 17E090E711498FC9007FC1B4 /* SPPrintController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPPrintController.m; sourceTree = "<group>"; }; + 17E0937D114AE154007FC1B4 /* sequel-pro-table-info-print-template.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "sequel-pro-table-info-print-template.html"; sourceTree = "<group>"; }; 17E641440EF01EB5001BC333 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; 17E641450EF01EB5001BC333 /* sequel-pro_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "sequel-pro_Prefix.pch"; sourceTree = "<group>"; }; 17E641480EF01EF6001BC333 /* CustomQuery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomQuery.h; sourceTree = "<group>"; }; @@ -904,6 +906,7 @@ children = ( BCB56192106F88EC00167321 /* sequel-pro-print-template.html */, BC2C8E210FA8C2DB008468C7 /* sequel-pro-mysql-help-template.html */, + 17E0937D114AE154007FC1B4 /* sequel-pro-table-info-print-template.html */, ); name = Templates; sourceTree = "<group>"; @@ -1676,6 +1679,7 @@ BC5AD7FF10FB262F008769E3 /* field-small-square.tiff in Resources */, BC30C011111C98BD002701C9 /* DataMigrationDialog.xib in Resources */, BC962D661144EACA006170BD /* CompletionTokens.plist in Resources */, + 17E0937E114AE154007FC1B4 /* sequel-pro-table-info-print-template.html in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; |