Be Developers' Conference

The Tracker and You
Pavel Cisler

 

Pavel Cisler: I guess we are going to start. My name is Pavel Cisler, I work on the Tracker.

A Speaker: Yeah!

Pavel Cisler: This session is going to be about interfacing your applications with the Tracker, about ways to leverage in Tracker in your apps. And I'm going to start with a quick demo of some of new Tracker features in release 3.

In release 3, we continue to use MIME types throughout the system even more than we did in release 2. Tracker now uses MIME types for opening documents, for document drag & drop handling and opening.

You can now only drop a document on applications that support a given MIME type, (file type). Each application can specify one or more file types it supports, it can specify a group of types, it can specify that it supports any document.

Let me show you real quick.

I have a whole bunch of files in this folder and I have a whole bunch of applications in the folder here, I can grab a text document. And I'm going to try to drop it into a terminal. As you can see the icon does not highlight because Terminal does not actually actually handle text documents. StyledEdit, Eddie, BeIDE and Pe on the other hand all support text documents as well as HTML files. You can therefore see their icons highlight when you drag a text document onto them.

We will cover this in more detail later on. We understand there is going to be a bunch of applications that won't have their file types set up properly while still being able to open documents. And we didn't want you to have to go through the hassle of changing or fixing up an application just to be able to open a document.

So we built in a secret shortcut that can override this behavior. You can hold down the Control key while dropping a document onto an application that doesn't have the file type set properly and it will ignore the supported file type list and open as if it was supported just fine.

We have a new OpenWith feature. In the Tracker you can now select a document and bring up a menu that lists all the different applications that can handle the document.

You can also bring up a window with the same applications, all are sorted hierarchically with the preferred application, which is the application that would normally open the document if you double clicked it, at the top. And the OpenWith window actually shows a relation between the document and the application. So let's look at that real quick.

So I'm going to take this this text document again, and I'm going to click on it to bring up the contextual menu, and bring up the new OpenWith menu. As you can see there is a bunch of entries here. They are all sorted in different groups. You can see I have multiple copies of Eddie here, I have StyledEdit at the top, which happens to be a preferred application for text, but I also have other applications that can also run and open the document. I can go ahead and choose any of them to open the document. I'm not going to do that right now, instead I'm going to invoke the open with menu item here. It brings up a window, with the same set of applications. The applicaitons are sorted in the same manner, but you can see that the window includes a column that is titled Relation. It describes how the application handles the given document.

Up here you can see next to the StyledEdit entry that it's the preferred application for the document I'm trying to open. And the other apps claim they can support "Text File" (short description for "text/plain"), the applications in the group down here claim they can support "Any text file", so it might be HTML or some other type of a text file. And I have two apps down at the bottom of the list that claim they can open any file there is. I can go ahead and pick, let's see, BeIDE here, and I can say hit Open, or just double click it. I can also hit "Open and Make Preferred", which will not only open the document with BeIDE but it will set BeIDE to be the preferred application for this file type. So the next time I double click a text/plain document, it will open with BeIDE.

Extra Attributes are our next topic.

We supported extra attributes in Tracker in PR2, and in fact we supported them since the AA release. You can use them to display all sorts of different data in Tracker windows, you can customize a file type to have special attributes attached to them using either of the FileTypes application or using your own code, calling the BMimeType API. Release 3, extends the type of attributes you can actually edit and display in the Tracker. It used to only be strings, now it's also time and all sorts of scalar types such as floats, ints etc.

You may know that extra attributes are already heavily used for displaying e-mail, queries, People files, bookmarks, and you, as a developer, can take advantage of them and can use the Tracker to display some data you are using in your application, you don't have to write the visualization code yourself, instead you can use the Tracker to show it.

With the combination of scripting that I'm going to discuss later, you can integrate an application with Tracker and just leverage some of its functionality. So let's look at an example of using extra attributes. I'm going to create a person file. I'm going to call it Hiroshi. And I needed a new folder for People.

Now I have a file called Hiroshi. You may know that a person already defines a bunch of extra attributes that I can turn on in the attribute menu, I can edit them, that's not a new thing. But what I'm going to do here, though, is I'm going to modify a person mime type and I'm going to add some more attributes to it.

So let's see, weight might be of interest, it would be a float, and let's see, maybe a birth date. And that will be of type time. So back to my folder here that I had Hiroshi in, I can now turn weight and birthday on, and maybe I can get rid of the size attribute, it's not so relevant, I can get rid of creation date I can edit weight... I still don't know how pounds work, I will just use in kilos here. This is new in R3 and you can take advantage of it to show some data you might be using in your application.

There are actually apps out there that use extra attributes. I'd like to mention Andrew Kimpton's application, I believe it's included in source code in BeWare. He is using Tracker to show all the different data that he retrieves from a Palm Pilot.

Next feature that we have in the Tracker is a little, not a whole lot, but a little bit more of the drag and drop support in Tracker. We now create Text Clippings, the Tracker creates a clipping file when you drag and drop a text file onto the desktop. You can have the Tracker give it a specific name, you can customize the name to add some meaningful information that represents the drag and drop text. We are going to have more drag and drop support for the Tracker in R4, with probably an open ended API.

So let me show you ane example real quick, I will open StyledEdit and I will type something. A different font maybe, and I will drag it and drop it right here onto the desktop, and I don't know if you can see this, on the desktop, but it says "clipping from untitled 1," where untitled 1 is the name of my document, so it actually used the name of the document in the clipping file because StyledEdit told it to. I can do the same with Eddie. I'm going to clip some text from an eddie document, and drag it onto the desktop, and you see Eddie thinks the clipping file should be called "Code Snippet", because it's a programmer's editor and it thinks it's some code.

In R3 folders may now have preferred applications. You can take advantage of that, you can for instance have an e-mail reader, you can teach an e-mail reader to handle opening a folder by showing an email inbox, which is represented physically as a folder on your disk, and you can view it with some other fancier way than Tracker does right now. Even if you have a preferred handler set for a folder you can still open the folder using the OpenWith feature I showed you before. Let's try that.

I have this folder, I was using the files from before, I'm going to use FileType add-on, and I'm going to set the preferred application to be Eddie, and when I double click on it, it's in fact opening Eddie. Eddie is not very sophisticated about opening a folder, all it does is bring up an open panel set to the directory I just asked it to open. You can use OpenWith, and ask the Tracker to open the folder, and it will do the usual thing.

So that was a bunch of demos of some new Tracker features, now let's talk a little bit more how you can use them in your apps, let's show some real code here.

I mentioned Text Clippings, I told you already before that your application can suggest to the Tracker what name the clipping file should have when it's created by the Tracker. It's in fact real easy to do that.

We have an example here of some text engine that has a call InitiateDragMessage, and here is some code that you would have from before, creating a drag message, you would be stuffing it with some plain text, and the new code here is you that add string "Code Snippet", you saw Eddie how it asked the Tracker to call clipping files by that name. You then send the DragMessage to deal with it and indeed when the Tracker receives the DragMessage it will see the name in there and it will call whatever clipping file it creates by that name. So that's pretty easy to support.

And I have another example here, if you are using BTextView there is already a convenient call for available you, virtual function call GetDragParameters. I'm actually showing code from StyledEdit here, I just copy-pasted it into a slide and I hope I'm not giving any secrets away. We call the overridden GetDragParameters, StyledEdit embeds not only text but also styles this inherited call does all this for us. You just construct a name for the clipping file, it's a little bit more elaborate than I had in the previous example, you use the actual window title and again you add it as a string to the drag message and it gets handled appropriately, calling the resulting clipping file, clipping from the name of the document it originated from - the name of the window it originated from. So if you are using BTextView you can just add support by overriding this call.

How do you support OpenWith properly? Well, OpenWith relies entirely on file types and MIME information. You have to make sure your application has all the file types set up properly; if you don't do it, the MIME police will get you. Typically you would list specific types that your application supports, that it opens, saves, you can use supertypes such as "text" to support an entire group of files. If I have a video editing application that has a plug-in architecture that can read any sort of video file, you include the whole group "video" as a supported type and the video application will be able to not only accept drag and drop of video files but it will also be suggested to you as an OpenWith candidate, in the OpenWith window.

You can also have applications that can open any file type, no matter what its type is. To do that (we call these applications super-handlers) include the type "Generic Text" (aka application/octet-stream), that way if an application has this type listed as its supported type it can open a document of any type.

We are using that in two applications, Release 3 FileTypes that can set a type in any document, kind of makes sense, and this new application that can open any file and show it as a hexagram.

You can do that yourself for your apps, but you should think twice about doing it, you have to make sure that it actually makes sense for your application. To be a super-handler, you have to ask yourself whether it can actually handle any file type in the world or whether you only want to restrict it to a certain group of types instead. It's a sacred privilege to be a super-handler, and if you abuse it, the user will deal with you. They will get rid of your application, it will annoy them because it will keep showing up in the OpenWith menu and the OpenWith window, it will most likely end up in the trash.

Let's look at this a little bit in detail. Let's open NetPositive in FileTypes. So I have a copy of NetPositive here, that...

A Speaker: You haven't made the folder.

Pavel Cisler: Okay. So this is what we will do. I have a copy of NetPositive here that I hacked before, I removed a file type from it. I removed the "text" group file type, and as you can see, NetPositive now cannot open any of these text/plain documents.

However I can still open HTML (text/html) files. Let's open NetPositive in FileTypes again and look at why this has happened. You saw that I was able to open HTML files. Indeed NetPositive lists HTML as one of the supported types right here, but that's it as far as text files go. But NetPositive can in fact open any text file without problems. So what I'm going to do here is I'm going to add "text", you can see I am selecting the whole supertype, into NetPositive. Save it and let's see what happens now. I'm going to grab one of these text files again and open it. I will drop some source code on NetPositive too. Opens filne

So if I grab an application such like People, and I try to stuff it into in any of these applications, it won't open it except for FileTypes because FileTypes is a super-handler.

Let me open FileTypes in FileTypes and you can see that it lists "Generic File", (short description for "application/octet-stream"), which makes it a super-handler, which in turn makes it open any file. Let's look at OpenWith for a moment again.

Let me try to do something else, let me open a text file here and you can see FileTypes is included, offering to open the document, because it's a super-handler. In fact you will see it in every open with menu/window because of this.

Let me do one more example of OpenWith and how it relates to setting up FileTypes in our application. I just sked Tracker to do an OpenWith on a source code document. And you can see that BeIDE is a preferred application for source code, there is a whole bunch of other programs such as Eddie, I have two copies of Eddie here, Pe is Programmer's Editor, these two are suggested as handlers for source code, but you can see here in this group underneath NetPositive shows up and you know that I added the whole group "text" and that's why it appears there. It is kind of more relevant for a Programmer's Editor that specifically lists "text/source-code" as a more suitable handler for the document I'm trying to open. It's almost irrelevant for FileTypes to open, so that's why it appears at the bottom of the list. By including the right supported file types into your application, you can finely manipulate the order in which the application shows up in OpenWith.

We added a lot of scripting features to the Tracker. Right now the scripting suite is somewhat incomplete but it has enough features to allow you to integrate e-mail style applications. The things that scripting in the Tracker lets you do right now is iterating through a window for files, you can for instance ask the Tracker, "give me the next file", given a file you have already opened. You can manipulate a selection, you can add or remove from a selection. You can open a specific file, in fact you can execute a file or folder, execute it and it will open it, the same way as if you double clicked it in the Tracker. You can move specified files to the trash.

So what we are looking for is you guys out there who write e-mail apps, if you don't want to spend a lot of time working on implementing a list view of e-mail, an inbox style view, you could actually integrate with the Tracker to display an inbox the same way as BeMail does right now but you can improve the work flow by adding features like "Open the next e-mail in the same window", "Open the previous email in the same window", or "Delete this e-mail and open the next one". The scripting will now allow you to do that.

I'm going to try to show that real quick here. Using the doo tool, which is our internal scripting tool by Peter Potrebic, there are other simmilar scripting tools out there. I think there is a tool called Hey, which is pretty much the same as doo.

By the way, I have this test folder right here. Here is a question; does anybody know what these files are about?

A Speaker: I can't tell.

Pavel Cisler: All right. Anyway.

A Speaker: What were they?

A Speaker: Vacuum tubes?

Pavel Cisler: Vacuum tubes. I like this audience.

So I'm going to try these scripting examples real quick. In practice from a Be mail style app you would use actual code, you would build a scripting message and send it to Tracker. But this is easier to demonstrate. So I can ask the Tracker to count all the entries of Poses, and Poses is the entity in the Tracker window that I will be talking to, of the window test, if this works.

So it told me that I have five files in the folder, seems correct. I can get them all. And you can see it will enumerate the paths of all the files in the folder, all the tube names are there.

By the way, I'm using Eddie here, it has a worksheet, which works like a Terminal shell. So that's what you are seeing here. I can get the Entry number 2, so count with me, 0, 1, 2 which happens to be '6L6', you can see I get the correct answer. I can actually swap the sorting order by changing the sorting from the Tracker menu. I will do it the same example again and it will return a different file this time, 5881, which now has index 2 in the current sorting order. This way we can actually add and subtract from a selection, iterate a folder in the sorting order it currently uses. I can count the selection.

Right now I don't have anything selected, so I better select something. So let select entry with index 2. That's what I selected. I can get the selection again, by using this scripting command it will enumerate it, I can add to the selection, subtract from it, delete an entry. I can add, subtract to execute an entry. Remember I said execute means the same thing as double clicking. It will actually open the file in the preferred app. So let me delete the file with this next command. It's gone, it's in the trash.

A Speaker: Why are you calling it test/6L6 when you are already saying it's called window test?

Pavel Cisler: Because that's the directory I'm in here, which contains directory test. I'm specifying the full path name of the entry here. I have two options of specifying an entry. I can either give it an index or I can specify the entry's path. I'm using the partial path in this example.

A Speaker: Why do you need the window test then?

Pavel Cisler: Why do I need it? Because I'm talking to the window in the Doo tool.

A Speaker: That's what we are trying to get at.

Pavel Cisler: Okay.

A Speaker: Shouldn't it be 6L6 Window Test, shouldn't that already implicitly...

A Speaker: No, because he is not in that directory, he is in the directory above that.

Pavel Cisler: I'm talking about two things here. I'm talking about the entry, which is... even if I had multiple windows showing this entry at the same time it would be the same entry, but I'm also talking about a window which has the state containing sort order and other things, for example if this was a query window I would be... I would have the same result. So I'm taking advantage of the window in that it gives me the sorting order. The sequence of iteration that I want to use in like an e-mail style application for the inbox, right? That's why I'm specifying the window.

I could have it open, like I said, in query window, and it would be the same file, but a different sort order. So. And you are going to be doing this automatically, so it's not going to be a big deal because you are just pass...

A Speaker: What would happen if you had two windows called test?

Pavel Cisler: Right now it will get confused. I guess.

Peter Potrebic: But again remember this is just the example of the doo tool. In your program you would know which window you were really wanting to talk to, not by some stupid name, but by your code.

Pavel Cisler: I don't want to get too deep into scripting, there will be at least, I think, two or three more sessions about it, where the mechanics will be explained. Right now all that I want to say is that this set of commands specify the handler that receives the scripting message, and in your application in your code you will typically be talking to a BMessenger that you get from the Tracker to identify the window. So it's not going to be a problem, you will be able to deal with two Tracker windows that are both called Test, and you will be able to identify each of them.

So let me go through the rest of this real quick since we are running out of time. I showed you how to execute, I can set the selection to a range. You see it selected from index 0, it selected two files as specified. I can set the selection to a file, I can create a selection, which is sort of a fun way of asking the selection to add something to itself. So you can see I added the file to the selection, now I have two files selected. Clearly this is just a subset of scripting support, even though a usefull one. We have more scripting calls already and we will have more in the future, and if you need a specific scripting call that is not covered in the current release, let us know and we will add it for you in R4.

So the last thing I wanted to talk about a little bit is Tracker add-ons. Tracker add-ons have been covered a lot in articles and in our newsletter, they are real easy and fun to write. All you have to do to be a Tracker add-on is instead of a main call have a process_refs call that receives a list of entry refs, a list of files that are selected when you invoked Tracker add-on, and the entry of the folder in which you invoked the add-on. I prepared an example of a Tracker add-on for you today. There is actually a similar Tracker add-on on BeWare by Chris Herberoth, but it is kind of a nice and simple example to show you here.

So let me show you the code. First of all, what does the Tracker add-on do? It's a set permission style add-on, you can open the file and set its permissions from the add-on.

As I said, you have a process_refs call that gets a list of entry refs in a BMessage, you iterate through the entry refs, on each of the entry refs you open a permissions window, which let's you edit the permissions.

The permissions window, I'm not going to go through the code in detail, but it basically puts up a number of check boxes for all the different permissions and then it looks at the entry ref, gets its permissions and stuffs the check boxes with the values of these permissions, then it adds an OK and a Cancel button.

The MessageReceived call: If I press the Okay button, it looks at all the check boxes and sets permissions on the entry ref, if I press cancel it just closes the window.

Now let's try to do that.

Okay. So I'm going to compile this. (Puzzled...) That was quick. (Realizes...) It's the machine! Wow. We have slower machines at Be because that way we have more of an incentive to make BeOS perform faster.

I'm going to install the add-on that I just compiled in the Tracker Add-On folder. And I'm going to use a symbolic link, which is another thing that works on now in Release 3, and I'm going to try the new add-on. You can see if it shows up in the addon menu, yes! Run it and I have the permissions window and I can set the permissions.

So that was easy.

There is a pitfall that has been happening to developers that we didn't mention before. If you have some user interface code in your Tracker add-on, and for instance you put up a window like this, your Tracker add-on will crash mysteriously if you have a code sequence like this. What happened? - You put up a window here and you do a Show on it and you return from the Tracker add-on. What happens is as your process_refs returns, the Tracker add-on gets unloaded from memory right when your MySuperTrackerAddonWindow code is executing and there is no code to execute, so it crashes. There is a simple fix.

What you have to do is you wait for the thread of the window that you just showed, using wait_for_thread, and that's going to take care of the problem.

This is just a little problem people were running into.

And the last thing I wanted to talk about is that you can have a Tracker add-on with a dual personality, it can be an add-on and an application at the same time. Just by adding a main you can have the same binary behave as both. That's kind of a neat thing to do.

Let's do that in our example here. This time you will see it actually compiles. I have got this code here that I'm going to turn on. I have a new main call here, all it does is it calls the simple SetPermissionApp class, which is a very simple override of the BApplication. All it does is it overrides RefsReceived and again it iterates through all the entry refs it gets and runs a permission window on it after which it does a show. This time I don't need to wait for the thread to finish. Let's compile that. (Puzzled...) Oh, what's going on here? I didn't save it, let's try this again.

So I have to manipulate the FileTypes before I use it first. Let's say we make it a super-handler, right? It's a permission editing app. Makes sense to make it handle any type. Let's see if it still works as an add-on. It still does. And how about if I drag and drop a file? See, it highlights because I made it a super-handler and it opens the file I dropped it to.

So that's it. Thanks for suffering through this, and do you have any questions? (Applause.)

A Speaker: I have a question about the Tracker. What if you don't know the types of files you need to open?

Pavel Cisler: That's a good question.

A Speaker: Repeat the question, Pavel.

Pavel Cisler: I'm sorry. The question is: What if you do not know the file types you can handle? Is that exactly what you asked? And I assume you are asking about like if you have an plugin filter architecture.

A Speaker: Or like if you use Datatypes.

Pavel Cisler: Right. In general if your application focuses on translating an area of types, like if it's a video converting app, and it understands all sorts of video import and export plug-ins, so you would include video as the supertype that it handles and you can drop any video file. There are applications that can convert probably "video" and "image" and maybe "audio", so you can list all three supertypes in the app and if it can just translate anything in the world, you will make it a super-handler by including generic file.

A Speaker: I guess you have to go to the... you have to put up with (inaudible)...

Pavel Cisler: That's a good point. If you don't support the given file type, it won't let you drag and drop a document on it.

A Speaker: Right.

Pavel Cisler: I see. So you mean if you actually list the video supertype, the whole video group but you don't have a plug-in for a certain video type. Yes, you have to do a second level checking, you have to do that in any case because there are other ways to bypass the mime based checking.

A Speaker: Sort of an exception to MIME release?

Pavel Cisler: What's that?

A Speaker: Sort of an exception to MIME release?

Pavel Cisler: Yes. I guess. Any other questions? Wow. Okay, thank you.

(Applause.)