fixed URL
[stockthis] / stockthis.py
index de12beb..31f6a4c 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #
-# StocksPy: Application to get stocks data from Yahoo Finance.
-# Version 0.1
+# StocksThis: Application to get stocks data from Yahoo Finance.
 #
 
-_version = "StockThis 0.3 alpha1 rev1"
+_version = "StockThis 0.3 rev1"
 
 import urllib2
 import gtk, gobject
@@ -31,13 +30,15 @@ import settings
 import logging
 import sys
 
+from portrait import FremantleRotation
+
 import osso
 osso_c = osso.Context("net.yerga.stockthis", "0.3", False)
 
 #detect if is ran locally or not
 runningpath = sys.path[0]
 
-if '/usr/share' in runningpath:
+if '/opt/' in runningpath:
     runninglocally = False
 else:
     runninglocally = True
@@ -47,7 +48,6 @@ HOME = os.path.expanduser("~")
 settingsdb, imgdir, configdir, logfile = \
     settings.define_paths(runninglocally, HOME)
 
-
 logger = logging.getLogger('st')
 logging.basicConfig(filename=logfile,level=logging.ERROR, filemode='w')
 
@@ -72,7 +72,8 @@ ui_normal = gtk.HILDON_UI_MODE_NORMAL
 ui_edit = gtk.HILDON_UI_MODE_EDIT
 winprogind = hildon.hildon_gtk_window_set_progress_indicator
 
-logger.debug("test this log")
+allnames = []
+allsymbols = []
 
 gtk.gdk.threads_init()
 
@@ -87,10 +88,12 @@ class StocksPy:
         self.program.add_window(self.window)
         self.window.connect("destroy", gtk.main_quit)
 
+        FremantleRotation('StockThis', None, "0.3", 0)
+
         self.create_menu(self.window)
 
         vbox = gtk.VBox()
-        toolbar = self.main_toolbar(False, False, None, '', '')
+        toolbar = self.main_toolbar(False, False, None, '', '', True)
 
         parea = hildon.PannableArea()
         tv = hildon.GtkTreeView(ui_normal)
@@ -109,6 +112,10 @@ class StocksPy:
         self.window.add(vbox)
         self.window.show_all()
 
+        self.show_info_banner(self.window,
+            ("StockThis uses your network connection to get data.\n"
+            "Be aware of the high costs that your network provider may apply."))
+
     def create_menu(self, window):
         menu = hildon.AppMenu()
         window.set_app_menu(menu)
@@ -128,10 +135,10 @@ class StocksPy:
 
         window = hildon.StackableWindow()
         self.create_menu(window)
-        window.set_title("StockThis - " + inmodel[path][1])
+        window.set_title(inmodel[path][1])
 
         vbox = gtk.VBox()
-        toolbar = self.main_toolbar(False, False, None, '', '')
+        toolbar = self.main_toolbar(False, False, None, '', '', False)
 
         parea = hildon.PannableArea()
         parea.connect("horizontal-movement", self.horizontal_mov)
@@ -153,15 +160,18 @@ class StocksPy:
         #direction = 2 right-to-left
         #direction = 3 lefto-to-right
 
+        vadj = parea.get_vadjustment()
+        val = vadj.get_value()
+
         if direction == 2:
-            parea.scroll_to(-1, initial_y-400)
+            if int(val)-2500 < 0:
+                 parea.scroll_to(-1, 0)
+            else:
+                parea.scroll_to(-1, int(val)-2500)
         elif direction == 3:
-            parea.scroll_to(-1, initial_y+400)
-
-        print direction
-        print initial_x
-        print initial_y
+            parea.scroll_to(-1, int(val)+3500)
 
+        #print val
 
     def show_quotes_view(self, widget, path, column, model, portfolio):
         quote = model[path][0], model[path][1]
@@ -206,7 +216,7 @@ class StocksPy:
 
         win = hildon.StackableWindow()
         self.create_menu(win)
-        win.set_title("StockThis - Quotes View - " + quote[1])
+        win.set_title(quote[1])
 
         vbox = gtk.VBox()
 
@@ -217,51 +227,75 @@ class StocksPy:
         ltitle.modify_fg(gtk.STATE_NORMAL, color)
 
         parea = hildon.PannableArea()
+        parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
 
         vbox1 = gtk.VBox()
 
         hbox = gtk.HBox()
         label = gtk.Label('')
-        label.set_markup('<b><big>Price:</big></b>')
+        label.set_markup('<b><big>%39s:</big></b>' % '<u>Price</u>')
         lprice = gtk.Label('')
-        hbox.pack_start(label, False, False, 20)
-        hbox.pack_start(lprice, False, False, 245)
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(lprice, False, False, 25)
+        #else:
+        #    hbox.pack_start(lprice, False, False, 245)
+
         vbox1.pack_start(hbox, True, True, 0)
 
         hbox = gtk.HBox()
         label = gtk.Label('')
-        label.set_markup('<b><big>Change:</big></b>')
+        label.set_markup('<b><big>%35s:</big></b>' % '<u>Change</u>')
         lchange = gtk.Label('')
         lpercent = gtk.Label('')
-        hbox.pack_start(label, False, False, 20)
-        hbox.pack_start(lchange, False, False, 205)
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(lchange, False, False, 25)
         hbox.pack_start(lpercent, False, False, 0)
+        #else:
+        #    hbox.pack_start(lchange, False, False, 205)
+        #    hbox.pack_start(lpercent, False, False, 0)
+
         vbox1.pack_start(hbox, True, True, 0)
 
         hbox = gtk.HBox()
         label = gtk.Label('')
-        label.set_markup('<b><big>Volume:</big></b>')
+        label.set_markup('<b><big>%35s:</big></b>' % '<u>Volume</u>')
         lvolume = gtk.Label('')
-        hbox.pack_start(label, False, False, 20)
-        hbox.pack_start(lvolume, False, False, 207)
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(lvolume, False, False, 25)
+        #else:
+        #    hbox.pack_start(lvolume, False, False, 207)
+
         vbox1.pack_start(hbox, True, True, 0)
 
         hbox = gtk.HBox()
         label = gtk.Label('')
-        label.set_markup('<b><big>52 week high:</big></b>')
+        label.set_markup('<b><big>%30s:</big></b>' % '<u>52 week high</u>')
         l52whigh = gtk.Label('')
-        hbox.pack_start(label, False, False, 20)
-        hbox.pack_start(l52whigh, False, False, 125)
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(l52whigh, False, False, 25)
+        #else:
+        #    hbox.pack_start(l52whigh, False, False, 125)
+
         vbox1.pack_start(hbox, True, True, 0)
 
         hbox = gtk.HBox()
         label = gtk.Label('')
-        label.set_markup('<b><big>52 week low:</big></b>')
+        label.set_markup('<b><big>%30s:</big></b>' % '<u>52 week low</u>')
         l52wlow = gtk.Label('')
-        hbox.pack_start(label, False, False, 20)
-        hbox.pack_start(l52wlow, False, False, 140)
+        hbox.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox.pack_start(l52wlow, False, False, 26)
+        #else:
+        #    hbox.pack_start(l52wlow, False, False, 140)
         vbox1.pack_start(hbox, True, True, 0)
 
+        #if self.is_portrait():
+        #    hbox = gtk.VBox()
+        #else:
         hbox = gtk.HBox()
         button1 = hildon.PickerButton(fhsize, horbtn)
         data = ["50", "100", "200", "300", "400", "500", "600", "700", "800",
@@ -280,24 +314,33 @@ class StocksPy:
 
         hbox1 = gtk.HBox()
         label = gtk.Label('')
-        label.set_markup('<b><big>Shares:</big></b>')
+        label.set_markup('<b><big>%37s:</big></b>' % '<u>Shares</u>')
         lshares = gtk.Label(shares)
-        hbox1.pack_start(label, False, False, 20)
-        hbox1.pack_start(lshares, False, False, 220)
+        hbox1.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox1.pack_start(lshares, False, False, 25)
+        #else:
+        #    hbox1.pack_start(lshares, False, False, 220)
 
         hbox2 = gtk.HBox()
         label = gtk.Label('')
-        label.set_markup('<b><big>Holdings Value:</big></b>')
+        label.set_markup('<b><big>%29s:</big></b>' % '<u>Holdings Value</u>')
         holdingsvalue = gtk.Label("")
-        hbox2.pack_start(label, False, False, 20)
-        hbox2.pack_start(holdingsvalue, False, False, 105)
+        hbox2.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox2.pack_start(holdingsvalue, False, False, 25)
+        #else:
+        #    hbox2.pack_start(holdingsvalue, False, False, 105)
 
         hbox3 = gtk.HBox()
         label = gtk.Label('')
-        label.set_markup("<b><big>Day's Value Change:</big></b>")
+        label.set_markup("<b><big>%25s:</big></b>" % "<u>Day's Value Change</u>")
         dayvaluechange = gtk.Label("")
-        hbox3.pack_start(label, False, False, 20)
-        hbox3.pack_start(dayvaluechange, False, False, 45)
+        hbox3.pack_start(label, False, False, 0)
+        #if self.is_portrait():
+        hbox3.pack_start(dayvaluechange, False, False, 25)
+        #else:
+        #    hbox3.pack_start(dayvaluechange, False, False, 45)
 
         if not portfolio:
             vbox1.pack_start(hbox, False, False, 0)
@@ -311,7 +354,7 @@ class StocksPy:
         widgets = [win, ltitle, lprice, lchange,  lpercent, lvolume, l52whigh,
                     l52wlow, lshares, holdingsvalue, dayvaluechange]
 
-        toolbar = self.main_toolbar(True, portfolio, widgets, quote[0], quote[1])
+        toolbar = self.main_toolbar(True, portfolio, widgets, quote[0], quote[1], False)
 
         vbox.pack_start(ltitle, False, False, 0)
         vbox.pack_start(gtk.HSeparator(), False, False, 0)
@@ -324,6 +367,14 @@ class StocksPy:
         win.show_all()
         self.show_data(quote[0], widgets, shares)
 
+    def is_portrait(self):
+        width = gtk.gdk.screen_width()
+        height = gtk.gdk.screen_height()
+        if width > height:
+            return False
+        else:
+            return True
+
     def get_shares_from_symbol(self, symbol):
         shares = "0"
         try:
@@ -333,7 +384,7 @@ class StocksPy:
                     shares = item[2]
             return shares
         except:
-            logger.exception("Getting shares from symbol")
+            logger.exception("Getting shares from symbol: %s" % symbol)
             return shares
 
     def add_to_portfolio(self, widget, button, symbol, name):
@@ -356,7 +407,7 @@ class StocksPy:
 
             self.show_info_banner(widget, "Added to portfolio")
         except:
-            logger.exception("Adding to portfolio")
+            logger.exception("Adding to portfolio: %s, %s" % (symbol, name))
             self.show_info_banner(widget, "Error adding to portfolio")
 
 
@@ -364,7 +415,7 @@ class StocksPy:
         if entry:
             selector = hildon.TouchSelectorEntry(text=True)
         else:
-            selector = hildon.hildon_touch_selector_new_text()
+            selector = hildon.TouchSelector(text=True)
         for i in range(len(data)):
             selector.append_text(data[i])
 
@@ -382,7 +433,7 @@ class StocksPy:
         try:
             data = yt.get_all(symbol)
         except:
-            logger.exception("Getting data from Yahoo")
+            logger.exception("Getting data from Yahoo: %s" % symbol)
             data = {'price': 'N/A', 'change': 'N/A', 'volume':'N/A',
                     '52_week_high': 'N/A', '52_week_low': 'N/A'}
             ltitle.set_markup('<b><big>Failed to get data</big></b>')
@@ -435,16 +486,19 @@ class StocksPy:
     def show_graph_view(self, widget, symbol, name):
         win = hildon.StackableWindow()
         self.create_menu(win)
-        win.set_title("StockThis - Graph View - " + name)
+        win.set_title(name)
 
         vbox = gtk.VBox()
-        toolbar = self.main_toolbar(False, True, None, '', '')
+        toolbar = self.main_toolbar(False, True, None, '', '', False)
 
         self.graphs_title = gtk.Label(name)
         color = gtk.gdk.color_parse("#03A5FF")
         self.graphs_title.modify_fg(gtk.STATE_NORMAL, color)
 
         parea = hildon.PannableArea()
+        parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
+
+        vbox1 = gtk.VBox()
 
         hbox = gtk.HBox()
         hbox.set_homogeneous(True)
@@ -469,6 +523,10 @@ class StocksPy:
         button.connect("clicked", self.show_graph, '6m', win, symbol)
         hbox.pack_start(button)
 
+        vbox1.pack_start(hbox, False, False, 0)
+        hbox = gtk.HBox()
+        hbox.set_homogeneous(True)
+
         button = hildon.Button(fhsize, horbtn)
         button.set_label('1y')
         button.connect("clicked", self.show_graph, '1y', win, symbol)
@@ -489,7 +547,6 @@ class StocksPy:
         button.connect("clicked", self.show_graph, 'max', win, symbol)
         hbox.pack_start(button)
 
-        vbox1 = gtk.VBox()
         vbox1.pack_start(hbox, False, False, 0)
 
         self.graph = gtk.Image()
@@ -539,11 +596,12 @@ class StocksPy:
             pbl.write(imgdata)
 
             pbuf = pbl.get_pixbuf()
+            pbuf = pbuf.scale_simple(475, 235, gtk.gdk.INTERP_TILES)
             pbl.close()
             self.graph.set_from_pixbuf(pbuf)
             winprogind(win, 0)
         except:
-            logger.exception("Getting graph data")
+            logger.exception("Getting graph data: %s" % url)
             winprogind(win, 0)
             self.graphs_title.set_label('Failed to get data')
             self.graph.destroy()
@@ -563,9 +621,9 @@ class StocksPy:
             lstore.set(iter, 0, ids[item], 1, names[item])
         return lstore
 
-    def main_toolbar(self, quotesview, portfolio, widgets, symbol, name):
+    def main_toolbar(self, quotesview, portfolio, widgets, symbol, name, initial):
         toolbar = gtk.HBox()
-        toolbar.set_homogeneous(True)
+        #toolbar.set_homogeneous(True)
 
         portfolio_btn = hildon.Button(fhsize, horbtn)
         portfolio_btn.set_title("Portfolio")
@@ -580,26 +638,156 @@ class StocksPy:
         refresh_btn.connect("clicked", self.refresh_stock_data, portfolio,
                             widgets, symbol)
 
+
+        stockiconspath = "/usr/share/icons/hicolor/48x48/hildon/"
+        info_btn = hildon.Button(fhsize, horbtn)
+        img = gtk.Image()
+        img.set_from_file(stockiconspath + "general_information.png")
+        info_btn.set_image(img)
+        info_btn.connect("clicked", self.show_app_information)
+
+        search_btn = hildon.Button(fhsize, horbtn)
+        img = gtk.Image()
+        img.set_from_file(stockiconspath + "general_search.png")
+        search_btn.set_image(img)
+        search_btn.connect("clicked", self.show_search_dialog)
+
         if not portfolio:
             toolbar.pack_start(portfolio_btn)
+            if not quotesview:
+                toolbar.pack_start(info_btn, False, False, 0)
         if quotesview:
             toolbar.pack_start(graph_btn)
             toolbar.pack_start(refresh_btn)
 
+        if initial:
+            toolbar.pack_start(search_btn, False, False, 0)
+
         toolbar.show_all()
 
         return toolbar
 
+    def show_search_dialog(self, widget):
+        dlg = gtk.Dialog(title='Search company', parent=None, flags=0)
+        dlg.set_has_separator(False)
+
+        entry = hildon.Entry(fhsize)
+        dlg.vbox.pack_start(entry, False, False, 0)
+
+        button = hildon.Button(fhsize, horbtn)
+        button.set_label("Search")
+        button.connect("clicked", self.do_search, entry, dlg)
+        dlg.vbox.pack_start(button, False, False, 0)
+
+        dlg.show_all()
+        dlg.run()
+        dlg.destroy()
+
+
+    def do_search(self, widget, entry, dlg):
+        import thread
+        text = entry.get_text()
+        dlg.destroy()
+
+        winprogind(self.window, 1)
+        thread.start_new_thread(self._really_do_search, (text,))
+
+    def _really_do_search(self, text):
+
+        if allnames == []:
+            for market in marketdata.eunames:
+                for company in market:
+                    allnames.append(company)
+
+            for market in marketdata.omnames:
+                for company in market:
+                    allnames.append(company)
+
+            for market in marketdata.usnames:
+                for company in market:
+                    allnames.append(company)
+
+        if allsymbols == []:
+            for market in marketdata.eusymbols:
+                for company in market:
+                    allsymbols.append(company)
+
+            for market in marketdata.omsymbols:
+                for company in market:
+                    allsymbols.append(company)
+
+            for market in marketdata.ussymbols:
+                for company in market:
+                    allsymbols.append(company)
+
+        new_model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+        for i in range(len(allnames)):
+            if text.lower() in allnames[i].lower():
+                niter = new_model.append()
+                #print allsymbols[i], allnames[i]
+                #FIXME: repeated companies in the results list
+                #print if allnames[i]
+                #for j in new_model:
+                #    if j[1] == allnames[i]:
+                new_model.set(niter, 0, allsymbols[i], 1, allnames[i])
+
+        if len(new_model) == 0:
+            winprogind(self.window, 0)
+            gtk.gdk.threads_enter()
+            self.show_info_banner(self.window, "No items found for this search")
+            gtk.gdk.threads_leave()
+            return
+
+        gtk.gdk.threads_enter()
+        self.show_search_screen(new_model, text)
+        gtk.gdk.threads_leave()
+        winprogind(self.window, 0)
+
+
+    def show_search_screen(self, model, text):
+        window = hildon.StackableWindow()
+        self.create_menu(window)
+        window.set_title("Search for " + text)
+
+        vbox = gtk.VBox()
+        toolbar = self.main_toolbar(False, False, None, '', '', False)
+
+        parea = hildon.PannableArea()
+        parea.connect("horizontal-movement", self.horizontal_mov)
+        tv = hildon.GtkTreeView(ui_normal)
+        tv.connect("row-activated", self.show_quotes_view, model, False)
+        tv.set_model(model)
+        self._tv_columns(tv)
+        parea.add(tv)
+
+        vbox.pack_start(parea, True, True, 0)
+        vbox.pack_start(gtk.HSeparator(), False, False, 5)
+        vbox.pack_start(toolbar, False, False, 0)
+
+        window.add(vbox)
+        window.show_all()
+
+
+    def show_app_information(self, widget):
+        self.show_information_note(self.window, (
+        "The data is got from Yahoo! Finance.\n"
+        "It could be delayed or even wrong.\n"
+        "The author doesn't validate in any way this data and therefore he is not responsible for any damage that may occur.\n\n"
+        "You can scroll large list with gestures:\n"
+        "Left-to-right gesture: scroll down.\n"
+        "Right-to-left gesture: scroll up."))
+
     def show_portfolio_view(self, widget):
         data = settings.load_portfolio(settingsdb)
 
         win = hildon.StackableWindow()
         self.create_menu(win)
-        win.set_title("StockThis - Portfolio")
+        win.set_title("Portfolio")
 
         vbox = gtk.VBox()
 
         parea = hildon.PannableArea()
+        parea.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
         tv = hildon.GtkTreeView(ui_normal)
         tv.set_headers_visible(True)
         self.portfolio_model = self._create_portfolio_model(data)
@@ -749,7 +937,7 @@ class StocksPy:
             price = yt.get_price(symbol)
             return price
         except:
-            logger.exception("Getting price from Yahoo")
+            logger.exception("Getting price from Yahoo: %s" % symbol)
             return "N/A"
 
     def _create_portfolio_model(self, data):
@@ -786,6 +974,12 @@ class StocksPy:
         dialog.destroy()
         return False
 
+    def show_information_note(self, window, msg):
+        dialog = hildon.hildon_note_new_information(window, msg)
+        dialog.show_all()
+        result = dialog.run()
+        dialog.destroy()
+
     def show_info_banner(self, widget, msg):
         hildon.hildon_banner_show_information(widget, 'qgn_note_infoprint', msg)
 
@@ -800,9 +994,9 @@ class StocksPy:
 class About:
 
     def __init__(self, widget):
-        dialog = gtk.Dialog(title='About', parent=None, flags=0)
-        dialog.set_has_separator(False)
-        dialog.set_size_request(-1, 400)
+        self.abdialog = gtk.Dialog(title='About', parent=None, flags=0)
+        self.abdialog.set_has_separator(False)
+        self.abdialog.set_size_request(-1, 400)
 
         self.info_lb = gtk.Label()
         self.info_lb.set_line_wrap(True)
@@ -846,26 +1040,34 @@ class About:
 
         self.show_info(None, 'description')
 
-        dialog.vbox.pack_start(self.action_btn, False, False, 0)
-        dialog.vbox.pack_start(self.image, False, False, 5)
-        dialog.vbox.pack_start(self.info_lb, True, True, 0)
-        dialog.vbox.pack_start(hbox1, False, False, 0)
+        self.abdialog.vbox.pack_start(self.action_btn, False, False, 0)
+        self.abdialog.vbox.pack_start(self.image, False, False, 5)
+        self.abdialog.vbox.pack_start(self.info_lb, True, True, 0)
+        self.abdialog.vbox.pack_start(hbox1, False, False, 0)
 
-        dialog.show_all()
+        self.abdialog.show_all()
         self.action_btn.hide()
         self.image.hide()
-        dialog.run()
-        dialog.destroy()
+        self.abdialog.run()
+        self.abdialog.destroy()
 
     def do_action(self, widget, action):
-        import webbrowser
+        import dbus
+
+        self.abdialog.destroy()
+
+        bus = dbus.SystemBus()
+        proxy = bus.get_object("com.nokia.osso_browser", "/com/nokia/osso_browser/request")
+        iface = dbus.Interface(proxy, 'com.nokia.osso_browser')
+
         if action == "donate":
             url = "http://stockthis.garage.maemo.org/donate.html"
         elif action == "report":
             url = "http://stockthis.garage.maemo.org/reporting.html"
         elif action == "vote":
-            url = "http://maemo.org/downloads/product/stockthis"
-        webbrowser.open_new(url)
+            url = "http://maemo.org/downloads/product/Maemo5/stockthis"
+
+        iface.open_new_window(url)
 
     def show_info(self, widget, kind):
         if kind == 'license':
@@ -905,7 +1107,6 @@ Developing good software takes time and hard work.
 If you like the program and it's helpful, consider donating a small amount of money.
 Donations are a great incentive and help the developer feel that the hard work is appreciated.</small>
 """
-
         elif kind == 'report':
             self.action_btn.show()
             self.image.hide()
@@ -913,11 +1114,10 @@ Donations are a great incentive and help the developer feel that the hard work i
             if self.id:
                 self.action_btn.disconnect(self.id)
             self.id = self.action_btn.connect("clicked", self.do_action, "report")
-            info = """<small>StockThis is being improved thanks to bug reports. The author appreciates very much all these reports.
+            info = """<small>StockThis is being improved thanks to bug reports that users have submitted. The author appreciates these reports.
 If the application is raising an error when you're using it, you have two choices to report this error:
 1) Send the log from the application menu (if there's an error in the log).
-2) Write a bug report in the bugtracker of StockThis with as much information as possible (especially the log from the menu).</small>"""
-
+2) Press the button and write a bug report with as much information as possible.</small>"""
         elif kind == 'vote':
             self.action_btn.show()
             self.image.show()
@@ -1030,6 +1230,20 @@ class Log:
             stockspy.show_info_banner(widget, 'Error saving the log file')
 
     def send(self, widget, dlg, logfile):
+        sendtxt = ("You are going to send the log to the developers.\n"
+        "This helps the developers to track problems with the application.\n"
+        "It doesn't send any personal information (like passwords or similar).")
+
+        dialog = hildon.hildon_note_new_confirmation(dlg, sendtxt)
+        dialog.set_button_texts("Send", "Cancel")
+        dialog.show_all()
+        response = dialog.run()
+        if response == gtk.RESPONSE_OK:
+            self.do_pre_send(dlg, logfile)
+
+        dialog.destroy()
+
+    def do_pre_send(self, dlg, logfile):
         import thread
         hildon.hildon_gtk_window_set_progress_indicator(dlg, 1)
         thread.start_new_thread(self._do_send, (dlg, logfile))