Monthly Archives: January 2009

Setting Mac Office 2008 default save formats

Microsoft Office 2008 for Mac uses the new Office Open XML formats by default which is a pain in an office where many staff will be using previous versions for some time.

You can easily change the default save format within the preferences for Word, Excel and PowerPoint, but the simplest thing when deploying Office 2008 to a whole bunch of machines is to set the default format once and have every user pick up that setting.

Fortunately Microsoft Office 2008 uses the system defaults database and even honours preferences from the Library domain.

Here’s the preference files in /Library/Preferences for Excel, PowerPoint and Word:

computer:~ david$ ls -al /Library/Preferences/com.microsoft.*
-rw-r--r--  1 root    admin  256 29 Jan 14:21 com.microsoft.Excel.plist
-rw-r--r--  1 root    admin  301 29 Jan 14:21 com.microsoft.Powerpoint.plist
-rw-r--r--  1 root    admin  257 29 Jan 14:14 com.microsoft.Word.plist

Contents of the Excel plist to save in Excel 97-2004 Workbook (.xls) format by default:

computer:~ david$ cat /Library/Preferences/com.microsoft.Excel.plist 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>2008\Default Save\Default Format</key>
    <integer>57</integer>
</dict>
</plist>

I wonder what the significance of 57 is… Probably meaningful in hex or something.

PowerPoint plist to save as PowerPoint 97-2004 Presentation (.ppt) by default:

computer:~ david$ cat /Library/Preferences/com.microsoft.Powerpoint.plist 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>2008\Default Save\Default Save\Default Format</key>
    <string>Microsoft PowerPoint 98 Presentation</string>
</dict>
</plist>

Word plist to save as Word 97-2004 Document (.doc) by default:

tfg02215-2:Preferences dbuxton$ cat /Library/Preferences/com.microsoft.Word.plist 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>2008\Default Save\Default Format</key>
    <string>Doc97</string>
</dict>
</plist>

Let’s create these all using the defaults command in one go:

defaults write /Library/Preferences/com.microsoft.Excel "2008\Default Save\Default Format" -int 57
defaults write /Library/Preferences/com.microsoft.Powerpoint "2008\Default Save\Default Save\Default Format" "Microsoft PowerPoint 98 Presentation"
defaults write /Library/Preferences/com.microsoft.Word "2008\Default Save\Default Format" "Doc97"

Sweet.

Now any new user on that machine will pick up these preferences and will use the old formats by default (but can choose to use the new formats by changing preferences if necessary).

Ignore the docs, use ‘value’ to set value in jQuery.UI.progressbar

The online documentation for the progressbar plugin for jQuery.UI says to use “progress” as the keyword when setting the value of your progress bar, something like this:

var percent = Math.floor(data.received / data.size * 100);
$("#upload-progress").progressbar('progress', percent);

It doesn’t work. At least, it doesn’t work with the 1.6rc5 release. The correct keyword for setting the value is “value”:

var percent = Math.floor(data.received / data.size * 100);
$("#upload-progress").progressbar('value', percent);

The documentation doesn’t mention the default range of values for progressbar, but it is from 0 to 100. Actually the docs have all this stuff about showing custom text and the numeric value in the bar and that doesn’t seem to work neither.

In a way this small imperfection makes me admire jQuery even more. And this post is a kiss on her cheek.

I’ve filed a bug! #3871 on jQuery.UI’s Trac.

Using screen to log a terminal session

Note to self: use screen when doing a bunch of remote administration stuff over an SSH connection. You can tell it to log the session to a separate file, and can detach the session and log off without having the remote shell be terminated. Then later you can resume the session and haven’t lost anything.

To start a shell and log everything to a file, do

screen -L -S mysession

That drops you into a new shell, and lets you refer to that session later (in case you are ambitious and have many screen sessions running simultaneously). To detach the session type CTRL+a then d. From there you can exit cleanly. To resume the session later, type

screen -r mysession

The session history will be saved to a file named screenlog.0 or similar in the directory where screen was first invoked.

screen man page online (Hmmm… looks like the hmug man pages have renamed themselves.)

I should use screen more often. I should also get in the habit of going through the contents of $PATH every time Mac OS X gets updated.

Using separate forms for adding and changing in Django’s admin

The Django documentation describes how to override the form class used by the admin site when adding or editing your objects. It is easy, you just specify a form attribute on your ModelAdmin sub-class, and point it at your custom Form or ModelForm class.

But there is no documented method to specify one form class for creating an object and a different form class for editing an object.

My solution is to override the get_form method on your ModelAdmin sub-class. When adding an object, ModelAdmin will use the add_view method, whereas when changing an existing object ModelAdmin will use the change_view method. You could override the add_view method and specify a different form class there, but you would need to handle the entire business of object creation, including checking the client has permission, validating the form instance and populating the template context. Django’s auth application takes that approach for adding a new user, providing a simple username / password form in place of the full-blown object form.

A simpler method is to override get_form. When changing an object, get_form is called with the optional argument obj set to the object instance. When adding an object the obj argument is None. This makes it easy to determine when to return a different form for adding versus changing.

Here is an example of how to sub-class ModelAdmin and override the get_form method to return a different form depending on whether the client is adding a new object or changing an existing object.

# admin.py
from django.contrib import admin
from forms import MyAddForm
from models import MyModel


class MyModelAdmin(admin.ModelAdmin):
    """A ModelAdmin that uses a different form class when adding an object."""
    def get_form(self, request, obj=None, **kwargs):
        if obj is None:
            return MyAddForm
        else:
            return super(MyModelAdmin, self).get_form(request, obj, **kwargs)


admin.site.register(MyModel, MyModelAdmin)

Note a certain amount of hand-waving in the example where I’ve assumed that the appropriate models and forms are defined elsewhere. The custom form class will need to be a sub-class of ModelForm (or at least implement a suitable save method).

Avoiding the config menu when installing a FreeBSD port

Note to self: if you want to install a port from the FreeBSD ports collection and you want to avoid the configuration menu that some ports use, then set the BATCH build variable.

For example, to install Apache 2.2 with the default configuration, use this:

cd /usr/ports/www/apache22 && make BATCH=1 install clean

Handy for scripting. More detail in the FreeBSD porter’s handbook