GSoC08 Roster Improvements
From PsiWiki
Roster rewrite was a Google Summer of Code 2008 project, developed by Adam Czachorowski (student) and Remko Troncon (mentor).
Original application can be found here. Keep in mind that these goals has changed before and during development so the end effect differs.
Contents |
[edit] Current status
As for today (11 IX 2008), the new roster is embeded next to old one (with QSplitter) which makes testing much easier. It is usable, but not fully featured yet. You can see items, drag them, open context menus and even change some look & feel options (avatars, status messages, slim/normal items, colors, etc). However, there's still a lot of things not working. These are mostly minor things, including:
- animated icons
- missing (just few) context menu items
- not respecting few options (i.e. single / double click for default action)
- unchangeble nested group delimiter set to "::"
- ugly tooltips
- group counts, pgp icons for accounts
- keyboard shortcuts
There are also some known bugs:
- group collapsing with double click stops working sometimes
- psi occasionaly crashes during renaming groups.
- there's small memory leak in View, marked with FIXMEs
- roster is rebuilded every time account changes. This is silly performance killer, but I just forgot to change it ;-)
[edit] Metacontacts
Metacontacts are tricky. While most of code is working and ready, there is no real metacontacts support. Only way to get metacontacts now is to use "join by name" option, where multiple contacts with same name in same group are joined together as metacontact. This is turned off by default, but can be changed with just one line of code.
In order to get proper metacontacts we need to get metacontact's tags from server and join proper items. We could also try doing 'join by jid', especially useful when you use 'joined accounts'. This metacontacts building will be similar to what we've got now with 'join by name' and shouldn't take more than 30 lines of code and around 15 minutes to get working once XMPP stuff is done.
The tricky part is UI. For example: what do you do when 'show offline' is set to false and there's only one active account within metacontact. Do you show it as contact or metacontact with just one item? What if metacontact consists of 3 items: A (online, priority 3), B (dnd, 5) and C (offline) and user clicks on it? Do you open chat to A (highest status), B (highest priority) or C (i.e. user already has that window opened somewhere? Again, this will be easy to get working, but I believe that we should focus on getting everything else working before finishing metacontacts.
[edit] Architecture overview
Here's a short description of how things work in new roster.
The UI is done using Qt's Model/View/Delegate architecture, so we've got view.h with custom QTreeView widget, delegate.h, which paints each item and model.h which provides data for those.
The data used by model is a tree structure consisting of classes from roster.h, contact.h, self.h, transport.h, resource.h, metacontact.h, notinlist.h, group.h and account.h. These classes represent single items on roster and store only informations that are needed for roster. The all inherit Item from item.h or GroupItem from groupitem.h. This tree structure represents roster as it is displayed right now, which means that if 'show offline' is set to false then there are no offline items inside. All operations on this items are performed by Manager (manager.h) in order to keep everything consistent.
Roster tree is built by RosterBuilder (rosterbuilder.h), which takes data from data service (rosterdataservice.h and psidataservice.h), which is just a proxy class to PsiAccount. UserListItem and UserResource classes are passed to RosterBuilder, but they are never used anywhere else. RosterBuilder is responsible for building and updating roster tree when new data comes or user changes filtering rules (i.e. roster search, show offline, etc). It also puts all data into Item-derived classes. These data can be taken from UserListItem or from separate data service (i.e. viewstatemanager.h for collapsed/expanded info).
All actions performed on view are passed to viewactionsservice.h, which then calls proper RosterActionsService's method (rosteractionsservice.h, just an abstract interface for PsiAccount at the moment).
statusiconprovider.h is used by model to get icons for roster. Name of this file/class is really bad since it provides icons not only for statuses, but also for events. I'll change it some day.
globals.h is propably worse file name ever. It has some boring contants and will be removed some day.
Information whether an item is expanded or collapsed on roster is stored in viewstatemanager.h. It can be used to save this data on exit and load on startup.
Finally, rosterinstance.h is a class that creates all required objects. This could be done in PsiCon's constructor, but due to namespace problems I figured out that it's better to move it to Roster namespace ;-)
I hope that this gives you at least a little idea of how things work here.
[edit] Namespace problem
Currently many header files in Psi has "using namespace XMPP;" inside. This doesn't look that bad until you realize that g++ cannot distinguish XMPP::Roster and Roster namespace and will refuse to compile any file with "using namespace XMPP;" and Roster keyword in it. I'm working on removing these from Psi, but until then we need to relay on some dirty tricks to make it work.
[edit] How to get it
You can download new roster code from
git://github.com/gislan/gsoc.git
Make sure you use 'full' branch, 'master' is not used anymore
Here's a short listing for downloading this repo using command line
git clone git://github.com/gislan/gsoc.git cd gsoc git branch --track full origin/full git checkout full git submodule init git submodule update
And then normal psi stuff (./configure; make; make install or w/e you want)

