aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Resources/English.lproj/sequel-pro-print-template.html19
-rw-r--r--Resources/sequel-pro-table-info-print-template.html149
-rw-r--r--Source/SPConstants.h1
-rw-r--r--Source/SPConstants.m1
-rw-r--r--Source/SPExtendedTableInfo.h1
-rw-r--r--Source/SPExtendedTableInfo.m66
-rw-r--r--Source/SPPrintController.h5
-rw-r--r--Source/SPPrintController.m154
-rw-r--r--Source/TableDocument.m4
-rw-r--r--Source/TableSource.m46
-rw-r--r--sequel-pro.xcodeproj/project.pbxproj4
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;
};