2 # -*- coding: utf-8 -*-
5 This file is part of Multilist.
7 Multilist is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 Multilist is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Multilist. If not, see <http://www.gnu.org/licenses/>.
20 Copyright (C) 2008 Christoph Würstle
47 import libliststorehandler
57 _moduleLogger = logging.getLogger(__name__)
58 PROFILE_STARTUP = False
61 class Multilist(hildonize.get_app_class()):
63 _user_data = os.path.join(os.path.expanduser("~"), ".%s" % constants.__app_name__)
64 _user_settings = "%s/settings.ini" % _user_data
67 super(Multilist, self).__init__()
68 self._clipboard = gtk.clipboard_get()
70 logging.info('Starting Multilist')
73 os.makedirs(self._user_data)
78 self.db = libspeichern.Speichern()
79 self.window_in_fullscreen = False #The window isn't in full screen mode initially.
81 #Haupt vbox für alle Elemente
82 self.window = gtk.Window()
83 self.vbox = gtk.VBox(homogeneous = False, spacing = 0)
85 self.selection = libselection.Selection(self.db, isHildon)
86 self.liststorehandler = libliststorehandler.Liststorehandler(self.db, self.selection)
87 self.view = libview.View(self.db, self.liststorehandler, self.window)
88 self.bottombar = libbottombar.Bottombar(self.db, self.view, isHildon)
91 if hildonize.GTK_MENU_USED:
94 menu_items = gtk.MenuItem(_("Choose database file"))
95 menu_items.connect("activate", self.select_db_dialog, None)
96 fileMenu.append(menu_items)
98 menu_items = gtk.MenuItem(_("SQL history"))
99 menu_items.connect("activate", self.view_sql_history, None)
100 fileMenu.append(menu_items)
102 menu_items = gtk.MenuItem(_("SQL optimize"))
103 menu_items.connect("activate", self.optimizeSQL, None)
104 fileMenu.append(menu_items)
106 menu_items = gtk.MenuItem(_("Sync items"))
107 menu_items.connect("activate", self.sync_notes, None)
108 fileMenu.append(menu_items)
110 menu_items = gtk.MenuItem(_("Quit"))
111 menu_items.connect("activate", self.destroy, None)
112 fileMenu.append(menu_items)
114 fileMenuItem = gtk.MenuItem(_("File"))
116 fileMenuItem.set_submenu(fileMenu)
118 viewMenu = gtk.Menu()
120 menu_items = gtk.MenuItem(_("Show Active"))
121 menu_items.connect("activate", self._on_toggle_filter, None)
122 viewMenu.append(menu_items)
124 viewMenuItem = gtk.MenuItem(_("View"))
126 viewMenuItem.set_submenu(viewMenu)
128 toolsMenu = gtk.Menu()
130 menu_items = gtk.MenuItem(_("Choose columns"))
131 menu_items.connect("activate", self.show_columns_dialog, None)
132 toolsMenu.append(menu_items)
134 menu_items = gtk.MenuItem(_("Rename Category"))
135 menu_items.connect("activate", self.bottombar.rename_category, None)
136 toolsMenu.append(menu_items)
138 menu_items = gtk.MenuItem(_("Rename List"))
139 menu_items.connect("activate", self.bottombar.rename_list, None)
140 toolsMenu.append(menu_items)
142 toolsMenuItem = gtk.MenuItem(_("Tools"))
144 toolsMenuItem.set_submenu(toolsMenu)
146 helpMenu = gtk.Menu()
147 menu_items = gtk.MenuItem(_("About"))
148 helpMenu.append(menu_items)
149 menu_items.connect("activate", self.show_about, None)
151 helpMenuItem = gtk.MenuItem(_("Help"))
153 helpMenuItem.set_submenu(helpMenu)
155 menu_bar = gtk.MenuBar()
157 menu_bar.append (fileMenuItem)
158 menu_bar.append (toolsMenuItem)
159 menu_bar.append (viewMenuItem)
160 # unten -> damit als letztes menu_bar.append (helpMenuItem)
162 menu_bar.append (helpMenuItem)
164 self.vbox.pack_start(menu_bar, False, False, 0)
166 menuBar = gtk.MenuBar()
168 self.vbox.pack_start(menuBar, False, False, 0)
170 #add to vbox below (to get it on top)
171 self.vbox.pack_end(self.bottombar, expand = False, fill = True, padding = 0)
172 self.vbox.pack_end(self.view, expand = True, fill = True, padding = 0)
173 self.vbox.pack_end(self.selection, expand = False, fill = True, padding = 0)
175 #Get the Main Window, and connect the "destroy" event
176 self.window.add(self.vbox)
178 self.window = hildonize.hildonize_window(self, self.window)
179 hildonize.set_application_title(self.window, "%s" % constants.__pretty_app_name__)
180 menu_bar = hildonize.hildonize_menu(
184 if hildonize.IS_FREMANTLE_SUPPORTED:
187 if not hildonize.IS_HILDON_SUPPORTED:
188 _moduleLogger.info("No hildonization support")
191 self.osso_c = osso.Context(
192 constants.__app_name__,
193 constants.__version__,
197 _moduleLogger.info("No osso support")
200 self.window.connect("delete_event", self.delete_event)
201 self.window.connect("destroy", self.destroy)
202 self.window.connect("key-press-event", self.on_key_press)
203 self.window.connect("window-state-event", self.on_window_state_change)
205 self.window.show_all()
206 self.prepare_sync_dialog()
209 @gtk_toolbox.log_exception(_moduleLogger)
210 def _on_toggle_filter(self, *args):
211 if self.liststorehandler.get_filter() == self.liststorehandler.SHOW_ALL:
212 self.liststorehandler.set_filter(self.liststorehandler.SHOW_ACTIVE)
213 elif self.liststorehandler.get_filter() == self.liststorehandler.SHOW_ACTIVE:
214 self.liststorehandler.set_filter(self.liststorehandler.SHOW_ALL)
216 assert False, "Unknown"
218 @gtk_toolbox.log_exception(_moduleLogger)
219 def on_key_press(self, widget, event, *args):
220 RETURN_TYPES = (gtk.keysyms.Return, gtk.keysyms.ISO_Enter, gtk.keysyms.KP_Enter)
221 isCtrl = bool(event.get_state() & gtk.gdk.CONTROL_MASK)
223 event.keyval == gtk.keysyms.F6 or
224 event.keyval in RETURN_TYPES and isCtrl
226 # The "Full screen" hardware key has been pressed
227 if self.window_in_fullscreen:
228 self.window.unfullscreen ()
230 self.window.fullscreen ()
232 #elif event.keyval == gtk.keysyms.f and isCtrl:
233 # self._toggle_search()
236 event.keyval in (gtk.keysyms.w, gtk.keysyms.q) and
237 event.get_state() & gtk.gdk.CONTROL_MASK
239 self.window.destroy()
240 elif event.keyval == gtk.keysyms.l and event.get_state() & gtk.gdk.CONTROL_MASK:
241 with open(constants._user_logpath_, "r") as f:
242 logLines = f.xreadlines()
243 log = "".join(logLines)
244 self._clipboard.set_text(str(log))
247 @gtk_toolbox.log_exception(_moduleLogger)
248 def on_window_state_change(self, widget, event, *args):
249 if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
250 self.window_in_fullscreen = True
252 self.window_in_fullscreen = False
254 def speichereAlles(self, data = None, data2 = None):
255 logging.info("Speichere alles")
257 def ladeAlles(self, data = None, data2 = None):
258 logging.info("Lade alles")
260 def beforeSync(self, data = None, data2 = None):
261 logging.info("Lade alles")
263 @gtk_toolbox.log_exception(_moduleLogger)
264 def sync_finished(self, data = None, data2 = None):
265 self.selection.comboList_changed()
266 self.selection.comboCategory_changed()
267 self.liststorehandler.update_list()
269 def prepare_sync_dialog(self):
270 self.sync_dialog = gtk.Dialog(_("Sync"), None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
272 self.sync_dialog.set_position(gtk.WIN_POS_CENTER)
273 sync = libsync.Sync(self.db, self.window, 50503)
274 sync.connect("syncFinished", self.sync_finished)
275 self.sync_dialog.vbox.pack_start(sync, True, True, 0)
276 self.sync_dialog.set_size_request(500, 350)
277 self.sync_dialog.vbox.show_all()
279 @gtk_toolbox.log_exception(_moduleLogger)
280 def sync_notes(self, widget = None, data = None):
281 if self.sync_dialog == None:
282 self.prepare_sync_dialog()
283 self.sync_dialog.run()
284 self.sync_dialog.hide()
286 @gtk_toolbox.log_exception(_moduleLogger)
287 def show_columns_dialog(self, widget = None, data = None):
288 col_dialog = gtk.Dialog(_("Choose columns"), self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
290 col_dialog.set_position(gtk.WIN_POS_CENTER)
291 cols = libview.Columns_dialog(self.db, self.liststorehandler)
293 col_dialog.vbox.pack_start(cols, True, True, 0)
294 col_dialog.set_size_request(500, 350)
295 col_dialog.vbox.show_all()
297 resp = col_dialog.run()
299 if resp == gtk.RESPONSE_ACCEPT:
300 logging.info("changing columns")
301 cols.save_column_setting()
302 self.view.reload_view()
303 #children = self.vbox.get_children()
304 #while len(children)>1:
305 # self.vbox.remove(children[1])
307 #self.vbox.pack_end(self.bottombar, expand = True, fill = True, padding = 0)
308 #self.vbox.pack_end(view, expand = True, fill = True, padding = 0)
309 #self.vbox.pack_end(self.selection, expand = False, fill = True, padding = 0)
313 @gtk_toolbox.log_exception(_moduleLogger)
314 def destroy(self, widget = None, data = None):
316 self.speichereAlles()
320 except AttributeError:
321 pass # Either None or close was removed (in Fremantle)
325 @gtk_toolbox.log_exception(_moduleLogger)
326 def delete_event(self, widget, event, data = None):
327 #print "delete event occurred"
330 def dlg_delete(self, widget, event, data = None):
333 @gtk_toolbox.log_exception(_moduleLogger)
334 def show_about(self, widget = None, data = None):
335 dialog = gtk.AboutDialog()
336 dialog.set_position(gtk.WIN_POS_CENTER)
337 dialog.set_name(constants.__pretty_app_name__)
338 dialog.set_version(constants.__version__)
339 dialog.set_copyright("")
340 dialog.set_website("http://axique.de/f = Multilist")
341 comments = "%s is a program to handle multiple lists." % constants.__pretty_app_name__
342 dialog.set_comments(comments)
343 dialog.set_authors(["Christoph Wurstle <n800@axique.net>", "Ed Page <eopage@byu.net> (Blame him for the most recent bugs)"])
347 def on_info1_activate(self, menuitem):
348 self.show_about(menuitem)
350 @gtk_toolbox.log_exception(_moduleLogger)
351 def view_sql_history(self, widget = None, data = None, data2 = None):
352 sqldiag = sqldialog.SqlDialog(self.db)
357 if res != gtk.RESPONSE_OK:
359 logging.info("exporting sql")
362 dlg = gtk.FileChooserDialog(
363 parent = self.window,
364 action = gtk.FILE_CHOOSER_ACTION_SAVE
366 dlg.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
367 dlg.add_button( gtk.STOCK_OK, gtk.RESPONSE_OK)
369 dlg = hildon.FileChooserDialog(self.window, gtk.FILE_CHOOSER_ACTION_SAVE)
371 dlg.set_title(_("Select SQL export file"))
372 exportFileResponse = dlg.run()
374 if exportFileResponse == gtk.RESPONSE_OK:
375 fileName = dlg.get_filename()
376 sqldiag.exportSQL(fileName)
382 @gtk_toolbox.log_exception(_moduleLogger)
383 def optimizeSQL(self, widget = None, data = None, data2 = None):
385 self.db.speichereSQL("VACUUM", log = False)
387 @gtk_toolbox.log_exception(_moduleLogger)
388 def select_db_dialog(self, widget = None, data = None, data2 = None):
389 if (isHildon == False):
390 dlg = gtk.FileChooserDialog(parent = self.window, action = gtk.FILE_CHOOSER_ACTION_SAVE)
391 dlg.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
392 dlg.add_button( gtk.STOCK_OK, gtk.RESPONSE_OK)
394 #dlg = hildon.FileChooserDialog(parent = self.window, action = gtk.FILE_CHOOSER_ACTION_SAVE)
395 dlg = hildon.FileChooserDialog(self.window, gtk.FILE_CHOOSER_ACTION_SAVE)
397 if self.db.ladeDirekt('datenbank'):
398 dlg.set_filename(self.db.ladeDirekt('datenbank'))
399 dlg.set_title(_("Choose your database file"))
400 if dlg.run() == gtk.RESPONSE_OK:
401 fileName = dlg.get_filename()
402 self.db.speichereDirekt('datenbank', fileName)
403 self.speichereAlles()
410 if hildonize.IS_HILDON_SUPPORTED:
411 gtk.set_application_name(constants.__pretty_app_name__)
413 if not PROFILE_STARTUP:
417 if __name__ == "__main__":
418 logging.basicConfig(level = logging.DEBUG)