Songs of Doom

Archive for the 'Psi' category

Psi under new^h^h^h^h old management

10:16 pm

A copy of an email I just sent to the Psi development list:

Hi all,
After a few days, I’ve given up doing a long and explanatory post.
After four and a half great years of Psi, I know that I don’t have the
energy for running the project that I had back in 2004 when Justin
handed over to me. Fortunately, Justin is recharged, active again, and
available to continue his calling as project leader, so I’m handing
project leadership back to him. I won’t be going anywhere, so please
feel free to contact me about Psi things, and maybe I’ll even have a
chance to write some code again, I’ll certainly still be around the
XMPP world doing some new and interesting things :)

Thanks to everyone for their support over the last 4 1/2 years in
allowing me such a rewarding role.

I hand you now to the new project leader of Psi … Justin Karneges.
Good luck to Justin :)

Why I /do/ document and unit test

6:17 pm

I’ve just read Justin’s Why I don’t document or unit test post that explains the way he works, so here’s a counterpoint from the way I work. I’ve inherited not documenting and not unit testing from Justin for the Psi project, where it’s fairly hard to change, and at my day job I unit test and document quite a lot, so I’ve worked with both approaches – this post mimicks Justin’s, as I would have written it – it will only make sense immediately after reading his article.

Why I document and unit test

I write documentation and create unit tests, because they’re great things. Software projects are, almost universally, written to address a perceived problem, and fail if they can’t address this need, so they need to be tested. Similarly, very little software is write-only, and if someone needs to read it, it needs to be understandable; it needs documentation. Not all projects satisfy these criteria, but those that do are successful and fun to work with. Maybe that’s because you have some degree of certainty that your code does what you want it to, maybe it’s because you can stand straight and say “I did what I thought was best” and not feel guilty, maybe it’s because you can show your code to people and not have to make excuses, or explain what your method ‘doSomethingWithSideEffects()’ does, maybe it’s because your unit tests caught a critical bug that you just know would have taken you days to find in 6 months without them, maybe it’s just a matter of pride in your craft as a developer. Tests are particularly gratifying – when they pass you can move on, and when they fail you save yourself a lot of heartache (and headache) in the future.

Or maybe it’s because documentation and tests add such huge value to everything else that you’re doing. I’ve worked (and continue to) in both professional and open-source environments where code is unit tested and sufficiently documented – I suspect that it takes a brave person to notice that an undertested, underdocumented project is a well of unproductivity and to invest the manpower to turn it around, usually in the face of considerable pressure for more, more, more, now, now, now. On the other hand, I can’t imagine any type of person who’d deliberately go the other way. I think the biggest problem for a lot of people is legacy – it’s hard to update your practices when you’re knee deep in code that’s certifiably untestable, but I never hear those that do as much as they are able to do complaining about the results.

Deferring documentation and testing is a misguided attempt to get the most bang for your development buck this morning by sacrificing your productivity this afternoon. By the time this afternoon comes, you find yourself wondering why you don’t have the time anymore to be productive. It’s easy to be lazy about these things if you don’t believe in them, but if you don’t believe your code is worth testing are you saying that you don’t believe the code is worth writing? If it’s worth writing something, surely it’s worth writing the right thing. Do you find yourself saying that you don’t want to add features now because you’re going to rewrite it later? How bad must the code quality have been for you not to trust yourself to add a new feature without breaking something? Yes, there is an overhead writing code that can be unit tested – that overhead is the overhead of writing code that works. If you find yourself resisting testing, is it because you know that your code is broken, but you can’t bear to find out how badly? Would unit testing your code show that you wasted a lot of time that could have been saved if you’d written the tests before? If you do fall into this trap, then you’re going to have a hard time getting out of it, because you’ll be wondering how much time you’ve wasted. Ostrichs aren’t the only creature that (mythically) can bury its head in the sand.

I document my code, because I like my design

Do you find yourself writing a big paragraph of Doxygen, or Javadoc comment for your method? Why? Shouldn’t your method name tell you what it does? Shouldn’t your method parameters’ names, plus their type (if such is your language) tell you how to call it? If not, why not? If your method is called “addTwoNumbers(int num1, int num2)”, you shouldn’t be documenting to say that, by the way, it also resets some internal mutable state; if you need to put that comment in, the smart money says that your code’s broken. Why bother spending the time with sensible naming and self-documenting code when you don’t even know that you need this method? Back up a minute – why are you writing this method if you don’t know that you need it yet? Yes, requirements for a project change (and we embrace those changes, as Agile developers), and if code goes out of (project) scope, we’re glad that our methods were small, single-responsibility methods so we don’t spend time splitting out the functionality we don’t need from that we do. We’re also glad that we wrote no more code for that requirement than we were sure that we needed.

It happens in software that you have to refactor stuff. That’s just the way it goes. Requirements are never right first time, but at least we know that, and we keep checking them with the users of the system, and the users of our methods, as appropriate. When you know that your requirements are going to change, you have no business writing code that’s going to be hard to refactor, or code that doesn’t need to be there. You had your requirements from your user, and turned those into the minimal API requirements for your code, wrote your unit tests to assert that the minimal requirements are met, and wrote the minimal code to satisfy the tests, and therefore the requirements. You really don’t want to be committing to such a heavy design up front that it’s going to be a hassle to update it.
As the saying could go: code that needs documentation is worse than wrong documentation, is worse than no documentation.

In general, if the code is such that other developers are able to tell you what your code does from the class, method and variable names, your energies are being well spent.

I test, because I care about my implementation

And I always care about my implementation – you do too, or you wouldn’t be so far down this gargantuan post. There’re only three reasons that immediately come to my mind why you might not care about your implementation:

  1. You hate the task that your code is written for. This is going to be a problem if you’re captured by an evil genius, ideally with a cat, and are working on an advanced intelligence, or orbital laser platform, to be used to enslave all mankind, but for most of us this doesn’t apply.
  2. You simply don’t care about the result. You’re demotivated, and if it doesn’t work then it’s someone else’s problem to solve, the testers will pick up the problems and you’ll be on holiday when the bug reports come in. This isn’t you.
  3. You do care about your implementations, but you don’t know how to do a job you’re proud of, so you tell yourself that you don’t care about them as a self-preservation mechanism. This may be you, it’s been most of us. Thankfully there are smart people who’ve written books giving advice on how to be a better developer. In fact, titles like Agile Software Development, Clean Code, Extreme Programming Explained, and The Pragmatic Programmer make this post redundant – read them and save yourself reading the rest of my post. Books may not make you smarter, but they’re not going to make you a worse developer.

It’s possible to get tied up with design, and delegate implementation to being a second class entity. Think about this for a moment. What’s design, and what’s implementation? When class A calls a few methods on class B, what is that code – design or implementation? It may be a design for class B, but it’s the implementation of class A. Don’t get too hung up on which is which – generally the design is driven by the needs of the implementation. You know what methods class B needs once you’ve written class A’s method that makes the calls. Divorcing design and implementation is a great way to make sure your code isn’t going to do quite what it was meant to. I’ve done this, you may have done this. Live and learn. This is just another case of ‘code what you need’. If you only code what you need, you only test what you need (equally: if you only test what you need then you only code what you need).

Some people will start testing and find that they can’t test it all. If this is you, and you’re finding that your methods have side-effects that you can’t test, then you’re one of the lucky ones: congratulations! Your unit testing has found problems with your code even before you’ve written your first line of a test. There is a definite desire for mutable objects (objects whose state can be changed through method calls) – certainly, Java code would look very different if ArrayLists were immutable, but this doesn’t mean that your objects should be mutable. In the rare cases where your object /does/ need to be mutable, make it explicit: don’t have a method that does one thing superficially, but also changes state. Oh, and don’t make classes such that your objects can get into an inconsistent state, either – a common example of this from my past is constructing an object, but requiring another ‘set’ method call before the object is usable. I kick myself when I wonder why I didn’t pass the value in the constructor. If you can’t unit test your code, you probably need to reconsider your approach. The obvious counter to this is a dependency on external state (particularly databases, or networks) – unit testers get around this with mock objects that look like the external state object, but are deterministically controllable from the tests, and you can easily fall in love with them very quickly.

In general, code that works will continue working if you don’t touch it. Psi’s a great case in point – if it didn’t consist of a majority of working code, then nobody would use it. It hasn’t traditionally had any unit tests, and that’s taken its toll on development – development cycles are long because no-one dares to refactor the code to support new features, and once the features are in, release candidate cycles are typically even longer because it’s difficult (and demoralising) to hunt down the bugs that have been introduced, especially when the bugs often cause crashes in unrelated code, due to mutable objects. Until we build up adequate tests, the cycle will continue, as people spend their energies on new features, avoiding fixing bugs that’re difficult to reproduce, or are in code that is perceived to be risky to modify. That doesn’t mean that Psi’s buggy, or that it will become buggy – we don’t leave the Release Candidate phase until we have reasonable confidence that we’ve got all those bugs out, and we do a pretty good job of it (I hope). It’d just be nice to not need to introduce them, or spend so much time in RC getting rid of them.

There are no exceptions (almost)

It’s easy in the early stages of a project to neglect testing, or to write code whose behaviour isn’t obvious, but this is the greatest of false economies – when your early code doesn’t work, your later code isn’t going to work. It’s also easy to slip into the mindset that unless you can get complete coverage now you shouldn’t test at all. If, for some reason, you can’t get as much coverage as you want, every behaviour that you test is another bug that can’t happen.

About Documentation

Above, I claim that all code should be self-documenting. I stand by that – it should be obvious what code does from its method name and signature. That doesn’t mean that I believe code should never have a Doxygen comment, or a Javadoc – some people (that I respect) hold this opinion, and I may too, some day. At the moment, though, I can still see a value in a greater explanation in a comment, especially if there’s a business requirement that makes something non-obvious – you know the sort of thing “oh, yeah, all numbers must always be rounded up, 2.1 is really 3″. Why you have to do something, where it’s not obvious, is a great thing to document. If you have to document what you’re doing then you probably need to consider why it’s not obvious from your code.

Conclusion

Deferring documentation or unit tests is not always about laziness. It’s about efficiency. Note my usage of the word “defer” – someone else will need to understand your code eventually, and you’re going to need to do the testing, either manually or automatically, to make it work someday. You’re sacrificing your efficiency later for a tiny gain now. It’s clear to me that it’s necessary to prioritise the tasks with highest impact first, with your tests to ensure that they work, and to only put effort into the next features once all the problems with the first code are solved, and the probability of later needing to expend considerable effort fixing them, or being unable to modify them for fear of breaking them, is low.

Happy coding!

Here ends my version – thanks to Justin for providing the original as a talking piece, which gave me a chance to get some thoughts down on electrons that previously I hadn’t taken the time to express.

XMPP: The Definitive Guide – Rough Cuts edition

7:51 am

It’s been an exciting time recently for the “XMPP: The Definitive Guide” book that Peter, Remko and I have been working on. Just over a week ago, Remko announced the availability of the book in the Rough Cuts scheme, where you can buy a PDF of the unfinished manuscript to read now, and receive the full version when it’s ready. Then, earlier this week, Peter posted about our submission of the full manuscript to O’Reilly, ready for technical review. Now it’s my turn with the good news: O’Reilly have updated the Rough Cut of the book with our submission, meaning that there is a complete, current book on the XMPP technologies available.

There will still be changes to the manuscript as a result of reviewers’ comments, but we think this is now a text we’re happy to have available. O’Reilly have feedback mechanisms for Rough Cuts, so if you read the book and anything is unclear (or, let us hope not, wrong) please help us make this book something that can guide current and future developers in their work with XMPP.

XMPP: The Definitive Guide

Psi 0.12

8:50 pm

Say hello to Psi 0.12. Thanks to everyone involved in this or previous releases.

New in 0.12
– Multi-user chat windows now join one on one chat windows and can be opened in tabbed form, either sharing a window, or seperately.
– The roster search has been updated, and now triggers a filter when typing into the roster window.
– An XML ringbuffer is now used, allowing access to already received XML in the XML console.
– When resolving a name for new contacts, the full name is now used if the nick name is missing from the vcard.
– Auto-connect on wake is now an independent option.
– MUCs can now be bookmarked, and auto-joined.
– The old config.xml file has been dropped in favour of the new options.xml format – all options in Psi can now be configured from the Advanced options pane (no more hand-editing of config files is required).
– Vcard avatars are now transmitted for the benefit of legacy clients and servers not supporting PEP.
– A new diagnostics group is available in the help menu, to allow debugging problems with the QCA security layer.
– Launching several instances of the same profile on Windows and Unices with DBUS now behaves more sensibly.
– On X11, the taskbar should now flash on new messages for compliant window managers.

Downloads from http://psi-im.org/download/

Thanks, Psi

9:09 pm

I’ve been meaning to make this post for an age…
A decent number of people thank the Psi project, and that’s great; I get thanked more than most, I think, because I’m the one who gets to make the release announcements, and it looks like I do all the work because of this. These days, I write very little code, because I just try and keep the other things ticking over and bad things happen when I touch the codebase (and I never wrote that much code, anyway). Trying to spread around the thanks to the people who do the work, at least all the following guys deserve it. In no particular order:
Thanks Remko, Mblsha, Textshell and Machekku, our developers.
Thanks Justin, who despite leaving is still churning out code for us.
Thanks Hal, the webmaster.
Thanks Fritzy, for hosting our dev tools.
Thanks Jason, for graphics.
Thanks IceRam, for the windows installer.
Thanks AlekSi, Gislan and Senu, working on projects for GSoC this year.
Thanks MichalJ, who’s /still/ moderating the forums and making sure people get answers.
Thanks Joonas, who’s still working on his previous GSoC project.

Also, thanks to our numerous other code contributors, translators and packagers, who between them would make this post infeasibly long. You are not forgotten, however hard it is to make sure all the patches are reviewed and integrated, to give you a string freeze with as much warning as we should, or to give you long enough to run off builds at release time, and you’re all appreciated.

Thanks to everyone who hangs around the mailing lists, or the forums, or the muc being useful.

It’s nice to say thank-you sometimes.

If I didn’t thank you and you deserve to be, I’m sorry, and thank you.

Summer of Code ’08

9:15 pm

As summer 2008 approaches, students have been busy applying, the XSF has been busy scoring applications, and mentors have been busy preparing. It’s time again for Google’s Summer of code, a scheme to pay students to work on open source code for the summer, and hopefully for them to continue contributing afterwards. This year has been a good year for the XSF, and we had a good selection of strong applications. Congratulations to those students who made it through, and consolations to those students that didn’t make it into our limited number of slots – we hope you’ll contribute anyway to the great developer communities that make up the XSF.

Psi has been particularly lucky this year to have had many strong applications, and for the XSF to have assigned three of its six slots to Psi projects.

In no particular order:

Adam Czachorowski (gislan) is going to be working together with Remko on “Metacontacts support and various roster improvements for Psi”. Adam’s project will be looking at overhauling our roster support, to add many interesting features designed to make the roster more accessible, and less prone to its current verbosity.

Paweł Wiejacha (senu) is going to be working with me on “Themable WebKit-based Chat Dialogs”. Paweł’s project is going to produce a new, friendlier face for our chat windows. Not only will you be able to theme the windows with the same themes as Adium, Kopete, and Google Talk, but you’ll also be able to see extended presence information about your contacts, such as the tune they’re listening to, and their mood.

Aleksey Palazchenko (AlekSi) is going to be working with me on “Psi: Message history”. AlekSi’s project is going to address several shortcomings in our history system. Particular highlights of the plan are to support server-side history (XEP-136), to provide a much more usable GUI, and to log MUC history.

I’d like to take the opportunity to welcome our new contributors to the project, and wish them the best of luck for the summer. These are all projects with a high importance to Psi, and I’m hoping we can make major advancements in our usability.

Psi-0.12-RC2

8:55 pm

Just late enough in the day that people will believe this isn’t an April’s fool, the Psi team are delighted to announce the release of Psi-0.12-RC2, fixing all blocking bugs found in RC1.

Download sites are:
Mac: http://downloads.sourceforge.net/psi/Psi-0.12-RC2.dmg
Windows: http://downloads.sourceforge.net/psi/psi-0.12-RC2-win32.zip
Source: http://downloads.sourceforge.net/psi/psi-0.12-RC2.tar.bz2

If no issues are found, we’ll go gold in a couple of weeks.

Psi 0.12-RC1 released

1:07 pm

Hi all,
After only a little over four months since 0.11′s release, the Psi team are delighted to announce that we’ve got the first release candidate prepared for the 0.12 release. This is a great step towards a more regular release cycle, which we’re sure everyone will appreciate, but this does not mean that 0.12 will be lacking in the new and cool. Recognising that Psi’s user interface could be more usable at times, the majority of our changes for 0.12 revolve around usability. Please see the README for full release details, but probably the most important are:

Tabbed MUCs.
Tabbed chat has been very well received in previous releases, but has only gone to highlight just how badly tabbed groupchat/muc was needed, so we’ve gone ahead and implemented this. Those of us who’ve been using this new feature for a while can’t understand quite how we did without it, and various options are available for you to tweak exactly whether mucs and chats are tabbed together, or seperately, or not at all.

Improved roster search.
The roster search function has been improved, and will now filter the roster down to only matching contacts, making it much easier to find your contacts in the list.

Bookmarked conferences.
MUCs/groupchats can now be bookmarked (subject to server support, which almost every server has), so the user interface provides quick access to favourite mucs, and also to autojoin settings at login time.

Advanced option exposure.
While we’re confident our default settings will work for most of our users, we know how much many of you like to tinker with settings and to tweak Psi to be uniquely yours. Now all the options in Psi have been converted to a new internal format which allows us to provide access in the UI to every option. Those of you familiar with Firefox’s about:config will no doubt feel at home here, and will find the options in the Advanced tab of the options window (be warned that, of course, these options are only intended to be changed if you’re sure of what you’re doing and with a recent config backup, some of these may not be for the faint of heart).

We’d like to thank all the contributors, including those who’ve submitted patches for us, tested for bugs, fixed bugs, supported other users and translated Psi, and anyone else who helps the project in any way.

Now, please, go forth and test:
Mac: http://downloads.sourceforge.net/psi/Psi-0.12-RC1.dmg
Windows: http://downloads.sourceforge.net/psi/psi-win32-0.12-RC1.zip
Source: http://downloads.sourceforge.net/psi/psi-0.12-RC1.tar.bz2

Yours in Psi,
/K

Psi 0.11 released

9:01 pm

After over a year of hard work, we are thrilled to finally release 0.11. A lot of stuff happened over all this time, including a complete rework of the codebase to support the newest Qt4 library. Some of the changes in 0.11 include:
* Reworked account registration process (including proper support for XEP-0077 (In-band registration))
* Finished support for XEP-0004 (Data Forms) by supporting forms in messages. (thanks to Roelof Naude)
* Added support for JEP-0070 (Verifying HTTP Requests via XMPP).
* Customizable shortcuts (thanks to Ephraim)
* Added spell checking (thanks to Ephraim). Currently only aspell is supported on non-Macs.
* Added option to automatically set the resource (using the hostname)
* Added new default Stellar3 iconset
* Added support for JEP-138 (Stream Compression)
* Added support for using JEP-33 (Extended Stanza Addressing) to multicast messages to multiple users. Use option.enable-multicasting to enable it.
* Added ‘Show status message’ toggle. There is a hidden option to put status messages under the nickname (at the cost of 2 extra pixels when no status message is shown)
* Support for Bookmark Storage (JEP-0048), where bookmarked conferences are auto-joined. No UI is provided for creating bookmarks (yet).
* Better error messages, including error condition mappings (JEP-0086)
* Support dynamically changing priority
* Improved PGP error messages
* Hiding the deprecated protocol selector for service discovery by default. Use option.ui.show-deprecated.service-discovery.protocol-selector to re-enable it.
* New options system (see options.xml)
* Receiving support for vCard-Based Avatars (JEP-0153)
* Support for Multi-User-Chat (JEP-0045)
* Preliminary support for User Nickname (JEP-0172)
* Preliminary support for Roster Item Exchange (JEP-0144)
* Psi now uses the Qt4(>=4.2.3) and QCA2 libraries, replacing the Qt3 and QCA1 requirements.
* “Privacy List” support in the account dialog.
* Support for JEP-0050 (Ad-hoc commands)
* Preliminary support for JEP-0163 (Personal Eventing Protocol)
* Preliminary support for JEP-0146 (Remote Controlling Clients)
* Large parts of the codebase have been restructured.
* Fixed a chat room bug where subject/topic changes were not shown.
* Mac OS X builds are now universal binaries, supporting the new Intel based Macs.
* Support for JEP-85 (Chat State Notifications).
* Support for JEP-0115 (Entity Capabilities).
* There is now a config.xml option to make some windows use the brushed metal theme on Mac OS X.
* Window opacity support is now present for all three supported platforms.
* Fixed Unicode URL opening bug #510
* Auto-reconnect accounts on wakeup
* Copy-pasting with emoticons now works
* Fixed issue #263 where emoticons would disappear in a reply or quote
* History index is rebuilt faster
* Configure toolbars merged into main preferences dialog
* Moving tooltips
* MingW32 compiler support (Coupled with the open source Qt4 Windows library this now allows completely free building of Psi on Windows)

There’s not much else to say here that isn’t said in the release notes / readme, which everyone is encouraged to read before upgrading.

To get your latest copy of Psi, just click on one of the links below.

Windows installer:
http://downloads.sourceforge.net/psi/psi-0.11-win-setup.exe

Mac image:
http://downloads.sourceforge.net/psi/Psi-0.11.dmg

Source:
http://downloads.sourceforge.net/psi/psi-0.11.tar.bz2

Other archives:
http://sourceforge.net/project/showfiles.php?group_id=14635&package_id=53260&release_id=545913

Other packages will trickle in as they’re available, I know that Suse packages are ready thanks to Nikolay Derkach.

Translations will be coming in shortly.

Thanks to everyone who’s contributed to this (or past) releases.

Happy release time :)

Psi 0.11-RC3 released

9:40 am

It’s release candidate time. This should be the last RC3, touch wood.
Psi-0.11-RC3 is out, please grab your copies from:

Source: http://downloads.sourceforge.net/psi/psi-0.11-RC3.tar.bz2
Mac: http://downloads.sourceforge.net/psi/Psi-0.11-RC3.dmg”
Windows: http://downloads.sourceforge.net/psi/psi-win32-0.11-RC3.zip”

Known Issues:
A very small number of users (currently only one that we know of reproducably) are affected by a crash in this version of Psi; we’re working on trying to track this down and fix it but have decided to not delay the release of 0.11 any further for it, as it will work fine for the vast majority of users. However; if you use Psi in an absolutely mission-critical environment, it may be safest to continue to use 0.10 until the bugfix is applied.

Please test; if no show-stopping bugs are revealed in the next few weeks, we’ll go gold. The changelog since 0.10 is as follows:

* Reworked account registration process (including proper support for XEP-0077 (In-band registration))
* Finished support for XEP-0004 (Data Forms) by supporting forms in messages. (thanks to Roelof Naude)
* Added support for JEP-0070 (Verifying HTTP Requests via XMPP).
* Customizable shortcuts (thanks to Ephraim)
* Added spell checking (thanks to Ephraim). Currently only aspell is supported on non-Macs.
* Added option to automatically set the resource (using the hostname)
* Added new default Stellar3 iconset
* Added support for JEP-138 (Stream Compression)
* Added support for using JEP-33 (Extended Stanza Addressing) to multicast messages to multiple users. Use option.enable-multicasting to enable it.
* Added ‘Show status message’ toggle. There is a hidden option to put status messages under the nickname (at the cost of 2 extra pixels when no status message is shown)
* Support for Bookmark Storage (JEP-0048), where bookmarked conferences are auto-joined. No UI is provided for creating bookmarks (yet).
* Better error messages, including error condition mappings (JEP-0086)
* Support dynamically changing priority
* Improved PGP error messages
* Hiding the deprecated protocol selector for service discovery by default. Use option.ui.show-deprecated.service-discovery.protocol-selector to re-enable it.
* New options system (see options.xml)
* Receiving support for vCard-Based Avatars (JEP-0153)
* Support for Multi-User-Chat (JEP-0045)
* Preliminary support for User Nickname (JEP-0172)
* Preliminary support for Roster Item Exchange (JEP-0144)
* Psi now uses the Qt4(>=4.2.3) and QCA2 libraries, replacing the Qt3 and QCA1 requirements.
* “Privacy List” support in the account dialog.
* Support for JEP-0050 (Ad-hoc commands)
* Preliminary support for JEP-0163 (Personal Eventing Protocol)
* Preliminary support for JEP-0146 (Remote Controlling Clients)
* Large parts of the codebase have been restructured.
* Fixed a chat room bug where subject/topic changes were not shown.
* Mac OS X builds are now universal binaries, supporting the new Intel based Macs.
* Support for JEP-85 (Chat State Notifications).
* Support for JEP-0115 (Entity Capabilities).
* There is now a config.xml option to make some windows use the brushed metal theme on Mac OS X.
* Window opacity support is now present for all three supported platforms.
* Fixed Unicode URL opening bug #510
* Auto-reconnect accounts on wakeup
* Copy-pasting with emoticons now works
* Fixed issue #263 where emoticons would disappear in a reply or quote
* History index is rebuilt faster
* Configure toolbars merged into main preferences dialog
* Moving tooltips
* MingW32 compiler support (Coupled with the open source Qt4 Windows library this now allows completely free building of Psi on Windows)

Bad Behavior has blocked 67 access attempts in the last 7 days.