desktop: added concept of configured PST type mask
[barry.git] / desktop / src / osconfig.h
blob3709cd8b8b22c4858bb5c02520e146d8b7b11742
1 ///
2 /// \file osconfig.h
3 /// Class which detects a set of available or known devices
4 /// in an opensync-able system.
5 ///
7 /*
8 Copyright (C) 2009-2012, Net Direct Inc. (http://www.netdirect.ca/)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #ifndef __BARRY_OSCONFIG_H__
24 #define __BARRY_OSCONFIG_H__
26 #include <barry/barry.h>
27 #include <memory>
28 #include <tr1/memory>
29 #include <stdexcept>
30 #include "osbase.h"
31 #include "ostypes.h"
32 #include <iostream>
34 namespace OpenSync { namespace Config {
36 // Exception class for configuration load errors
37 class LoadError : public std::exception
39 std::string m_msg;
40 public:
41 LoadError(const std::string &msg) : m_msg(msg) {}
42 virtual ~LoadError() throw() {}
43 virtual const char* what() const throw() { return m_msg.c_str(); }
46 class SaveError : public std::exception
48 std::string m_msg;
49 public:
50 SaveError(const std::string &msg) : m_msg(msg) {}
51 virtual ~SaveError() throw() {}
52 virtual const char* what() const throw() { return m_msg.c_str(); }
55 /// Thrown when a member cannot be deleted from the group
56 class DeleteError : public std::logic_error
58 public:
59 DeleteError(const std::string &msg) : std::logic_error(msg) {}
62 // Base class for all opensync plugin configurations
63 class Plugin
65 long m_member_id; // -1 if not saved to the group yet
67 public:
68 Plugin()
69 : m_member_id(-1)
73 virtual ~Plugin()
77 virtual long GetMemberId() const { return m_member_id; }
78 virtual void SetMemberId(long id) { m_member_id = id; }
81 // operations
84 virtual Plugin* Clone() const = 0;
86 /// IsUnsupported() returns true if the config format for this
87 /// plugin has no OpenSync::Config::* class to parse / handle it.
88 virtual bool IsUnsupported() const { return true; }
89 virtual std::string GetAppName() const = 0; // returns a GUI-friendly
90 // name for the application that this plugin
91 // is for... i.e. plugin name might
92 // be "evo2-sync" but the app name
93 // would be "Evolution"
94 /// Throws SaveError if member_id is -1
95 virtual void Save(OpenSync::API &api, const std::string &group_name) const = 0;
96 // sample implementation:
97 //{
98 // api.GetConverter().Save(*this, group_name);
99 //}
100 virtual std::string GetPluginName(OpenSync::API &api) const = 0;
101 // sample implementation:
103 // return api.GetConverter().GetPluginName(*this);
105 virtual bool IsConfigured(OpenSync::API &api) const = 0;
106 // sample implementation:
108 // return api.GetConverter().IsConfigured(*this);
110 virtual pst_type GetConfiguredSyncTypes() const { return PST_NONE; }
111 virtual pst_type GetSupportedSyncTypes(OpenSync::API &api) const = 0;
112 // sample implementation:
114 // return api.GetConverter().GetSupportedSyncTypes(*this)
115 // && GetConfiguredSyncTypes();
118 /// Support function for Group::Compare(). If plugin is the
119 /// same type as this, sametype is set to true. If sametype
120 /// is true, and the data is functionally equivalent,
121 /// equal is set to true. Returns (sametype && equal).
122 virtual bool Compare(const Plugin &plugin,
123 bool &sametype, bool &equal) const
125 sametype = equal = false;
126 return sametype && equal;
130 class Unsupported : public Plugin
132 private:
133 // configuration settings
134 std::string m_raw_config;
136 public:
137 Unsupported()
141 explicit Unsupported(Converter *load_converter, const Member &member)
143 load_converter->Load(*this, member);
146 const std::string& GetRawConfig() const { return m_raw_config; }
148 void SetRawConfig(const std::string &c) { m_raw_config = c; }
150 // virtual overrides
151 virtual Unsupported* Clone() const { return new Unsupported(*this); }
152 virtual bool IsUnsupported() const { return true; }
153 virtual std::string GetAppName() const { return AppName(); }
154 virtual void Save(OpenSync::API &api, const std::string &group_name) const
156 api.GetConverter().Save(*this, group_name);
158 virtual std::string GetPluginName(OpenSync::API &api) const
160 return api.GetConverter().GetPluginName(*this);
162 virtual bool IsConfigured(OpenSync::API &api) const
164 return api.GetConverter().IsConfigured(*this);
166 virtual pst_type GetSupportedSyncTypes(OpenSync::API &api) const
168 return api.GetConverter().GetSupportedSyncTypes(*this) &
169 GetConfiguredSyncTypes();;
172 // statics
173 static std::string AppName() { return "Unsupported"; }
176 class Barry : public Plugin
178 private:
179 // configuration settings
180 bool m_debug_mode;
181 ::Barry::Pin m_pin;
182 std::string m_password;
184 protected:
185 // This constructor is protected, so that only derived
186 // classes can create a configuration without a pin number.
187 Barry()
188 : m_debug_mode(false)
192 public:
193 explicit Barry(const ::Barry::Pin &pin)
194 : m_debug_mode(false)
195 , m_pin(pin)
197 if( !m_pin.Valid() )
198 throw std::logic_error("Barry config must have valid pin number.");
201 explicit Barry(Converter *load_converter, const Member &member)
202 : m_debug_mode(false)
204 load_converter->Load(*this, member);
206 // check that the loaded pin is valid... if not, it is
207 // likely safe to assume that something is horribly wrong.
208 // in the case where the Application wishes to add a new
209 // barry plugin, it should use the Pin constructor.
210 // if you *really* need to try to salvage an old
211 // corrupt config, you can always do the
212 // converter->Load(barry_obj) manually, and pick out
213 // the left overs.
215 if( !m_pin.Valid() ) {
216 std::ostringstream oss;
217 oss << "Unable to load pin number from Barry plugin config. Consider this group corrupt, or not fully configured: " << member;
218 throw LoadError(oss.str());
222 bool IsDebugMode() const { return m_debug_mode; }
223 ::Barry::Pin GetPin() const { return m_pin; }
224 std::string GetPassword() const { return m_password; }
226 void DebugMode(bool mode = true) { m_debug_mode = mode; }
227 void SetPin(const ::Barry::Pin &pin) { m_pin = pin; }
228 void SetPassword(const std::string &pass) { m_password = pass; }
230 // virtual overrides
231 virtual Barry* Clone() const { return new Barry(*this); }
232 virtual bool IsUnsupported() const { return false; }
233 virtual std::string GetAppName() const { return AppName(); }
234 virtual void Save(OpenSync::API &api, const std::string &group_name) const
236 api.GetConverter().Save(*this, group_name);
238 virtual std::string GetPluginName(OpenSync::API &api) const
240 return api.GetConverter().GetPluginName(*this);
242 virtual bool IsConfigured(OpenSync::API &api) const
244 return api.GetConverter().IsConfigured(*this);
246 virtual pst_type GetConfiguredSyncTypes() const
248 return m_pin.Valid() ? PST_ALL : PST_NONE;
250 virtual pst_type GetSupportedSyncTypes(OpenSync::API &api) const
252 return api.GetConverter().GetSupportedSyncTypes(*this) &
253 GetConfiguredSyncTypes();
255 virtual bool Compare(const Plugin &plugin,
256 bool &sametype, bool &equal) const
258 sametype = equal = false;
259 const Barry *other = dynamic_cast<const Barry*> (&plugin);
260 if( other ) {
261 sametype = true;
263 if( m_debug_mode == other->m_debug_mode &&
264 m_pin == other->m_pin &&
265 m_password == other->m_password )
266 equal = true;
268 return sametype && equal;
271 // statics
272 static std::string AppName() { return "Barry"; }
273 static std::string PluginName(OpenSync::API &api)
275 return api.GetConverter().GetPluginName(Barry());
277 static pst_type SupportedSyncTypes(OpenSync::API &api)
279 return api.GetConverter().GetSupportedSyncTypes(Barry());
283 class Evolution : public Plugin
285 private:
286 // configuration settings
287 std::string m_address_path;
288 std::string m_calendar_path;
289 std::string m_tasks_path;
290 std::string m_memos_path;
292 protected:
293 static void SetIfExists(std::string &var, const std::string &dir);
295 public:
296 Evolution()
300 explicit Evolution(Converter *load_converter, const Member &member)
302 load_converter->Load(*this, member);
305 const std::string& GetAddressPath() const { return m_address_path; }
306 const std::string& GetCalendarPath() const { return m_calendar_path; }
307 const std::string& GetTasksPath() const { return m_tasks_path; }
308 const std::string& GetMemosPath() const { return m_memos_path; }
310 void SetAddressPath(const std::string &p) { m_address_path = p; }
311 void SetCalendarPath(const std::string &p) { m_calendar_path = p; }
312 void SetTasksPath(const std::string &p) { m_tasks_path = p; }
313 void SetMemosPath(const std::string &p) { m_memos_path = p; }
315 // specific operations
316 bool AutoDetect(); // throw if unable to detect??
318 // virtual overrides
319 virtual Evolution* Clone() const { return new Evolution(*this); }
320 virtual bool IsUnsupported() const { return false; }
321 virtual std::string GetAppName() const { return AppName(); }
322 virtual void Save(OpenSync::API &api, const std::string &group_name) const
324 api.GetConverter().Save(*this, group_name);
326 virtual std::string GetPluginName(OpenSync::API &api) const
328 return api.GetConverter().GetPluginName(*this);
330 virtual bool IsConfigured(OpenSync::API &api) const
332 return api.GetConverter().IsConfigured(*this);
334 virtual pst_type GetConfiguredSyncTypes() const
336 pst_type pst = PST_NONE;
337 if( m_address_path.size() ) pst |= PST_CONTACTS;
338 if( m_calendar_path.size() ) pst |= PST_EVENTS;
339 if( m_tasks_path.size() ) pst |= PST_TODOS;
340 if( m_memos_path.size() ) pst |= PST_NOTES;
341 return pst;
343 virtual pst_type GetSupportedSyncTypes(OpenSync::API &api) const
345 // supported types include what the plugin is capable of,
346 // ANDed against what has been configured
347 return api.GetConverter().GetSupportedSyncTypes(*this) &
348 GetConfiguredSyncTypes();
350 virtual bool Compare(const Plugin &plugin,
351 bool &sametype, bool &equal) const
353 sametype = equal = false;
354 const Evolution *other = dynamic_cast<const Evolution*> (&plugin);
355 if( other ) {
356 sametype = true;
358 if( m_address_path == other->m_address_path &&
359 m_calendar_path == other->m_calendar_path &&
360 m_tasks_path == other->m_tasks_path &&
361 m_memos_path == other->m_memos_path )
362 equal = true;
364 return sametype && equal;
367 // statics
368 static std::string AppName() { return "Evolution"; }
369 static std::string PluginName(OpenSync::API &api)
371 return api.GetConverter().GetPluginName(Evolution());
373 static pst_type SupportedSyncTypes(OpenSync::API &api)
375 return api.GetConverter().GetSupportedSyncTypes(Evolution());
379 class Evolution3 : public Evolution
381 public:
382 Evolution3()
386 explicit Evolution3(Converter *load_converter, const Member &member)
388 load_converter->Load(*this, member);
391 // virtual overrides
392 virtual Evolution3* Clone() const { return new Evolution3(*this); }
393 virtual std::string GetAppName() const { return AppName(); }
394 virtual void Save(OpenSync::API &api, const std::string &group_name) const
396 api.GetConverter().Save(*this, group_name);
398 virtual std::string GetPluginName(OpenSync::API &api) const
400 return api.GetConverter().GetPluginName(*this);
402 virtual bool IsConfigured(OpenSync::API &api) const
404 return api.GetConverter().IsConfigured(*this);
406 virtual pst_type GetSupportedSyncTypes(OpenSync::API &api) const
408 return api.GetConverter().GetSupportedSyncTypes(*this) &
409 GetConfiguredSyncTypes();
411 virtual bool Compare(const Plugin &plugin,
412 bool &sametype, bool &equal) const
414 sametype = equal = false;
415 const Evolution3 *other = dynamic_cast<const Evolution3*> (&plugin);
416 if( other ) {
417 // we've established that Evolution3 == Evolution3,
418 // but the actual compare can be done by the base
419 // class...
420 return Evolution::Compare(plugin, sametype, equal);
422 else
423 return false;
426 // statics
427 static std::string AppName() { return "Evolution 3"; }
428 static std::string PluginName(OpenSync::API &api)
430 return api.GetConverter().GetPluginName(Evolution3());
432 static pst_type SupportedSyncTypes(OpenSync::API &api)
434 return api.GetConverter().GetSupportedSyncTypes(Evolution3());
438 class Google : public Plugin
440 private:
441 // configuration settings
442 std::string m_username;
443 std::string m_password;
444 bool m_contacts_enabled;
445 bool m_calendar_enabled;
447 public:
448 Google()
449 : m_contacts_enabled(true)
450 , m_calendar_enabled(true)
454 explicit Google(Converter *load_converter, const Member &member)
456 load_converter->Load(*this, member);
459 const std::string& GetUsername() const { return m_username; }
460 const std::string& GetPassword() const { return m_password; }
461 bool IsContactsEnabled() const { return m_contacts_enabled; }
462 bool IsCalendarEnabled() const { return m_calendar_enabled; }
464 void SetUsername(const std::string &u) { m_username = u; }
465 void SetPassword(const std::string &p) { m_password = p; }
466 bool EnableContacts(bool setting = true)
468 bool old = m_contacts_enabled;
469 m_contacts_enabled = setting;
470 return old;
472 bool EnableCalendar(bool setting = true)
474 bool old = m_calendar_enabled;
475 m_calendar_enabled = setting;
476 return old;
479 // virtual overrides
480 virtual Google* Clone() const { return new Google(*this); }
481 virtual bool IsUnsupported() const { return false; }
482 virtual std::string GetAppName() const { return AppName(); }
483 virtual void Save(OpenSync::API &api, const std::string &group_name) const
485 api.GetConverter().Save(*this, group_name);
487 virtual std::string GetPluginName(OpenSync::API &api) const
489 return api.GetConverter().GetPluginName(*this);
491 virtual bool IsConfigured(OpenSync::API &api) const
493 return api.GetConverter().IsConfigured(*this);
495 virtual pst_type GetConfiguredSyncTypes() const
497 pst_type pst = PST_NONE;
498 if( m_contacts_enabled ) pst |= PST_CONTACTS;
499 if( m_calendar_enabled ) pst |= PST_EVENTS;
500 return pst;
502 virtual pst_type GetSupportedSyncTypes(OpenSync::API &api) const
504 return api.GetConverter().GetSupportedSyncTypes(*this) &
505 GetConfiguredSyncTypes();
507 virtual bool Compare(const Plugin &plugin,
508 bool &sametype, bool &equal) const
510 sametype = equal = false;
511 const Google *other = dynamic_cast<const Google*> (&plugin);
512 if( other ) {
513 sametype = true;
515 if( m_username == other->m_username &&
516 m_password == other->m_password &&
517 m_contacts_enabled == other->m_contacts_enabled &&
518 m_calendar_enabled == other->m_calendar_enabled )
519 equal = true;
521 return sametype && equal;
524 // statics
525 static std::string AppName() { return "Google Calendar"; }
526 static std::string PluginName(OpenSync::API &api)
528 return api.GetConverter().GetPluginName(Google());
530 static pst_type SupportedSyncTypes(OpenSync::API &api)
532 return api.GetConverter().GetSupportedSyncTypes(Google());
536 class KDEPim : public Plugin
538 private:
539 // version 0.22 has no config
541 public:
542 KDEPim()
546 explicit KDEPim(Converter *load_converter, const Member &member)
548 load_converter->Load(*this, member);
551 // virtual overrides
552 virtual KDEPim* Clone() const { return new KDEPim(*this); }
553 virtual bool IsUnsupported() const { return false; }
554 virtual std::string GetAppName() const { return AppName(); }
555 virtual void Save(OpenSync::API &api, const std::string &group_name) const
557 api.GetConverter().Save(*this, group_name);
559 virtual std::string GetPluginName(OpenSync::API &api) const
561 return api.GetConverter().GetPluginName(*this);
563 virtual bool IsConfigured(OpenSync::API &api) const
565 return api.GetConverter().IsConfigured(*this);
567 virtual pst_type GetConfiguredSyncTypes() const
569 return PST_ALL;
571 virtual pst_type GetSupportedSyncTypes(OpenSync::API &api) const
573 return api.GetConverter().GetSupportedSyncTypes(*this) &
574 GetConfiguredSyncTypes();
576 virtual bool Compare(const Plugin &plugin,
577 bool &sametype, bool &equal) const
579 sametype = equal = false;
580 const KDEPim *other = dynamic_cast<const KDEPim*> (&plugin);
581 if( other ) {
582 sametype = true;
584 // no data for this config, so always equal
585 equal = true;
587 return sametype && equal;
590 // statics
591 static std::string AppName() { return "KDEPim / Kontact"; }
592 static std::string PluginName(OpenSync::API &api)
594 return api.GetConverter().GetPluginName(KDEPim());
596 static pst_type SupportedSyncTypes(OpenSync::API &api)
598 return api.GetConverter().GetSupportedSyncTypes(KDEPim());
603 // Group
605 /// This class handles the loading of all the config plugins in a
606 /// given group.
608 class Group :
609 private std::vector<std::tr1::shared_ptr<OpenSync::Config::Plugin> >
611 public:
612 typedef std::tr1::shared_ptr<OpenSync::Config::Plugin> value_type;
613 typedef std::tr1::shared_ptr<Group> group_ptr;
614 typedef value_type plugin_ptr;
615 typedef std::vector<value_type> base_type;
616 typedef base_type::iterator iterator;
617 typedef base_type::const_iterator const_iterator;
619 private:
620 std::string m_group_name;
622 protected:
623 static void BarryCheck(OpenSync::API &api,
624 const std::string &group_name,
625 const member_list_type &members,
626 unsigned throw_mask);
628 // not copyable... use Clone()
629 Group(const Group &other);
630 Group& operator=(const Group &other);
632 public:
633 // OpenSync Config Group Throw Masks
634 #define OSCG_THROW_ON_UNSUPPORTED 0x01
635 #define OSCG_THROW_ON_NO_BARRY 0x02
636 #define OSCG_THROW_ON_MULTIPLE_BARRIES 0x04
638 /// This constructor loads an existing Group from the
639 /// given OpenSync api resource, filling the vector
640 /// array with the required plugin config classes.
642 /// If desired, specify a mask, which will cause the
643 /// constructor to throw exceptions on the given conditions.
645 /// OSCG_THROW_ON_UNSUPPORTED - if set, the constructor will
646 /// throw LoadError if there is a plugin in the group
647 /// for which there is no corresponding Plugin-
648 /// derived class to handle it
649 /// OSCG_THROW_ON_NO_BARRY - if set, the constructor will
650 /// throw LoadError if there are no Barry plugins
651 /// in the group
652 /// OSCG_THROW_ON_MULTIPLE_BARRIES - if set, the constructor will
653 /// throw LoadError if there is more than one Barry
654 /// plugin in the group
656 Group(const std::string &group_name, OpenSync::API &api,
657 unsigned throw_mask = 0);
659 /// This constructor creates an empty, but named, Group.
660 explicit Group(const std::string &group_name);
662 bool HasUnsupportedPlugins() const;
663 bool HasBarryPlugins() const;
664 bool GroupExists(OpenSync::API &api) const;
665 bool AllConfigured(OpenSync::API &api) const;
666 int GetConnectedCount() const;
667 const std::string& GetGroupName() const { return m_group_name; }
669 /// Cycles through all plugins and ANDs the supported types
670 /// for each together, and returns it. The returned value is
671 /// the minimum set of supportable sync types for this group for
672 /// the given API engine.
673 pst_type GetSupportedSyncTypes(OpenSync::API &api) const;
675 /// Returns comma separated string of application/plugin names,
676 /// excluding Barry
677 std::string GetAppNames() const;
679 /// Returns a reference to the (first) Barry plugin in the group.
680 /// Will throw std::logic_error if not found.
681 OpenSync::Config::Barry& GetBarryPlugin();
682 const OpenSync::Config::Barry& GetBarryPlugin() const;
684 /// Returns a pointer to the first non-Barry plugin in the group.
685 /// Returns 0 if not found.
686 OpenSync::Config::Plugin* GetNonBarryPlugin();
687 const OpenSync::Config::Plugin* GetNonBarryPlugin() const;
689 /// Sets the member_id of all plugins to -1, thereby making them
690 /// appear like they have never been saved to an API before.
691 /// A call to Save() after a call to DisconnectMembers() will
692 /// create a completely new group. Note that if the group name
693 /// already exists in the API, saving to it again may cause
694 /// a low level exception to be thrown.
695 void DisconnectMembers();
697 /// Loads all available plugins from the named group, using
698 /// the api given. If this Group isn't empty (size() != 0),
699 /// then DisconnectMembers() will be called first.
700 void Load(OpenSync::API &api, unsigned throw_mask = 0);
701 /// Same as Load() above, but loads from src_group_name instead
702 /// of m_group_name. m_group_name will not be changed.
703 void Load(const std::string &src_group_name, OpenSync::API &api,
704 unsigned throw_mask = 0);
706 /// Overwrites m_group_name with a new one.
707 void ResetGroupName(const std::string &new_group_name);
709 /// Adds plugin to group, and takes ownership of the pointer
710 void AddPlugin(OpenSync::Config::Plugin *plugin);
712 /// Remove the plugin from the group. Only can guarantee removal
713 /// of non-saved (i.e. disconnected) plugins. If a plugin has
714 /// already been saved to the underlying OpenSync API, it
715 /// may not be possible to delete just one member from the
716 /// group (0.22), and a DeleteError will be thrown.
718 /// If you don't want to actually delete any members from any
719 /// existing configs, then DisconnectMembers() first.
720 void DeletePlugin(iterator i, OpenSync::API &api);
722 /// Returns true if it is possible to resave this
723 /// Group to the existing opensync config. If this returns
724 /// false, and there are connected members, Save() will
725 /// throw. Save() will automatically call this function
726 /// during saving.
728 /// Note: only call this if GroupExists() is true, otherwise,
729 /// this function is irrelevant.
730 bool GroupMatchesExistingConfig(OpenSync::API &api);
732 /// Save all plugins as members of the group. If the group doesn't
733 /// exist, it will be created. If the group does exist, and its
734 /// existing plugin list and member_id's don't match this Group's
735 /// list, SaveError will be thrown. If a plugin doesn't have a
736 /// member_id, it will be added as a new member to the group and
737 /// given an id. Note that an exception thrown from this function
738 /// means that the group is left in an undefined state. Best to
739 /// delete it and start over. Or load it, delete it (through the API),
740 /// disconnect it, and save it again.
741 void Save(OpenSync::API &api);
743 /// Compares against another group, including all the plugins,
744 /// and each plugin data. Order of plugins in group does not
745 /// matter, nor do file-specific data, like member IDs.
746 /// If saving both groups would result in functionally equivalent
747 /// sync groups, then they are equal. This is used to avoid
748 /// re-saving when not necessary.
749 /// Returns true if equal.
750 bool Compare(const Group &group) const;
752 /// Clones this Group object and returns a group_ptr of the new one
753 group_ptr Clone() const;
755 /// Forget all plugins and delete them all
756 using base_type::clear;
758 // bring underlying implementation forward
759 using base_type::size;
760 using base_type::begin;
761 using base_type::end;
762 using base_type::operator[];
766 }} // namespace OpenSync::Config
768 #endif