Initial commit
authoraxique <n800@axique.de>
Fri, 8 Feb 2008 22:32:53 +0000 (22:32 +0000)
committeraxique <n800@axique.de>
Fri, 8 Feb 2008 22:32:53 +0000 (22:32 +0000)
git-svn-id: file:///svnroot/multilist@2 bd6b1de3-02cc-4133-82b9-a2a787a87b1d

23 files changed:
data/multilist.desktop [new file with mode: 0644]
data/multilist.png [new file with mode: 0644]
data/multilist.service [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/dirs [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/files [new file with mode: 0644]
debian/rules [new file with mode: 0755]
src/copydb.py [new file with mode: 0755]
src/multilist [new file with mode: 0755]
src/multilistclasses/__init__.py [new file with mode: 0755]
src/multilistclasses/libbottombar.py [new file with mode: 0644]
src/multilistclasses/libliststorehandler.py [new file with mode: 0644]
src/multilistclasses/libmultilist.py [new file with mode: 0755]
src/multilistclasses/libselection.py [new file with mode: 0644]
src/multilistclasses/libspeichern.py [new file with mode: 0644]
src/multilistclasses/libsqldialog.py [new file with mode: 0755]
src/multilistclasses/libsync.py [new file with mode: 0755]
src/multilistclasses/libview.py [new file with mode: 0644]
src/upload.sh [new file with mode: 0755]

diff --git a/data/multilist.desktop b/data/multilist.desktop
new file mode 100644 (file)
index 0000000..272f2c0
--- /dev/null
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Version=0.3.0
+Encoding=UTF-8
+Name=Multilist
+Exec=/usr/bin/multilist
+Icon=multilist
+Type=Application
+#X-Osso-Service=schulplaner
+X-Osso-Type=application/x-executable 
diff --git a/data/multilist.png b/data/multilist.png
new file mode 100644 (file)
index 0000000..d978b6d
Binary files /dev/null and b/data/multilist.png differ
diff --git a/data/multilist.service b/data/multilist.service
new file mode 100644 (file)
index 0000000..6b43128
--- /dev/null
@@ -0,0 +1,3 @@
+[D-BUS Service] 
+Name=com.axique.multilist
+Exec=/usr/bin/multilist
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..f5154e8
--- /dev/null
@@ -0,0 +1,6 @@
+multilist (0.3.0) unstable; urgency=low
+
+  * Initial Release.
+
+ -- unknown <n800@axique.de>  Mon,  6 Aug 2007 08:12:53 +0100
+
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..b8626c4
--- /dev/null
@@ -0,0 +1 @@
+4
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..aa57b00
--- /dev/null
@@ -0,0 +1,20 @@
+Source: multilist
+Section: user/other
+Priority: optional
+Maintainer: Christoph Würstle <n800 at axique de>
+Build-Depends: debhelper (>= 4.0.0), python2.5-dev
+Standards-Version: 3.6.1
+
+Package: multilist
+Architecture: all
+Depends: python2.5, python2.5-hildon, python2.5-gtk2, python2.5-osso, python2.5-dbus, python2.5-gstreamer
+Description: Multilist
+XB-Maemo-Icon-26:
+ iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAA
+ AAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9gCBQkmAyqhfqEAAAAddEVYdENv
+ bW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAP9JREFUSMfNVsERgzAMk7lMAGPwYv8h
+ eDEGrKA+eiluEqcOBdrc5S5AkCxbmAhJ4obR4aYR4kJELiMh+QNFmv2sobPUWRtKszZGOWgGkm+z
+ BDrKDa4bBVjoVxa+rYNXVVcr5Kf6RFWpshJ5sOrjSVkJcDFeldiCYtQkTQWt1teYh1yHSex1nKf2
+ uhLhzIuaqgae6W9B7iY7yQ4c1UzSRuQqehq9vi4QZq4De/V0U+zP+8Sag2Ao31euy7s31ucG9hkp
+ SQiGfZ9B0NZUFYCl4pRfuY42BSVWt5K669gDskFQqFslsFoGgpk2pq6xU+VRF1q+n6jwpTRZ/9dx
+ 6+pz5APOkH7tCcRtTQAAAABJRU5ErkJggg==
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..3c80733
--- /dev/null
@@ -0,0 +1,12 @@
+This package was debianized by Christoph Würstle <n800 !at! axique .dotx de> on
+Mon, 22 Jan 2007 22:44:33 +0200.
+
+It was downloaded from <fill in ftp site>
+
+Copyright:
+
+Upstream Author(s): <put author(s) name and email here>
+
+License:
+
+Special drop a mail
diff --git a/debian/dirs b/debian/dirs
new file mode 100644 (file)
index 0000000..ca882bb
--- /dev/null
@@ -0,0 +1,2 @@
+usr/bin
+usr/sbin
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..724e084
--- /dev/null
@@ -0,0 +1,2 @@
+README
+TODO
diff --git a/debian/files b/debian/files
new file mode 100644 (file)
index 0000000..8658f8f
--- /dev/null
@@ -0,0 +1 @@
+multilist_0.3.0_all.deb user/other optional
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..185e870
--- /dev/null
@@ -0,0 +1,93 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       INSTALL_PROGRAM += -s
+endif
+
+configure: configure-stamp
+configure-stamp:
+       dh_testdir
+       # Add here commands to configure the package.
+
+       touch configure-stamp
+
+
+build: build-stamp
+
+build-stamp: configure-stamp 
+       dh_testdir
+
+       # Add here commands to compile the package.
+       $(MAKE)
+
+       touch build-stamp
+
+clean:
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp configure-stamp
+
+       # Add here commands to clean up after the build process.
+       -$(MAKE) clean
+
+       dh_clean
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k
+       dh_installdirs
+
+       # Add here commands to install the package into debian/multilist
+       $(MAKE) install DESTDIR=$(CURDIR)/debian/multilist
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+       dh_installchangelogs
+#      dh_installdocs
+       dh_installexamples
+#      dh_install
+#      dh_installmenu
+#      dh_installdebconf       
+#      dh_installlogrotate
+#      dh_installemacsen
+#      dh_installpam
+#      dh_installmime
+#      dh_installinit
+#      dh_installcron
+#      dh_installinfo
+       dh_installman
+       dh_link
+       dh_strip
+       dh_compress
+       dh_fixperms
+#      dh_perl
+#      dh_python
+#      dh_makeshlibs
+       dh_installdeb
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/src/copydb.py b/src/copydb.py
new file mode 100755 (executable)
index 0000000..e50f303
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import time
+import sqlite3
+import shelve
+import uuid
+
+db="/home/chris/Documents/Schule/Schule/schulplaner/schuljahr200708enni.s3db"
+conn = sqlite3.connect(db)
+cur = conn.cursor()
+
+sql="UPDATE sync SET syncpartner=? WHERE syncpartner=?"
+cur.execute(sql,(str(uuid.uuid4()),"self")) #Eigene Id ändern feststellen
+conn.commit()
+
+sql="DELETE FROM sync WHERE syncpartner=?"
+cur.execute(sql,("self",))
+conn.commit()
+
+sql="INSERT INTO sync (syncpartner,uuid,pcdatum) VALUES (?,?,?)"
+cur.execute(sql,("self",str(uuid.uuid4()),int(time.time())))
+
+sql="UPDATE sync SET pcdatum=?"
+cur.execute(sql,(int(time.time()),))
+
+conn.commit()
\ No newline at end of file
diff --git a/src/multilist b/src/multilist
new file mode 100755 (executable)
index 0000000..555d36b
--- /dev/null
@@ -0,0 +1,47 @@
+#!/usr/bin/env python2.5
+# -*- coding: utf-8 -*-
+
+#/scratchbox/login
+#Xephyr :2 -host-cursor -screen 800x480x16 -dpi 96 -ac
+#af-sb-init.sh start
+#run-standalone.sh ./eggtimer.py
+#
+#https://stage.maemo.org/svn/maemo/projects/haf/trunk/
+#http://www.maemo.org/platform/docs/pymaemo/pyosso_context.html
+#http://maemo-hackers.org/apt/
+
+import os
+import sys
+                       
+if __name__ == "__main__":
+       
+       try:
+               import tempfile
+               import gtk
+               tmpdir=tempfile.gettempdir()
+               
+               os.mkdir(os.path.join(tmpdir, "multilist_lock"))
+       except OSError:
+               ## Failed: another instance is running
+               
+               mbox=gtk.MessageDialog(None,gtk.DIALOG_MODAL,gtk.MESSAGE_ERROR,gtk.BUTTONS_YES_NO,"Multilist already runnging.Start anyway? (Could result in db problems!)") 
+               response=mbox.run() 
+               mbox.hide() 
+               mbox.destroy() 
+               if response==gtk.RESPONSE_NO:
+                       sys.exit()
+
+       try:
+               
+               from multilistclasses import libmultilist
+               #print dir(eggtimerclasses)
+               app = libmultilist.multilistclass() 
+               app.main() 
+   
+       finally:
+               ## Remove the PID file
+               # (...)
+               ## Delete directory
+               os.rmdir(os.path.join(tmpdir, "multilist_lock"))
+               
+       
diff --git a/src/multilistclasses/__init__.py b/src/multilistclasses/__init__.py
new file mode 100755 (executable)
index 0000000..8d1c8b6
--- /dev/null
@@ -0,0 +1 @@
diff --git a/src/multilistclasses/libbottombar.py b/src/multilistclasses/libbottombar.py
new file mode 100644 (file)
index 0000000..f8f5e7d
--- /dev/null
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*- 
+
+
+import gobject
+import time
+import logging
+
+import gtk
+
+class Bottombar(gtk.HBox):
+       
+       __gsignals__ = {
+               'changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_STRING,gobject.TYPE_STRING)),
+               #'changedCategory': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_STRING,gobject.TYPE_STRING))
+       }
+
+               
+       def new_item(self,widget=None,data1=None,data2=None):
+               self.view.liststorehandler.add_row()
+
+               
+       def del_item(self,widget=None,data1=None,data2=None):
+               path, col = self.view.treeview.get_cursor()
+               if path!=None:
+                       mbox=gtk.MessageDialog(None,gtk.DIALOG_MODAL,gtk.MESSAGE_QUESTION,gtk.BUTTONS_YES_NO,"Delete current item?") 
+                       response=mbox.run() 
+                       mbox.hide() 
+                       mbox.destroy() 
+                       if response==gtk.RESPONSE_YES:
+                               self.view.del_active_row()
+               else:
+                       mbox=gtk.MessageDialog(None,gtk.DIALOG_MODAL,gtk.MESSAGE_ERROR,gtk.BUTTONS_OK,"No item selected!") 
+                       response=mbox.run() 
+                       mbox.hide() 
+                       mbox.destroy()                  
+               
+               
+       def checkout_items(self,widget=None,data1=None,data2=None):
+               #self.view.del_active_row()
+               mbox=gtk.MessageDialog(None,gtk.DIALOG_MODAL,gtk.MESSAGE_QUESTION,gtk.BUTTONS_YES_NO,"Really checlout all items?") 
+               response=mbox.run() 
+               mbox.hide() 
+               mbox.destroy() 
+               if response==gtk.RESPONSE_YES:
+                       n=len(self.view.liststorehandler.get_liststore())
+                       for i in range(n):
+                               self.view.liststorehandler.checkout_rows()
+                               #print i
+                       
+       def search_list(self,widget=None,data1=None,data2=None):
+               self.view.liststorehandler.get_liststore(widget.get_text())
+                       
+       
+       def rename_category(self,widget=None,data1=None,data2=None):
+               dialog = gtk.Dialog("New categrory name:",None,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
+               
+               dialog.set_position(gtk.WIN_POS_CENTER)
+               entryKlasse=gtk.Entry()
+               entryKlasse.set_text(self.view.liststorehandler.selection.get_category())
+               
+               dialog.vbox.pack_start(entryKlasse, True, True, 0)
+               
+               dialog.vbox.show_all()
+               #dialog.set_size_request(400,300)
+
+               if dialog.run() == gtk.RESPONSE_ACCEPT:
+                       logging.info("new category name "+entryKlasse.get_text())
+                       self.view.liststorehandler.rename_category(entryKlasse.get_text())
+               else:
+                       #print "Cancel",res
+                       pass
+               dialog.destroy()
+               
+               
+       def rename_list(self,widget=None,data1=None,data2=None):
+               dialog = gtk.Dialog("New list name:",None,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
+               
+               dialog.set_position(gtk.WIN_POS_CENTER)
+               entryKlasse=gtk.Entry()
+               entryKlasse.set_text(self.view.liststorehandler.selection.get_list())
+               
+               dialog.vbox.pack_start(entryKlasse, True, True, 0)
+               
+               dialog.vbox.show_all()
+               #dialog.set_size_request(400,300)
+
+               if dialog.run() == gtk.RESPONSE_ACCEPT:
+                       logging.info("new list name "+entryKlasse.get_text())
+                       self.view.liststorehandler.rename_list(entryKlasse.get_text())
+               else:
+                       #print "Cancel",res
+                       pass
+               dialog.destroy()
+       
+       def __init__(self,db,view,isHildon):
+               gtk.HBox.__init__(self,homogeneous=False, spacing=3)
+               
+               self.db=db
+               self.isHildon=isHildon
+               self.view=view
+               
+               logging.info("libBottomBar, init")
+                       
+               
+               button=gtk.Button("New item")
+               button.connect("clicked",self.new_item)
+               self.pack_start(button, expand=False, fill=True, padding=0)
+               
+               label=gtk.Label("  ")
+               self.pack_start(label, expand=True, fill=True, padding=0)
+               
+               label=gtk.Label("Search:")
+               self.pack_start(label, expand=False, fill=True, padding=0)
+               searchEntry=gtk.Entry()
+               searchEntry.connect("changed",self.search_list)
+               self.pack_start(searchEntry, expand=True, fill=True, padding=0)
+               
+               label=gtk.Label("  ")
+               self.pack_start(label, expand=True, fill=True, padding=0)
+               
+               button=gtk.Button("Checkout all items")
+               button.connect("clicked",self.checkout_items)
+               self.pack_start(button, expand=False, fill=True, padding=0)
+               
+               button=gtk.Button("Del item")
+               button.connect("clicked",self.del_item)
+               self.pack_start(button, expand=False, fill=True, padding=0)
+               
+               
+               
\ No newline at end of file
diff --git a/src/multilistclasses/libliststorehandler.py b/src/multilistclasses/libliststorehandler.py
new file mode 100644 (file)
index 0000000..757de2e
--- /dev/null
@@ -0,0 +1,198 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*- 
+
+import gtk
+import gobject
+import libspeichern
+import logging
+
+
+class Liststorehandler():
+       
+       def get_unitsstore(self):
+               if (self.unitsstore==None):
+                       self.unitsstore=gtk.ListStore(str, str, str,str,str,  str,str, str, str,str, str, str,str)
+               self.unitsstore.clear()
+               #row(3) quantities
+               #row 4 units
+               #row 6 priority
+               self.unitsstore.append(["-1","-1","","","","","","","","","","",""])    
+               self.unitsstore.append(["-1","-1","","1","g","","0","","","","","",""]) 
+               self.unitsstore.append(["-1","-1","","2","kg","","1","","","","","",""])        
+               self.unitsstore.append(["-1","-1","","3","liter","","2","","","","","",""])     
+               self.unitsstore.append(["-1","-1","","4","packs","","3","","","","","",""])     
+               self.unitsstore.append(["-1","-1","","5","","","4","","","","","",""])  
+               self.unitsstore.append(["-1","-1","","6","","","5","","","","","",""])  
+               self.unitsstore.append(["-1","-1","","7","","","6","","","","","",""])  
+               self.unitsstore.append(["-1","-1","","8","","","7","","","","","",""])  
+               self.unitsstore.append(["-1","-1","","9","","","8","","","","","",""])  
+               self.unitsstore.append(["-1","-1","","","","","9","","","","","",""])   
+               
+               return self.unitsstore
+               
+               
+       
+       
+       def get_liststore(self,titlesearch=""):
+               if (self.liststore==None):
+                       self.liststore=gtk.ListStore(str, str, str,str,str,  str,str, str, str,str, str, str,str)
+               self.liststore.clear()
+               
+               titlesearch=titlesearch+"%"
+               
+               
+               if (self.selection.get_status()=="0"): #only 0 and 1 (active items)
+                       sql="SELECT uid,status,title,quantitiy,unit,price,priority,date,private,stores,note,custom1,custom2 FROM items WHERE list=? AND category LIKE ? AND status>=? AND title like ? ORDER BY category, status, title"
+                       rows=self.db.ladeSQL(sql,(self.selection.get_list(),self.selection.get_category(True),self.selection.get_status(),titlesearch))
+               else:
+                       sql="SELECT uid,status,title,quantitiy,unit,price,priority,date,private,stores,note,custom1,custom2 FROM items WHERE list=? AND category LIKE ? AND title LIKE ? ORDER BY category, title ASC"
+                       rows=self.db.ladeSQL(sql,(self.selection.get_list(),self.selection.get_category(True),titlesearch))
+                       
+               #print rows
+               if ((rows!=None)and(len(rows)>0)):
+                       for row in rows:
+                               uid,status,title,quantitiy,unit,price,priority,date,private,stores,note,custom1,custom2 = row
+                               if unit==None:
+                                       pass
+                                       #unit=""
+                               self.liststore.append([uid,status,title,quantitiy,unit,price,priority,date,private,stores,note,custom1,custom2])
+                       #else:
+                       #self.liststore.append(["-1","-1",""," ","","","","","","","","",""])   
+               #import uuid
+               #self.liststore.append(["-1","-1","","","","","","","","","","",""])
+               
+               return self.liststore
+       
+       
+       def emptyValueExists(self):
+               for child in self.liststore:
+                       if child[2]=="":
+                               return True
+               return False
+               
+       
+
+       def update_row(self,irow,icol,new_text):
+               #print "liststore 1"
+               #for x in self.liststore:
+               #       print x[0],x[2]
+               
+               if (irow>-1)and(self.liststore[irow][0]!="-1")and(self.liststore[irow][0]!=None):
+                       sql = "UPDATE items SET "+self.collist[icol]+"=? WHERE uid=?"
+                       self.db.speichereSQL(sql,(new_text,self.liststore[irow][0]),rowid=self.liststore[irow][0])
+                       
+                       logging.info("Updated row: "+self.collist[icol]+" new text "+new_text+" Titel: "+str(self.liststore[irow][2])+" with uid "+str(self.liststore[irow][0]))
+                       
+                       self.liststore[irow][icol]=new_text 
+               else:
+                       logging.warning("update_row: row does not exist")
+                       return
+                       #if (self.emptyValueExists()==True)and(icol<2):
+                       #       #print "letzter Eintrag ohne inhalt"
+                       #       return
+                       
+               #print "liststore 2"
+               #for x in self.liststore:
+               #       print x[0],x[2]
+               
+               
+       def checkout_rows(self):
+               sql = "UPDATE items SET status=? WHERE list=? AND category=?"
+               self.db.speichereSQL(sql,("-1",self.selection.get_list(),self.selection.get_category()))
+               for i in range(len(self.liststore)):
+                       self.liststore[i][1]="-1"
+                       
+                       
+               
+               
+       def add_row(self):
+               #self.update_row(-1,1,"-1")
+               #for x in self.liststore:
+               #       print x[0],x[2]
+               status=self.selection.get_status()
+               import uuid
+               uid=str(uuid.uuid4())
+               sql = "INSERT INTO items (uid,list,category,status, title) VALUES (?,?,?,?,?)"
+               self.db.speichereSQL(sql,(uid,self.selection.get_list(),self.selection.get_category(),status,""),rowid=uid)
+               logging.info("Insertet row: status = "+status+" with uid "+str(uid))
+                       #self.liststore[irow][0]=str(uuid.uuid4())
+                       
+               self.liststore.append([uid,status,""," ","","","","","","","","",""])
+               self.selection.comboLists_check_for_update()
+               #       if (irow>-1):
+               #               self.liststore[irow][icol]=new_text
+               #               self.liststore[irow][0]=uid
+               #       else:
+               #               self.liststore.append([uid,"-1",""," ","","","","","","","","",""])
+                               #print "xy",self.liststore[len(self.liststore)-1][0]
+                       #Check if a new list/category is opened
+               #       self.selection.comboLists_check_for_update()
+               
+       def del_row(self,irow,row_iter):
+               uid=self.liststore[irow][0]
+               self.liststore.remove(row_iter)
+               sql = "DELETE FROM items WHERE uid=?"
+               self.db.speichereSQL(sql,(uid,))
+               #
+               
+               
+       def get_colname(self,i):
+               if i<len(self.collist):
+                       return self.collist[i]
+               else:
+                       return None
+               
+       def get_colcount(self):
+               return len(self.collist)
+
+       
+       def rename_category(self,new_name):
+               sql = "UPDATE items SET category=? WHERE list=? AND category=?"
+               self.db.speichereSQL(sql,(new_name,self.selection.get_list(),self.selection.get_category()))
+               self.selection.comboList_changed()
+               self.selection.set_category(new_name)
+                               
+       def rename_list(self,new_name):
+               sql = "UPDATE items SET list=? WHERE list=?"
+               self.db.speichereSQL(sql,(new_name,self.selection.get_list(),))
+               self.selection.load()
+               self.selection.set_list(new_name)       
+       
+       
+       #def update_category(self,widget=None,data=None,data2=None,data3=None):
+       #       self.get_liststore()
+               
+       def update_list(self,widget=None,data=None,data2=None,data3=None):
+               self.get_liststore()
+               
+       def __init__(self,db,selection):
+               self.db=db
+               self.liststore=None
+               self.unitsstore=None
+               self.selection=selection
+               self.collist=("uid","status","title","quantitiy","unit","price","priority","date","private","stores","note","custom1","custom2")
+               
+               #sql="DROP TABLE items"
+               #self.db.speichereSQL(sql)
+               
+               sql = "CREATE TABLE items (uid TEXT, list TEXT, category TEXT, status TEXT, title TEXT, quantitiy TEXT, unit TEXT, price TEXT, priority TEXT, date TEXT, pcdate TEXT, private TEXT, stores TEXT, note TEXT, custom1 TEXT, custom2 TEXT)"
+               self.db.speichereSQL(sql)
+               
+               
+               self.selection.load()
+               self.selection.connect("changed",self.update_list)
+               #self.selection.connect("changedCategory",self.update_category)
+               
+
+               """
+               sql = "INSERT INTO items (uid,list,category,title) VALUES (?,?,?,?)"
+               import uuid
+               self.db.speichereSQL(sql,(str(uuid.uuid4()),"default","default","atitel1"))
+               self.db.speichereSQL(sql,(str(uuid.uuid4()),"default","default","btitel2"))
+               self.db.speichereSQL(sql,(str(uuid.uuid4()),"default","default","ctitel3"))
+               
+               print "inserted"
+               """
+
+               
+               
\ No newline at end of file
diff --git a/src/multilistclasses/libmultilist.py b/src/multilistclasses/libmultilist.py
new file mode 100755 (executable)
index 0000000..cb14f82
--- /dev/null
@@ -0,0 +1,382 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#/scratchbox/login
+#Xephyr :2 -host-cursor -screen 800x480x16 -dpi 96 -ac
+#af-sb-init.sh start
+#run-standalone.sh ./eggtimer.py
+#
+#https://stage.maemo.org/svn/maemo/projects/haf/trunk/
+#http://www.maemo.org/platform/docs/pymaemo/pyosso_context.html
+#http://maemo-hackers.org/apt/
+
+import time
+import os
+import sys
+import logging
+
+try:
+        import gtk
+        #import gtk.glade
+except:
+       print "gtk import failed"
+        sys.exit(1)
+       
+try:
+       import hildon
+       import osso
+       isHildon=True
+except:
+       isHildon=False
+       class hildon():
+               def __init__(self):
+                       print "PseudoClass hildon"
+               class Program():
+                       def __init__(self):
+                               print "PseudoClass hildon.Program"
+
+#import libextdatei
+import libspeichern
+import libsqldialog
+import libselection
+import libview
+import libliststorehandler
+import libsync
+import libbottombar
+
+version = "0.3.0"
+app_name = "Multilist"
+
+               
+       
+
+class multilistclass(hildon.Program):
+               
+       def on_key_press(self, widget, event, *args):
+               #Hildon Fullscreen Modus
+               if (isHildon==False): return
+               if event.keyval == gtk.keysyms.F6: 
+                       # The "Full screen" hardware key has been pressed 
+                       if self.window_in_fullscreen: 
+                               self.window.unfullscreen () 
+                       else: 
+                               self.window.fullscreen () 
+               
+       def on_window_state_change(self, widget, event, *args): 
+               if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN: 
+                       self.window_in_fullscreen = True 
+               else: 
+                       self.window_in_fullscreen = False 
+
+       
+       def speichereAlles(self,data=None,data2=None):
+               logging.info("Speichere alles")
+
+
+       def ladeAlles(self,data=None,data2=None):
+               logging.info("Lade alles")
+               
+       def beforeSync(self,data=None,data2=None):
+               logging.info("Lade alles")
+
+
+       def sync_finished(self,data=None,data2=None):
+               self.selection.comboList_changed()
+               self.selection.comboCategory_changed()
+               self.liststorehandler.update_list()
+               
+       
+       def prepare_sync_dialog(self):
+               self.sync_dialog = gtk.Dialog("Sync",None,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
+               
+               self.sync_dialog.set_position(gtk.WIN_POS_CENTER)
+               sync=libsync.Sync(self.db)
+               sync.connect("syncFinished",self.sync_finished)
+               self.sync_dialog.vbox.pack_start(sync, True, True, 0)
+               self.sync_dialog.set_size_request(500,350)
+               self.sync_dialog.vbox.show_all()
+               sync.connect("syncFinished",self.sync_finished)
+       
+       
+       def sync_notes(self,widget=None,data=None):
+               if self.sync_dialog==None:
+                       self.prepare_sync_dialog()
+               self.sync_dialog.run()
+               self.sync_dialog.hide()
+
+
+       def show_columns_dialog(self,widget=None,data=None):
+               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))
+               
+               col_dialog.set_position(gtk.WIN_POS_CENTER)
+               cols=libview.Columns_dialog(self.db,self.liststorehandler)
+
+               col_dialog.vbox.pack_start(cols, True, True, 0)
+               col_dialog.set_size_request(500,350)
+               col_dialog.vbox.show_all()
+               
+               resp=col_dialog.run()
+               col_dialog.hide()
+               if resp==gtk.RESPONSE_ACCEPT:
+                       logging.info("changing columns")
+                       cols.save_column_setting()
+                       self.view.reload_view()
+                       #children=self.vbox.get_children()
+                       #while len(children)>1:
+                       #       self.vbox.remove(children[1])
+
+                       #self.vbox.pack_end(self.bottombar, expand=True, fill=True, padding=0)
+                       #self.vbox.pack_end(view, expand=True, fill=True, padding=0)
+                       #self.vbox.pack_end(self.selection, expand=False, fill=True, padding=0)
+                       
+
+               col_dialog.destroy()
+               
+
+
+       def __init__(self):
+               home_dir = os.path.expanduser('~')
+               dblog=os.path.join(home_dir, "multilist.log") 
+               logging.basicConfig(level=logging.INFO,format='%(asctime)s %(levelname)-8s %(message)s', datefmt='%a, %d %b %Y %H:%M:%S', filename=dblog,filemode='a')
+               #logging.getLogger('').addHandler(console)
+               
+               # define a Handler which writes INFO messages or higher to the sys.stderr
+               console = logging.StreamHandler()
+               console.setLevel(logging.INFO)
+               # set a format which is simpler for console use
+               formatter = logging.Formatter('%(asctime)s  %(levelname)-8s %(message)s')
+               # tell the handler to use this format
+               console.setFormatter(formatter)
+               # add the handler to the root logger
+               logging.getLogger('').addHandler(console)
+               
+               logging.info('Starting Multilist')
+               
+               if (isHildon==True): 
+                       logging.info('Hildon erkannt, rufe Hildon constructor auf')
+                       hildon.Program.__init__(self)
+                               
+                #Get the Main Window, and connect the "destroy" event
+               if (isHildon==False):
+                       self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+                       self.window.set_default_size(700,500)
+               else:
+                       self.window = hildon.Window()
+                       self.add_window(self.window)
+                       
+               #print "1b: ",time.clock() 
+               
+                if (self.window):
+                       self.window.connect("delete_event", self.delete_event)
+                       self.window.connect("destroy", self.destroy)
+                       self.window.set_title("Multilist")
+                       
+                       
+                       
+                       if (isHildon==True): self.window.connect("key-press-event", self.on_key_press) 
+                       self.window.connect("window-state-event", self.on_window_state_change) 
+                       self.window_in_fullscreen = False #The window isn't in full screen mode initially.
+
+
+               self.db=libspeichern.Speichern()
+               
+               self.selection=libselection.Selection(self.db,isHildon)
+               self.liststorehandler=libliststorehandler.Liststorehandler(self.db,self.selection)
+               self.view=libview.View(self.db,self.liststorehandler,self.window)
+               self.bottombar=libbottombar.Bottombar(self.db,self.view,isHildon)
+               
+               #Haupt vbox für alle Elemente
+               self.vbox = gtk.VBox(homogeneous=False, spacing=0)
+               
+               
+               
+               #Menue
+               dateimenu = gtk.Menu()
+               
+               menu_items = gtk.MenuItem("DB auswählen")
+               dateimenu.append(menu_items)
+               menu_items.connect("activate", self.select_db_dialog, None)
+               
+               menu_items = gtk.MenuItem("SQL History anschauen")
+               dateimenu.append(menu_items)
+               menu_items.connect("activate", self.view_sql_history, None)
+               
+               menu_items = gtk.MenuItem("SQL optimieren")
+               dateimenu.append(menu_items)
+               menu_items.connect("activate", self.optimizeSQL, None)
+               
+               menu_items = gtk.MenuItem("Sync items")
+               self.prepare_sync_dialog()
+               dateimenu.append(menu_items)
+               menu_items.connect("activate", self.sync_notes, None)
+               
+               
+               menu_items = gtk.MenuItem("Beenden")
+               dateimenu.append(menu_items)
+               menu_items.connect("activate", self.destroy, None)
+               #menu_items.show()
+               
+               datei_menu = gtk.MenuItem("Datei")
+               datei_menu.show()
+               datei_menu.set_submenu(dateimenu)
+               
+               
+               toolsmenu = gtk.Menu()
+               
+               
+               menu_items = gtk.MenuItem("Choose columns")
+               toolsmenu.append(menu_items)
+               menu_items.connect("activate", self.show_columns_dialog, None)
+               
+               menu_items = gtk.MenuItem("Rename Category")
+               toolsmenu.append(menu_items)
+               menu_items.connect("activate", self.bottombar.rename_category, None)
+               
+               menu_items = gtk.MenuItem("Rename List")
+               toolsmenu.append(menu_items)
+               menu_items.connect("activate", self.bottombar.rename_list, None)
+               
+               tools_menu = gtk.MenuItem("Tools")
+               tools_menu.show()
+               tools_menu.set_submenu(toolsmenu)
+               
+               
+               hilfemenu = gtk.Menu()
+               menu_items = gtk.MenuItem("Über")
+               hilfemenu.append(menu_items)
+               menu_items.connect("activate", self.show_about, None)
+               
+               hilfe_menu = gtk.MenuItem("Hilfe")
+               hilfe_menu.show()
+               hilfe_menu.set_submenu(hilfemenu)
+               
+               menu_bar = gtk.MenuBar()
+               menu_bar.show()
+               menu_bar.append (datei_menu)
+               menu_bar.append (tools_menu)
+               # unten -> damit als letztes menu_bar.append (hilfe_menu)
+               #Als letztes menü
+               menu_bar.append (hilfe_menu)
+               
+               if (isHildon==True):
+                       menu = gtk.Menu() 
+                       for child in menu_bar.get_children():
+                               child.reparent(menu) 
+                       self.window.set_menu(menu)
+                       menu_bar.destroy()
+               else:
+                       self.vbox.pack_start(menu_bar, False, False, 2)
+               
+               
+               
+
+               #add to vbox below (to get it on top)
+               
+               
+               
+               self.vbox.pack_end(self.bottombar, expand=False, fill=True, padding=0)
+               self.vbox.pack_end(self.view, expand=True, fill=True, padding=0)
+               self.vbox.pack_end(self.selection, expand=False, fill=True, padding=0)
+               
+
+               if (isHildon==True): self.osso_c = osso.Context(app_name, version, False)
+               self.window.add(self.vbox)
+               self.window.show_all()
+               
+               #print "8a"
+               self.ladeAlles()
+               
+               
+               #print "9: ",time.clock()
+                       
+       def main(self):
+               gtk.main()
+               if (isHildon==True): self.osso_c.close()
+               
+       def destroy(self, widget=None, data=None):
+               self.speichereAlles()
+               self.db.close()
+               gtk.main_quit()
+               
+               
+       def delete_event(self, widget, event, data=None):
+               #print "delete event occurred"
+               return False
+       
+       def dlg_delete(self,widget,event,data=None):
+               return False
+
+
+       def show_about(self, widget=None,data=None):
+               dialog = gtk.AboutDialog()
+               dialog.set_position(gtk.WIN_POS_CENTER)
+               dialog.set_name(app_name)
+               dialog.set_version(version)
+               dialog.set_copyright("")
+               dialog.set_website("http://axique.de/f=Multilist")
+               comments = "%s is a program to handle multiple lists." % app_name
+               dialog.set_comments(comments)        
+               dialog.run()     
+               dialog.destroy()
+       
+       def on_info1_activate(self,menuitem):
+               self.show_about(menuitem)
+
+  
+       def view_sql_history(self,widget=None,data=None,data2=None):
+               sqldiag=libsqldialog.sqlDialog(self.db)
+               res=sqldiag.run()
+               sqldiag.hide()
+               if res==444:
+                       logging.info("exporting sql")
+                       
+                       if (isHildon==False):
+                               dlg = gtk.FileChooserDialog(parent = self.window, action = gtk.FILE_CHOOSER_ACTION_SAVE)
+                               dlg.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
+                               dlg.add_button( gtk.STOCK_OK, gtk.RESPONSE_OK)
+                       else:
+                               #dlg = hildon.FileChooserDialog(parent = self.window, action = gtk.FILE_CHOOSER_ACTION_SAVE)
+                               dlg=hildon.FileChooserDialog(self.window, gtk.FILE_CHOOSER_ACTION_SAVE)
+                       
+                       dlg.set_title("Wähle SQL-Export-Datei")
+                       if dlg.run() == gtk.RESPONSE_OK:
+                               fileName = dlg.get_filename()
+                               dlg.destroy()
+                               sqldiag.exportSQL(fileName)
+                       else:
+                               dlg.destroy()
+                               
+               sqldiag.destroy()
+
+               
+       def optimizeSQL(self,widget=None,data=None,data2=None): 
+               #optimiere sql
+               self.db.speichereSQL("VACUUM",log=False)
+               
+  
+
+  
+       def select_db_dialog(self,widget=None,data=None,data2=None):
+               if (isHildon==False):
+                       dlg = gtk.FileChooserDialog(parent = self.window, action = gtk.FILE_CHOOSER_ACTION_SAVE)
+                       dlg.add_button( gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
+                       dlg.add_button( gtk.STOCK_OK, gtk.RESPONSE_OK)
+               else:
+                       #dlg = hildon.FileChooserDialog(parent = self.window, action = gtk.FILE_CHOOSER_ACTION_SAVE)
+                       dlg=hildon.FileChooserDialog(self.window, gtk.FILE_CHOOSER_ACTION_SAVE)
+                       
+               
+               if self.db.ladeDirekt('datenbank'):
+                       dlg.set_filename(self.db.ladeDirekt('datenbank'))
+               dlg.set_title("Wähle Datenbank-Datei")
+               if dlg.run() == gtk.RESPONSE_OK:
+                       fileName = dlg.get_filename()
+                       self.db.speichereDirekt('datenbank',fileName)
+                       self.speichereAlles()
+                       self.db.openDB()
+                       self.ladeAlles()
+               dlg.destroy()
+               
+               
+               
+
diff --git a/src/multilistclasses/libselection.py b/src/multilistclasses/libselection.py
new file mode 100644 (file)
index 0000000..1a0a3af
--- /dev/null
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*- 
+
+
+import gobject
+import time
+import logging
+
+import gtk
+
+class Selection(gtk.HBox):
+       
+       __gsignals__ = {
+               'changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_STRING,gobject.TYPE_STRING)),
+               #'changedCategory': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_STRING,gobject.TYPE_STRING))
+       }
+
+       def load(self):
+               model=self.comboList.get_model()
+               model.clear()
+               #self.comboList.remove(0)
+                       
+               
+               sql="SELECT DISTINCT list FROM items ORDER BY list"
+               rows=self.db.ladeSQL(sql)
+               if ((rows!=None)and(len(rows)>0)):
+                       for row in rows:
+                               self.comboList.append_text(row[0])
+               else:
+                       self.comboList.append_text("default")
+                       
+               s=self.db.ladeDirekt("comboListText")
+               if s!="":
+                       self.comboList.get_child().set_text(s)
+               else:
+                       self.comboList.set_active(0)
+
+       def comboList_changed(self, widget=None, data=None):
+               #self.comboCategory.set_model(None)
+               #print "reload categories"
+               while len(self.comboCategory.get_model())>0:
+                       self.comboCategory.remove_text(0)
+               
+               sql="SELECT DISTINCT category FROM items WHERE list=? ORDER BY category"
+               rows=self.db.ladeSQL(sql,(self.get_list(),))
+               
+               self.comboCategory.append_text("all")
+               if ((rows!=None)and(len(rows)>0)):
+                       for row in rows:
+                               if (row[0]!="all"):
+                                       self.comboCategory.append_text(row[0])
+               
+               s=self.db.ladeDirekt("comboCategoryText"+self.comboList.get_child().get_text())
+               if len(s)>0:
+                       self.comboCategory.get_child().set_text(s)
+               else:
+                       self.comboCategory.set_active(0)
+               
+               self.emit("changed","list","")
+               self.db.speichereDirekt("comboListText",self.comboList.get_child().get_text())
+               
+
+               
+       def comboCategory_changed(self, widget=None, data=None):
+               #logging.info("Klasse geaendert zu ")
+               #self.hauptRegister.set_current_page(0)
+               self.emit("changed","category","")
+               if self.comboCategory.get_active()>-1:
+                       self.db.speichereDirekt("comboCategoryText"+self.comboList.get_child().get_text(),self.comboCategory.get_child().get_text())
+               
+       def radioActive_changed(self, widget, data=None):
+               self.emit("changed","radio","")
+
+       def comboLists_check_for_update(self):
+               if self.comboCategory.get_active()==-1:
+                       model=self.comboCategory.get_model()
+                       found=False
+                       cat=self.get_category()
+                       for x in model:
+                               if x[0]==cat:
+                                       found=True
+                       if found==False:
+                               self.comboCategory.append_text(self.get_category())
+                               self.comboCategory.set_active(len(self.comboCategory.get_model())-1)
+               if self.comboList.get_active()==-1:
+                       model=self.comboList.get_model()
+                       found=False
+                       list=self.get_list()
+                       for x in model:
+                               if x[0]==list:
+                                       found=True
+                       if found==False:
+                               self.comboList.append_text(self.get_list())
+                               self.comboList.set_active(len(self.comboList.get_model())-1)
+               
+
+       def lade(self):
+               logging.warning("Laden der aktuellen position noch nicht implementiert")
+
+       
+       def speichere(self):
+               logging.warning("Speichern der aktuellen position noch nicht implementiert")
+       
+       
+       def getIsHildon(self):
+               return self.isHildon
+       
+       def get_category(self,select=False):
+               s=self.comboCategory.get_child().get_text()
+               if s=="all":
+                       if (select==False):
+                               return "undefined"
+                       else:
+                               return "%"
+               else:
+                       return s
+       def set_category(self,category):
+               self.comboCategory.get_child().set_text(category)
+                       
+       def set_list(self,listname):
+               self.comboList.get_child().set_text(listname)
+               
+       def get_list(self):
+               return self.comboList.get_child().get_text()
+
+
+       
+       def get_status(self):
+               #return self.comboCategory.get_child().get_text()
+               if self.radio_all.get_active()==True:
+                       return "-1"
+               else:
+                       return "0"
+               
+       
+       def __init__(self,db,isHildon):
+               gtk.HBox.__init__(self,homogeneous=False, spacing=3)
+               
+               self.db=db
+               self.isHildon=isHildon
+               
+               logging.info("libSelection, init")
+                       
+               
+               label=gtk.Label("List:")
+               self.pack_start(label, expand=False, fill=True, padding=0)
+               
+               self.comboList = gtk.combo_box_entry_new_text()
+               self.comboList.set_size_request(180,-1)
+               self.pack_start(self.comboList, expand=False, fill=True, padding=0)
+                       
+               label=gtk.Label("  Category:")
+               self.pack_start(label, expand=False, fill=True, padding=0)
+               
+               self.comboCategory = gtk.combo_box_entry_new_text()
+               self.comboCategory.set_size_request(180,-1)
+               self.pack_start(self.comboCategory, expand=False, fill=True, padding=0)
+               
+               self.comboList.connect("changed", self.comboList_changed, None)
+               self.comboCategory.connect("changed", self.comboCategory_changed, None)
+               
+               label=gtk.Label("  View:")
+               self.pack_start(label, expand=False, fill=True, padding=0)
+               
+               self.radio_all=gtk.RadioButton(group=None, label="All", use_underline=True)
+               self.pack_start(self.radio_all, expand=False, fill=True, padding=0)
+               self.radio_active=gtk.RadioButton(group=self.radio_all, label="Active", use_underline=True)
+               self.pack_start(self.radio_active, expand=False, fill=True, padding=0)
+               self.radio_all.connect("toggled",self.radioActive_changed, None)
+               
+               
+               
\ No newline at end of file
diff --git a/src/multilistclasses/libspeichern.py b/src/multilistclasses/libspeichern.py
new file mode 100644 (file)
index 0000000..bde55b3
--- /dev/null
@@ -0,0 +1,172 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import time
+import sqlite3
+import shelve
+import sys
+import string
+import shutil
+import os
+import logging
+
+class Speichern():
+       def speichereDirekt(self,schluessel,daten):
+               self.d[schluessel]=daten
+               logging.info("speichereDirekt "+str(schluessel)+" "+str(daten)+" lesen: "+str(self.d[schluessel]))
+
+       
+       def ladeDirekt(self,schluessel,default=""):
+               #print "ladeDirekt",schluessel, "Schluessel vorhanden",self.d.has_key(schluessel)
+               if (self.d.has_key(schluessel)==True):
+                       data=self.d[schluessel]
+                       #print data
+                       return data
+               else:
+                       return default
+                               
+                               
+       def speichereSQL(self,sql,tupel=None,commit=True,host="self",log=True,pcdatum=None,rowid=""):
+               #print "speichereSQL:",sql,tupel
+               try:
+                       programSQLError=True
+                       if (tupel==None):
+                               self.cur.execute(sql)
+                       else:
+                               self.cur.execute(sql,tupel)
+                       programSQLError=False   
+                       
+                       #print int(time.time()), sql, pickle.dumps(tupel), host
+                       if (log==True):
+                               strtupel=[]
+                               if (tupel!=None):
+                                       for t in tupel:
+                                               strtupel.append(str(t))
+
+
+                               if pcdatum==None: pcdatum=int(time.time())
+                               self.cur.execute("INSERT INTO logtable ( pcdatum,sql,param,host,rowid ) VALUES (?,?,?,?,?)",(pcdatum, sql, string.join(strtupel," <<Tren-ner>> "), host,str(rowid) ))
+                       if (commit==True): self.conn.commit()
+                       
+                       return True
+               except:
+                       s=str(sys.exc_info())
+                       if (s.find(" already exists")==-1):
+                       #if len(s)>0:
+                               if (programSQLError==True):
+                                       logging.error("speichereSQL-Exception "+str(sys.exc_info())+" "+str(sql)+" "+str(tupel))
+                               else:
+                                       logging.error("speichereSQL-Exception in Logging!!!! :"+str(sys.exc_info())+" "+str(sql)+" "+str(tupel))
+                       return False
+
+       def commitSQL(self):
+               self.conn.commit()
+               
+               
+       def ladeSQL(self,sql,tupel=None):
+               #print sql,tupel
+               try:
+                       if (tupel==None):
+                               self.cur.execute(sql)
+                       else:
+                               self.cur.execute(sql,tupel)
+                       return self.cur.fetchall()
+               except:
+                       logging.error("ladeSQL-Exception "+str(sys.exc_info())+" "+str(sql)+" "+str(tupel))
+                       return ()
+               
+       def ladeHistory(self,sql_condition,param_condition):
+               sql="SELECT * FROM logtable WHERE sql LIKE '%"+str(sql_condition)+"%' AND param LIKE '%"+str(param_condition)+"%'"
+               rows=self.ladeSQL(sql)
+               #print rows 
+               i=0
+               erg=[]
+               while i<len(rows):
+                       datum=time.strftime("%d.%m.%y %H:%M:%S", (time.localtime(rows[i][1])))
+                       erg.append([rows[i][1],datum,rows[i][2],rows[i][3],rows[i][3].split(" <<Tren-ner>> ")])
+                                       #pcdatum #datum #sql # Param_org #param 
+                       
+                       i+=1
+                       
+               return erg
+               
+       def delHistory(self,sql_condition,param_condition,exceptTheLastXSeconds=0):
+               pcdatum=int(time.time())-exceptTheLastXSeconds
+               sql="DELETE FROM logtable WHERE sql LIKE '%"+str(sql_condition)+"%' AND param LIKE '%"+str(param_condition)+"%' AND pcdatum<?"
+               self.speichereSQL(sql,(pcdatum,))
+               
+       def delHistoryWithRowID(self,rowid,sql_condition=" ",exceptTheLastXSeconds=0):
+               pcdatum=int(time.time())-exceptTheLastXSeconds
+               sql="DELETE FROM logtable WHERE rowid=? AND pcdatum<? AND sql LIKE '%"+str(sql_condition)+"%'"
+               self.speichereSQL(sql,(rowid,pcdatum,))
+               
+       def openDB(self):
+               try:
+                       self.cur.close()
+               except:
+                       pass
+               try:
+                       self.conn.close()
+               except:
+                       pass
+               
+               db=self.ladeDirekt("datenbank")
+               if db=="": 
+                       home_dir = os.path.expanduser('~')
+                       db=os.path.join(home_dir, "multilist.s3db") 
+                       
+               
+               datum=time.strftime("%Y-%m-%d--", (time.localtime(time.time())))+str(int(time.time()))+"--"
+               if (os.path.exists(db))and(os.path.exists(os.path.dirname(db)+os.sep+"backup/")):
+                       try:
+                               shutil.copyfile(db,str(os.path.dirname(db))+os.sep+"backup"+os.sep+datum+os.path.basename(db))
+                               #logging.debug(str(os.path.dirname(db))+os.sep+"backup"+os.sep+datum+os.path.basename(db))
+                       except:
+                               logging.info("Achtung Backup-Datei NICHT (!!!) angelegt!")
+                               #print db,str(os.path.dirname(db))+os.sep+"backup"+os.sep+datum+os.path.basename(db)
+               
+               self.conn = sqlite3.connect(db)         
+               self.cur = self.conn.cursor()
+               try:
+                       sql="CREATE TABLE logtable (id INTEGER PRIMARY KEY AUTOINCREMENT, pcdatum INTEGER ,sql TEXT, param TEXT, host TEXT, rowid TEXT)"
+                       self.cur.execute(sql)
+                       self.conn.commit()
+               except:
+                       pass
+               
+               #Add rowid line (not in old versions included)
+               try:
+                       sql="ALTER TABLE logtable ADD rowid TEXT"
+                       self.cur.execute(sql)
+                       self.conn.commit()
+               except:
+                       pass
+               
+               
+       def __init__(self):
+               home_dir = os.path.expanduser('~')
+               filename=os.path.join(home_dir, ".multilist.dat") 
+               self.d = shelve.open(filename)
+               self.openDB()
+
+       
+
+               
+               
+       def close(self):
+               try:
+                       self.d.close()
+               except:
+                       pass
+               try:
+                       self.cur.close()
+               except:
+                       pass
+               try:
+                       self.conn.close()
+               except:
+                       pass
+               logging.info("Alle Daten gespeichert")
+               
+       def __del__(self):
+               self.close()
\ No newline at end of file
diff --git a/src/multilistclasses/libsqldialog.py b/src/multilistclasses/libsqldialog.py
new file mode 100755 (executable)
index 0000000..e8bfa04
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import gobject
+import time
+import string
+import gtk
+import sys
+import logging
+
+import libspeichern 
+class sqlDialog(gtk.Dialog):
+       
+       def exportSQL(self,filename):
+               f = open(filename, 'w')
+               msgstring=""
+               sql="SELECT pcdatum,sql,param FROM logtable WHERE pcdatum>? ORDER BY pcdatum DESC"
+               rows=self.db.ladeSQL(sql,(time.time()-2*24*3600,))
+               for row in rows:
+                       pcdatum,sql,param = row
+                       datum=str(time.strftime("%d.%m.%y %H:%M:%S ", (time.localtime(pcdatum))))
+                       f.write( datum +"\t" + sql + "\t\t" + param+ "\n")
+                       
+                       
+               f.close()
+               
+       
+       def __init__(self,db):
+               self.db=db
+               
+               logging.info("sqldialog, init")
+               
+               gtk.Dialog.__init__(self,"SQL History (der letzten 2 Tage (max. 50)):",None,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
+               
+               
+               self.add_button("Export", 444)
+               self.set_position(gtk.WIN_POS_CENTER)
+               
+               
+               self.liststore = gtk.ListStore(str, str, str)
+
+               # create the TreeView using liststore
+               self.treeview = gtk.TreeView(self.liststore)
+               
+               # create a CellRenderers to render the data
+               self.cell1 = gtk.CellRendererText()
+               self.cell2 = gtk.CellRendererText()
+               self.cell3 = gtk.CellRendererText()
+               #self.cell1.set_property('markup', 1)
+               
+               # create the TreeViewColumns to display the data
+               self.tvcolumn1 = gtk.TreeViewColumn('Datum')
+               self.tvcolumn2 = gtk.TreeViewColumn('SQL')
+               self.tvcolumn3 = gtk.TreeViewColumn('Parameter')
+               
+               # add columns to treeview
+               self.treeview.append_column(self.tvcolumn1)
+               self.treeview.append_column(self.tvcolumn2)
+               self.treeview.append_column(self.tvcolumn3)
+               
+               
+               self.tvcolumn1.pack_start(self.cell1, True)
+               self.tvcolumn2.pack_start(self.cell2, True)
+               self.tvcolumn3.pack_start(self.cell3, True)
+               
+               self.tvcolumn1.set_attributes(self.cell1, text=0) #Spalten setzten hier!!!!
+               self.tvcolumn2.set_attributes(self.cell2, text=1)
+               self.tvcolumn3.set_attributes(self.cell3, text=2)
+
+               # make treeview searchable
+               #self.treeview.set_search_column(0)
+               #self.tvcolumn.set_sort_column_id(0)
+               
+               # Allow NOT drag and drop reordering of rows
+               self.treeview.set_reorderable(False)
+               
+               scrolled_window = gtk.ScrolledWindow()
+               scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
+               scrolled_window.add(self.treeview)
+               #self.pack_start(scrolled_window, expand=True, fill=True, padding=0)
+               
+               
+               self.vbox.pack_start(scrolled_window, True, True, 0)
+               
+               self.vbox.show_all()
+               
+               msgstring=""
+               sql="SELECT pcdatum,sql,param FROM logtable WHERE pcdatum>? ORDER BY pcdatum DESC"
+               rows=db.ladeSQL(sql,(time.time()-3*24*3600,))
+               i=0
+               for row in rows:
+                       pcdatum,sql,param = row
+                       datum=str(time.strftime("%d.%m.%y %H:%M:%S ", (time.localtime(pcdatum))))
+                       if len(param)>100:
+                               param=param[:20]+" (Parameter gekürzt) "+param[20:]
+                       self.liststore.append([datum, sql,param])
+                       i+=1
+                       if (i>50):
+                               break
+                       
+               self.set_size_request(500,400)
+               
+               
+               
diff --git a/src/multilistclasses/libsync.py b/src/multilistclasses/libsync.py
new file mode 100755 (executable)
index 0000000..53ea775
--- /dev/null
@@ -0,0 +1,331 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import gobject
+import time
+import string
+from SimpleXMLRPCServer import SimpleXMLRPCServer 
+import random
+import socket 
+socket.setdefaulttimeout(60) # Timeout auf 60 sec. setzen 
+import xmlrpclib 
+import select
+#import fcntl
+import struct
+import gtk
+import uuid
+import sys
+import logging
+
+import libspeichern 
+class Sync(gtk.VBox): 
+       
+       __gsignals__ = {
+               'syncFinished' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_STRING,)),
+               'syncBeforeStart' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_STRING,)),
+       }
+       
+       def getUeberblickBox(self):
+               frame=gtk.Frame("Abfrage")
+               return frame
+                       
+       def handleRPC(self):
+               try:
+                       if (self.rpcserver==None): return False
+               except:
+                       return False
+                       
+               while (len(self.poll.poll(0))>0):
+                       self.rpcserver.handle_request()
+               return True
+
+       def get_ip_address(self,ifname):
+               return socket.gethostbyname(socket.gethostname())
+               #try:
+               #       s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+               #       ip=socket.inet_ntoa(fcntl.ioctl(s.fileno(),0x8915,struct.pack('256s', ifname[:15]))[20:24])
+               #       s.close()
+               #except:
+               #       ip=socket.gethostbyname(socket.gethostname())
+               #       s.close()
+               
+               #return ip FixME
+               
+       def getLastSyncDate(self,sync_uuid):
+               sql="SELECT syncpartner,pcdatum FROM sync WHERE uuid=?"
+               rows=self.db.ladeSQL(sql,(sync_uuid,))
+               if (rows!=None)and(len(rows)==1): 
+                       syncpartner,pcdatum = rows[0]
+               else:
+                       pcdatum=-1
+               logging.info("LastSyncDatum: "+str(pcdatum)+" Jetzt "+str(int(time.time())))
+               return pcdatum
+               
+       
+       def writeSQLTupel(self,newSQLs):
+               if (newSQLs==None):
+                        return
+               pausenzaehler=0
+               for newSQL in newSQLs:
+                       #print ""
+                       #print "SQL1: ",newSQL[1]
+                       #print "SQL2: ",newSQL[2]
+                       #print "SQL3: ",newSQL[3]
+                       #print "Param:",string.split(newSQL[3]," <<Tren-ner>> ")
+                       #print ""
+                       if (newSQL[3]!=""):
+                               param=string.split(newSQL[3]," <<Tren-ner>> ")
+                       else:
+                               param=None
+               
+                       if (len(newSQL)>2):
+                               commitSQL=True
+                               
+                               if (newSQL[5]!=None)and(len(newSQL[5])>0):
+                                       sql="SELECT * FROM logtable WHERE rowid=? ORDER BY pcdatum DESC"
+                                       rows=self.db.ladeSQL(sql,(newSQL[5],))
+                                       if (rows!=None)and(len(rows)>0):
+                                               if (rows[0][1]>newSQL[1])and(len(rows[0][5])>0):
+                                                       logging.info("newer sync entry, ignoring old one")
+                                                       print "newer sync entry, ignoring old one"
+                                                       commitSQL=False
+                                       
+                               if (commitSQL==True):
+                                       self.db.speichereSQL(newSQL[2],param,commit=False,pcdatum=newSQL[1],rowid=newSQL[5])
+                       else: 
+                               logging.error("writeSQLTupel: Error")
+                               
+                       pausenzaehler+=1
+                       if (pausenzaehler % 10)==0:
+                               pass
+                               while (gtk.events_pending()):
+                                       gtk.main_iteration();
+                               
+               logging.info("Alle SQLs an sqlite geschickt, commiting now")
+               self.db.commitSQL()
+               logging.info("Alle SQLs commited")
+               
+       
+       def doSync(self,sync_uuid,pcdatum,newSQLs,pcdatumjetzt):
+               #print uuid,pcdatum,newSQLs
+               self.syncStatusLabel.set_text("sync process running")
+               while (gtk.events_pending()):
+                       gtk.main_iteration();
+               diff=time.time()-pcdatumjetzt
+               if diff<0:
+                       diff=diff*(-1)
+               if diff>30:
+                       return -1
+               
+               sql="SELECT * FROM logtable WHERE pcdatum>?"
+               rows=self.db.ladeSQL(sql,(pcdatum,))
+               logging.info("doSync read sqls")
+               self.writeSQLTupel(newSQLs)
+               logging.info("doSync wrote sqls")
+               i=0
+               return rows
+               
+       def getRemoteSyncUUID(self):
+               return self.sync_uuid
+       
+       
+       def startServer(self, widget, data=None):
+               #Starte RPCServer
+               self.db.speichereDirekt("syncServerIP",self.comboIP.get_child().get_text())
+               
+               if (widget.get_active()==True):
+                       logging.info("Starting Server")
+                       
+                       try:
+                               ip=self.comboIP.get_child().get_text()
+                               self.rpcserver = SimpleXMLRPCServer((ip, 50503),allow_none=True) 
+                               self.rpcserver.register_function(pow)
+                               self.rpcserver.register_function(self.getLastSyncDate)
+                               self.rpcserver.register_function(self.doSync)
+                               self.rpcserver.register_function(self.getRemoteSyncUUID)
+                               self.rpcserver.register_function(self.doSaveFinalTime)
+                               self.poll=select.poll()
+                               self.poll.register(self.rpcserver.fileno())
+                               gobject.timeout_add(1000, self.handleRPC)
+                               self.syncServerStatusLabel.set_text("Syncserver running...")
+                       
+                               #save
+                               self.db.speichereDirekt("startSyncServer",True)
+                       except:
+                               s=str(sys.exc_info())
+                               logging.error("libsync: could not start server. Error: "+s)
+                               mbox=gtk.MessageDialog(None,gtk.DIALOG_MODAL,gtk.MESSAGE_ERROR,gtk.BUTTONS_OK,"Konnte Sync-Server nicht starten. Bitte IP und Port überprüfen.") #gtk.DIALOG_MODAL
+                               mbox.set_modal(False)
+                               response=mbox.run() 
+                               mbox.hide() 
+                               mbox.destroy() 
+                               widget.set_active(False)
+                               
+               else:
+                       logging.info("Stopping Server")
+                       try:
+                               del self.rpcserver      
+                       except:
+                               pass
+                       self.syncServerStatusLabel.set_text("Syncserver not running...")
+                       #save
+                       self.db.speichereDirekt("startSyncServer",False)
+               
+       def doSaveFinalTime(self,sync_uuid,pcdatum=None):
+               if (pcdatum==None): pcdatum=int(time.time())
+               if (time.time()>pcdatum):
+                       pcdatum=int(time.time()) #größere Zeit nehmen
+                       
+               #fime save time+uuid
+               sql="DELETE FROM sync WHERE uuid=?"
+               self.db.speichereSQL(sql,(sync_uuid,),log=False)
+               sql="INSERT INTO sync (syncpartner,uuid,pcdatum) VALUES (?,?,?)"
+               self.db.speichereSQL(sql,("x",str(sync_uuid),pcdatum),log=False)
+               self.emit("syncFinished","syncFinished")
+               self.syncStatusLabel.set_text("no sync process (at the moment)")
+               return (self.sync_uuid,pcdatum)
+               
+       
+       def syncButton(self, widget, data=None):
+               logging.info("Syncing")
+               #sql="DELETE FROM logtable WHERE sql LIKE externeStundenplanung"
+               #self.db.speichereSQL(sql)
+               
+               self.syncStatusLabel.set_text("sync process running")
+               while (gtk.events_pending()):
+                       gtk.main_iteration();
+               self.emit("syncBeforeStart","syncBeforeStart")
+
+               self.db.speichereDirekt("syncRemoteIP",self.comboRemoteIP.get_child().get_text())
+               try:
+                       server = xmlrpclib.ServerProxy("http://"+self.comboRemoteIP.get_child().get_text()+":50503",allow_none=True) 
+                       #lastDate=server.getLastSyncDate(str(self.sync_uuid))
+                       server_sync_uuid=server.getRemoteSyncUUID()
+                       lastDate=self.getLastSyncDate(str(server_sync_uuid))
+                       
+                       print ("LastSyncDate: "+str(lastDate)+" Now: "+str(int(time.time())))
+               
+                       sql="SELECT * FROM logtable WHERE pcdatum>?"
+                       rows=self.db.ladeSQL(sql,(lastDate,))
+               
+                       newSQLs=server.doSync(self.sync_uuid,lastDate,rows,time.time())
+               
+                       logging.info("did do sync, processing sqls now")
+                       if newSQLs!=-1:
+                               self.writeSQLTupel(newSQLs)
+       
+                               sync_uuid, finalpcdatum=server.doSaveFinalTime(self.sync_uuid)
+                               self.doSaveFinalTime(sync_uuid, finalpcdatum)
+                       
+                               mbox =  gtk.MessageDialog(None,gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_OK,"Synchronisation erfolgreich beendet") 
+                               response = mbox.run() 
+                               mbox.hide() 
+                               mbox.destroy() 
+                               self.syncStatusLabel.set_text("no sync process (at the moment)")
+                       else:
+                               logging.warning("Zeitdiff zu groß/oder anderer db-Fehler")
+                               mbox =  gtk.MessageDialog(None,gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_OK,"Zeit differiert zu viel zwischen den Systemen") 
+                               response = mbox.run() 
+                               mbox.hide() 
+                               mbox.destroy() 
+                               self.syncStatusLabel.set_text("no sync process (at the moment)")
+                       
+               except:
+                               logging.warning("Sync connect failed")
+                               mbox =  gtk.MessageDialog(None,gtk.DIALOG_MODAL,gtk.MESSAGE_INFO,gtk.BUTTONS_OK,"Sync gescheitert. Fehler:"+str(sys.exc_info()))
+                               response = mbox.run() 
+                               mbox.hide() 
+                               mbox.destroy() 
+                               self.syncStatusLabel.set_text("no sync process (at the moment)")
+                               
+       
+       def __init__(self,db):
+               gtk.VBox.__init__(self,homogeneous=False, spacing=0)
+               
+               logging.info("Sync, init")
+               self.db=db
+               
+               #print "Sync, 2"
+               #sql = "DROP TABLE sync"
+               #self.db.speichereSQL(sql,log=False)
+               
+               sql = "CREATE TABLE sync (id INTEGER PRIMARY KEY, syncpartner TEXT, uuid TEXT, pcdatum INTEGER)"
+               self.db.speichereSQL(sql,log=False)
+               
+               #print "Sync, 3"
+               
+               sql="SELECT uuid,pcdatum FROM sync WHERE syncpartner=?"
+               rows=self.db.ladeSQL(sql,("self",)) #Eigene Id feststellen
+               
+               #print "Sync, 3a"
+               if (rows==None)or(len(rows)!=1):
+                       sql="DELETE FROM sync WHERE syncpartner=?"
+                       self.db.speichereSQL(sql,("self",),log=False)
+                       #uuid1=uuid()
+                       #print "Sync, 3b"
+                       
+                       #print "Sync, 3bb"
+                       self.sync_uuid=str(uuid.uuid4())
+                       sql="INSERT INTO sync (syncpartner,uuid,pcdatum) VALUES (?,?,?)"
+                       self.db.speichereSQL(sql,("self",str(self.sync_uuid),int(time.time())),log=False)
+                       #print "Sync, 3c"
+               else:
+                       sync_uuid,pcdatum = rows[0]
+                       self.sync_uuid=sync_uuid
+               #print "x1"
+               
+               
+               
+               #print "Sync, 4"
+
+               
+               frame=gtk.Frame("LokalerSync-Server (Port 50503)")
+               
+               
+               
+               self.comboIP=gtk.combo_box_entry_new_text()
+               
+               
+               self.comboIP.append_text("") #self.get_ip_address("eth0"))
+               #self.comboIP.append_text(self.get_ip_address("eth1")) #fixme
+               #self.comboIP.append_text(self.get_ip_address("eth2"))
+               #self.comboIP.append_text(self.get_ip_address("eth3"))
+               #print "Sync, 4d"
+               #self.comboIP.append_text(self.get_ip_address("wlan0"))
+               #self.comboIP.append_text(self.get_ip_address("wlan1"))
+               
+               #print "Sync, 4e"
+               
+               frame.add(self.comboIP)
+               serverbutton=gtk.ToggleButton("SyncServer starten")
+               serverbutton.connect("clicked",self.startServer,(None,))
+               self.pack_start(frame, expand=False, fill=True, padding=1)
+               self.pack_start(serverbutton, expand=False, fill=True, padding=1)
+               self.syncServerStatusLabel=gtk.Label("Syncserver not running")
+               self.pack_start(self.syncServerStatusLabel, expand=False, fill=True, padding=1)         
+                               
+               frame=gtk.Frame("RemoteSync-Server (Port 50503)")
+               self.comboRemoteIP=gtk.combo_box_entry_new_text()
+               self.comboRemoteIP.append_text("192.168.0.?")
+               self.comboRemoteIP.append_text("192.168.1.?")
+               self.comboRemoteIP.append_text("192.168.176.?")
+               frame.add(self.comboRemoteIP)
+               syncbutton=gtk.Button("Verbinde zu Remote-SyncServer")
+               syncbutton.connect("clicked",self.syncButton,(None,))
+               self.pack_start(frame, expand=False, fill=True, padding=1)
+               self.pack_start(syncbutton, expand=False, fill=True, padding=1)
+               self.syncStatusLabel=gtk.Label("no sync process (at the moment)")
+               self.pack_start(self.syncStatusLabel, expand=False, fill=True, padding=1)
+
+
+               #self.comboRemoteIP.set_text_column("Test")
+               self.comboRemoteIP.get_child().set_text(self.db.ladeDirekt("syncRemoteIP"))
+               self.comboIP.get_child().set_text(self.db.ladeDirekt("syncServerIP"))
+               
+               #load
+               if (self.db.ladeDirekt("startSyncServer",False)==True):
+                       serverbutton.set_active(True)
+                       
+               #print "Sync, 9"
\ No newline at end of file
diff --git a/src/multilistclasses/libview.py b/src/multilistclasses/libview.py
new file mode 100644 (file)
index 0000000..223452e
--- /dev/null
@@ -0,0 +1,544 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+  
+import gtk
+import gobject
+import logging
+import pango
+import libliststorehandler
+  
+
+class Columns_dialog(gtk.VBox):
+       
+       def is_col_selected(self, icol):
+               children=self.framebox.get_children()
+               if icol<len(children):
+                       return children[icol].get_active()
+               else:
+                       return None
+       
+       def save_column_setting(self):
+               i=1 #uid can not be shown
+               while self.liststorehandler.get_colname(i)!=None:
+                       name=str(self.liststorehandler.get_colname(i))
+                       if self.is_col_selected(i-1)==True:
+                               self.db.speichereDirekt("showcol_"+name,"1")
+                       else:
+                               self.db.speichereDirekt("showcol_"+name,"0")
+                       i=i+1
+               
+       
+
+       
+       def __init__(self,db,liststorehandler):
+               gtk.VBox.__init__(self,homogeneous=False, spacing=0)
+               
+               self.db=db
+               self.liststorehandler=liststorehandler
+               
+               #serverbutton=gtk.ToggleButton("SyncServer starten")
+               #serverbutton.connect("clicked",self.startServer,(None,))
+               #self.pack_start(serverbutton, expand=False, fill=True, padding=1)
+               #print "x1"
+               
+               frame=gtk.Frame("Columns")
+               self.framebox=gtk.VBox(homogeneous=False, spacing=0)
+               
+               self.scrolled_window = gtk.ScrolledWindow()
+               self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
+
+               self.scrolled_window.add_with_viewport(self.framebox)
+               
+               
+               i=1 #uid can not be shown
+               while self.liststorehandler.get_colname(i)!=None:
+                       name=str(self.liststorehandler.get_colname(i))
+                       checkbutton=gtk.CheckButton(name)
+                       if self.db.ladeDirekt("showcol_"+name)=="1":
+                               checkbutton.set_active(True)
+                               
+                       self.framebox.pack_start(checkbutton)
+                       i=i+1
+               
+               frame.add(self.scrolled_window)
+               self.pack_start(frame, expand=True, fill=True, padding=1)
+               
+               
+               
+       
+
+
+class CellRendererTriple(gtk.GenericCellRenderer):
+       __gproperties__ = {
+                "status": (gobject.TYPE_STRING, "Status",
+                "Status", "", gobject.PARAM_READWRITE),
+        }
+       
+       __gsignals__ = {
+               'status_changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_INT,gobject.TYPE_STRING)),
+       }
+
+
+       def __init__(self):
+               #self.__gobject_init__()
+               #gtk.GenericCellRenderer.__init__(self,*args,**kwargs)
+               gtk.GenericCellRenderer.__init__(self)
+               #self.__gobject_init__()
+               self.status=-1
+               self.xpad = 2
+               self.ypad = 2
+               self.mode = gtk.CELL_RENDERER_MODE_ACTIVATABLE
+               self.xpad = -2; self.ypad = -2
+               self.xalign = 0.5; self.yalign = 0.5
+               self.active = 0
+               self.widget=None
+               self.last_cell=None
+               self.connect('editing-started', self.on_clicked)
+
+       def do_set_property(self,property,value):
+               setattr(self, property.name, value)
+
+       def do_get_property(self, property):
+               return getattr(self, property.name)
+
+       def get_layout(self, widget):
+               '''Gets the Pango layout used in the cell in a TreeView widget.'''
+
+               layout = pango.Layout(widget.get_pango_context())
+               layout.set_width(-1)    # Do not wrap text.
+
+               layout.set_text('  ')
+
+               return layout
+
+       def on_get_size(self, widget, cell_area=None):
+               xpad = 2
+               ypad = 2
+
+               xalign = 0
+               yalign = 0.5
+
+               layout = self.get_layout(widget)
+               width, height = layout.get_pixel_size()
+
+               x_offset = xpad
+               y_offset = ypad
+
+               if cell_area:
+
+                       x_offset = xalign * (cell_area.width - width)
+                       x_offset = max(x_offset, xpad)
+                       x_offset = int(round(x_offset, 0))
+
+                       y_offset = yalign * (cell_area.height - height)
+                       y_offset = max(y_offset, ypad)
+                       y_offset = int(round(y_offset, 0))
+
+               width  = width  + (xpad * 2)
+               height = height + (ypad * 2)
+
+               
+               return x_offset, y_offset, width, height
+               
+       def on_clicked(self,  widget, data):
+               print widget,data
+
+       def clicked(self, widget, data1=None):
+               x,y=widget.get_pointer()
+               widget.realize()
+               
+               path=widget.get_path_at_pos(x,y)
+               
+               #print "a",widget.get_cursor()
+               #print path
+               
+       
+               
+               path=widget.get_cursor()[0]
+               
+               if path!=None:
+                       irow=path[0]    #path[0][0]-1
+                       rect=widget.get_cell_area(irow, widget.get_column(0)) #FixME 0 is hardcoded
+                       if x<rect.x+rect.width:
+                               self.emit("status_changed",irow,self.status)
+               else:
+                       return
+               
+               
+                       #workarround -1 means last item, because bug in treeview?!
+                       #print "not in list"
+                       rect=widget.get_visible_rect() #widget.get_cell_area(-1, widget.get_column(0))
+                       #print rect.x,rect.y,rect.width,rect.height,x,y
+                       irow=-1
+                       rect=widget.get_cell_area(0, widget.get_column(0)) #FixME 0 is hardcoded
+                       if x<rect.x+rect.width:
+                               self.emit("status_changed",irow,"-1")
+               
+
+       def on_render(self, window, widget, background_area, cell_area, expose_area, flags ):
+               if (self.widget==None):
+                       #print widget
+                       self.widget=widget
+                       self.widget.connect("cursor-changed",self.clicked) #button-press-event
+               
+               self.last_cell=cell_area
+               
+               x=int(cell_area.x+(cell_area.width-2)/2-(cell_area.height-2)/2)
+               y=int(cell_area.y+1)
+               height=int(cell_area.height-2)
+               width=int(height)
+
+               if (self.status=="1"):
+                       widget.style.paint_check(window,gtk.STATE_NORMAL, gtk.SHADOW_IN,cell_area, widget, "cellradio",x,y,width,height)
+               elif (self.status=="0"):
+                       #width=height
+                       height=height-3
+                       width=height
+                       
+                       widget.style.paint_flat_box(window, gtk.STATE_NORMAL, gtk.SHADOW_NONE, cell_area, widget, "cellunselected",x,y,width,height)
+                       
+                       widget.style.paint_hline(window, gtk.STATE_NORMAL,cell_area, widget, "cellunselected",x,x+width,y)
+                       widget.style.paint_hline(window, gtk.STATE_NORMAL,cell_area, widget, "cellunselected",x,x+width,y+height)
+                       widget.style.paint_vline(window, gtk.STATE_NORMAL,cell_area, widget, "cellunselected",y,y+height,x)
+                       widget.style.paint_vline(window, gtk.STATE_NORMAL,cell_area, widget, "cellunselected",y,y+height,x+width)
+                       
+               else:
+                       widget.style.paint_diamond(window, gtk.STATE_NORMAL, gtk.SHADOW_IN, cell_area, widget, "cellunselected",x,y,width,height)
+                       
+               #widget.show_all()
+               #print "render"
+               pass
+    
+       def on_start_editing(self, event, widget, path, background_area, cell_area, flags):
+               print "on_start_editing",path
+               return None
+       
+       
+       def on_activate(self, event, widget, path, background_area, cell_area, flags):
+               print "activate",path
+               return False
+
+               
+               
+class CellRendererCombo2(gtk.GenericCellRenderer):
+       __gproperties__ = {
+                "text": (gobject.TYPE_STRING, "text",
+                "Text", "", gobject.PARAM_READWRITE),
+        }
+       
+       __gsignals__ = {
+               'status_changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,(gobject.TYPE_INT,gobject.TYPE_STRING)),
+       }
+
+
+       def __init__(self):
+               #self.__gobject_init__()
+               #gtk.GenericCellRenderer.__init__(self,*args,**kwargs)
+               gtk.GenericCellRenderer.__init__(self)
+               #self.__gobject_init__()
+               self.status=-1
+               self.xpad = 2
+               self.ypad = 2
+               self.mode = gtk.CELL_RENDERER_MODE_ACTIVATABLE
+               self.xpad = -2; self.ypad = -2
+               self.xalign = 0.5; self.yalign = 0.5
+               self.active = 0
+               self.widget=None
+               self.last_cell=None
+               self.text="(none)"
+               self.connect('editing-started', self.on_clicked)
+
+       def do_set_property(self,property,value):
+               #print property,value
+               setattr(self, property.name, value)
+
+       def do_get_property(self, property):
+               return getattr(self, property.name)
+
+       def get_layout(self, widget):
+               '''Gets the Pango layout used in the cell in a TreeView widget.'''
+
+               layout = pango.Layout(widget.get_pango_context())
+               layout.set_width(-1)    # Do not wrap text.
+
+               layout.set_text(self.text)
+
+               return layout
+
+       def on_get_size(self, widget, cell_area=None):
+               xpad = 2
+               ypad = 2
+
+               xalign = 0
+               yalign = 0.5
+
+               layout = self.get_layout(widget)
+               width, height = layout.get_pixel_size()
+
+               x_offset = xpad
+               y_offset = ypad
+
+               if cell_area:
+
+                       x_offset = xalign * (cell_area.width - width)
+                       x_offset = max(x_offset, xpad)
+                       x_offset = int(round(x_offset, 0))
+
+                       y_offset = yalign * (cell_area.height - height)
+                       y_offset = max(y_offset, ypad)
+                       y_offset = int(round(y_offset, 0))
+
+               width  = width  + (xpad * 2)
+               height = height + (ypad * 2)
+
+               
+               return x_offset, y_offset, width, height
+               
+       def on_clicked(self,  widget, data):
+               print widget,data
+
+       def clicked(self, widget, data1=None):
+               return
+               x,y=widget.get_pointer()
+               widget.realize()
+               
+               #path=widget.get_path_at_pos(x,y)
+               
+               path=widget.get_cursor()[0]
+               
+               if path!=None:
+                       irow=path[0]    #path[0][0]-1
+                       rect=widget.get_cell_area(irow, widget.get_column(0)) #FixME 0 is hardcoded
+                       if x<rect.x+rect.width:
+                               self.emit("status_changed",irow,self.status)
+               else:
+                       return
+               
+               
+                       #workarround -1 means last item, because bug in treeview?!
+                       #print "not in list"
+                       rect=widget.get_visible_rect() #widget.get_cell_area(-1, widget.get_column(0))
+                       #print rect.x,rect.y,rect.width,rect.height,x,y
+                       irow=-1
+                       rect=widget.get_cell_area(0, widget.get_column(0)) #FixME 0 is hardcoded
+                       if x<rect.x+rect.width:
+                               self.emit("status_changed",irow,"-1")
+               
+
+       def on_render(self, window, widget, background_area, cell_area, expose_area, flags ):
+               if (self.widget==None):
+                       self.widget=widget
+                       self.widget.connect("cursor-changed",self.clicked) #button-press-event
+               
+               self.last_cell=cell_area
+               
+               x=int(cell_area.x+(cell_area.width-2)/2-(cell_area.height-2)/2)
+               y=int(cell_area.y+1)
+               height=int(cell_area.height-2)
+               width=int(height)
+               
+               widget.style.paint_layout(window,gtk.STATE_NORMAL, True, cell_area, widget, "cellradio",x,y,self.get_layout(widget))
+                       
+               #widget.show_all()
+    
+       def on_start_editing(self, event, widget, path, background_area, cell_area, flags):
+               print "on_start_editing",path
+               return None
+       
+       
+       def on_activate(self, event, widget, path, background_area, cell_area, flags):
+               print "activate",path
+               return False
+
+
+gobject.type_register(CellRendererCombo2)
+gobject.type_register(CellRendererTriple)
+
+       
+  
+class View(gtk.VBox):
+       
+       def loadList(self):
+               ls=self.liststorehandler.get_liststore()
+               self.treeview.set_model(ls)
+               #self.tvcolumn[i].add_attribute( self.cell[i], "active", 1)
+               #print "setup",ls
+               
+               
+       
+       
+       def col_edited(self,cell, irow, new_text,icol=None):
+               if (irow!=4):
+                       self.liststorehandler.update_row(irow,icol,new_text)
+               else:
+                       print cell, irow, new_text,icol
+               
+       def col_toggled(self,widget,irow, status ):
+               #print irow,ls[irow][1],status
+               ls=self.treeview.get_model()
+               
+               if self.liststorehandler.selection.get_status()=="0":
+                       if ls[irow][1]=="0":
+                               self.liststorehandler.update_row(irow,1,"1")
+                       else:
+                               self.liststorehandler.update_row(irow,1,"0")
+               else:
+                       if ls[irow][1]=="1":
+                               self.liststorehandler.update_row(irow,1,"-1")
+                       elif ls[irow][1]=="0":
+                               self.liststorehandler.update_row(irow,1,"1")
+                       else:
+                               self.liststorehandler.update_row(irow,1,"0")
+                       
+               #self.tvcolumn[i].set_attributes( self.cell[i], active=i)
+               
+               
+       
+       def convert(self,s):
+               #print s
+               if (s=="1"):
+                       return 1
+               else:
+                       return 0
+               
+               
+       def del_active_row(self):
+               path, col = self.treeview.get_cursor()
+               #print path, col
+               if path!=None:
+                       irow=path[0]
+                       row_iter=self.treeview.get_model().get_iter(path)
+                       self.liststorehandler.del_row(irow,row_iter)
+
+                       
+               #treemodel.get_iter()
+               
+               
+               
+       def sort_func_function(self,model, iter1, iter2, data=None):
+               print "sorting"
+               
+               
+       def reload_view(self):
+               # create the TreeView using liststore
+               self.modelsort = gtk.TreeModelSort(self.liststorehandler.get_liststore())
+               self.modelsort.set_sort_column_id(2, gtk.SORT_ASCENDING)
+               
+               self.treeview = gtk.TreeView(self.modelsort)
+               self.treeview.set_headers_visible(True)
+               
+               
+               self.cell=range(self.liststorehandler.get_colcount())
+               self.tvcolumn=range(self.liststorehandler.get_colcount())
+
+               
+               m = self.liststorehandler.get_unitsstore()
+               
+               for i in range(self.liststorehandler.get_colcount()):
+                       
+                       if i>5:
+                               default="0"
+                       else:
+                               default="1"
+                       if self.db.ladeDirekt("showcol_"+str(self.liststorehandler.get_colname(i)),default)=="1":
+
+                               if (i==1):
+                                       self.cell[i] = CellRendererTriple()
+                                       self.tvcolumn[i] =      gtk.TreeViewColumn(self.liststorehandler.get_colname(i),self.cell[i])
+                                       self.cell[i].connect( 'status_changed', self.col_toggled)
+                                       self.tvcolumn[i].set_attributes( self.cell[i], status=i)
+                               
+                               elif (i==3)or(i==4)or(i==6):
+                                       self.cell[i] = gtk.CellRendererCombo()
+                                       self.tvcolumn[i] =      gtk.TreeViewColumn(self.liststorehandler.get_colname(i),self.cell[i])
+                                       self.cell[i].set_property("model",m)
+                                       self.cell[i].set_property('text-column', i)
+                                       self.cell[i].set_property('editable',True)
+                                       self.cell[i].connect("edited", self.col_edited,i) 
+                                       self.tvcolumn[i].set_attributes( self.cell[i], text=i)
+                               else:
+                                       self.cell[i] = gtk.CellRendererText()
+                                       self.tvcolumn[i] = gtk.TreeViewColumn(self.liststorehandler.get_colname(i),self.cell[i])
+                                       self.cell[i].set_property('editable',True)
+                                       self.cell[i].set_property('editable-set',True)
+                                       self.cell[i].connect("edited", self.col_edited,i) 
+                                       #self.cell[i].connect("editing-canceled", self.col_edited2,i) 
+                                       self.tvcolumn[i].set_attributes(self.cell[i], text=i)
+
+                               self.cell[i].set_property('cell-background', 'lightgray')
+                               self.tvcolumn[i].set_sort_column_id(i)
+                               self.tvcolumn[i].set_resizable(True)
+                               
+                               
+                               if (i>0):
+                                       self.treeview.append_column(self.tvcolumn[i])
+                               
+               
+               # Allow NOT drag and drop reordering of rows
+               self.treeview.set_reorderable(False)
+               
+               
+               if self.scrolled_window != None:
+                       self.scrolled_window.destroy()
+               
+               self.scrolled_window = gtk.ScrolledWindow()
+               self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
+
+               self.scrolled_window.add(self.treeview)
+               self.pack_start(self.scrolled_window, expand=True, fill=True, padding=0)
+               self.loadList()
+               
+               self.show_all()
+       
+       def __init__(self,db,liststorehandler,parent_window):
+               
+               self.db=db
+               self.parent_window=parent_window
+               self.liststorehandler = liststorehandler
+               
+               
+               gtk.VBox.__init__(self,homogeneous=False, spacing=0)
+               
+               logging.info("libview, init")
+
+               self.scrolled_window = None
+               self.reload_view()
+               
+               
+               
+               
+               
+               """
+               bearbeitenFrame=gtk.Frame("Verteilung kopieren nach")
+               bearbeitenvBox=gtk.VBox(homogeneous=False, spacing=0)
+               
+               bearbeitenhBox=gtk.HBox(homogeneous=False, spacing=0)
+               self.comboKlassen = gtk.combo_box_new_text()
+               bearbeitenhBox.pack_start(self.comboKlassen, expand=False, fill=True, padding=0)
+               button=gtk.Button("Kopieren")
+               button.connect("clicked", self.kopiereStoffverteilung, None)
+               bearbeitenhBox.pack_start(button, expand=False, fill=True, padding=0)
+               
+               label=gtk.Label("   ")
+               bearbeitenhBox.pack_start(label, expand=False, fill=True, padding=0)
+               
+               button=gtk.Button("Export in CSV-Datei")
+               button.connect("clicked", self.exportStoffverteilung, None)
+               bearbeitenhBox.pack_start(button, expand=False, fill=True, padding=0)
+               
+               bearbeitenvBox.pack_start(bearbeitenhBox, expand=False, fill=True, padding=0)
+               
+       
+               bearbeitenFrame.add(bearbeitenvBox)
+               self.pack_start(bearbeitenFrame, expand=False, fill=True, padding=0)
+               """
+               
+               #self.connect("unmap", self.speichere) 
+               #self.connect("map", self.ladeWirklich) 
+
+               #self.show_all()
+               
+               
+
+               #print "libstoffverteilung 9: ",time.clock()
+
diff --git a/src/upload.sh b/src/upload.sh
new file mode 100755 (executable)
index 0000000..3a3fd46
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+scp ../../multilist_0.3.0_all.deb user@192.168.0.34:/media/mmc2/
+
+
+
+