[conduit/gsoc09_alexandre: 124/125] Merge branch 'master' into gsoc09_alexandre



commit 3198084babaae620559f66c00b15b7f6817da27b
Merge: afe7530 57158f4
Author: Alexandre Rosenfeld <alexandre rosenfeld gmail com>
Date:   Thu Sep 23 22:05:18 2010 -0300

    Merge branch 'master' into gsoc09_alexandre
    
    Conflicts:
    	conduit/DBus.py
    	conduit/Main.py
    	conduit/ModuleWrapper.py
    	conduit/SyncSet.py
    	conduit/conduit.real
    	conduit/dataproviders/HalFactory.py
    	conduit/dataproviders/VolumeFactory.py
    	conduit/dataproviders/__init__.py
    	conduit/gtkui/UI.py
    	conduit/gtkui/WindowConfigurator.py
    	conduit/modules/FileModule/FileModule.py
    	conduit/modules/iPodModule/iPodModule.py

 AUTHORS                                            |    1 +
 ChangeLog => ChangeLog-20090720                    |    0
 INSTALL                                            |   17 +-
 MAINTAINERS                                        |    8 +
 Makefile.am                                        |   24 +-
 NEWS                                               |   21 +-
 conduit.doap                                       |    6 +-
 conduit/Conduit.py                                 |    9 +
 conduit/DBus.py                                    |   41 +-
 conduit/Database.py                                |   20 +-
 conduit/Globals.py                                 |    8 +
 conduit/Knowledge.py                               |   23 +-
 conduit/Main.py                                    |  100 +-
 conduit/Makefile.am                                |    5 +-
 conduit/Module.py                                  |    2 +-
 conduit/ModuleWrapper.py                           |   11 +-
 conduit/Settings.py                                |    2 +-
 conduit/SyncSet.py                                 |   11 +-
 conduit/Synchronization.py                         |    4 +-
 conduit/Vfs.py                                     |  290 --
 conduit/Web.py                                     |    6 +-
 conduit/XMLSerialization.py                        |    8 +-
 conduit/__init__.py                                |    8 +-
 conduit/conduit                                    |   35 +-
 conduit/conduit.real                               |   37 -
 conduit/dataproviders/DataProvider.py              |   15 +-
 conduit/dataproviders/File.py                      |    9 +-
 conduit/dataproviders/HalFactory.py                |  118 +-
 conduit/dataproviders/Makefile.am                  |    2 +-
 conduit/dataproviders/MediaPlayerFactory.py        |   66 +
 conduit/dataproviders/VolumeFactory.py             |   58 -
 conduit/datatypes/File.py                          |   38 +-
 conduit/datatypes/__init__.py                      |    2 +-
 conduit/defs.py.in                                 |    3 -
 conduit/gtkui/Canvas.py                            |  103 +-
 conduit/gtkui/ConfigContainer.py                   |    1 -
 conduit/gtkui/ConfigItems.py                       |    3 +-
 conduit/gtkui/ConflictResolver.py                  |   22 +-
 conduit/gtkui/EmbedConfigurator.py                 |    2 +-
 conduit/gtkui/MsgArea.py                           |  278 +--
 conduit/gtkui/Tree.py                              |    9 +-
 conduit/gtkui/UI.py                                |  485 ++--
 conduit/gtkui/WindowConfigurator.py                |    9 +-
 conduit/modules/EvolutionModule/EvolutionModule.py |   33 +-
 .../modules/FacebookModule/pyfacebook/__init__.py  |  167 +-
 conduit/modules/FileModule/FileConfiguration.py    |    7 +-
 conduit/modules/FileModule/FileModule.py           |  120 +-
 conduit/modules/FlickrModule/FlickrModule.py       |   28 +-
 conduit/modules/FlickrModule/Makefile.am           |    2 -
 conduit/modules/FlickrModule/flickrapi/LICENSE     |   27 -
 conduit/modules/FlickrModule/flickrapi/Makefile.am |    5 -
 conduit/modules/FlickrModule/flickrapi/__init__.py |  772 ------
 conduit/modules/FlickrModule/flickrapi/cache.py    |  105 -
 .../modules/FlickrModule/flickrapi/exceptions.py   |   15 -
 .../modules/FlickrModule/flickrapi/multipart.py    |  101 -
 .../FlickrModule/flickrapi/reportinghttp.py        |  101 -
 .../modules/FlickrModule/flickrapi/tokencache.py   |   93 -
 conduit/modules/FlickrModule/flickrapi/xmlnode.py  |  102 -
 conduit/modules/FspotModule/FspotModule.py         |    9 +-
 conduit/modules/GoogleModule/Makefile.am           |   13 -
 conduit/modules/GoogleModule/atom/Makefile.am      |    5 -
 conduit/modules/GoogleModule/atom/__init__.py      | 1407 ----------
 conduit/modules/GoogleModule/atom/auth.py          |   37 -
 conduit/modules/GoogleModule/atom/client.py        |  111 -
 conduit/modules/GoogleModule/atom/core.py          |  395 ---
 conduit/modules/GoogleModule/atom/http.py          |  286 --
 conduit/modules/GoogleModule/atom/http_core.py     |  407 ---
 .../modules/GoogleModule/atom/http_interface.py    |  158 --
 conduit/modules/GoogleModule/atom/mock_http.py     |  132 -
 .../modules/GoogleModule/atom/mock_http_core.py    |  141 -
 conduit/modules/GoogleModule/atom/mock_service.py  |  243 --
 conduit/modules/GoogleModule/atom/service.py       |  726 -----
 conduit/modules/GoogleModule/atom/token_store.py   |  117 -
 conduit/modules/GoogleModule/atom/url.py           |  139 -
 conduit/modules/GoogleModule/calendar-config.glade |  254 --
 .../GoogleModule/gdata/Crypto/Cipher/AES.pyd       |  Bin 27648 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/ARC2.pyd      |  Bin 15872 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/ARC4.pyd      |  Bin 8704 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/Blowfish.pyd  |  Bin 19968 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/CAST.pyd      |  Bin 26112 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/DES.pyd       |  Bin 20480 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/DES3.pyd      |  Bin 20992 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/IDEA.pyd      |  Bin 15360 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/RC5.pyd       |  Bin 15872 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/XOR.pyd       |  Bin 8704 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Cipher/__init__.py   |   33 -
 .../modules/GoogleModule/gdata/Crypto/Hash/HMAC.py |  108 -
 .../modules/GoogleModule/gdata/Crypto/Hash/MD2.pyd |  Bin 8704 -> 0 bytes
 .../modules/GoogleModule/gdata/Crypto/Hash/MD4.pyd |  Bin 9728 -> 0 bytes
 .../modules/GoogleModule/gdata/Crypto/Hash/MD5.py  |   13 -
 .../GoogleModule/gdata/Crypto/Hash/RIPEMD.pyd      |  Bin 14336 -> 0 bytes
 .../modules/GoogleModule/gdata/Crypto/Hash/SHA.py  |   11 -
 .../GoogleModule/gdata/Crypto/Hash/SHA256.pyd      |  Bin 9216 -> 0 bytes
 .../GoogleModule/gdata/Crypto/Hash/__init__.py     |   24 -
 .../gdata/Crypto/Protocol/AllOrNothing.py          |  295 --
 .../GoogleModule/gdata/Crypto/Protocol/Chaffing.py |  229 --
 .../GoogleModule/gdata/Crypto/Protocol/__init__.py |   17 -
 .../GoogleModule/gdata/Crypto/PublicKey/DSA.py     |  238 --
 .../GoogleModule/gdata/Crypto/PublicKey/ElGamal.py |  132 -
 .../GoogleModule/gdata/Crypto/PublicKey/RSA.py     |  256 --
 .../gdata/Crypto/PublicKey/__init__.py             |   17 -
 .../GoogleModule/gdata/Crypto/PublicKey/pubkey.py  |  172 --
 .../GoogleModule/gdata/Crypto/PublicKey/qNEW.py    |  170 --
 .../GoogleModule/gdata/Crypto/Util/RFC1751.py      |  342 ---
 .../GoogleModule/gdata/Crypto/Util/__init__.py     |   16 -
 .../GoogleModule/gdata/Crypto/Util/number.py       |  201 --
 .../GoogleModule/gdata/Crypto/Util/randpool.py     |  421 ---
 .../modules/GoogleModule/gdata/Crypto/Util/test.py |  453 ----
 .../modules/GoogleModule/gdata/Crypto/__init__.py  |   25 -
 conduit/modules/GoogleModule/gdata/Crypto/test.py  |   38 -
 conduit/modules/GoogleModule/gdata/Makefile.am     |    7 -
 conduit/modules/GoogleModule/gdata/__init__.py     |  835 ------
 conduit/modules/GoogleModule/gdata/alt/__init__.py |   20 -
 .../modules/GoogleModule/gdata/alt/appengine.py    |  302 ---
 .../modules/GoogleModule/gdata/apps/Makefile.am    |    5 -
 .../modules/GoogleModule/gdata/apps/__init__.py    |  496 ----
 .../gdata/apps/emailsettings/__init__.py           |   15 -
 .../gdata/apps/emailsettings/service.py            |  250 --
 .../GoogleModule/gdata/apps/migration/__init__.py  |  212 --
 .../GoogleModule/gdata/apps/migration/service.py   |  129 -
 conduit/modules/GoogleModule/gdata/apps/service.py |  449 ----
 conduit/modules/GoogleModule/gdata/auth.py         |  929 -------
 .../modules/GoogleModule/gdata/base/Makefile.am    |    5 -
 .../modules/GoogleModule/gdata/base/__init__.py    |  687 -----
 conduit/modules/GoogleModule/gdata/base/service.py |  256 --
 .../modules/GoogleModule/gdata/blogger/Makefile.am |    5 -
 .../modules/GoogleModule/gdata/blogger/__init__.py |  202 --
 .../modules/GoogleModule/gdata/blogger/service.py  |  142 -
 .../GoogleModule/gdata/calendar/Makefile.am        |    5 -
 .../GoogleModule/gdata/calendar/__init__.py        |  907 -------
 .../modules/GoogleModule/gdata/calendar/service.py |  595 ----
 conduit/modules/GoogleModule/gdata/client.py       |  101 -
 .../GoogleModule/gdata/codesearch/Makefile.am      |    5 -
 .../GoogleModule/gdata/codesearch/__init__.py      |  136 -
 .../GoogleModule/gdata/codesearch/service.py       |  109 -
 .../GoogleModule/gdata/contacts/Makefile.am        |    5 -
 .../GoogleModule/gdata/contacts/__init__.py        |  355 ---
 .../modules/GoogleModule/gdata/contacts/service.py |  335 ---
 .../modules/GoogleModule/gdata/docs/Makefile.am    |    5 -
 .../modules/GoogleModule/gdata/docs/__init__.py    |   66 -
 conduit/modules/GoogleModule/gdata/docs/service.py |  286 --
 .../modules/GoogleModule/gdata/exif/Makefile.am    |    5 -
 .../modules/GoogleModule/gdata/exif/__init__.py    |  217 --
 conduit/modules/GoogleModule/gdata/geo/__init__.py |  185 --
 .../modules/GoogleModule/gdata/media/Makefile.am   |    5 -
 .../modules/GoogleModule/gdata/media/__init__.py   |  331 ---
 .../modules/GoogleModule/gdata/oauth/CHANGES.txt   |   17 -
 .../modules/GoogleModule/gdata/oauth/__init__.py   |  524 ----
 conduit/modules/GoogleModule/gdata/oauth/rsa.py    |  120 -
 .../modules/GoogleModule/gdata/photos/Makefile.am  |    5 -
 .../modules/GoogleModule/gdata/photos/__init__.py  | 1112 --------
 .../modules/GoogleModule/gdata/photos/service.py   |  680 -----
 conduit/modules/GoogleModule/gdata/service.py      | 1627 -----------
 .../GoogleModule/gdata/spreadsheet/Makefile.am     |    5 -
 .../GoogleModule/gdata/spreadsheet/__init__.py     |  474 ----
 .../GoogleModule/gdata/spreadsheet/service.py      |  478 ----
 .../GoogleModule/gdata/spreadsheet/text_db.py      |  559 ----
 conduit/modules/GoogleModule/gdata/test_data.py    | 2838 --------------------
 .../modules/GoogleModule/gdata/tlslite/BaseDB.py   |  120 -
 .../modules/GoogleModule/gdata/tlslite/Checker.py  |  146 -
 .../GoogleModule/gdata/tlslite/FileObject.py       |  220 --
 .../gdata/tlslite/HandshakeSettings.py             |  159 --
 .../modules/GoogleModule/gdata/tlslite/Session.py  |  131 -
 .../GoogleModule/gdata/tlslite/SessionCache.py     |  103 -
 .../GoogleModule/gdata/tlslite/SharedKeyDB.py      |   58 -
 .../GoogleModule/gdata/tlslite/TLSConnection.py    | 1600 -----------
 .../GoogleModule/gdata/tlslite/TLSRecordLayer.py   | 1123 --------
 .../GoogleModule/gdata/tlslite/VerifierDB.py       |   90 -
 conduit/modules/GoogleModule/gdata/tlslite/X509.py |  133 -
 .../GoogleModule/gdata/tlslite/X509CertChain.py    |  181 --
 .../modules/GoogleModule/gdata/tlslite/__init__.py |   39 -
 conduit/modules/GoogleModule/gdata/tlslite/api.py  |   75 -
 .../GoogleModule/gdata/tlslite/constants.py        |  225 --
 .../modules/GoogleModule/gdata/tlslite/errors.py   |  149 -
 .../gdata/tlslite/integration/AsyncStateMachine.py |  235 --
 .../gdata/tlslite/integration/ClientHelper.py      |  163 --
 .../gdata/tlslite/integration/HTTPTLSConnection.py |  169 --
 .../gdata/tlslite/integration/IMAP4_TLS.py         |  132 -
 .../gdata/tlslite/integration/IntegrationHelper.py |   52 -
 .../gdata/tlslite/integration/POP3_TLS.py          |  142 -
 .../gdata/tlslite/integration/SMTP_TLS.py          |  114 -
 .../tlslite/integration/TLSAsyncDispatcherMixIn.py |  139 -
 .../tlslite/integration/TLSSocketServerMixIn.py    |   59 -
 .../integration/TLSTwistedProtocolWrapper.py       |  196 --
 .../gdata/tlslite/integration/XMLRPCTransport.py   |  137 -
 .../gdata/tlslite/integration/__init__.py          |   17 -
 .../modules/GoogleModule/gdata/tlslite/mathtls.py  |  170 --
 .../modules/GoogleModule/gdata/tlslite/messages.py |  561 ----
 .../GoogleModule/gdata/tlslite/utils/AES.py        |   31 -
 .../GoogleModule/gdata/tlslite/utils/ASN1Parser.py |   34 -
 .../gdata/tlslite/utils/Cryptlib_AES.py            |   34 -
 .../gdata/tlslite/utils/Cryptlib_RC4.py            |   28 -
 .../gdata/tlslite/utils/Cryptlib_TripleDES.py      |   35 -
 .../gdata/tlslite/utils/OpenSSL_AES.py             |   49 -
 .../gdata/tlslite/utils/OpenSSL_RC4.py             |   25 -
 .../gdata/tlslite/utils/OpenSSL_RSAKey.py          |  148 -
 .../gdata/tlslite/utils/OpenSSL_TripleDES.py       |   44 -
 .../gdata/tlslite/utils/PyCrypto_AES.py            |   22 -
 .../gdata/tlslite/utils/PyCrypto_RC4.py            |   22 -
 .../gdata/tlslite/utils/PyCrypto_RSAKey.py         |   61 -
 .../gdata/tlslite/utils/PyCrypto_TripleDES.py      |   22 -
 .../GoogleModule/gdata/tlslite/utils/Python_AES.py |   68 -
 .../GoogleModule/gdata/tlslite/utils/Python_RC4.py |   39 -
 .../gdata/tlslite/utils/Python_RSAKey.py           |  209 --
 .../GoogleModule/gdata/tlslite/utils/RC4.py        |   17 -
 .../GoogleModule/gdata/tlslite/utils/RSAKey.py     |  264 --
 .../GoogleModule/gdata/tlslite/utils/TripleDES.py  |   26 -
 .../GoogleModule/gdata/tlslite/utils/__init__.py   |   31 -
 .../gdata/tlslite/utils/cipherfactory.py           |  111 -
 .../GoogleModule/gdata/tlslite/utils/codec.py      |   94 -
 .../GoogleModule/gdata/tlslite/utils/compat.py     |  140 -
 .../GoogleModule/gdata/tlslite/utils/cryptomath.py |  403 ---
 .../GoogleModule/gdata/tlslite/utils/dateFuncs.py  |   75 -
 .../GoogleModule/gdata/tlslite/utils/entropy.c     |  173 --
 .../GoogleModule/gdata/tlslite/utils/hmac.py       |  104 -
 .../gdata/tlslite/utils/jython_compat.py           |  195 --
 .../GoogleModule/gdata/tlslite/utils/keyfactory.py |  243 --
 .../GoogleModule/gdata/tlslite/utils/rijndael.py   |  392 ---
 .../GoogleModule/gdata/tlslite/utils/win32prng.c   |   63 -
 .../GoogleModule/gdata/tlslite/utils/xmltools.py   |  201 --
 conduit/modules/GoogleModule/gdata/urlfetch.py     |  247 --
 .../GoogleModule/gdata/webmastertools/__init__.py  |  542 ----
 .../GoogleModule/gdata/webmastertools/service.py   |  516 ----
 .../modules/GoogleModule/gdata/youtube/Makefile.am |    5 -
 .../modules/GoogleModule/gdata/youtube/__init__.py |  684 -----
 .../modules/GoogleModule/gdata/youtube/service.py  | 1557 -----------
 conduit/modules/Makefile.am                        |    2 +-
 conduit/modules/N800Module/N800Module.py           |    4 +-
 conduit/modules/RhythmboxModule/RhythmboxModule.py |   34 +-
 conduit/modules/ShotwellModule/Makefile.am         |    7 +
 conduit/modules/ShotwellModule/ShotwellModule.py   |  104 +
 .../geo => ShotwellModule/shotwell}/Makefile.am    |    2 +-
 .../modules/ShotwellModule/shotwell/__init__.py    |  233 ++
 conduit/modules/TestModule.py                      |   20 +
 conduit/modules/TomboyModule.py                    |   11 +-
 .../{ => UNSUPPORTED}/GoogleModule/GoogleModule.py |    0
 .../modules/UNSUPPORTED/GoogleModule/Makefile.am   |    5 +
 .../{ => UNSUPPORTED}/GoogleModule/__init__.py     |    0
 .../GoogleModule/contacts_example.py               |    0
 .../PicasaDesktopModule/PicasaDesktopModule.py     |    2 +-
 conduit/modules/{ => UNSUPPORTED}/SynceModule.py   |    0
 conduit/modules/ZotoModule/Makefile.am             |    2 +-
 conduit/modules/iPodModule/iPodModule.py           |  172 ++-
 conduit/platform/FilePython.py                     |   95 -
 conduit/platform/Makefile.am                       |    5 +-
 conduit/platform/WebBrowserMozilla.py              |  139 -
 conduit/platform/__init__.py                       |  180 +--
 conduit/utils/AutostartManager.py                  |   47 +
 conduit/utils/Makefile.am                          |    1 +
 conduit/utils/Singleton.py                         |    8 +-
 conduit/utils/UDev.py                              |   25 +
 conduit/utils/__init__.py                          |   26 +-
 conduit/{platform/FileGio.py => vfs/File.py}       |  232 ++-
 conduit/vfs/Makefile.am                            |    7 +
 conduit/vfs/__init__.py                            |  204 ++
 configure.ac                                       |   52 +-
 data/Makefile.am                                   |    5 +-
 data/conduit-progress.svg                          |  831 ------
 data/conduit.desktop.in.in                         |    1 -
 data/{conduit.glade => conduit.ui}                 |  889 +++----
 data/evolution-memos.png                           |  Bin 964 -> 0 bytes
 data/evolution-tasks.png                           |  Bin 1132 -> 0 bytes
 data/icons/hicolor/16x16/status/Makefile.am        |    8 -
 .../hicolor/16x16/status/conduit-progress-1.png    |  Bin 761 -> 0 bytes
 .../hicolor/16x16/status/conduit-progress-2.png    |  Bin 777 -> 0 bytes
 .../hicolor/16x16/status/conduit-progress-3.png    |  Bin 738 -> 0 bytes
 .../hicolor/16x16/status/conduit-progress-4.png    |  Bin 783 -> 0 bytes
 .../hicolor/16x16/status/conduit-progress-5.png    |  Bin 763 -> 0 bytes
 .../hicolor/16x16/status/conduit-progress-6.png    |  Bin 748 -> 0 bytes
 .../hicolor/16x16/status/conduit-progress-7.png    |  Bin 765 -> 0 bytes
 .../hicolor/16x16/status/conduit-progress-8.png    |  Bin 747 -> 0 bytes
 data/note.png                                      |  Bin 0 -> 2644 bytes
 help/Makefile.am                                   |    2 +-
 help/cs/cs.po                                      |  685 +++++
 help/cs/figures/conduit-dp.png                     |  Bin 0 -> 17391 bytes
 help/cs/figures/conduit-folder-configuration.png   |  Bin 0 -> 18221 bytes
 help/cs/figures/conduit-gui-parts.png              |  Bin 0 -> 76326 bytes
 help/cs/figures/conduit-login.png                  |  Bin 0 -> 81866 bytes
 help/cs/figures/network-sync-pc1.png               |  Bin 0 -> 51286 bytes
 help/cs/figures/network-sync-pc2.png               |  Bin 0 -> 50603 bytes
 help/de/de.po                                      |  892 +++++--
 help/sl/sl.po                                      |  686 +++++
 help/zh_CN/zh_CN.po                                | 1043 +++++++
 m4/gnome-doc-utils.m4                              |    3 +
 po/LINGUAS                                         |    5 +
 po/POTFILES.in                                     |    7 +-
 po/POTFILES.skip                                   |   12 +-
 po/cs.po                                           | 1332 +++++-----
 po/da.po                                           | 1044 +++++++
 po/de.po                                           | 1126 +++++----
 po/en_GB.po                                        | 1144 ++++++---
 po/es.po                                           |  562 ++---
 po/eu.po                                           | 1047 ++++++++
 po/fi.po                                           | 1126 ++++++---
 po/fr.po                                           | 1185 +++++----
 po/gl.po                                           | 1625 +++++++-----
 po/hu.po                                           |  378 +---
 po/it.po                                           | 1244 +++++----
 po/nds.po                                          | 1266 +++++++++
 po/pt.po                                           | 2504 ++++++++++-------
 po/pt_BR.po                                        | 1592 ++++++------
 po/ru.po                                           | 1402 +++++++---
 po/sl.po                                           | 1689 ++++++++-----
 po/sv.po                                           | 1201 ++++++----
 po/uk.po                                           | 1042 +++++++
 po/zh_CN.po                                        | 1217 +++++++++
 po/zh_HK.po                                        | 1492 +++++++----
 po/zh_TW.po                                        | 1494 +++++++----
 scripts/CheckGtkMozEmbed.py                        |   12 -
 scripts/get-closed-bugs.sh                         |   26 -
 scripts/run-tests.sh                               |   16 +-
 scripts/update-3rdparty-libs.sh                    |   10 +-
 setup-env.sh                                       |    1 +
 test/python-tests/TestCoreConduit.py               |    1 +
 test/python-tests/TestCoreConflict.py              |    3 +-
 test/python-tests/TestCoreConvert.py               |    4 +-
 test/python-tests/TestCoreConvertAudioVideo.py     |    4 +
 test/python-tests/TestCoreConvertSubtypesArgs.py   |    1 +
 test/python-tests/TestCoreDBus.py                  |    9 +-
 test/python-tests/TestCoreDatatypes.py             |    1 +
 test/python-tests/TestCoreFile.py                  |  570 ++--
 test/python-tests/TestCoreFileCopyMany.py          |   13 +-
 test/python-tests/TestCoreSyncFolderFolder.py      |   11 +-
 test/python-tests/TestCoreSyncFolderFolder2.py     |    7 +
 test/python-tests/TestCoreSyncLogic.py             |    1 +
 test/python-tests/TestCoreSyncTestDataProviders.py |   22 +
 test/python-tests/TestCoreSyncWithConversion.py    |    1 +
 test/python-tests/TestCoreUtil.py                  |    4 +-
 test/python-tests/TestCoreVfs.py                   |  164 +-
 test/python-tests/TestDataProviderFolder.py        |    2 +-
 test/python-tests/TestDataProviderPicasa.py        |    2 +-
 test/python-tests/TestDataProviderSmugMug.py       |    2 +-
 test/python-tests/common.py                        |   45 +-
 test/python-tests/data/1.vcard                     |    5 +-
 test/soup/test_synchronization.py                  |    1 -
 tools/eog-plugin/conduit.py                        |    4 +-
 tools/nautilus-extension/conduit.py                |    4 +-
 tools/test-db-wrapper/main.py                      |   11 +-
 tools/test-db-wrapper/{main.glade => main.ui}      |   64 +-
 339 files changed, 24176 insertions(+), 52464 deletions(-)
---
diff --cc conduit/DBus.py
index bb01ff8,6bbf456..d1dc1d7
--- a/conduit/DBus.py
+++ b/conduit/DBus.py
@@@ -474,26 -447,14 +477,25 @@@ class DBusInterface(DBusItem)
          #type converter and sync manager
          self.type_converter = typeConverter
          self.sync_manager = syncManager
 +
 +        print gconf.all_dirs(GCONF_PATH)
 +        for syncset_path in gconf.all_dirs(GCONF_PATH):
 +            name = syncset_path.split("/")[-1]
 +            if name not in ('gui', 'dbus'):
 +                ss = SyncSet.SyncSet(
 +                         moduleManager=self.moduleManager,
 +                         syncManager=self.sync_manager
 +                     )
 +                new = SyncSetDBusItem(ss, name)
 +                EXPORTED_OBJECTS[new.get_path()] = new
          
          #export the syncsets
-         if guiSyncSet != None:
-             new = SyncSetDBusItem(guiSyncSet, "gui")
-             EXPORTED_OBJECTS[new.get_path()] = new
+         new = SyncSetDBusItem(guiSyncSet, "gui")
+         EXPORTED_OBJECTS[new.get_path()] = new
  
-         if dbusSyncSet != None:
-             new = SyncSetDBusItem(dbusSyncSet, "dbus")
-             EXPORTED_OBJECTS[new.get_path()] = new
+         self.sync_set = SyncSet.SyncSet(moduleManager,syncManager)
+         new = SyncSetDBusItem(self.sync_set, "dbus")
+         EXPORTED_OBJECTS[new.get_path()] = new
              
          #export myself
          EXPORTED_OBJECTS[self.get_path()] = self
@@@ -513,18 -474,6 +515,18 @@@
          new = SyncSetDBusItem(ss, i)
          EXPORTED_OBJECTS[new.get_path()] = new
          return new
 +        
 +    def _new_named_syncset(self, name):
 +        if "/dataprovider/%s" % name in EXPORTED_OBJECTS:
 +            return EXPORTED_OBJECTS["/dataprovider/%s" % name]
 +        else:
 +            ss = SyncSet.SyncSet(
 +                        moduleManager=self.moduleManager,
 +                        syncManager=self.sync_manager
 +                        )
 +            new = SyncSetDBusItem(ss, name)
 +            EXPORTED_OBJECTS[new.get_path()] = new
-             return new        
++            return new
      
      def _get_dataprovider(self, key):
          """
diff --cc conduit/Main.py
index 0f27343,940bb5d..d18d57d
--- a/conduit/Main.py
+++ b/conduit/Main.py
@@@ -189,20 -183,9 +187,15 @@@ class Application(dbus.service.Object)
                          syncManager=conduit.GLOBALS.syncManager,
                          xmlSettingFilePath=self.settingsFile
                          )
+ 
 +        self.dbusSyncSet = SyncSet(
 +                    'dbus',
 +                    moduleManager=conduit.GLOBALS.moduleManager,
 +                    syncManager=conduit.GLOBALS.syncManager
 +                    )
 +
-         #Set the view models
-         if options.build_gui:
-             self.BuildGUI()
-             if not options.iconify:
-                 self.ShowGUI()
-         
          #Dbus view...
-         self.dbus = DBusInterface(
+         conduit.GLOBALS.dbus = DBusInterface(
                          conduitApplication=self,
                          moduleManager=conduit.GLOBALS.moduleManager,
                          typeConverter=conduit.GLOBALS.typeConverter,
diff --cc conduit/Module.py
index fc42825,e04a234..7eea5dc
--- a/conduit/Module.py
+++ b/conduit/Module.py
@@@ -19,170 -15,10 +19,170 @@@ log = logging.getLogger("Module"
  import conduit.dataproviders
  import conduit.ModuleWrapper as ModuleWrapper
  import conduit.Knowledge as Knowledge
- import conduit.Vfs as Vfs
+ import conduit.vfs as Vfs
  
 +class Error(Exception):
 +    pass
 +    
  from gettext import gettext as _
  
 +def is_factory(filename):
 +    return filename.endswith("Factory.py")
 +
 +def is_module(filename):
 +    return filename.endswith("Module.py")
 +
 +def is_module_dir(dirname):
 +    return dirname.endswith("Module")
 +    
 +def is_valid_path(path):
 +    return is_factory(path) or is_module(path)
 +
 +class ModuleInfo(object):
 +
 +    def __init__(self, path):
 +        self.path = path
 +        self.mtime = os.stat(path).st_mtime
 +        self.internal_modules = []
 +        self.factories = []
 +        self.cached = False
 +        self.cached_info = []
 +
 +    def _import_file(self, filename):
 +        """
 +        Tries to import the specified file. Returns the python module on succes.
 +        Primarily for internal use. Note that the python module returned may actually
 +        contain several more loadable modules.
 +        """
 +        mods = pydoc.importfile (filename)
 +        try:
 +            if (mods.MODULES): pass
 +        except AttributeError:
 +            log.warn("The file %s is not a valid module. Skipping." % (filename))
 +            log.warn("A module must have the variable MODULES defined as a dictionary.")
 +            raise
 +        for modules, infos in mods.MODULES.items():
 +            for i in ModuleWrapper.COMPULSORY_ATTRIBUTES:
 +                if i not in infos:
 +                    log.warn("Class %s in file %s does define a %s attribute. Skipping." % (modules, filename, i))
 +                    raise Exception
 +        return mods
 +    
 +    def _load_module(self, classname, *args, **kwargs):
 +        mod = self._import_file(self.path)
 +        for module, info in mod.MODULES.items():
 +            klass = getattr(mod, module)
 +            if getattr(klass, '__name__') == classname:
 +                return klass(*args, **kwargs)
 +        raise Error("Module %s not found" % classname)
 +    
 +    def load(self):
 +        if self.cached and not self.is_factory():
 +            for module_info in self.cached_info:
 +                mod_wrapper = ModuleWrapper.ModuleWrapper(
 +                    klass=self._load_module,
 +                    initargs=(module_info['classname'],),
 +                    category=module_info['category'],
 +                    cached_info=module_info,
 +                )
 +                self.internal_modules.append((mod_wrapper, module_info['classname']))
 +        else:
 +            mod = self._import_file(self.path)
 +            for name, info in mod.MODULES.items():
 +                klass = getattr(mod, name)
 +                if info["type"] == "dataprovider" or info["type"] == "converter":
 +                    mod_wrapper = ModuleWrapper.ModuleWrapper(
 +                        klass=klass,
 +                        initargs=(),
 +                        category=getattr(klass, "_category_", conduit.dataproviders.CATEGORY_TEST)
 +                    )
 +                    #Save the module (signal is emitted in _append_module)
 +                    #self._append_module(
 +                    #        mod_wrapper,
 +                    #        klass
 +                    #        )
 +                    self.internal_modules.append((mod_wrapper, klass))
 +                    self.cached_info.append(mod_wrapper.get_info())
 +                    #modules_cache.append(mod_wrapper.get_info())
 +                    #log.critical("Saving to cache %s" % mod_wrapper.get_info())                        
 +                elif info["type"] == "dataprovider-factory":
 +                    #log.critical("Creating factory %s" % self.path)
 +                    # build a dict of kwargs to pass to factories
 +                    kwargs = {
 +                        "moduleManager": self,
 +                    }
 +                    #instantiate and store the factory
 +                    instance = klass(**kwargs)
 +                    self.factories.append(instance)
 +                else:
 +                    log.warn("Class is an unknown type: %s" % klass)
 +            #except AttributeError:
 +            #    log.warn("Could not find module %s in %s\n%s" % (modules,filename,traceback.format_exc()))
 +
 +    def is_factory(self):
 +        return is_factory(self.path)
 +
 +    def is_module(self):
 +        return is_module(self.path)
 +        
 +class CacheManager(object):
 +
 +    def __init__(self, cache_filename = "modules.list"):
 +        self.cache_path = os.path.join(conduit.USER_CACHE_DIR, cache_filename)
 +        self.modules = {}
 +        self._load_cache()
 +        
 +    def _load_cache(self):
 +        if not os.path.exists(self.cache_path):
 +            log.info("No modules cache found (doing a cold start)")
 +            return
 +        cache_file = open(self.cache_path, "rb")
 +        try:
 +            cache_contents = pickle.load(cache_file)
 +            #We check all the contents so we dont load an invalid cache
 +            for path, module_info in cache_contents.iteritems():
 +                
 +                if not isinstance(path, basestring):
 +                    raise Error("Error loading cache: key is not a string (clearing cache)")
 +                self.modules[path] = ModuleInfo(path)
 +                self.modules[path].mtime = module_info['mtime']
 +                self.modules[path].cached_info = module_info['cached_info']
 +        except Exception:
 +            log.warn("Modules cache invalid (clearing cache)")
 +            self.modules = {}
 +        finally:
 +            cache_file.close()
 +
 +    def _save_cache(self):
 +        log.critical("Saving cache")
 +        cache = {}
 +        for module in self.modules.values():
 +            cache[module.path] = {'mtime': module.mtime, 'cached_info': module.cached_info}
 +        cache_file = open(self.cache_path, "wb")
 +        try:
 +            pickle.dump(cache, cache_file)
 +        finally:
 +            cache_file.close()       
 +            
 +    def add_module(self, path):
 +        if path in self.modules and self.modules[path].mtime == os.stat(path).st_mtime:
 +            self.modules[path].cached = True
 +        elif os.path.basename(path) not in [os.path.basename(j) for j in self.modules.keys()]:
 +            self.modules[path] = ModuleInfo(path)
 +    
 +    def load(self, blacklist, whitelist):
 +        for module in self.modules.values():
 +            name, ext = Vfs.uri_get_filename_and_extension(module.path)
 +            if whitelist:
 +                if name in whitelist:
 +                    module.load()
 +            elif blacklist:
 +                if name not in blacklist: 
 +                    module.load()
 +            else:
 +                module.load()
 +        self._save_cache()
 +
  class ModuleManager(gobject.GObject):
      """
      Generic dynamic module loader for conduit. Given a path
diff --cc conduit/ModuleWrapper.py
index 640e8d3,6d93bc6..65ddfcc
--- a/conduit/ModuleWrapper.py
+++ b/conduit/ModuleWrapper.py
@@@ -203,13 -157,13 +203,13 @@@ class ModuleWrapper
          may override this function
          """
          import gtk
 -        if not self.icon.has_key(size) or self.icon[size] is None:
 +        if size not in self.icon or self.icon[size] is None:
              if self.module_type in ["source", "sink", "twoway", "category"]:
-                 info = gtk.icon_theme_get_default().lookup_icon(self.icon_name, size, 0)
-                 if info:
+                 try:
+                     info = gtk.icon_theme_get_default().lookup_icon(self.icon_name, size, gtk.ICON_LOOKUP_GENERIC_FALLBACK)
                      self.icon[size] = info.load_icon()
                      self.icon_path = info.get_filename()
 -                except:
 +                else:
                      self.icon[size] = None
                      log.warn("Could not load icon %s for %s" % (self.icon_name, self.name))
                      #Last resort: Try the non icon-naming-spec compliant icon
diff --cc conduit/SyncSet.py
index dc5c854,daf85de..70608e8
--- a/conduit/SyncSet.py
+++ b/conduit/SyncSet.py
@@@ -46,15 -45,8 +46,19 @@@ class SyncSet(gobject.GObject)
          # FIXME: temporary hack - need to let factories know about this factory :-\!
          self.moduleManager.emit("syncset-added", self)
          
++<<<<<<< HEAD
 +    def _unitialize_dataproviders(self, cond):
 +        for dp in cond.get_all_dataproviders():
 +            if dp.module:
 +                try:
 +                    dp.module.uninitialize()
 +                except Exception:
 +                    log.warn("Could not uninitialize %s" % dp, exc_info=True)
 +                
 +    def _restore_dataprovider(self, cond, wrapperKey, dpName="", dpxml="", xml_version="2", trySourceFirst=True):
++=======
+     def _restore_dataprovider(self, cond, wrapperKey, dpName="", dpxml="", trySourceFirst=True):
++>>>>>>> master
          """
          Adds the dataprovider back onto the canvas at the specifed
          location and configures it with the given settings
@@@ -64,12 -56,10 +68,12 @@@
          if dpName:
              wrapper.set_name(dpName)
          if wrapper is not None:
 -            if dpxml:
 +            if dpxml and isinstance(dpxml, basestring):
 +                wrapper.set_configuration_xml(xmltext=dpxml, xmlversion=xml_version)
 +            elif dpxml:
                  for i in dpxml.childNodes:
                      if i.nodeType == i.ELEMENT_NODE and i.localName == "configuration":
-                         wrapper.set_configuration_xml(xmltext=i.toxml(), xmlversion=xml_version)
+                         wrapper.set_configuration_xml(xmltext=i.toxml())
          cond.add_dataprovider(wrapper, trySourceFirst)
  
      def on_dataprovider_available_unavailable(self, loader, dpw):
diff --cc conduit/gtkui/UI.py
index a4cd58b,ae6d83b..d956b88
--- a/conduit/gtkui/UI.py
+++ b/conduit/gtkui/UI.py
@@@ -27,10 -28,6 +29,9 @@@ import conduit.gtkui.Database as Databa
  
  def N_(message): return message
  
 +from conduit.gtkui.ConfigContainer import ConfigContainer
 +from conduit.gtkui.DataproviderWizard import DataproviderWizard
 +
- DEFAULT_CONDUIT_BROWSER = "gtkmozembed"
  DEVELOPER_WEB_LINKS = (
  #name,                      #url
  (N_("Introduction"),            "http://www.conduit-project.org/wiki/Development";),
@@@ -46,266 -43,236 +47,456 @@@ for module in (gettext,)
      if hasattr(module, 'bind_textdomain_codeset'):
          module.bind_textdomain_codeset('conduit','UTF-8')
  
 -class _PreconfiguredConduitMenu:
 -    """
 -    Manages the list of preconfigured conduits examples
 -    """
 -    def __init__(self):
 -        self.menu = gtk.Menu()
 -        self.item = gtk.ImageMenuItem(_("Examples"))
 -        self.item.set_image(
 -                gtk.image_new_from_stock(gtk.STOCK_OPEN,gtk.ICON_SIZE_MENU))
 -        self.item.set_submenu(self.menu)
 -
 -        #FIXME: Add remove items when dps become availalbe
 -        # self._items = {}
 -        # conduit.GLOBALS.moduleManager.connect("dataprovider-available", self._dp_added)
 -        # conduit.GLOBALS.moduleManager.connect("dataprovider-unavailable", self._dp_removed)
 -
 -        preconfigured = conduit.GLOBALS.moduleManager.list_preconfigured_conduits()
 -        if preconfigured:
 -            for sok,sik,desc,w in preconfigured:
 -                item = gtk.MenuItem(desc)
 -                item.connect("activate", self._create, sok, sik, w)
 -                item.show()
 -                self.menu.append(item)
 -        else:
 -            self.item.set_sensitive(False)
++<<<<<<< HEAD
 +class Error(Exception):
 +    ''' Generic error for the UI'''
 +    pass
 +
 +PIX_COLUMN, STR_COLUMN, CONDUIT_COLUMN = range(3)
  
 -    def _create(self, menu, sok, sik, w):
 -        self.syncSet.create_preconfigured_conduit(sok,sik,w)
 +class ConduitView(object):
 +    def __init__(self, cond, main_window):
 +        self.conduit = cond
 +        self.main_window = main_window
          
 -    def _dp_added(self, manager, dpw):
 -        item = gtk.MenuItem(dpw.get_key())
 -        self._items[dpw] = item
 -        self.menu.append(item)
 -        item.show()
 +        # We have to load the UI file every time because gtk.Builder cant create
 +        # several instances from the same file
 +        glade_file = os.path.join(conduit.SHARED_DATA_DIR, "conduit_box_ui.glade")
 +        builder = gtk.Builder()
 +        builder.add_from_file(glade_file)
 +        builder.connect_signals(self)
 +
 +        self.widget = builder.get_object("root")
 +        self.revert_action = builder.get_object("revert_action")
 +        self.apply_action = builder.get_object("apply_action")
 +        self.status_label = builder.get_object("status_label")
 +        #builder.get_object("conduit_name_label").set_text(cond.name)
 +        self.sizegroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
          
 -    def _dp_removed(self, manager, dpw):
 -        self.menu.remove(self._items[dpw])
 -
 -    def set_sync_set(self, syncSet):
 -        self.syncSet = syncSet
 +        self.dps_buttons_box = builder.get_object('dps_buttons_box')
 +        self.no_sink_label = builder.get_object('no_sink_label')
 +        
 +        self.dp_notebook = builder.get_object("dp_notebook")
 +        
 +        self.status_button = builder.get_object('status_button')
 +        self.status_button.connect('clicked', self.on_dp_button_clicked)
 +        
 +        self.status_widget = builder.get_object('status_widget')
 +        
 +        self.source_button = builder.get_object('source_button')
 +        self.source_button.connect('clicked', self.on_dp_button_clicked)
 +        
 +        self.dp_buttons = [self.status_button]
 +        self.db_widgets = []
 +        self.button_widgets = {self.status_button: self.status_widget}
 +        
 +        self.updating_buttons = False
 +        
 +        self.views = []
 +        
 +        self.source_view = None
 +        self.sink_views = []
 +        
 +        self.source_box = builder.get_object("source_vbox")
 +        if cond.datasource:
 +            self.add_dataprovider(cond.datasource)
 +        self.sink_box = builder.get_object("sink_vbox")
 +        for datasink in cond.datasinks:
 +            self.add_dataprovider(datasink)
 +        
 +        self.syncing = False
 +        self.error_syncing = None
 +        self.has_conflicts = False
 +        self.is_configured = False
 +        
 +        cond.connect("dataprovider-added", self.on_dataprovider_added)
 +        cond.connect("dataprovider-removed", self.on_dataprovider_removed)
 +        cond.connect("sync-started", self.on_sync_started)
 +        cond.connect("sync-completed", self.on_sync_completed)
 +        
 +        self.refresh_status()
 +        
 +        
 +    def on_sync_started(self, cond):
 +        self.syncing = True
 +        self.refresh_status()
 +        
 +    def on_sync_completed(self, cond, fatal, nonfatal, conflict):
 +        self.syncing = False
 +        if fatal:
 +            self.error_syncing = "Fatal error"
 +        elif nonfatal:
 +            self.error_syncing = "Errors during sync"
 +        elif conflict:
 +            self.error_syncing = "Conflicts during sync"
 +        
 +    def set_status(self, text, image = None):
 +        self.status_label.set_text(text)
 +        
 +    def refresh_status(self):
 +        if self.syncing:
 +            self.set_status("Syncing...")
 +        elif self.error_syncing:
 +            self.set_status(self.error_syncing)
 +        elif self.is_configured:
 +            self.set_status("Ready")
 +        else:
 +            self.set_status("Not configured correctly")
 +            
 +    def on_status_changed(self, dp):
 +        self.status_label.set_text(dp.get_status())
 +        
 +    def on_add_sink_action_activate(self, action):
 +        self.main_window.open_add_sink_window(self.conduit)
 +        
 +    def on_revert_action_activate(self, action):
 +        for dp_view in [self.source_view] + self.sink_views:
 +            if not dp_view:
 +                continue
 +            modified = dp_view.config.cancel_config()
 +            
 +    def on_apply_action_activate(self, action):
 +        for dp_view in [self.source_view] + self.sink_views:
 +            if not dp_view:
 +                continue
 +            modified = dp_view.config.apply_config()
 +
 +    def on_dataprovider_added(self, cond, dp):
 +        self.add_dataprovider(dp)
 +        
 +    def on_dataprovider_removed(self, cond, dp):
 +        #for widget in self.dp_notebook.get_children():
 +        #    if widget
 +        if dp == cond.datasource:
 +            self.remove_dataprovider(self.source_view)
 +        else:
 +            for dp_view in self.sink_views:
 +                if dp_view.dp == dp:
 +                    self.remove_dataprovider(dp_view)
 +                    break
 +        
 +    def on_config_changed(self, config, item):
 +        modified = True
 +        for dp_view in [self.source_view] + self.sink_views:
 +            if not dp_view:
 +                continue
 +            modified = dp_view.config.is_modified()
 +            if modified:
 +                break
 +        self.revert_action.set_sensitive(modified)
 +        self.apply_action.set_sensitive(modified)        
 +        
 +    def on_dp_button_clicked(self, button):
 +        if self.updating_buttons:
 +            return
 +        self.updating_buttons = True
 +        for dp_button in self.dp_buttons:
 +            if dp_button.get_active():
 +                dp_button.set_active(False)
 +        button.set_active(True)
 +        if button in self.button_widgets:
 +            self.dp_notebook.set_current_page(self.dp_notebook.page_num(self.button_widgets[button]))
 +        self.updating_buttons = False
 +    
 +    def add_dataprovider(self, dp):
 +        dp_view = DataproviderView(self, dp, source = self.conduit.datasource == dp)        
 +        self.dp_notebook.append_page(dp_view.widget, gtk.Label(dp.get_name()))
 +        if self.conduit.datasource == dp:
 +            button = self.source_button
 +            self.source_view = dp_view
 +        else:
 +            self.no_sink_label.hide()
 +            button = gtk.ToggleButton()
 +            button.show_all()
 +            self.dps_buttons_box.pack_start(button, False, False)
 +            self.sink_views.append(dp_view)
 +        button.add(self.make_dp_button(dp))
 +        button.connect('clicked', self.on_dp_button_clicked)
 +        self.dp_buttons.append(button)
 +        self.button_widgets[button] = dp_view.widget
 +        return
 +        if self.conduit.datasource == dp:
 +            self.source_view = DataproviderView(self, dp, source = True)
 +            self.source_box.add(self.source_view.widget)
 +            dp.module.connect("status-changed", self.on_status_changed)
 +        else:
 +            sink_view = DataproviderView(self, dp, source = False)
 +            self.sink_views.append(sink_widget)
 +            self.sink_box.add(sink_widget.widget)
 +            
 +    def remove_dataprovider(self, dp_view):
 +        dp_view.remove_dp()
 +        #return
 +        if self.source_view == dp_view:
 +            if not self.source_view:
 +                return
 +            #self.source_box.remove(self.source_widget.widget)
 +            self.source_widget = None
 +        elif dp_view in self.sink_views:
 +            self.sink_views.remove(dp_view)
 +            #self.sink_box.remove(dp_widget.widget)
 +        else:
 +            raise Error("Dataprovider not found on this conduit")
 +            
 +        
 +class DataproviderView(object):
 +    def __init__(self, conduit_view, dp, source = True):
 +        self.conduit_view = conduit_view
 +        self.dp = dp
 +        self.source = source
 +        
 +        self.widget = gtk.VBox()
 +        self.widget.set_spacing(8)
 +        hbox = gtk.HBox()
 +        hbox.set_spacing(8)
 +        icon = gtk.image_new_from_pixbuf(dp.get_icon(48))
 +        icon.set_property("pixel-size", 48)
 +        label = gtk.Label("<b>%s</b>" % dp.get_name())
 +        label.set_use_markup(True)
 +        label.props.xalign = 0
 +        button_box = gtk.HButtonBox()
 +        #config_button = gtk.Button(stock="gtk-preferences")
 +        #refresh_button = gtk.Button(stock="gtk-refresh")
 +        if not source:
 +            remove_button = gtk.Button(stock="gtk-delete")
 +            remove_button.connect("clicked", self.on_remove_button_activate)
 +            #button_box.add(remove_button)
 +            hbox.pack_end(remove_button, expand=False, fill=False)
 +        hbox.pack_start(icon, expand=False, fill=False)
 +        hbox.pack_start(label, expand=True, fill=True)
 +        #hbox.pack_start(button_box, expand=False, fill=False)
 +        self.widget.pack_start(hbox, False, False)
 +        try:
 +            self.config = dp.module.get_config_container(ConfigContainer, dp.name, dp.get_icon(), self)
 +            self.config.connect("changed", conduit_view.on_config_changed)
 +            config_widget = self.config.get_config_widget()
 +        except Exception:
 +            self.config = None
 +            config_widget = gtk.Label("Ouch, something went wrong!")
 +        if config_widget:
 +            align = gtk.Alignment(xalign=0.0, yalign=0.0, xscale=1.0, yscale=1.0)
 +            align.add(config_widget)
 +            conduit_view.sizegroup.add_widget(config_widget)
 +            #self.widget.pack_start(align, False, False)
 +            self.widget.pack_start(align, True, True)
 +        self.widget.show_all()
 +    
 +    def make_dp_button(self, button):
 +        hbox = gtk.HBox()
 +        hbox.set_spacing(4)
 +        icon = gtk.image_new_from_pixbuf(self.dp.get_icon())
 +        #icon.set_property("pixel-size", 48)
 +        label = gtk.Label(self.dp.get_name())
 +        #label.props.xalign = 0
 +        label.set_alignment(xalign = 0, yalign = 0.5)
 +        
 +        hbox.pack_start(icon)
 +        hbox.pack_start(label)
 +        hbox.show_all()
 +        
 +        button.add(hbox)
 +        
 +        self.button = button
 +        return button
 +        
 +    def remove_dp(self):
 +        parent = self.widget.get_parent()
 +        if parent:
 +            parent.remove(self.widget)
 +            self.widget = None
 +        
 +    def on_remove_button_activate(self, button):
 +        self.conduit_view.conduit.delete_dataprovider(self.dp)
  
+ class _GtkBuilderWrapper(gtk.Builder):
+     def __init__(self, *path):
+         gtk.Builder.__init__(self)
+         self.add_from_file(os.path.join(*path))
+         self._resources = {}
+ 
+     def set_instance_resources(self, obj, *resources):
+         for r in resources:
+             setattr(obj, "_%s" % r.lower(), self.get_resource(r))
+ 
+     def get_object(self, name):
+         if name not in self._resources:
+             w = gtk.Builder.get_object(self,name)
+             if not w:
+                 raise Exception("Could not find widget: %s" % name)
+             self._resources[name] = w
+ 
+         return self._resources[name]
+ 
+     def connect_signals(self, obj):
+         #FIXME: connect_signals seems to be only able to be called once
+         missing = gtk.Builder.connect_signals(self, obj)
+         if missing:
+             log.critical("Failed to connect signals: %s" % ",".join(missing))
+ 
+ class PreferencesWindow:
+ 
+     NOTEBOOK_FIXED_PAGES = 3
+ 
+     def __init__(self, gtkbuilder):
+         self._gtkbuilder = gtkbuilder
+         self._extra_pages = []
+         self._notebook = self._gtkbuilder.get_object("prop_notebook")
+         self._autostartmanager = AutostartManager.AutostartManager()
+ 
+     def _add_page(self, widget, label):
+         self._notebook.append_page(widget,label)
+         self._extra_pages.append(widget)
+ 
+     def _remove_extra_pages(self):
+         for w in self._extra_pages:
+             pn = self._notebook.page_num(w)
+             if pn >= self.NOTEBOOK_FIXED_PAGES:
+                 self._notebook.remove_page( pn )
+ 
+     def show(self, parent):
+         def on_clear_button_clicked(sender, treeview, sqliteListStore):
+             treeview.set_model(None)
+             conduit.GLOBALS.mappingDB.delete()
+             treeview.set_model(sqliteListStore)
+ 
+         #Build some liststores to display
+         CONVERT_FROM_MESSAGE = _("Convert from")
+         CONVERT_INTO_MESSAGE = _("into")
+ 
+         #reset the prefs window, removing all dynamically added pages
+         self._remove_extra_pages()
+ 
+         convertables = conduit.GLOBALS.typeConverter.get_convertables_list()
+         converterListStore = gtk.ListStore( str )
+         for froms,tos in convertables:
+             string = "%s %s %s %s" % (CONVERT_FROM_MESSAGE, froms, CONVERT_INTO_MESSAGE, tos)
+             converterListStore.append( (string,) )
+         dataProviderListStore = gtk.ListStore( str, bool )
+         #get all dataproviders
+         for i in conduit.GLOBALS.moduleManager.get_modules_by_type("sink","source","twoway"):
+             dataProviderListStore.append(("Name: %s\nDescription: %s)" % (i.name, i.description), True))
+         #include files that could not be loaded
+         for f in conduit.GLOBALS.moduleManager.invalidFiles:
+             dataProviderListStore.append(("Error loading file: %s" % f, False))
+ 
+         #Show the DB contents to help debugging
+         if conduit.IS_DEVELOPMENT_VERSION:
+             vbox = gtk.VBox(False,5)
+             
+             #build the treeview to show all column fields. For performance
+             #reasons it is fixed_height and fixed_FIXE
+             treeview = gtk.TreeView()
+             treeview.set_headers_visible(True)
+             treeview.set_fixed_height_mode(True)
+             index = 1
+             db = conduit.GLOBALS.mappingDB._db
+             for name in db.get_fields("mappings"):
+                 column = gtk.TreeViewColumn(
+                                     name, 
+                                     gtk.CellRendererText(),
+                                     text=index)
+                 column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+                 column.set_fixed_width(250)
+                 treeview.append_column(column)
+                 index = index + 1
+ 
+             store = Database.GenericDBListStore("mappings", db)
+             treeview.set_model(store)            
+             
+             sw = gtk.ScrolledWindow()
+             sw.add(treeview)
+             vbox.pack_start(sw,True,True)
+ 
+             clear = gtk.Button(None,gtk.STOCK_CLEAR)
+             clear.connect("clicked", on_clear_button_clicked, treeview, store)
+             vbox.pack_start(clear, False, False)
+ 
+             self._add_page(vbox,gtk.Label(_('Relationship Database')))
+         
+         converterTreeView = self._gtkbuilder.get_object("dataConversionsTreeView")
+         converterTreeView.set_model(converterListStore)
+         converterTreeView.append_column(gtk.TreeViewColumn(_("Conversions Available"), 
+                                         gtk.CellRendererText(), 
+                                         text=0)
+                                         )
+         dataproviderTreeView = self._gtkbuilder.get_object("dataProvidersTreeView")
+         dataproviderTreeView.set_model(dataProviderListStore)
+         dataproviderTreeView.append_column(gtk.TreeViewColumn(_("Name"), 
+                                         gtk.CellRendererText(), 
+                                         text=0)
+                                         )                                                   
+         dataproviderTreeView.append_column(gtk.TreeViewColumn(_("Loaded"), 
+                                         gtk.CellRendererToggle(), 
+                                         active=1)
+                                         )                                        
+                                         
+         #fill out the configuration tab
+         save_settings_check = self._gtkbuilder.get_object("save_settings_check")
+         save_settings_check.set_active(conduit.GLOBALS.settings.get("save_on_exit"))
+         status_icon_check = self._gtkbuilder.get_object("status_icon_check")
+         status_icon_check.set_active(conduit.GLOBALS.settings.get("show_status_icon")) 
+         minimize_to_tray_check = self._gtkbuilder.get_object("minimize_to_tray_check")
+         minimize_to_tray_check.set_active(conduit.GLOBALS.settings.get("gui_minimize_to_tray")) 
+         show_hints_check = self._gtkbuilder.get_object("show_hints_check")
+         show_hints_check.set_active(conduit.GLOBALS.settings.get("gui_show_hints"))
+ 
+         #special case start at login. Because we copy the desktop file from the
+         #system to ~/.config/autostart, we require conduit to be installed
+         start_at_login_check = self._gtkbuilder.get_object("start_at_login")
+         if conduit.IS_INSTALLED:
+             start_at_login_check.set_active(self._autostartmanager.is_start_at_login_enabled())
+         else:
+             start_at_login_check.set_sensitive(False)
+ 
+         #restore the current policy
+         for policyName in Conduit.CONFLICT_POLICY_NAMES:
+             currentValue = conduit.GLOBALS.settings.get("default_policy_%s" % policyName)
+             for policyValue in Conduit.CONFLICT_POLICY_VALUES:
+                 name = "%s_%s" % (policyName,policyValue)
+                 widget = self._gtkbuilder.get_object(name+"_radio")
+                 widget.set_image(
+                         gtk.image_new_from_icon_name(
+                                 Conduit.CONFLICT_POLICY_VALUE_ICONS[name],
+                                 gtk.ICON_SIZE_MENU))
+                 if currentValue == policyValue:
+                     widget.set_active(True)
+ 
+         #The dataprovider factories can provide a configuration widget which is
+         #packed into the notebook
+         for i in conduit.GLOBALS.moduleManager.dataproviderFactories:#get_modules_by_type("dataprovider-factory"):
+             widget = i.setup_configuration_widget()
+             if widget:
+                 self._add_page(
+                             widget,
+                             gtk.Label(i.get_name()))
+ 
+         #Show the dialog
+         dialog = self._gtkbuilder.get_object("PreferencesDialog")
+         dialog.show_all()
+         dialog.set_transient_for(parent)
+ 
+         response = dialog.run()
+         if response == gtk.RESPONSE_OK:
+             conduit.GLOBALS.settings.set("save_on_exit", save_settings_check.get_active())
+             conduit.GLOBALS.settings.set("show_status_icon", status_icon_check.get_active())
+             conduit.GLOBALS.settings.set("gui_minimize_to_tray", minimize_to_tray_check.get_active())
+             conduit.GLOBALS.settings.set("gui_show_hints", show_hints_check.get_active())
+             self._autostartmanager.update_start_at_login(start_at_login_check.get_active())
+             #save the current policy
+             for policyName in Conduit.CONFLICT_POLICY_NAMES:
+                 for policyValue in Conduit.CONFLICT_POLICY_VALUES:
+                     name = "%s_%s" % (policyName,policyValue)
+                     if self._gtkbuilder.get_object(name+"_radio").get_active() == True:
+                         conduit.GLOBALS.settings.set(
+                                 "default_policy_%s" % policyName,
+                                 policyValue)
+ 
+         #give the dataprovider factories to ability to save themselves
+         for factory in conduit.GLOBALS.moduleManager.dataproviderFactories:
+             factory.save_configuration(response == gtk.RESPONSE_OK)
+ 
 -        dialog.hide()                
++        dialog.hide()
+ 
  class MainWindow:
      """
      The main conduit window.
@@@ -327,13 -294,8 +518,16 @@@
              gtk.icon_theme_get_default().prepend_search_path(i)
          gtk.window_set_default_icon_name("conduit")
  
++<<<<<<< HEAD
 +        self.conduitApplication = conduitApplication
 +        self.gladeFile = os.path.join(conduit.SHARED_DATA_DIR, "conduit_ui.glade")
 +        self.widgets = gtk.Builder()
 +        self.widgets.add_from_file(self.gladeFile)
 +        self.widgets.connect_signals(self)
-         
-         dic = { "on_mainwindow_delete" : self.on_window_closed,
++       
+         signals = { 
+                 "on_mainwindow_delete" : self.on_window_closed,
++
                  "on_mainwindow_state_event" : self.on_window_state_event,
                  "on_synchronize_activate" : self.on_synchronize_all_clicked,
                  "on_cancel_activate" : self.on_cancel_all_clicked,  
@@@ -343,17 -305,18 +537,17 @@@
                  "on_about_activate" : self.on_about_conduit,
                  "on_contents_activate" : self.on_help,
                  "on_save1_activate" : self.save_settings,
-                 None : None
                  }
-         #self.widgets.signal_autoconnect(dic)
+ 
 -        self.conduitApplication = conduitApplication
 -        self.builder = _GtkBuilderWrapper(conduit.SHARED_DATA_DIR, "conduit.ui")
 -        self.builder.connect_signals(signals)
  
          #type converter and sync manager
          self.type_converter = typeConverter
          self.sync_manager = syncManager
 +        self.module_manager = moduleManager
          
          #Initialize the mainWindow
 -        self.mainWindow = self.builder.get_object("MainWindow")
 +        self.mainWindow = self.widgets.get_object("main_window")
++
          #Enable RGBA colormap
          if conduit.GLOBALS.settings.get("gui_use_rgba_colormap") == True:
              screen = self.mainWindow.get_screen()
@@@ -367,43 -330,14 +561,43 @@@
          if not conduit.IS_INSTALLED:
              title = title + _(" - Running Uninstalled")
          self.mainWindow.set_title(title)
 -
 +        
 +        self.remove_conduit_action = self.widgets.get_object("remove_conduit_action")
 +        self.sync_conduit_action = self.widgets.get_object("sync_conduit_action")
 +        self.cancel_sync_action = self.widgets.get_object("cancel_sync_action")
 +
 +        self.conduits_treemodel = gtk.ListStore(gtk.gdk.Pixbuf, str, object)
 +
 +        self.conduits_tree = self.widgets.get_object("conduits_tree")
 +        self.conduits_tree.set_model(self.conduits_treemodel)
 +        #self.conduits_tree.insert_column_with_data_func(-1, "Conduit Name", 
 +        #    gtk.CellRendererText(), self._tree_get_conduit_name)
 +        self.conduits_tree.insert_column_with_attributes(-1, "Conduit Icon", 
 +            gtk.CellRendererPixbuf(), pixbuf=PIX_COLUMN)
 +        self.conduits_tree.insert_column_with_attributes(-1, "Conduit Name", 
 +            gtk.CellRendererText(), text=STR_COLUMN)
 +
 +        self.conduits_widgets = {}
 +        self.conduits_notebook = self.widgets.get_object("conduits_notebook")
 +        
 +        self.add_conduit_label = gtk.Label("Start by adding a new Conduit")
 +        self.conduits_notebook.append_page(self.add_conduit_label)
 +        self.select_conduit_label = gtk.Label("Select a Conduit to change it's configuration")
 +        self.conduits_notebook.append_page(self.select_conduit_label)
 +        
 +        self.conduits_notebook.set_current_page(self.conduits_notebook.page_num(self.add_conduit_label))
 +        self.conduits_notebook.show_all()
 +        
          #Configure canvas
 -        self.canvasSW = self.builder.get_object("canvasScrolledWindow")
 -        self.hpane = self.builder.get_object("hpaned1")
 -
 +        #self.canvasSW = self.widgets.get_widget("canvasScrolledWindow")
 +        #self.hpane = self.widgets.get_widget("hpaned1")
 +        
 +        self.selected_conduit = None
 +        
          #start up the canvas
 +        '''
          msg = MsgArea.MsgAreaController()
-         self.widgets.get_widget("mainVbox").pack_start(msg, False, False)
+         self.builder.get_object("mainVbox").pack_start(msg, False, False)
          self.canvas = Canvas.Canvas(
                          parentWindow=self.mainWindow,
                          typeConverter=self.type_converter,
@@@ -462,57 -394,17 +654,66 @@@
          self.hpane.set_position(conduit.GLOBALS.settings.get("gui_hpane_postion"))
          self.dataproviderTreeView.set_expand_rows()
          self.window_state = 0                
 +        
 +        '''
 +        #self.hpane.set_position(conduit.GLOBALS.settings.get("gui_hpane_postion"))
          log.info("Main window constructed  (thread: %s)" % thread.get_ident())
 +        
 +    def _tree_get_conduit_name(self, column, cell, model, iter_):
 +        cell.props.text = model.get_value(iter_, 0)
 +        
 +    def _update_actions(self):
 +        cond = self.selected_conduit
 +        self.remove_conduit_action.set_sensitive(cond is not None)
 +        self.sync_conduit_action.set_sensitive(cond is not None)
 +        
 +    def on_sync_conduit_action_activate(self, action):
 +        self.selected_conduit.sync()
 +        
 +    def on_conduits_tree_cursor_changed(self, tree):
 +        #print "Cursor changed"
 +        model, iter_ = tree.get_selection().get_selected()
 +        cond = model.get_value(iter_, CONDUIT_COLUMN)
 +        page_num = self.conduits_notebook.page_num(self.conduits_widgets[cond].widget)
 +        self.conduits_notebook.set_current_page(page_num)
 +        self.selected_conduit = cond
 +        self._update_actions()
 +        
 +    def on_remove_conduit_action_activate(self, action):
 +        self.syncSet.remove_conduit(self.selected_conduit)
 +        
 +    def open_add_sink_window(self, cond):
 +        wizard = DataproviderWizard(self.mainWindow, self.syncSet, self.module_manager,
 +            ("sink","twoway"), cond)
 +        wizard.show()
 +        
 +    def _make_dataprovider_widget(self, dp):
 +        return widget
 +        
 +    def set_busy(self, value):
 +        '''
 +        Config container implementation to set the current window busy
 +        '''
 +        pass
 +        
 +    def _make_conduit_page(self, cond):
 +        return ConduitView(cond, self)
 +        
 +    def on_main_window_destroy(self, window):
 +        self.conduitApplication.Quit()
 +        
 +    def on_add_conduit_action_activate(self, action):
 +        self.dataprovider_wizard.show()
-     
+ 
+     def _ui_get_resource(self, name):
+         if name not in self.builder_resources:
+             w = self.builder.get_object(name)
+             if not w:
+                 raise Exception("Could not find widget: %s" % name)
+             self.builder_resources[name] = w
+ 
+         return self.builder_resources[name]
+                 
      def on_developer_menu_item_clicked(self, menuitem, name, url):
          threading.Thread(
                      target=Web.LoginMagic,
diff --cc conduit/modules/iPodModule/iPodModule.py
index 81f71d4,5348b62..aa14eb5
--- a/conduit/modules/iPodModule/iPodModule.py
+++ b/conduit/modules/iPodModule/iPodModule.py
@@@ -36,21 -39,25 +39,26 @@@ import conduit.datatypes.Video as Vide
  from gettext import gettext as _
  
  errormsg = ""
 +availiable = False
  try:
      import gpod
-     if gpod.version_info >= (0,6,0):
-         availiable = True
+     if gpod.version_info >= (0,7,0):
+         MODULES = {
+             "iPodFactory" :         { "type":   "dataprovider-factory"  },
+             "iPhoneFactory" :       { "type":   "dataprovider-factory"  },
+         }
          log.info("Module Information: %s" % Utils.get_module_information(gpod, 'version_info'))
  except ImportError:
      errormsg = "iPod support disabled (python-gpod not availiable)"
  except locale.Error:
      errormsg = "iPod support disabled (Incorrect locale)"
  
- MODULES = {}
+ PROPS_KEY_MOUNT = "CONDUIT_MOUNTPOINT"
+ PROPS_KEY_NAME  = "CONDUIT_NAME"
+ PROPS_KEY_ICON  = "CONDUIT_ICON"
  
  if errormsg:
 -    MODULES = {}
 +    #MODULES = {}
      log.warn(errormsg)
      #Solve the initialization problem without gpod
      class gpod():



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]