diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-02-16 20:17:18 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-02-16 20:17:18 +0000 |
commit | cb7eddb91455a69cf66fcd717e91a51ca5e2cfef (patch) | |
tree | cf5546e4d7c44370fbe9ca2be937bd254f30ebaa /lib/plugin.h | |
download | kpilot-cb7eddb91455a69cf66fcd717e91a51ca5e2cfef.tar.gz kpilot-cb7eddb91455a69cf66fcd717e91a51ca5e2cfef.zip |
Moved kpilot from kdepim to applications, as the core Trinity libraries should not contain hardware-dependent software
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kpilot@1221127 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'lib/plugin.h')
-rw-r--r-- | lib/plugin.h | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/lib/plugin.h b/lib/plugin.h new file mode 100644 index 0000000..5300c58 --- /dev/null +++ b/lib/plugin.h @@ -0,0 +1,476 @@ +#ifndef _KPILOT_PLUGIN_H +#define _KPILOT_PLUGIN_H +/* KPilot +** +** Copyright (C) 2001 by Dan Pilone +** Copyright (C) 2002-2004,2006 Adriaan de Groot <groot@kde.org> +** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> +** +*/ + +/* +** This program 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.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-pim@kde.org +*/ + +#include <tqstringlist.h> + +#include "syncAction.h" + +/** @file +* This file defines the base class of all KPilot conduit plugins configuration +* dialogs. This is necessary so that we have a fixed API to talk to from +* inside KPilot. +* +* The factories used by KPilot plugins are also documented here. +*/ + + +class TQTabWidget; +class KAboutData; +class KLibrary; + +class PilotDatabase; + +namespace Pilot +{ + /** + * As the API for conduits may change in the course of time, + * identify them and refuse to load incompatible API versions. + * Bump this number every release to the current YYYYMMDD + * value. + */ + static const unsigned int PLUGIN_API = 20061118; +} + +/** +* ConduitConfigBase is for configuration purposes. +* +* ConduitConfigBase: this is an object (with a widget!) that is embedded +* in a dialog. This is the currently preferred form for configuration, +* and it's what is used in the KPilot conduit configuration dialog. +* The factory is asked for a "ConduitConfigBase" object. +* +* NB. The reason that this is a TQObject which needs to create a +* separate widget - instead of a TQWidget subclass - has to do with +* tqlayouting. If you make the widget with designer then the easiest +* thing to do is to use a grid tqlayout there. Making ConduitConfigBase +* a TQWidget subclass would require an additional tqlayout here, which +* seems a little foolish. +* +*/ +class KDE_EXPORT ConduitConfigBase : public QObject +{ +Q_OBJECT +public: + /** + * Constructor. Creates a conduit configuration support object + * with the given parent @p parent and name (optional) @p n. + */ + ConduitConfigBase(TQWidget *parent=0L, const char *n=0L); + + /** Destructor. */ + virtual ~ConduitConfigBase(); + + /** + * This function is called to check whether the configuration + * of the conduit has changed -- and hence, whether the user + * needs to be prompted. By default, this just returns + * fModified, but you can do more complicated things. + */ + virtual bool isModified() const + { + return fModified; + } ; + + /** Accessor for the actual widget for the configuration. */ + TQWidget *widget() const + { + return fWidget; + } ; + + /** + * Load or save the config widget's settings in the given + * KConfig object; leave the group unchanged. load() and + * commit() should both call unmodified() to indicate that + * the current settings match the on-disk ones. + */ + virtual void commit() = 0; + virtual void load() = 0; + /** + * Called when the object is to be hidden again and might + * need to save changed settings. Should prompt the user + * and call commit() if needed. Override this function only + * if you need a very different kind of prompt window. + * + * Returns false if the change is to be canceled. Returns + * true otherwise, whether or not the changes were saved. + */ + virtual bool maybeSave(); + + TQString conduitName() const { return fConduitName; } ; + + /** + * This is the function that does the work of adding an about + * page to a tabwidget. It is made public and static so that + * it can be used elsewhere wherever tabwidgets appear. + * + * The about tab is created using aboutPage(). The new about + * widget is added to the tab widget @p w with the heading + * "About". + * + * @param w The tab widget to which the about page is added. + * @param data The KAboutData that is used. + * + */ + static void addAboutPage(TQTabWidget *w, + KAboutData *data=0L); + + /** + * This creates the actual about widget. Again, public & static so + * you can slap in an about widget wherever. + * + * An about widget is created that shows the contributors to + * the application, along with copyright information and the + * application's icon. This widget can be used pretty much + * anywhere. Copied from KAboutDialog, mostly. + * + * @param parent The widget that holds the about widget. + * @param data The KAboutData that is used to populate the widget. + */ + static TQWidget *aboutPage(TQWidget *parent, KAboutData *data=0L); + +protected: + /** + * This function provides the string for the prompt used + * in maybeSave(). Override it to change the text. + */ + virtual TQString maybeSaveText() const; + + void unmodified() { fModified=false; } ; + + bool fModified; + TQWidget *fWidget; + TQString fConduitName; + + +protected slots: + void modified(); +signals: + void changed(bool); + +} ; + + +/** +* Create-Update-Delete tracking of the plugin, +* used for reporting purposes (in a consistent manner). The intent +* is that this class is used by the conduit as it is syncing data. +* For this to be useful (and be used properly), the conduit needs +* to tell us how many creates, updates, and deletes it has made to +* a data store (PC or HH). It also needs to tell us how many +* records it started with and how many records it has at the +* conclusion of its processing. Using this information, we can +* report on it consistently as well as analyze the activity taken +* by the conduit and offer rollback functionality if we think the +* conduit has behaved improperly. +*/ +class KDE_EXPORT CUDCounter +{ +public: + /** Create new counter initialized to 0, and be told what + * kind of CUD we're counting (PC or Handheld, etc.) */ + CUDCounter(TQString s); + + /** Track the creation of @p c items */ + void created(unsigned int c=1); + /** Track updates to @p u items */ + void updated(unsigned int u=1); + /** Track the destruction of @p d items */ + void deleted(unsigned int d=1); + /** How many @p t items did we start with? */ + void setStartCount(unsigned int t); + /** How many @p t items did we end with? */ + void setEndCount(unsigned int t); + + unsigned int countCreated() { return fC; } + unsigned int countUpdated() { return fU; } + unsigned int countDeleted() { return fD; } + unsigned int countStart() { return fStart; } + unsigned int countEnd() { return fEnd; } + + /** percentage of changes. unfortunately, we have to rely on our + * developers (hi, self!) to correctly set total number of records + * conduits start with, so add a little protection... + */ + unsigned int percentCreated() { return (fEnd > 0 ? fC/fEnd : 0); } + unsigned int percentUpdated() { return (fEnd > 0 ? fU/fEnd : 0); } + unsigned int percentDeleted() { return (fStart > 0 ? fD/fStart : 0); } + + /** Measurement Of Objects -- report numbers of + * objects created, updated, deleted. This + * string is already i18n()ed. + */ + TQString moo() const; + + /** Type of counter(Handheld or PC). This string is already + * i18n()ed. + */ + TQString type() const { return fType; } +private: + /** keep track of Creates, Updates, Deletes, and Total + * number of records so we can detect abnormal behavior and + * hopefully prevent data loss. + */ + unsigned int fC,fU,fD,fStart,fEnd; + + /** What kind of CUD are we keeping track of so we can + * moo() it out later? (PC, Handheld, etc.) + */ + TQString fType; +} ; + + +/** +* The SyncActions created by the factory should obey at least +* the argument test, indicating a dry run. The device link is +* the link where the sync should run -- don't get the pilotPort() +* until the sync runs! +* +* setConfig() will be called before the sync starts so that the +* conduit can read/write metadata and local settings. +*/ + +class KDE_EXPORT ConduitAction : public SyncAction +{ +Q_OBJECT + +public: + ConduitAction(KPilotLink *, + const char *name=0L, + const TQStringList &args = TQStringList()); + virtual ~ConduitAction(); + + /** ConduitAction is done doing work. Allow it to sanity-check the + * results + */ + void finished(); + + TQString conduitName() const { return fConduitName; } ; + + /** Retrieve the sync mode set for this action. */ + const SyncMode &syncMode() const { return fSyncDirection; }; + + /** + * A full sync happens for eFullSync, eCopyPCToHH and eCopyHHToPC. It + * completely ignores all modified flags and walks through all records + * in the database. + */ + bool isFullSync() const + { + return fFirstSync || fSyncDirection.isFullSync() ; + } + + /** + * A first sync (i.e. database newly fetched from the handheld ) + * does not check for deleted records, but understands them as + * added on the other side. The flag is set by the conduits + * when opening the local database, or the calendar/addressbook + * (if it is empty). This also implies a full sync. + */ + bool isFirstSync() const + { + return fFirstSync || fSyncDirection.isFirstSync() ; + } + +protected: + /** Retrieve the conflict resolution setting for this action. */ + ConflictResolution getConflictResolution() const + { return fConflictResolution; }; + + /** Try to change the sync mode from what it is now to the mode @p m. + * This may fail (ie. changing a backup to a restore is not kosher) and + * changeSync() will return false then. + */ + bool changeSync(SyncMode::Mode m); + + // Set the conflict resolution, except if the resolution + // form is UseGlobalSetting, in which case nothing changes + // (assumes then that the resolution form is already set + // according to that global setting). + // + void setConflictResolution(ConflictResolution res) + { + if (SyncAction::eUseGlobalSetting != res) + fConflictResolution=res; + } + + void setFirstSync(bool first) { fFirstSync=first; } ; + + PilotDatabase *fDatabase; + PilotDatabase *fLocalDatabase; // Guaranteed to be a PilotLocalDatabase + + /** + * Open both the local copy of database @p dbName + * and the version on the Pilot. Return true only + * if both opens succeed. If the local copy of the database + * does not exist, it is retrieved from the handheld. In this + * case, retrieved is set to true, otherwise it is left alone + * (i.e. retains its value and is not explicitly set to false). + * + * @param dbName database name to open. + * @param retrieved indicator whether the database had to be loaded + * from the handheld. + */ + bool openDatabases(const TQString &dbName, bool*retrieved=0L); + + /** + * Name of the conduit; might be changed by subclasses. Should + * normally be set in the constructor. + */ + TQString fConduitName; + + /** Every plugin has 2 CUDCounters--one for keeping track of + * changes made to PC data and one for keeping track of Palm data. */ + CUDCounter *fCtrHH; + CUDCounter *fCtrPC; + +private: + SyncMode fSyncDirection; + ConflictResolution fConflictResolution; + + bool fFirstSync; +} ; + +/** +* The ConduitProxy action delays loading the plugin for a conduit until the conduit +* actually executes; the proxy then loads the file, creates a SyncAction for the conduit +* and runs that. Once the conduit has finished, the proxy unloads everything +* and emits syncDone(). +*/ +class ConduitProxy : public ConduitAction +{ +Q_OBJECT + +public: + ConduitProxy(KPilotLink *, + const TQString &desktopName, + const SyncAction::SyncMode &m); + +protected: + virtual bool exec(); +protected slots: + void execDone(SyncAction *); + +protected: + TQString fDesktopName; + TQString fLibraryName; + ConduitAction *fConduit; +} ; + +/** A namespace containing only static helper methods. */ +namespace PluginUtility +{ + /** Searches the argument list for --foo=bar and returns bar, TQString::null if not found. + * Don't include the -- in the argname. */ + TQString findArgument(const TQStringList &a, const TQString argname); + + /** + * This function attempts to detect whether or not the given + * application is running. If it is, true is returned, otherwise + * false. + * + * The current approach is to ask the DCOP server if the application + * has registered. + */ + bool isRunning(const TQCString &appName); + + /** + * Check a given library for its version, returning 0 if no + * version symbol is found. + */ + unsigned long pluginVersion(const KLibrary *); + TQString pluginVersionString(const KLibrary *); +} + +/** +* All KPilot conduits should subclass KLibFactory like this. +* +* Boilerplate for inheritance: +* +* <pre> +* class KPilotPlugin : public KLibFactory +* { +* Q_OBJECT +* +* public: +* KPilotPlugin(TQObject * = 0L,const char * = 0L) ; +* virtual ~KPilotPlugin(); +* </pre> +* +* You don't @em have to provide about information for the plugin, +* but it's useful, particularly for the about box in a conduit. +* +* +* <pre> +* static KAboutData *about() { return fAbout; } ; +* </pre> +* +* +* This is what it's all about: creating objects for the plugin. +* One classname that @em must be supported is ConduitConfig, +* which is defined above. The other is SyncAction. +* +* +* <pre> +* protected: +* virtual TQObject* createObject( TQObject* parent = 0, +* const char* name = 0, +* const char* classname = "TQObject", +* const TQStringList &args = TQStringList() ); +* </pre> +* +* More boilerplate, and support for an instance and about data, used +* by about() above. +* +* <pre> +* KInstance *fInstance; +* static KAboutData *fAbout; +* } ; +* </pre> +* +* +* +* The implementation of a conduit needs an init_conduit_name() function, +* just like any KLibLoader library that uses factories. +* +* The createObject() function needs to support at least two creation +* calls: "ConduitConfigBase" and "SyncAction". +* "ConduitConfigBase" should return a subclass of ConduitConfigBase, +* "SyncAction" a subclass of SyncAction. +* +* Finally, a conduit should have a symbol version_conduit_name, +* that returns a long; much like the init_conduit_name() function. This +* should return the version of the plugin API (KPILOT_PLUGIN_VERSION) +* the conduit was compiled against. Additionally, a plugin may have a +* id_conduit_name, which should be a const char *. +* +*/ + +#endif |