Hello folks

I started to work on one point of our roadmap for Kopete 1.0 (see 
http://techbase.kde.org/Projects/Kopete/Roadmap)

As a first proof-of-concept, I implemented Kopete::DeleteContactTask.

The design is to have Kopete::Contact create the DeleteContactTask with the 
correct parameter. To handle deleting using protocol specific, it add a sub 
job coming from protocol code (via protocolDeleteTask()), thanks to 
KCompositeJob, the base of Kopete::Task

As in the future we will have many tasks that will depend on some protocol 
code, I think a factory class to create protocol subjobs will be better for a 
cleaner design than instead keeping adding protected methods to 
Kopete::Contact or other classes.

As now, the task doesn't support undo or redo, it could be added to the design 
if we really need it. Also, some actions like removing a metacontact will 
need to be recoded to take into account the job properly.
For example, the metacontact will not be removed from Kopete if one of the 
contacts can't be deleted. We need to handle this case.
-- 
Michaël Larouche
KDE developer working on Kopete, Gamefu(KDE), Solid...on dial-up :P
--------------------------------------
Website: http://www.tehbisnatch.org/
MSN: [EMAIL PROTECTED]
IRC: irc.freenode.org/DarkShock
Jabber/email: [EMAIL PROTECTED]
Index: libkopete/kopetecontactlist.cpp
===================================================================
--- libkopete/kopetecontactlist.cpp	(révision 661477)
+++ libkopete/kopetecontactlist.cpp	(copie de travail)
@@ -1,7 +1,7 @@
 /*
     kopetecontactlist.cpp - Kopete's Contact List backend
 
-    Copyright (c) 2005      by Michael Larouche       <[EMAIL PROTECTED]>
+    Copyright (c) 2005-2007 by Michael Larouche       <[EMAIL PROTECTED]>
     Copyright (c) 2002-2003 by Martijn Klingens       <[EMAIL PROTECTED]>
     Copyright (c) 2002-2004 by Olivier Goffart        <[EMAIL PROTECTED]>
     Copyright (c) 2002      by Duncan Mac-Vicar Prett <[EMAIL PROTECTED]>
@@ -20,29 +20,32 @@
 
 #include "kopetecontactlist.h"
 
-#include <qdir.h>
-#include <qregexp.h>
-#include <qtimer.h>
-//Added by qt3to4:
-#include <QTextStream>
+// Qt includes
+#include <QtCore/QDir>
+#include <QtCore/QRegExp>
+#include <QtCore/QTimer>
+#include <QtCore/QTextStream>
 
+// KDE includes
+#include <kabc/stdaddressbook.h>
 #include <kapplication.h>
-#include <kabc/stdaddressbook.h>
 #include <kdebug.h>
+#include <kglobal.h>
 #include <ksavefile.h>
 #include <kstandarddirs.h>
-#include <kglobal.h>
-#include "kopetemetacontact.h"
-#include "kopetecontact.h"
-#include "kopetechatsession.h"
-//#include "kopetemessage.h"
-#include "kopetepluginmanager.h"
-#include "kopeteprotocol.h"
+
+// Kopete includes
 #include "kopeteaccount.h"
 #include "kopeteaccountmanager.h"
+#include "kopetechatsession.h"
+#include "kopetecontact.h"
+#include "kopetedeletecontacttask.h"
+#include "kopetegeneralsettings.h"
 #include "kopetegroup.h"
+#include "kopetemetacontact.h"
 #include "kopetepicture.h"
-#include "kopetegeneralsettings.h"
+#include "kopetepluginmanager.h"
+#include "kopeteprotocol.h"
 #include "xmlcontactstorage.h"
 
 namespace  Kopete
@@ -256,11 +259,12 @@
 	}
 
 	//removes subcontact from server here and now.
-	QList<Contact *> cts = m->contacts();
-	QListIterator<Contact *> it(cts);
-	while( it.hasNext() )
+	Kopete::Contact *contactToDelete = 0;
+	foreach( contactToDelete, m->contacts() )
 	{
-		it.next()->deleteContact();
+		// TODO: Check for good execution of task
+		Kopete::DeleteContactTask *deleteTask = contactToDelete->deleteContactTask();
+		deleteTask->start();
 	}
 
 	d->contacts.removeAll( m );
Index: libkopete/tasks/kopetedeletecontacttask.h
===================================================================
--- libkopete/tasks/kopetedeletecontacttask.h	(révision 0)
+++ libkopete/tasks/kopetedeletecontacttask.h	(révision 0)
@@ -0,0 +1,110 @@
+/*
+    kopetedeletecontacttask.h - Kopete Delete Contact Task
+
+    Copyright (c) 2007      by Michaël Larouche      <[EMAIL PROTECTED]>
+
+    Kopete    (c) 2002-2007 by the Kopete developers <kopete-devel@kde.org>
+
+    *************************************************************************
+    *                                                                       *
+    * This library is free software; you can redistribute it and/or         *
+    * modify it under the terms of the GNU Lesser General Public            *
+    * License as published by the Free Software Foundation; either          *
+    * version 2 of the License, or (at your option) any later version.      *
+    *                                                                       *
+    *************************************************************************
+*/
+#ifndef KOPETE_DELETECONTACTTASK_H
+#define KOPETE_DELETECONTACTTASK_H
+
+#include <kopete_export.h>
+#include <kopetetask.h>
+
+namespace Kopete
+{
+
+class Contact;
+/**
+ * @brief Delete a contact in Kopete
+ *
+ * Example code:
+ * @code
+Kopete::DeleteContactTask *deleteTask = new Kopete::DeleteContactTask(aContact);
+deleteTask->addSubTask( new JabberDeleteContactTask(aContact) );
+connect(deleteTask, SIGNAL(result(KJob*)), receiver, SLOT(slotResult(KJob*)));
+deleteTask->start();
+ * @endcode
+ *
+ * @section protocol_delete Implementing protocol subtask for deleting
+ * It is a good idea to inherit from DeleteContactTask. In your implementation
+ * of start() method, please DO NOT class parent start() from DeleteContactTask,
+ * otherwise the task will always return an error.
+ *
+ * DeleteContactTask will delete the contact after the subjob,
+ * so you don't need to explicit call deleteLater() on contact.
+ *
+ * Next, you don't need to check if the network(or account if you prefer)
+ * is available, DeleteContactTask do it for you.
+ *
+ * @author Michaël Larouche <[EMAIL PROTECTED]>
+ */
+class DeleteContactTask : public Kopete::Task
+{
+	Q_OBJECT
+public:
+	/**
+	 * Error code for this task
+	 */
+	enum DeleteContactTaskError
+	{
+		/**
+		 * Forgot to add the protocol subtask for deleting the contact
+		 */
+		NoProtocolSubTaskError = KJob::UserDefinedError+1,
+		/**
+		 * The network is unavailable and thus cannot delete the contact
+		 */
+		NetworkUnavailableError
+    };
+
+	/**
+	 * @brief Delete the given contact
+	 * @param contact Kopete contact to delete
+	 */
+	DeleteContactTask(Kopete::Contact *contact);
+	/**
+	 * @internal
+	 * Destructor
+	 */
+	~DeleteContactTask();
+
+	/**
+	 * @brief Begin the task.
+	 * Inherited from KJob::start()
+	 */
+	virtual void start();
+
+protected:
+	/**
+	 * @brief Get access to Kopete::Contact being deleted.
+	 * @return a Kopete::Contact pointer.
+	 */
+	Kopete::Contact *contact();
+
+protected Q_SLOTS:
+	/**
+	 * @brief Execute the next sub job
+	 *
+	 * This slot is called when a subjob has finished.
+	 * @param subJob sub job that has been finished.
+	 */
+	virtual void slotResult(KJob *subJob);
+
+private:
+	class Private;
+	Private *d;
+};
+
+}
+
+#endif
Index: libkopete/tasks/kopetetask.h
===================================================================
--- libkopete/tasks/kopetetask.h	(révision 661821)
+++ libkopete/tasks/kopetetask.h	(copie de travail)
@@ -39,6 +39,12 @@
 	Task(QObject *parent = 0);
 	virtual ~Task();
 
+	/**
+	 * @brief Add a new sub task
+	 * @param task a new task
+	 */
+	void addSubTask(KJob *task);
+
 private:
 	class Private;
 	Private *d;
Index: libkopete/tasks/kopetedeletecontacttask.cpp
===================================================================
--- libkopete/tasks/kopetedeletecontacttask.cpp	(révision 0)
+++ libkopete/tasks/kopetedeletecontacttask.cpp	(révision 0)
@@ -0,0 +1,96 @@
+/*
+    kopetedeletecontacttask.h - Kopete Delete Contact Task
+
+    Copyright (c) 2007      by Michaël Larouche      <[EMAIL PROTECTED]>
+
+    Kopete    (c) 2002-2007 by the Kopete developers <kopete-devel@kde.org>
+
+    *************************************************************************
+    *                                                                       *
+    * This library is free software; you can redistribute it and/or         *
+    * modify it under the terms of the GNU Lesser General Public            *
+    * License as published by the Free Software Foundation; either          *
+    * version 2 of the License, or (at your option) any later version.      *
+    *                                                                       *
+    *************************************************************************
+*/
+#include "kopetedeletecontacttask.h"
+
+// Qt includes
+#include <QtCore/QPointer>
+
+// KDE includes
+#include <kdebug.h>
+
+// Kopete includes
+#include <kopeteaccount.h>
+#include <kopetecontact.h>
+
+namespace Kopete
+{
+
+class DeleteContactTask::Private
+{
+public:
+	QPointer<Kopete::Contact> contact;
+};
+
+DeleteContactTask::DeleteContactTask(Kopete::Contact *contact)
+ : Kopete::Task(contact), d(new Private)
+{
+	d->contact = contact;
+}
+
+DeleteContactTask::~DeleteContactTask()
+{
+	delete d;
+}
+
+void DeleteContactTask::start()
+{
+	if( subjobs().empty() )
+	{
+		kDebug(14010) << k_funcinfo << "ERROR: No protocol sub task added to the class" << endl;
+		setError( DeleteContactTask::NoProtocolSubTaskError );
+		emitResult();
+		return;
+	}
+
+	if( d->contact->account() && !d->contact->account()->isConnected() )
+	{
+		kDebug(14010) << k_funcinfo << "ERROR: Network is unavailable" << endl;
+		setError( DeleteContactTask::NetworkUnavailableError );
+		emitResult();
+		return;
+	}
+
+	kDebug(14010) << k_funcinfo << "Executing subjobs for deleting a contact." << endl;
+	KJob *subTask = 0;
+	foreach( subTask, subjobs() )
+	{
+		subTask->start();
+	}
+}
+
+Kopete::Contact *DeleteContactTask::contact()
+{
+	return d->contact;
+}
+
+void DeleteContactTask::slotResult(KJob *job)
+{
+	KCompositeJob::slotResult(job);
+	// We executed all subjobs, delete the contact from memory.
+	// This is the default behavior from Kopete::Contact old deleteContact()
+	// method.
+	if( !job->error() && subjobs().empty() )
+	{
+		kDebug(14010) << k_funcinfo << "Deleting Kopete::Contact from memory" << endl;
+		d->contact->deleteLater();
+		emitResult();
+	}
+}
+
+} // namespace Kopete
+
+#include "kopetedeletecontacttask.moc"
Index: libkopete/tasks/kopetetask.cpp
===================================================================
--- libkopete/tasks/kopetetask.cpp	(révision 661821)
+++ libkopete/tasks/kopetetask.cpp	(copie de travail)
@@ -38,6 +38,11 @@
 	delete d;
 }
 
+void Task::addSubTask(KJob *task)
+{
+	addSubjob(task);
 }
 
+}
+
 #include "kopetetask.moc"
Index: libkopete/kopetecontact.h
===================================================================
--- libkopete/kopetecontact.h	(révision 661477)
+++ libkopete/kopetecontact.h	(copie de travail)
@@ -4,6 +4,7 @@
     Copyright (c) 2002-2004 by Duncan Mac-Vicar Prett <[EMAIL PROTECTED]>
     Copyright (c) 2002-2003 by Martijn Klingens       <[EMAIL PROTECTED]>
     Copyright (c) 2002-2004 by Olivier Goffart        <[EMAIL PROTECTED]>
+    Copyright (c) 2007      by Michaël Larouche       <[EMAIL PROTECTED]>
 
     Kopete    (c) 2002-2004 by the Kopete developers  <kopete-devel@kde.org>
 
@@ -32,6 +33,8 @@
 class KMenu;
 class KAction;
 
+class KJob;
+
 namespace Kopete
 {
 
@@ -43,6 +46,7 @@
 class Protocol;
 class Account;
 class StatusMessage;
+class DeleteContactTask;
 
 typedef QList<Group *> GroupList;
 
@@ -50,6 +54,7 @@
  * @author Duncan Mac-Vicar P. <[EMAIL PROTECTED]>
  * @author Martijn Klingens <[EMAIL PROTECTED]>
  * @author Olivier Goffart <[EMAIL PROTECTED]>
+ * @author Michaël Larouche <[EMAIL PROTECTED]>
  *
  * This class abstracts a generic contact
  * Use it for inserting contacts in the contact list for example.
@@ -427,6 +432,9 @@
 	 */
 	void setPhoto(const QString &photoPath);
 
+	// TODO: rename to deleteContact();
+	Kopete::DeleteContactTask *deleteContactTask();
+
 public slots:
 	/**
 	 * This should typically pop up a KopeteChatWindow
@@ -473,13 +481,14 @@
 	virtual void sync(unsigned int changed = 0xFF);
 
 	/**
+	 * @deprecated Use DeleteContactTask instead.
 	 * Method to delete a contact from the contact list,
 	 * should be implemented by protocol plugin to handle
 	 * protocol-specific actions required to delete a contact
 	 * (ie. messages to the server, etc)
 	 * the default implementation simply call deleteLater()
 	 */
-	virtual void deleteContact();
+	virtual KDE_DEPRECATED void deleteContact();
 
 	/**
 	 * This is the Contact level slot for sending files. It should be
@@ -497,6 +506,13 @@
 	virtual void sendFile( const KUrl &sourceURL = KUrl(),
 			       const QString &fileName = QString::null, uint fileSize = 0L );
 
+protected:
+	/**
+	 * Method called by deleteContactTask() to create the
+	 * protocol subjob to delete a contact.
+	 */
+	virtual KJob *protocolDeleteTask();
+
 private slots:
 
 	/**
Index: libkopete/kopetecontact.cpp
===================================================================
--- libkopete/kopetecontact.cpp	(révision 661477)
+++ libkopete/kopetecontact.cpp	(copie de travail)
@@ -3,7 +3,8 @@
 
     Copyright (c) 2002-2004 by Duncan Mac-Vicar Prett <[EMAIL PROTECTED]>
     Copyright (c) 2002-2003 by Martijn Klingens       <[EMAIL PROTECTED]>
-    Copyright (c) 2002-2004 by Olivier Goffart        <ogoffart @tiscalinet.be>
+    Copyright (c) 2002-2004 by Olivier Goffart        <ogoffart @ kde.org>
+    Copyright (c) 2007      by Michaël Larouche       <[EMAIL PROTECTED]>
 
     Kopete    (c) 2002-2004 by the Kopete developers  <kopete-devel@kde.org>
 
@@ -49,6 +50,7 @@
 #include "metacontactselectorwidget.h"
 #include "kopeteemoticons.h"
 #include "kopetestatusmessage.h"
+#include <kopetedeletecontacttask.h>
 
 //For the moving to another metacontact dialog
 #include <qlabel.h>
@@ -487,7 +489,8 @@
 		QString::fromLatin1("askRemoveContact"), KMessageBox::Notify | KMessageBox::Dangerous )
 		== KMessageBox::Continue )
 	{
-		deleteContact();
+		Kopete::DeleteContactTask *deleteTask = deleteContactTask();
+		deleteTask->start();
 	}
 }
 
@@ -883,6 +886,31 @@
 	setProperty( Kopete::Global::Properties::self()->photo(), photoPath );
 }
 
+Kopete::DeleteContactTask *Contact::deleteContactTask()
+{
+	Kopete::DeleteContactTask *deleteTask = new Kopete::DeleteContactTask(this);
+	deleteTask->addSubTask( protocolDeleteTask() );
+	return deleteTask;
+}
+
+KJob *Contact::protocolDeleteTask()
+{
+	class DefaultJob : public Kopete::DeleteContactTask
+	{
+	public:
+		DefaultJob(Kopete::Contact *contact) : DeleteContactTask(contact) {}
+		virtual void start()
+		{
+			kDebug(14010) << k_funcinfo << "Using default subjob delete task." << endl;
+			contact()->deleteContact();
+			emitResult();
+		}
+	};
+	DefaultJob *defaultJob = new DefaultJob(this);
+
+	return defaultJob;
+}
+
 } //END namespace Kopete
 
 #include "kopetecontact.moc"
Index: libkopete/CMakeLists.txt
===================================================================
--- libkopete/CMakeLists.txt	(révision 661821)
+++ libkopete/CMakeLists.txt	(copie de travail)
@@ -50,6 +50,7 @@
 
 set(kopete_tasks_SRCS
   tasks/kopetetask.cpp
+  tasks/kopetedeletecontacttask.cpp
 )
 
 set(kopete_LIB_SRCS
@@ -205,6 +206,7 @@
   kopeteuiglobal.h
   kopeteversion.h
   tasks/kopetetask.h
+  tasks/kopetedeletecontacttask.h
 DESTINATION ${INCLUDE_INSTALL_DIR}/kopete )
 
 install( FILES org.kde.kopete.Client.xml DESTINATION ${DBUS_INTERFACES_DIR} )

Attachment: pgp0iCU5iU43P.pgp
Description: PGP signature

_______________________________________________
kopete-devel mailing list
kopete-devel@kde.org
https://mail.kde.org/mailman/listinfo/kopete-devel

Reply via email to