a glob of nerdishness

December 3, 2007

Hacking Stacks: A Failed Attempt

written by natevw @ 10:18 am

I’m pretty much enamored with optica-optima’s DRAWERS icons for Stacks. The concept, the icons, even the disk image they come in. Imagine my horror when my first subsequent download plopped itself right on top of my wonderful new “drawer”, once again shattering the illusion that I could like Stacks. “Date Added” is not a ‘touchable’ file property — the Dock somehow keeps track of this itself. Googling revealed a folder action based fix, but I wanted something that could be done automatically for all Stacks present and future. Poking and prodding revealed that I could sqlite3 ~/Library/Preferences/com.apple.dock.db and look at the fairly simple database the Dock uses for Stacks.

There’s a “directories” and a “files” table. The directories table has one row per stack, and just one main “path” column (it also has an sqlite3-implicit ROWID used as the directory_id elsewhere. The rest of each stack’s info is in the Dock’s plist). The files table had what I was looking for: an “ordering” column. So I added a drawers table, and inserted rows for each beautiful icon:

CREATE TABLE IF NOT EXISTS drawers (directory_id INTEGER, filesystemid INTEGER);

INSERT INTO drawers (directory_id, filesystemid) SELECT directory_id, filesystemid FROM files WHERE name LIKE ' %'; -- this should be a trigger for future additions, but see results....

Then I added a trigger so that whenever a new file is added to a stack with a drawer icon, the drawer’s icon would still have the highest “ordering” value:

CREATE TRIGGER drawer_defender AFTER INSERT ON files
 UPDATE files SET ordering=NEW.ordering+1 WHERE directory_id = NEW.directory_id AND filesystemid IN (SELECT filesystemid FROM drawers WHERE directory_id  = NEW.directory_id);
-- if BEFORE INSERT, the new row doesn't show up at all for some reason

CREATE TRIGGER drawer_cleanup ON files AFTER DELETE ON files
 DELETE FROM drawers WHERE drawers.filesystemid = OLD.filesystemid AND drawers.directory_id = OLD.directory_id;

The bad news is that while this works as far as the database is concerned, the Dock seems to keep track of the ordering itself until you “killall Dock”, which puts us right back in folder action territory with an even uglier transition. So unless somebody finds a way to get the Dock to read in the database without getting killed first, or Apple’s usability team regains a say in what prominent features get shipped, it looks looks like the sleight-of-hand folder action is still the best bet for helping Stacks out. That method has the added advantage of not requiring users to tinker with private Dock internals as well, which is probably a good thing.


  1. I should note that to clean up, simply:

    DROP TRIGGER drawer_defender;
    DROP TRIGGER drawer_cleanup;
    DROP TABLE drawers;

    …though if you wouldn’t have figured that out yourself, I very strongly recommend against setting up those tables/triggers in the first place. Caveat hacktor.

    Comment by natevw — December 3, 2007 @ 10:35 am

  2. I did have success using:

    on adding folder items to this_folder after receiving added_items
    	do shell script "mv ~/Downloads/' Downloads ' ~/DLIcon"
    	do shell script "mv ~/DLIcon ~/Downloads/' Downloads '"
    end adding folder items to

    saved from Script Editor to /Library/Scripts/Folder Actions Scripts/RefreshDownloadsDrawer.scpt and enabling it on the Downloads folder.

    Comment by natevw — December 5, 2007 @ 11:25 pm

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.