diff -urN -X psidiff.ignore sources/src/activitycatalog.cpp work/src/activitycatalog.cpp
--- sources/src/activitycatalog.cpp	1970-01-01 05:00:00.000000000 +0500
+++ work/src/activitycatalog.cpp	2009-03-07 01:53:06.000000000 +0500
@@ -0,0 +1,216 @@
+/*
+ * activitycatalog.cpp
+ * Copyright (C) 2008 Armando Jagucki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QString>
+#include <QObject>
+#include <QCoreApplication>
+
+#include "activity.h"
+#include "activitycatalog.h"
+		
+ActivityCatalog::Entry::Entry()
+{
+}
+
+ActivityCatalog::Entry::Entry(Activity::Type type, const QString& value, const QString& text)
+{
+	type_  = type;
+	specificType_ = Activity::UnknownSpecific;
+	value_ = value;
+	text_  = text;
+}
+
+ActivityCatalog::Entry::Entry(Activity::Type type, Activity::SpecificType specificType, const QString& value, const QString& text)
+{
+	type_ = type;
+	specificType_ = specificType;
+	value_ = value;
+	text_  = text;
+}
+
+Activity::Type ActivityCatalog::Entry::type() const
+{
+	return type_;
+}
+
+Activity::SpecificType ActivityCatalog::Entry::specificType() const
+{
+	return specificType_;
+}
+
+const QString& ActivityCatalog::Entry::value() const
+{
+	return value_;
+}
+
+const QString& ActivityCatalog::Entry::text() const
+{
+	return text_;
+}
+
+bool ActivityCatalog::Entry::isNull() const
+{
+	return type_ == Activity::Unknown && text_.isNull() && value_.isNull();
+}
+
+ActivityCatalog::ActivityCatalog() : QObject(QCoreApplication::instance())
+{
+	entries_ += Entry(Activity::DoingChores, "doing_chores", QObject::tr("Doing Chores"));
+	entries_ += Entry(Activity::DoingChores, Activity::BuyingGroceries, "buying_groceries", QObject::tr("Buying Groceries"));
+	entries_ += Entry(Activity::DoingChores, Activity::Cleaning, "cleaning", QObject::tr("Cleaning"));
+	entries_ += Entry(Activity::DoingChores, Activity::Cooking, "cooking", QObject::tr("Cooking"));
+	entries_ += Entry(Activity::DoingChores, Activity::DoingMaintenance, "doing_maintenance", QObject::tr("Doing Maintenance"));
+	entries_ += Entry(Activity::DoingChores, Activity::DoingTheDishes, "doing_the_dishes", QObject::tr("Doing The Dishes"));
+	entries_ += Entry(Activity::DoingChores, Activity::DoingTheLaundry, "doing_the_laundry", QObject::tr("Doing The Laundry"));
+	entries_ += Entry(Activity::DoingChores, Activity::Gardening, "gardening", QObject::tr("Gardening"));
+	entries_ += Entry(Activity::DoingChores, Activity::RunningAnErrand, "running_an_errand", QObject::tr("Running An Errand"));
+	entries_ += Entry(Activity::DoingChores, Activity::WalkingTheDog, "walking_the_dog", QObject::tr("Walking The Dog"));
+
+	entries_ += Entry(Activity::Drinking, "drinking", QObject::tr("Drinking"));
+	entries_ += Entry(Activity::Drinking, Activity::HavingABeer, "having_a_beer", QObject::tr("Having A Beer"));
+	entries_ += Entry(Activity::Drinking, Activity::HavingCoffee, "having_coffee", QObject::tr("Having Coffee"));
+	entries_ += Entry(Activity::Drinking, Activity::HavingTea, "having_tea", QObject::tr("Having Tea"));
+
+	entries_ += Entry(Activity::Eating, "eating", QObject::tr("Eating"));
+	entries_ += Entry(Activity::Eating, Activity::HavingASnack, "having_a_snack", QObject::tr("Having A Snack"));
+	entries_ += Entry(Activity::Eating, Activity::HavingBreakfast, "having_breakfast", QObject::tr("Having Breakfast"));
+	entries_ += Entry(Activity::Eating, Activity::HavingLunch, "having_lunch", QObject::tr("Having Lunch"));
+	entries_ += Entry(Activity::Eating, Activity::HavingDinner, "having_dinner", QObject::tr("Having Dinner"));
+
+	entries_ += Entry(Activity::Exercising, "exercising", QObject::tr("Exercising"));
+	entries_ += Entry(Activity::Exercising, Activity::Cycling, "cycling", QObject::tr("Cycling"));
+	entries_ += Entry(Activity::Exercising, Activity::Dancing, "dancing", QObject::tr("Dancing"));
+	entries_ += Entry(Activity::Exercising, Activity::Hiking, "hiking", QObject::tr("Hiking"));
+	entries_ += Entry(Activity::Exercising, Activity::Jogging, "jogging", QObject::tr("Jogging"));
+	entries_ += Entry(Activity::Exercising, Activity::PlayingSports, "playing_sports", QObject::tr("Playing Sports"));
+	entries_ += Entry(Activity::Exercising, Activity::Running, "running", QObject::tr("Running"));
+	entries_ += Entry(Activity::Exercising, Activity::Skiing, "skiing", QObject::tr("Skiing"));
+	entries_ += Entry(Activity::Exercising, Activity::Swimming, "swimming", QObject::tr("Swimming"));
+	entries_ += Entry(Activity::Exercising, Activity::WorkingOut, "working_out", QObject::tr("Working Out"));
+
+	entries_ += Entry(Activity::Grooming, "grooming", QObject::tr("Grooming"));
+	entries_ += Entry(Activity::Grooming, Activity::AtTheSpa, "at_the_spa", QObject::tr("At The Spa"));
+	entries_ += Entry(Activity::Grooming, Activity::BrushingTeeth, "brushing_teeth", QObject::tr("Brushing Teeth"));
+	entries_ += Entry(Activity::Grooming, Activity::GettingAHaircut, "getting_a_haircut", QObject::tr("Getting A Haircut"));
+	entries_ += Entry(Activity::Grooming, Activity::Shaving, "shaving", QObject::tr("Shaving"));
+	entries_ += Entry(Activity::Grooming, Activity::TakingABath, "taking_a_bath", QObject::tr("Taking A Bath"));
+	entries_ += Entry(Activity::Grooming, Activity::TakingAShower, "taking_a_shower", QObject::tr("Taking A Shower"));
+
+	entries_ += Entry(Activity::HavingAppointment, "having_appointment", QObject::tr("Having Appointment"));
+
+	entries_ += Entry(Activity::Inactive, "inactive", QObject::tr("Inactive"));
+	entries_ += Entry(Activity::Inactive, Activity::DayOff, "day_off", QObject::tr("Day Off"));
+	entries_ += Entry(Activity::Inactive, Activity::HangingOut, "hanging_out", QObject::tr("Hanging Out"));
+	entries_ += Entry(Activity::Inactive, Activity::Hiding, "hiding", QObject::tr("Hiding"));
+	entries_ += Entry(Activity::Inactive, Activity::OnVacation, "on_vacation", QObject::tr("On Vacation"));
+	entries_ += Entry(Activity::Inactive, Activity::Praying, "praying", QObject::tr("Praying"));
+	entries_ += Entry(Activity::Inactive, Activity::ScheduledHoliday, "scheduled_holiday", QObject::tr("Scheduled Holiday"));
+	entries_ += Entry(Activity::Inactive, Activity::Sleeping, "sleeping", QObject::tr("Sleeping"));
+	entries_ += Entry(Activity::Inactive, Activity::Thinking, "thinking", QObject::tr("Thinking"));
+
+	entries_ += Entry(Activity::Relaxing, "relaxing", QObject::tr("Relaxing"));
+	entries_ += Entry(Activity::Relaxing, Activity::Fishing, "fishing", QObject::tr("Fishing"));
+	entries_ += Entry(Activity::Relaxing, Activity::Gaming, "gaming", QObject::tr("Gaming"));
+	entries_ += Entry(Activity::Relaxing, Activity::GoingOut, "going_out", QObject::tr("Going Out"));
+	entries_ += Entry(Activity::Relaxing, Activity::Partying, "partying", QObject::tr("Partying"));
+	entries_ += Entry(Activity::Relaxing, Activity::Reading, "reading", QObject::tr("Reading"));
+	entries_ += Entry(Activity::Relaxing, Activity::Rehearsing, "rehearsing", QObject::tr("Rehearsing"));
+	entries_ += Entry(Activity::Relaxing, Activity::Shopping, "shopping", QObject::tr("Shopping"));
+	entries_ += Entry(Activity::Relaxing, Activity::Smoking, "smoking", QObject::tr("Smoking"));
+	entries_ += Entry(Activity::Relaxing, Activity::Socializing, "socializing", QObject::tr("Socializing"));
+	entries_ += Entry(Activity::Relaxing, Activity::Sunbathing, "sunbathing", QObject::tr("Sunbathing"));
+	entries_ += Entry(Activity::Relaxing, Activity::WatchingTv, "watching_tv", QObject::tr("Watching TV"));
+	entries_ += Entry(Activity::Relaxing, Activity::WatchingAMovie, "watching_a_movie", QObject::tr("Watching A Movie"));
+
+	entries_ += Entry(Activity::Talking, "talking", QObject::tr("Talking"));
+	entries_ += Entry(Activity::Talking, Activity::InRealLife, "in_real_life", QObject::tr("In Real Life"));
+	entries_ += Entry(Activity::Talking, Activity::OnThePhone, "on_the_phone", QObject::tr("On The Phone"));
+	entries_ += Entry(Activity::Talking, Activity::OnVideoPhone, "on_video_phone", QObject::tr("On Video Phone"));
+
+	entries_ += Entry(Activity::Traveling, "traveling", QObject::tr("Traveling"));
+	entries_ += Entry(Activity::Traveling, Activity::Commuting, "commuting", QObject::tr("Commuting"));
+	entries_ += Entry(Activity::Traveling, Activity::Cycling, "cycling", QObject::tr("Cycling"));
+	entries_ += Entry(Activity::Traveling, Activity::Driving, "driving", QObject::tr("Driving"));
+	entries_ += Entry(Activity::Traveling, Activity::InACar, "in_a_car", QObject::tr("In A Car"));
+	entries_ += Entry(Activity::Traveling, Activity::OnABus, "on_a_bus", QObject::tr("On A Bus"));
+	entries_ += Entry(Activity::Traveling, Activity::OnAPlane, "on_a_plane", QObject::tr("On A Plane"));
+	entries_ += Entry(Activity::Traveling, Activity::OnATrain, "on_a_train", QObject::tr("On A Train"));
+	entries_ += Entry(Activity::Traveling, Activity::OnATrip, "on_a_trip", QObject::tr("On A Trip"));
+	entries_ += Entry(Activity::Traveling, Activity::Walking, "walking", QObject::tr("Walking"));
+
+	entries_ += Entry(Activity::Working, "working", QObject::tr("Working"));
+	entries_ += Entry(Activity::Working, Activity::Coding, "coding", QObject::tr("Coding"));
+	entries_ += Entry(Activity::Working, Activity::InAMeeting, "in_a_meeting", QObject::tr("In A Meeting"));
+	entries_ += Entry(Activity::Working, Activity::Studying, "studying", QObject::tr("Studying"));
+	entries_ += Entry(Activity::Working, Activity::Writing, "writing", QObject::tr("Writing"));
+
+	// Undefined specific activity
+	entries_ += Entry(Activity::Unknown, Activity::Other, "other", QObject::tr("Other"));
+}
+
+ActivityCatalog* ActivityCatalog::instance()
+{
+	if (!instance_)
+		instance_ = new  ActivityCatalog();
+	return instance_;
+}
+
+ActivityCatalog::Entry ActivityCatalog::findEntryByType(Activity::Type type) const
+{
+	foreach(Entry e, entries_) {
+		if (e.type() == type)
+			return e;
+	}
+	return Entry();
+}
+
+ActivityCatalog::Entry ActivityCatalog::findEntryByType(Activity::SpecificType specificType) const
+{
+	foreach(Entry e, entries_) {
+		if (e.specificType() == specificType)
+			return e;
+	}
+	return Entry();
+}
+
+ActivityCatalog::Entry ActivityCatalog::findEntryByValue(const QString& value) const
+{
+	foreach(Entry e, entries_) {
+		if (e.value() == value)
+			return e;
+	}
+	return Entry();
+}
+
+ActivityCatalog::Entry ActivityCatalog::findEntryByText(const QString& text) const
+{
+	foreach(Entry e, entries_) {
+		if (e.text() == text)
+			return e;
+	}
+	return Entry();
+}
+
+const QList<ActivityCatalog::Entry>& ActivityCatalog::entries() const
+{
+	return entries_;
+}
+	
+ActivityCatalog* ActivityCatalog::instance_ = 0;
diff -urN -X psidiff.ignore sources/src/activitycatalog.h work/src/activitycatalog.h
--- sources/src/activitycatalog.h	1970-01-01 05:00:00.000000000 +0500
+++ work/src/activitycatalog.h	2009-03-07 01:53:06.000000000 +0500
@@ -0,0 +1,69 @@
+/*
+ * activitycatalog.h
+ * Copyright (C) 2008 Armando Jagucki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ACTIVITYCATALOG_H
+#define ACTIVITYCATALOG_H
+
+#include <QList>
+#include <QObject>
+
+#include "activity.h"
+
+class QString;
+
+class ActivityCatalog : public QObject
+{
+public:
+	class Entry {
+		public:
+			Entry();
+			Entry(Activity::Type, const QString&, const QString&);
+			Entry(Activity::Type, Activity::SpecificType, const QString&, const QString&);
+			Activity::Type type() const;
+			Activity::SpecificType specificType() const;
+			const QString& value() const;
+			const QString& text() const;
+			bool isNull() const;
+
+		private:
+			Activity::Type type_;
+			Activity::SpecificType specificType_;
+			QString value_;
+			QString text_;
+	};
+	
+	static ActivityCatalog* instance();
+
+	Entry findEntryByType(Activity::Type) const;
+	Entry findEntryByType(Activity::SpecificType) const;
+	Entry findEntryByValue(const QString&) const;
+	Entry findEntryByText(const QString& text) const;
+	
+	const QList<Entry>& entries() const;
+	
+private:
+	ActivityCatalog();
+	
+	QList<Entry> entries_;
+	static ActivityCatalog* instance_;
+
+};
+
+#endif
diff -urN -X psidiff.ignore sources/src/activity.cpp work/src/activity.cpp
--- sources/src/activity.cpp	1970-01-01 05:00:00.000000000 +0500
+++ work/src/activity.cpp	2009-03-07 01:53:06.000000000 +0500
@@ -0,0 +1,130 @@
+/*
+ * activity.cpp
+ * Copyright (C) 2008 Armando Jagucki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <QDomDocument>
+#include <QDomElement>
+
+#include "activity.h"
+#include "activitycatalog.h"
+
+Activity::Activity()
+{
+	type_ = Unknown;
+	specificType_ = UnknownSpecific;
+}
+
+Activity::Activity(Activity::Type type, Activity::SpecificType specificType, const QString& text)
+{
+	type_ = type;
+	specificType_ = specificType;
+	text_ = text;
+}
+
+Activity::Activity(const QDomElement& e)
+{
+	fromXml(e);
+}
+
+Activity::Type Activity::type() const
+{
+	return type_;
+}
+
+QString Activity::typeText() const
+{
+	return ActivityCatalog::instance()->findEntryByType(type_).text();
+}
+
+Activity::SpecificType Activity::specificType() const
+{
+	return specificType_;
+}
+
+QString Activity::specificTypeText() const
+{
+	return ActivityCatalog::instance()->findEntryByType(specificType_).text();
+}
+
+const QString& Activity::text() const
+{
+	return text_;
+}
+
+bool Activity::isNull() const
+{
+	return type_ == Unknown && text().isEmpty();
+}
+
+QDomElement Activity::toXml(QDomDocument& doc)
+{
+	QDomElement activity = doc.createElement("activity");
+	activity.setAttribute("xmlns", "http://jabber.org/protocol/activity");
+
+	if (!type() == Unknown) {
+		ActivityCatalog* ac = ActivityCatalog::instance();
+		QDomElement el = doc.createElement(ac->findEntryByType(type()).value());
+
+		if (!specificType() == UnknownSpecific) {
+			QDomElement elChild = doc.createElement(ac->findEntryByType(specificType()).value());
+			el.appendChild(elChild);
+		}
+
+		activity.appendChild(el);
+	}
+	else {
+		qWarning("activity.cpp: ERROR: Converting unknown activity");
+	}
+
+	if (!text().isEmpty()) {
+		QDomElement el = doc.createElement("text");
+		QDomText t = doc.createTextNode(text());
+		el.appendChild(t);
+		activity.appendChild(el);
+	}
+
+	return activity;
+}
+
+void Activity::fromXml(const QDomElement& element)
+{
+	if (element.tagName() != "activity")
+		return;
+
+	type_ = Activity::Unknown;
+	specificType_ = Activity::UnknownSpecific;
+
+	for (QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling()) {
+		QDomElement child = node.toElement();
+		if (child.tagName() == "text") {
+			text_ = child.text();
+		}
+		else {
+			ActivityCatalog* ac = ActivityCatalog::instance();
+			type_ = ac->findEntryByValue(child.tagName()).type();
+
+			if (child.hasChildNodes()) {
+				QDomElement specificTypeElement = child.firstChildElement();
+				if (!specificTypeElement.isNull()) {
+					specificType_ = ac->findEntryByValue(specificTypeElement.tagName()).specificType();
+				}
+			}
+		}
+	}
+}
diff -urN -X psidiff.ignore sources/src/activitydlg.cpp work/src/activitydlg.cpp
--- sources/src/activitydlg.cpp	1970-01-01 05:00:00.000000000 +0500
+++ work/src/activitydlg.cpp	2009-03-07 01:53:06.000000000 +0500
@@ -0,0 +1,90 @@
+/*
+ * activitydlg.cpp
+ * Copyright (C) 2008 Armando Jagucki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "xmpp_pubsubitem.h"
+#include "xmpp_client.h"
+#include "xmpp_task.h"
+#include "activitydlg.h"
+#include "activitycatalog.h"
+#include "psiaccount.h"
+#include "pepmanager.h"
+
+ActivityDlg::ActivityDlg(PsiAccount* pa) : QDialog(0), pa_(pa)
+{
+	setAttribute(Qt::WA_DeleteOnClose);
+	ui_.setupUi(this);
+	setModal(false);
+	connect(ui_.cb_general_type, SIGNAL(currentIndexChanged(const QString&)), SLOT(loadSpecificActivities(const QString&)));
+	connect(ui_.pb_cancel, SIGNAL(clicked()), SLOT(close()));
+	connect(ui_.pb_ok, SIGNAL(clicked()), SLOT(setActivity()));
+
+	ui_.cb_general_type->addItem(tr("<unset>"));
+	foreach(ActivityCatalog::Entry e, ActivityCatalog::instance()->entries()) {
+		if (e.specificType() == Activity::UnknownSpecific) {
+			// The entry e is for a 'general' type.
+			ui_.cb_general_type->addItem(e.text());
+		}
+	}
+}
+
+void ActivityDlg::loadSpecificActivities(const QString& generalActivityStr)
+{
+	ui_.cb_specific_type->clear();
+
+	if (generalActivityStr == tr("<unset>")) {
+		return;
+	}
+	else {
+		ui_.cb_specific_type->addItem(tr("<unset>"));
+		ActivityCatalog* ac = ActivityCatalog::instance();
+		foreach(ActivityCatalog::Entry e, ac->entries()) {
+			if (e.specificType() != Activity::UnknownSpecific) {
+				// The entry e is for a 'specific' type.
+				ActivityCatalog::Entry ge = ac->findEntryByText(generalActivityStr);
+				if (e.type() == ge.type()) {
+					ui_.cb_specific_type->addItem(e.text());
+				}
+			}
+		}
+	}
+
+	ui_.cb_specific_type->addItem(tr("Other"));
+}
+
+void ActivityDlg::setActivity()
+{
+	QString generalActivityStr  = ui_.cb_general_type->currentText();
+	QString specificActivityStr = ui_.cb_specific_type->currentText();
+
+	if (generalActivityStr == tr("<unset>")) {
+		pa_->pepManager()->retract("http://jabber.org/protocol/activity", "current");
+	}
+	else {
+		ActivityCatalog* ac = ActivityCatalog::instance();
+		Activity::Type generalType = ac->findEntryByText(generalActivityStr).type();
+
+		Activity::SpecificType specificType = Activity::UnknownSpecific;
+		if (specificActivityStr != tr("<unset>")) {
+			specificType = ac->findEntryByText(specificActivityStr).specificType();
+		}
+		pa_->pepManager()->publish("http://jabber.org/protocol/activity", PubSubItem("current",Activity(generalType,specificType,ui_.le_description->text()).toXml(*pa_->client()->rootTask()->doc())), PEPManager::PresenceAccess);
+	}
+	close();
+}
diff -urN -X psidiff.ignore sources/src/activitydlg.h work/src/activitydlg.h
--- sources/src/activitydlg.h	1970-01-01 05:00:00.000000000 +0500
+++ work/src/activitydlg.h	2009-03-07 01:53:06.000000000 +0500
@@ -0,0 +1,46 @@
+/*
+ * activitydlg.h
+ * Copyright (C) 2008 Armando Jagucki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ACTIVITYDLG_H
+#define ACTIVITYDLG_H
+
+#include <QDialog>
+
+#include "ui_activity.h"
+
+class PsiAccount;
+
+class ActivityDlg : public QDialog
+{
+	Q_OBJECT
+
+public:
+	ActivityDlg(PsiAccount*);
+
+protected slots:
+	void setActivity();
+	void loadSpecificActivities(const QString&);
+
+private:
+	Ui::Activity ui_;
+	PsiAccount* pa_;
+};
+
+#endif
diff -urN -X psidiff.ignore sources/src/activity.h work/src/activity.h
--- sources/src/activity.h	1970-01-01 05:00:00.000000000 +0500
+++ work/src/activity.h	2009-03-07 01:53:06.000000000 +0500
@@ -0,0 +1,94 @@
+/*
+ * activiy.h
+ * Copyright (C) 2008 Armando Jagucki
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef ACTIVITY_H
+#define ACTIVITY_H
+
+#include <QString>
+
+class QDomElement;
+class QDomDocument;
+
+class Activity
+{
+public:
+	enum Type { 
+		Unknown,
+		DoingChores, Drinking, Eating, Exercising, Grooming,
+		HavingAppointment, Inactive, Relaxing, Talking, Traveling,
+		Working
+	};
+
+	enum SpecificType {
+		UnknownSpecific,
+		// under 'doing_chores'
+		BuyingGroceries, Cleaning, Cooking, DoingMaintenance,
+		DoingTheDishes, DoingTheLaundry, Gardening, RunningAnErrand,
+		WalkingTheDog,
+		// under 'drinking'
+		HavingABeer, HavingCoffee, HavingTea,
+		// under 'eating'
+		HavingASnack, HavingBreakfast, HavingLunch, HavingDinner,
+		// under 'excercising'
+		Cycling, Dancing, Hiking, Jogging, PlayingSports, Running, Skiing,
+		Swimming, WorkingOut,
+		// under 'grooming'
+		AtTheSpa, BrushingTeeth, GettingAHaircut, Shaving, TakingABath,
+		TakingAShower,
+		// under 'having_appointment'
+		// under 'inactive'
+		DayOff, HangingOut, Hiding, OnVacation, Praying, ScheduledHoliday, Sleeping, Thinking,
+		// under 'relaxing'
+		Fishing, Gaming, GoingOut, Partying, Reading, Rehearsing, Shopping, Smoking,
+		Socializing, Sunbathing, WatchingTv, WatchingAMovie,
+		// under 'talking'
+		InRealLife, OnThePhone, OnVideoPhone,
+		// under 'traveling'
+		Commuting, /* Cycling (already included), */ Driving, InACar,
+		OnABus, OnAPlane, OnATrain, OnATrip, Walking,
+		// under 'working'
+		Coding, InAMeeting, Studying, Writing,
+		// undefined specific activity
+		Other
+	};
+
+	Activity();
+	Activity(Type, SpecificType, const QString& = QString());
+	Activity(const QDomElement&);
+
+	Type type() const;
+	QString typeText() const;
+	SpecificType specificType() const;
+	QString specificTypeText() const;
+	const QString& text() const;
+	bool isNull() const;
+
+	QDomElement toXml(QDomDocument&);
+
+protected:
+	void fromXml(const QDomElement&);
+	
+private:
+	Type type_;
+	SpecificType specificType_;
+	QString text_;
+};
+
+#endif
diff -urN -X psidiff.ignore sources/src/activity.ui work/src/activity.ui
--- sources/src/activity.ui	1970-01-01 05:00:00.000000000 +0500
+++ work/src/activity.ui	2009-03-07 01:53:06.000000000 +0500
@@ -0,0 +1,113 @@
+<ui version="4.0" >
+ <class>Activity</class>
+ <widget class="QDialog" name="Activity" >
+  <property name="geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>313</width>
+    <height>162</height>
+   </rect>
+  </property>
+  <property name="windowTitle" >
+   <string>User Activity</string>
+  </property>
+  <layout class="QVBoxLayout" >
+   <item>
+    <layout class="QGridLayout" >
+     <item row="0" column="0" >
+      <widget class="QLabel" name="label" >
+       <property name="text" >
+        <string>General:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1" >
+      <widget class="QComboBox" name="cb_general_type" />
+     </item>
+     <item row="1" column="0" >
+      <widget class="QLabel" name="label_3" >
+       <property name="text" >
+        <string>Specific:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1" >
+      <widget class="QComboBox" name="cb_specific_type" />
+     </item>
+     <item row="2" column="0" >
+      <widget class="QLabel" name="label_2" >
+       <property name="text" >
+        <string>Description:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="1" >
+      <widget class="QLineEdit" name="le_description" />
+     </item>
+    </layout>
+   </item>
+   <item>
+    <spacer>
+     <property name="orientation" >
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" >
+      <size>
+       <width>223</width>
+       <height>16</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" >
+     <property name="spacing" >
+      <number>6</number>
+     </property>
+     <property name="leftMargin" >
+      <number>0</number>
+     </property>
+     <property name="topMargin" >
+      <number>0</number>
+     </property>
+     <property name="rightMargin" >
+      <number>0</number>
+     </property>
+     <property name="bottomMargin" >
+      <number>0</number>
+     </property>
+     <item>
+      <spacer>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" >
+        <size>
+         <width>131</width>
+         <height>31</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pb_ok" >
+       <property name="text" >
+        <string>OK</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pb_cancel" >
+       <property name="text" >
+        <string>Cancel</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff -urN -X psidiff.ignore sources/src/contactview.cpp work/src/contactview.cpp
--- sources/src/contactview.cpp	2009-03-07 01:53:04.000000000 +0500
+++ work/src/contactview.cpp	2009-03-07 01:53:06.000000000 +0500
@@ -945,10 +945,13 @@ void ContactProfile::doContextMenu(Conta
 		pm.insertItem(tr("Mood"), 11);
 		pm.setItemEnabled(11, d->pa->serverInfoManager()->hasPEP());
 
+		pm.insertItem(tr("Activity"), 12);
+		pm.setItemEnabled(12, d->pa->serverInfoManager()->hasPEP());
+
 		Q3PopupMenu *avatarm = new Q3PopupMenu (&pm);
-		avatarm->insertItem(tr("Set Avatar"), 12);
-		avatarm->insertItem(tr("Unset Avatar"), 13);
-		pm.insertItem(tr("Avatar"), avatarm, 14);
+		avatarm->insertItem(tr("Set Avatar"), 13);
+		avatarm->insertItem(tr("Unset Avatar"), 14);
+		pm.insertItem(tr("Avatar"), avatarm, 15);
 		pm.setItemEnabled(14, d->pa->serverInfoManager()->hasPEP());
 #endif
 		const int bookmarks_start = STATUS_CHAT + status_start + 1; // STATUS_CHAT is the highest value of the states
@@ -1029,10 +1032,13 @@ void ContactProfile::doContextMenu(Conta
 		else if(x == 11 && pm.isItemEnabled(11)) {
 			emit actionSetMood();
 		}
-		else if(x == 12  && pm.isItemEnabled(14)) {
+		else if(x == 12 && pm.isItemEnabled(12)) {
+			emit actionSetActivity();
+		}
+		else if(x == 13  && pm.isItemEnabled(15)) {
 			emit actionSetAvatar();
 		}
-		else if(x == 13  && pm.isItemEnabled(14)) {
+		else if(x == 14  && pm.isItemEnabled(15)) {
 			emit actionUnsetAvatar();
 		}
 		else if(x >= status_start && x <= STATUS_CHAT + status_start) { // STATUS_CHAT is the highest value of the states
diff -urN -X psidiff.ignore sources/src/contactview.h work/src/contactview.h
--- sources/src/contactview.h	2009-03-07 01:25:53.000000000 +0500
+++ work/src/contactview.h	2009-03-07 01:53:06.000000000 +0500
@@ -124,6 +124,7 @@
 	void actionAssignKey(const Jid &);
 	void actionUnassignKey(const Jid &);
 	void actionSetMood();
+	void actionSetActivity();
 	void actionSetAvatar();
 	void actionUnsetAvatar();
 
diff -urN -X psidiff.ignore sources/src/psiaccount.cpp work/src/psiaccount.cpp
--- sources/src/psiaccount.cpp	2009-03-07 01:53:05.000000000 +0500
+++ work/src/psiaccount.cpp	2009-03-07 01:53:06.000000000 +0500
@@ -70,6 +70,7 @@
 #include "chatdlg.h"
 #include "contactview.h"
 #include "mood.h"
+#include "activity.h"
 #include "tune.h"
 #ifdef USE_PEP
 #include "tunecontroller.h"
@@ -104,6 +105,7 @@
 #include "vcardfactory.h"
 //#include "qssl.h"
 #include "mooddlg.h"
+#include "activitydlg.h"
 #include "qwextend.h"
 #include "geolocation.h"
 #include "physicallocation.h"
@@ -761,6 +763,7 @@
 	connect(d->cp, SIGNAL(actionExecuteCommand(const Jid &, const QString&)),SLOT(actionExecuteCommand(const Jid &, const QString&)));
 	connect(d->cp, SIGNAL(actionExecuteCommandSpecific(const Jid &, const QString&)),SLOT(actionExecuteCommandSpecific(const Jid &, const QString&)));
 	connect(d->cp, SIGNAL(actionSetMood()),SLOT(actionSetMood()));
+	connect(d->cp, SIGNAL(actionSetActivity()),SLOT(actionSetActivity()));
 	connect(d->cp, SIGNAL(actionSetAvatar()),SLOT(actionSetAvatar()));
 	connect(d->cp, SIGNAL(actionUnsetAvatar()),SLOT(actionUnsetAvatar()));
 	connect(d->cp, SIGNAL(actionDisco(const Jid &, const QString &)),SLOT(actionDisco(const Jid &, const QString &)));
@@ -894,6 +897,7 @@
 	if (d->options->getOption("options.extended-presence.notify").toBool()) {
 		QStringList pepNodes;
 		pepNodes += "http://jabber.org/protocol/mood+notify";
+		pepNodes += "http://jabber.org/protocol/activity+notify";
 		pepNodes += "http://jabber.org/protocol/tune+notify";
 		pepNodes += "http://jabber.org/protocol/physloc+notify";
 		pepNodes += "http://jabber.org/protocol/geoloc+notify";
@@ -1779,6 +1783,7 @@
 	if (b && !d->client->extensions().contains("ep")) {
 		QStringList pepNodes;
 		pepNodes += "http://jabber.org/protocol/mood";
+		pepNodes += "http://jabber.org/protocol/activity";
 		pepNodes += "http://jabber.org/protocol/tune";
 		pepNodes += "http://jabber.org/protocol/physloc";
 		pepNodes += "http://jabber.org/protocol/geoloc";
@@ -2841,6 +2846,12 @@
 			cpUpdate(*u);
 		}
 	}
+	else if (n == "http://jabber.org/protocol/activity") {
+		foreach(UserListItem* u, findRelevant(j)) {
+			u->setActivity(Activity());
+			cpUpdate(*u);
+		}
+	}
 	else if (n == "http://jabber.org/protocol/geoloc") {
 		// FIXME: try to find the right resource using JEP-33 'replyto'
 		// see tune case above
@@ -2894,6 +2905,13 @@
 			cpUpdate(*u);
 		}
 	}
+	else if (n == "http://jabber.org/protocol/activity") {
+		Activity activity(item.payload());
+		foreach(UserListItem* u, findRelevant(j)) {
+			u->setActivity(activity);
+			cpUpdate(*u);
+		}
+	}
 	else if (n == "http://jabber.org/protocol/geoloc") {
 		// FIXME: try to find the right resource using JEP-33 'replyto'
 		// see tune case above
@@ -3180,6 +3198,12 @@
 	w->show();
 }
 
+void PsiAccount::actionSetActivity()
+{
+	ActivityDlg *w = new ActivityDlg(this);
+	w->show();
+}
+
 void PsiAccount::actionSetAvatar()
 {
 	QString str = FileUtil::getImageFileName(0);
diff -urN -X psidiff.ignore sources/src/psiaccount.h work/src/psiaccount.h
--- sources/src/psiaccount.h	2009-03-07 01:53:04.000000000 +0500
+++ work/src/psiaccount.h	2009-03-07 01:53:06.000000000 +0500
@@ -288,6 +288,7 @@
 	void actionExecuteCommand(const Jid& j, const QString& = QString());
 	void actionExecuteCommandSpecific(const Jid&, const QString& = QString());
 	void actionSetMood();
+	void actionSetActivity();
 	void actionSetAvatar();
 	void actionUnsetAvatar();
 	void featureActivated(QString feature, Jid jid, QString node);
diff -urN -X psidiff.ignore sources/src/psicon.cpp work/src/psicon.cpp
--- sources/src/psicon.cpp	2009-03-07 01:25:53.000000000 +0500
+++ work/src/psicon.cpp	2009-03-07 01:53:06.000000000 +0500
@@ -500,6 +500,7 @@
 
 	registerCaps("ep", QStringList()
 	             << "http://jabber.org/protocol/mood"
+	             << "http://jabber.org/protocol/activity"
 	             << "http://jabber.org/protocol/tune"
 	             << "http://jabber.org/protocol/physloc"
 	             << "http://jabber.org/protocol/geoloc"
@@ -509,6 +510,7 @@
 
 	registerCaps("ep-notify", QStringList()
 	             << "http://jabber.org/protocol/mood+notify"
+	             << "http://jabber.org/protocol/activity+notify"
 	             << "http://jabber.org/protocol/tune+notify"
 	             << "http://jabber.org/protocol/physloc+notify"
 	             << "http://jabber.org/protocol/geoloc+notify"
diff -urN -X psidiff.ignore sources/src/src.pri work/src/src.pri
--- sources/src/src.pri	2009-03-07 01:53:06.000000000 +0500
+++ work/src/src.pri	2009-03-07 01:53:06.000000000 +0500
@@ -199,6 +199,9 @@
 	$$PWD/mood.h \
 	$$PWD/moodcatalog.h \
 	$$PWD/mooddlg.h \
+	$$PWD/activity.h \
+	$$PWD/activitycatalog.h \
+	$$PWD/activitydlg.h \
 	$$PWD/geolocation.h \
 	$$PWD/physicallocation.h \
 	$$PWD/urlbookmark.h \
@@ -322,6 +325,9 @@
 	$$PWD/mood.cpp \
 	$$PWD/moodcatalog.cpp \
 	$$PWD/mooddlg.cpp \
+	$$PWD/activity.cpp \
+	$$PWD/activitycatalog.cpp \
+	$$PWD/activitydlg.cpp \
 	$$PWD/geolocation.cpp \
 	$$PWD/physicallocation.cpp \
 	$$PWD/urlbookmark.cpp \
@@ -428,6 +434,7 @@
 	$$PWD/tip.ui \
 	$$PWD/filetrans.ui \
 	$$PWD/mood.ui \
+	$$PWD/activity.ui \
 	$$PWD/voicecall.ui \
 	$$PWD/chatdlg.ui \
 	$$PWD/groupchatdlg.ui \
diff -urN -X psidiff.ignore sources/src/userlist.cpp work/src/userlist.cpp
--- sources/src/userlist.cpp	2009-03-07 01:53:04.000000000 +0500
+++ work/src/userlist.cpp	2009-03-07 01:53:06.000000000 +0500
@@ -319,6 +319,16 @@
 	return v_mood;
 }
 
+void UserListItem::setActivity(const Activity& activity)
+{
+	v_activity = activity;
+}
+
+const Activity& UserListItem::activity() const
+{
+	return v_activity;
+}
+
 void UserListItem::setTune(const QString& t)
 {
 	v_tune = t;
@@ -489,6 +499,17 @@
 	if(!v_keyID.isEmpty())
 		str += QString("<div style='white-space:pre'>") + QObject::tr("OpenPGP") + ": " + v_keyID.right(8) + "</div>";
 
+	// User Activity
+	if (!activity().isNull()) {
+		str += QString("<div style='white-space:pre'>") + QObject::tr("Activity") + ": " + activity().typeText();
+		if (activity().specificType() != Activity::UnknownSpecific) {
+			str += QString(" - ") + activity().specificTypeText();
+		}
+		if (!activity().text().isEmpty())
+			str += QString(" (") + activity().text() + QString(")");
+		str += "</div>";
+	}
+
 	// User Mood
 	if (!mood().isNull()) {
 		str += QString("<div style='white-space:pre'>") + QObject::tr("Mood") + ": " +
diff -urN -X psidiff.ignore sources/src/userlist.h work/src/userlist.h
--- sources/src/userlist.h	2009-03-07 01:53:04.000000000 +0500
+++ work/src/userlist.h	2009-03-07 01:53:06.000000000 +0500
@@ -29,6 +29,7 @@
 #include "xmpp_resource.h"
 #include "xmpp_liverosteritem.h"
 #include "mood.h"
+#include "activity.h"
 #include "geolocation.h"
 #include "physicallocation.h"
 #include "utilities/maybe.h"
@@ -124,6 +125,7 @@
 	QString makeDesc() const;
 	bool isPrivate() const;
 	const Mood& mood() const;
+	const Activity& activity() const;
 
 	void setJid(const XMPP::Jid &);
 	void setInList(bool);
@@ -131,6 +133,7 @@
 	void setPresenceError(const QString &);
 	void setPrivate(bool);
 	void setMood(const Mood&);
+	void setActivity(const Activity&);
 	void setTune(const QString&);
 	const QString& tune() const;
 	void setGeoLocation(const GeoLocation&);
@@ -162,6 +165,7 @@
 	QString v_keyID;
 	QPixmap v_avatar;
 	Mood v_mood;
+	Activity v_activity;
 	QString v_tune;
 	GeoLocation v_geoLocation;
 	PhysicalLocation v_physicalLocation;
