1 import os
2 import getopt
3 import sys
4 import dbus, dbus.service, dbus.mainloop.glib
5 import gobject
6
7 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
8 dbus.mainloop.glib.threads_init()
9
10 import logging
11 log = logging.getLogger("Main")
12
13 import conduit
14 import conduit.utils as Utils
15 from conduit.Module import ModuleManager
16 from conduit.MappingDB import MappingDB
17 from conduit.TypeConverter import TypeConverter
18 from conduit.SyncSet import SyncSet
19 from conduit.Synchronization import SyncManager
20 from conduit.DBus import DBusInterface
21 from conduit.Settings import Settings
22
23 APPLICATION_DBUS_IFACE="org.conduit.Application"
24
27 """
28 Conduit application class
29 Parses command line arguments. Sets up the views and models;
30 restores application settings, shows the splash screen and the UI
31
32 Notes:
33 1) If conduit is launched without --console switch then the gui
34 and the console interfaces are started
35 2) If launched with --console and then later via the gui then set
36 up the gui and connect all the appropriate signal handlers
37 """
38 self.splash = None
39 self.gui = None
40 self.statusIcon = None
41 self.dbus = None
42 self.guiSyncSet = None
43 self.dbusSyncSet = None
44 self.uiLib = None
45
46 gobject.set_application_name("Conduit")
47 self.settingsFile = os.path.join(conduit.USER_DIR, "settings.xml")
48 self.dbFile = os.path.join(conduit.USER_DIR, "mapping.db")
49
50
51 conduit.GLOBALS.settings = Settings(conduit.SETTINGS_IMPL)
52
53 buildGUI = True
54 iconify = False
55 whitelist = None
56 blacklist = None
57 self.ui = "gtk"
58 settings = {}
59 try:
60 opts, args = getopt.getopt(
61 sys.argv[1:],
62 "hvf:ciu:w:x:s:",
63 ("help", "version", "config-file=",
64 "console", "iconify", "ui=", "with-modules=",
65 "without-modules=", "settings="))
66
67 for o, a in opts:
68 if o in ("-h", "--help"):
69 self._usage()
70 sys.exit(0)
71 if o in ("-v", "--version"):
72 print "Conduit %s" % conduit.VERSION
73 sys.exit(0)
74 if o in ("-f", "--config-file"):
75 self.settingsFile = os.path.join(os.getcwd(), a)
76 if o in ("-c", "--console"):
77 buildGUI = False
78 if o in ("-i", "--iconify"):
79 iconify = True
80 if o in ("-u", "--ui"):
81 self.ui = a
82 if o in ("-w", "--with-modules"):
83 whitelist = a.split(",")
84 if o in ("-x", "--without-modules"):
85 blacklist = a.split(",")
86 if o in ("-s", "--settings"):
87 try:
88 for i in a.split(','):
89 k,v = i.split('=')
90 settings[k] = v
91 except: pass
92 conduit.GLOBALS.settings.set_overrides(**settings)
93
94 except getopt.GetoptError:
95 log.warn("Unknown command line option")
96 self._usage()
97 sys.exit(1)
98
99 log.info("Conduit v%s Installed: %s" % (conduit.VERSION, conduit.IS_INSTALLED))
100 log.info("Python: %s" % sys.version)
101 if settings:
102 log.info("Settings have been overridden: %s" % settings)
103
104
105
106 sessionBus = dbus.SessionBus()
107 if Utils.dbus_service_available(APPLICATION_DBUS_IFACE, sessionBus):
108 log.info("Conduit is already running")
109 obj = sessionBus.get_object(APPLICATION_DBUS_IFACE, "/activate")
110 conduitApp = dbus.Interface(obj, APPLICATION_DBUS_IFACE)
111 if buildGUI:
112 if conduitApp.HasGUI():
113 conduitApp.ShowGUI()
114 else:
115 conduitApp.ImportGUI()
116 conduitApp.ShowSplash()
117 conduitApp.ShowStatusIcon()
118 conduitApp.BuildGUI()
119 conduitApp.ShowGUI()
120 conduitApp.HideSplash()
121 sys.exit(0)
122
123
124
125 bus_name = dbus.service.BusName(APPLICATION_DBUS_IFACE, bus=sessionBus)
126 dbus.service.Object.__init__(self, bus_name, "/activate")
127
128
129 if buildGUI:
130 log.info("Using UI: %s" % self.ui)
131 self.ImportGUI()
132 if not iconify:
133 self.ShowSplash()
134 self.ShowStatusIcon()
135
136
137 dirs_to_search = [
138 conduit.SHARED_MODULE_DIR,
139 os.path.join(conduit.USER_DIR, "modules")
140 ]
141
142
143 conduit.GLOBALS.app = self
144 conduit.GLOBALS.moduleManager = ModuleManager(dirs_to_search)
145 conduit.GLOBALS.moduleManager.load_all(whitelist, blacklist)
146 conduit.GLOBALS.typeConverter = TypeConverter(conduit.GLOBALS.moduleManager)
147 conduit.GLOBALS.syncManager = SyncManager(conduit.GLOBALS.typeConverter)
148 conduit.GLOBALS.mappingDB = MappingDB(self.dbFile)
149 conduit.GLOBALS.mainloop = gobject.MainLoop()
150
151
152 self.guiSyncSet = SyncSet(
153 moduleManager=conduit.GLOBALS.moduleManager,
154 syncManager=conduit.GLOBALS.syncManager,
155 xmlSettingFilePath=self.settingsFile
156 )
157 self.dbusSyncSet = SyncSet(
158 moduleManager=conduit.GLOBALS.moduleManager,
159 syncManager=conduit.GLOBALS.syncManager
160 )
161
162
163 if buildGUI:
164 self.BuildGUI()
165 if not iconify:
166 self.ShowGUI()
167
168
169 self.dbus = DBusInterface(
170 conduitApplication=self,
171 moduleManager=conduit.GLOBALS.moduleManager,
172 typeConverter=conduit.GLOBALS.typeConverter,
173 syncManager=conduit.GLOBALS.syncManager,
174 guiSyncSet=self.guiSyncSet,
175 dbusSyncSet=self.dbusSyncSet
176 )
177
178 if self.statusIcon:
179 self.dbusSyncSet.connect("conduit-added", self.statusIcon.on_conduit_added)
180 self.dbusSyncSet.connect("conduit-removed", self.statusIcon.on_conduit_removed)
181
182
183 self.HideSplash()
184 try:
185 conduit.GLOBALS.mainloop.run()
186 except KeyboardInterrupt:
187 self.Quit()
188
190 print """Usage: conduit [OPTIONS] - Synchronize things
191 OPTIONS:
192 -h, --help Show this message.
193 -c, --console Launch with no GUI.
194 (default=no)
195 -f, --config-file=FILE Save dataprovider configuration to FILE.
196 (default=$XDG_CONFIG_DIR/.conduit/settings.xml)
197 -i, --iconify Iconify on startup.
198 (default=no)
199 -u, --ui=NAME Run with the specified UI.
200 (default=gtk)
201 -w, --with-modules Only load modules in the named files.
202 (default=load all modules)
203 -x, --without-modules Do not load modules in the named files.
204 (default=load all modules)
205 -s, --settings=key=val,.. Explicitly set internal Conduit settings (keys)
206 to the given values for this session.
207 -v, --version Show version information."""
208
209 @dbus.service.method(APPLICATION_DBUS_IFACE, in_signature='', out_signature='b')
211 return self.gui != None
212
213 @dbus.service.method(APPLICATION_DBUS_IFACE, in_signature='', out_signature='')