4 from __future__ import with_statement
27 __pretty_app_name__ = "DoneIt"
28 __app_name__ = "doneit"
30 __app_magic__ = 0xdeadbeef
33 '/usr/lib/doneit/doneit.glade',
34 os.path.join(os.path.dirname(__file__), "doneit.glade"),
35 os.path.join(os.path.dirname(__file__), "../lib/doneit.glade"),
38 _user_data = os.path.expanduser("~/.%s/" % __app_name__)
39 _user_settings = "%s/settings.ini" % _user_data
45 self._deviceIsOnline = True
46 self._connection = None
47 self._fallbackUIName = ""
48 self._defaultUIName = ""
50 for path in self._glade_files:
51 if os.path.isfile(path):
52 self._widgetTree = gtk.glade.XML(path)
55 self.display_error_message("Cannot find doneit.glade")
58 os.makedirs(self._user_data)
63 self._clipboard = gtk.clipboard_get()
64 self.__window = self._widgetTree.get_widget("mainWindow")
65 self.__errorDisplay = gtk_toolbox.ErrorDisplay(self._widgetTree)
68 self._isFullScreen = False
69 if hildon is not None:
70 self._app = hildon.Program()
71 self.__window = hildon.Window()
72 self._widgetTree.get_widget("mainLayout").reparent(self.__window)
73 self._app.add_window(self.__window)
74 self._widgetTree.get_widget("usernameentry").set_property('hildon-input-mode', 7)
75 self._widgetTree.get_widget("passwordentry").set_property('hildon-input-mode', 7|(1 << 29))
76 self._widgetTree.get_widget("projectsCombo").get_child().set_property('hildon-input-mode', (1 << 4))
78 gtkMenu = self._widgetTree.get_widget("mainMenubar")
80 for child in gtkMenu.get_children():
82 self.__window.set_menu(menu)
85 self.__window.connect("key-press-event", self._on_key_press)
86 self.__window.connect("window-state-event", self._on_window_state_change)
88 pass # warnings.warn("No Hildon", UserWarning, 2)
91 "on_doneit_quit": self._on_close,
92 "on_paste": self._on_paste,
93 "on_about": self._on_about_activate,
95 self._widgetTree.signal_autoconnect(callbackMapping)
99 self.__window.set_title("%s" % self.__pretty_app_name__)
100 self.__window.connect("destroy", self._on_close)
101 self.__window.show_all()
103 backgroundSetup = threading.Thread(target=self._idle_setup)
104 backgroundSetup.setDaemon(True)
105 backgroundSetup.start()
107 def _idle_setup(self):
108 # Barebones UI handlers
110 with gtk_toolbox.gtk_lock():
111 nullView = null_view.GtkNull(self._widgetTree)
112 self._todoUIs[nullView.name()] = nullView
113 self._todoUI = nullView
114 self._todoUI.enable()
115 self._fallbackUIName = nullView.name()
117 # Setup maemo specifics
124 self._osso = osso.Context(DoneIt.__app_name__, DoneIt.__version__, False)
125 device = osso.DeviceState(self._osso)
126 device.set_device_state_callback(self._on_device_state_change, 0)
128 pass # warnings.warn("No OSSO", UserWarning, 2)
134 self._connection = None
135 if conic is not None:
136 self._connection = conic.Connection()
137 self._connection.connect("connection-event", self._on_connection_change, self.__app_magic__)
138 self._connection.request_connection(conic.CONNECT_FLAG_NONE)
140 pass # warnings.warn("No Internet Connectivity API ", UserWarning)
142 # Setup costly backends
144 with gtk_toolbox.gtk_lock():
145 rtmView = rtm_view.GtkRtMilk(self._widgetTree)
146 self._todoUIs[rtmView.name()] = rtmView
147 self._defaultUIName = rtmView.name()
149 config = ConfigParser.SafeConfigParser()
150 config.read(self._user_settings)
151 with gtk_toolbox.gtk_lock():
152 self.load_settings(config)
154 def display_error_message(self, msg):
158 error_dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg)
160 def close(dialog, response, editor):
161 editor.about_dialog = None
163 error_dialog.connect("response", close, self)
166 def load_settings(self, config):
170 for todoUI in self._todoUIs.itervalues():
172 todoUI.load_settings(config)
173 except ConfigParser.NoSectionError, e:
175 "Settings file %s is missing section %s" % (
183 activeUIName = config.get(self.__pretty_app_name__, "active")
184 except ConfigParser.NoSectionError, e:
187 "Settings file %s is missing section %s" % (
195 self._switch_ui(activeUIName)
197 self._switch_ui(self._defaultUIName)
199 def save_settings(self, config):
201 @note Thread Agnostic
203 config.add_section(self.__pretty_app_name__)
204 config.set(self.__pretty_app_name__, "active", self._todoUI.name())
206 for todoUI in self._todoUIs.itervalues():
207 todoUI.save_settings(config)
209 def _switch_ui(self, uiName):
213 newActiveUI = self._todoUIs[uiName]
217 return # User cancelled the operation
219 self._todoUI.disable()
220 self._todoUI = newActiveUI
221 self._todoUI.enable()
223 if uiName != self._fallbackUIName:
224 self._defaultUIName = uiName
226 def _save_settings(self):
228 @note Thread Agnostic
230 config = ConfigParser.SafeConfigParser()
231 self.save_settings(config)
232 with open(self._user_settings, "wb") as configFile:
233 config.write(configFile)
235 def _on_device_state_change(self, shutdown, save_unsaved_data, memory_low, system_inactivity, message, userData):
237 For system_inactivity, we have no background tasks to pause
239 @note Hildon specific
244 if save_unsaved_data or shutdown:
245 self._save_settings()
247 def _on_connection_change(self, connection, event, magicIdentifier):
249 @note Hildon specific
253 status = event.get_status()
254 error = event.get_error()
255 iap_id = event.get_iap_id()
256 bearer = event.get_bearer_type()
258 if status == conic.STATUS_CONNECTED:
259 self._deviceIsOnline = True
260 self._switch_ui(self._defaultUIName)
261 elif status == conic.STATUS_DISCONNECTED:
262 self._deviceIsOnline = False
263 self._switch_ui(self._fallbackUIName)
265 def _on_window_state_change(self, widget, event, *args):
267 @note Hildon specific
269 if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
270 self._isFullScreen = True
272 self._isFullScreen = False
274 def _on_close(self, *args, **kwds):
276 if self._osso is not None:
279 self._save_settings()
283 def _on_paste(self, *args):
286 def _on_key_press(self, widget, event, *args):
288 @note Hildon specific
290 if event.keyval == gtk.keysyms.F6:
291 if self._isFullScreen:
292 self.__window.unfullscreen()
294 self.__window.fullscreen()
296 def _on_logout(self, *args):
297 self._todoUI.logout()
298 self._switch_ui(self._fallbackUIName)
300 def _on_about_activate(self, *args):
301 dlg = gtk.AboutDialog()
302 dlg.set_name(self.__pretty_app_name__)
303 dlg.set_version(self.__version__)
304 dlg.set_copyright("Copyright 2008 - LGPL")
307 dlg.set_authors([""])
315 failureCount, testCount = doctest.testmod()
317 print "Tests Successful"
324 gtk.gdk.threads_init()
326 if hildon is not None:
327 gtk.set_application_name(DoneIt.__pretty_app_name__)
332 class DummyOptions(object):
338 if __name__ == "__main__":
339 if len(sys.argv) > 1:
345 if optparse is not None:
346 parser = optparse.OptionParser()
347 parser.add_option("-t", "--test", action="store_true", dest="test", help="Run tests")
348 (commandOptions, commandArgs) = parser.parse_args()
350 commandOptions = DummyOptions()
353 if commandOptions.test: