Using Vvidget for Quick Looking Line Graphs

Author: Lance
Web Site: www.vvi.com
Quick Look technology in Mac OS X 10.5 is used to change file content into a picture for the Finder. What would be more natural than turning files containing data into graphs? This tutorial shows how to do that for the staple of engineering, the line graph.

Of course, with a little persuasion the code shown below can be altered to make a browser for any visualization type provided by the Vvidget API, but to keep it simple only a line graph implementation is shown. Nearly identical code is used to make the Vvidget Quick Look Plugin shown in this movie: http://www.peervisual.com/coverflow.mov, which gives an idea of how the code described below looks when run in the Finder.

Data File Content
The data file for this tutorial is formatted as a sequence of x y points delimited by a tab (or space). Each unique sequence is delineated by a return. A stripped-down example of such content showing two curves represented by 3 points each follows.

1 2 2 5 3 20
1 1 2 3 3 10

In order to associate the file with a Quick Look plugin the data file is given the extension: linegraphdata, for example: sample1.linegraphdata and that extension is an entry in the Info.plist of the plugin in the usual way (the precompiled example plugin referenced below shows such a file if you look inside it).

Quick Look Preview Function
The function GeneratePreviewForURL, shown below, generates the graph for the Finder. It takes a url (which is the path of the focused file in the Finder) and converts it into a line graph.

OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options)
{

NSAutoreleasePool *pool;
VC_Client_State *client_state;
VC_Input_String_Constructor *input_string_constructor;
UInt8 filePathCString[1024];
NSString *filePathString;
NSData *image_data;
unsigned width, height;
unsigned image_output_type;

pool = [[NSAutoreleasePool alloc] init];

CFURLGetFileSystemRepresentation(url, TRUE, filePathCString, 1024);
filePathString = [NSString stringWithCString: filePathCString];

image_output_type = 1U;
width = 800U;
height = 600U;

client_state = [[VC_Client_State alloc] init];
input_string_constructor = [client_state get_VC_input_string_constructor];

[input_string_constructor VC_reset];
[input_string_constructor set_VC_input_string_type:1U];

[input_string_constructor VC_append_key:"pvs_version" unsigned_value:1U];

/* Add keys for a linear line graph specification */

[input_string_constructor VC_append_key:"image_maker" string_value:@"chart"];
[input_string_constructor VC_append_key:"chart_type" unsigned_value:1U];
[input_string_constructor VC_append_key:"chart_subtype" unsigned_value:0U];
[input_string_constructor VC_append_key:"chart_format_type" unsigned_value:1U];

/* Add keys for titles */

[input_string_constructor VC_append_key:"title" string_value:@"Quick Look Title"];
[input_string_constructor VC_append_key:"x_title" string_value:@"X Title"];
[input_string_constructor VC_append_key:"y_title" string_value:@"Y Title"];

/* Add keys for data references */

[input_string_constructor VC_append_key:"data_format_type" unsigned_value:0U];
[input_string_constructor VC_append_key:"data_reference_type" unsigned_value:1U];
[input_string_constructor VC_append_key:"data_values" string_value:filePathString];

/* Add keys for image output size and type */

[input_string_constructor VC_append_key:"image_width" unsigned_value:width];
[input_string_constructor VC_append_key:"image_height" unsigned_value:height];
[input_string_constructor VC_append_key:"image_output_type" unsigned_value:image_output_type];

/* Form query and get data from that query */

[client_state VC_update_using_input_string_constructor];

[client_state VC_form_query_data];

image_data = [client_state VC_output_data_from_query_data:[client_state get_VC_query_data]];

/* If present, pass the image data to the Finder */

if(image_data != nil)
{
QLPreviewRequestSetDataRepresentation(preview, (CFDataRef)image_data, kUTTypeImage, NULL);

[image_data release];
}

/* Cleanup */

[client_state VC_invalidate_connection];
[client_state release];
[pool release];

return noErr;
}

The function above takes a URL, converts it to a file system path and adds that as a file name reference to the input string constructor using the data_values key value. The key values are described in the online manual at http://www.vvidget.org/service/manual. It also sets values of keys associated with a graph in the usual way of the API. Then it retrieves the corresponding graph output (image) as an NSData object, which is the same as a CFDataRef (pointer) and passes that to the QLPreviewRequestSetDataRepresentation function which takes care of the internal workings of the Quick Look plugin. Thankfully, all the computer science code is taken care of and it is pretty cookbook programming and to the point.

Precompiled Example
To have this plugin work on your computer first download and install the base system at: http://www.vvidget.org/builder/download. Then download this file: http://www.vvidget.org/builder/download/LineGraphDataQuickLook.zip, unzip it and see the ReadMe file for installation. As long as your data is formatted in the prescribed way and the file names have extension linegraphdata then you will be set to browse data files in line graph format.

Conclusion
A previous tutorial (http://www.macresearch.org/graphs-vvidget-server) showed how to make a graph for web sites and custom standalone applications. This tutorial shows how to do the same for a Quick Look plugin that works within the Finder. The programming methodology is essentially the same which lends to reuse of code and know-how to the advantage of richer and more diverse end results. With a modicum of programming many different types of staple graphs can be had while maintaining that diversity and richness. For more challenging projects, direct programming using the Framework API gives increased latitude for the quick looking needs of publishing and business reporting as well.