This email list is read-only.  Emails sent to this list will be discarded
----------------------------------
 src/Makefile.am     |    2 +-
 src/hint_window.py  |  159 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/kvm-launcher    |   65 ++++++++++++---------
 src/sample_utils.py |   49 ----------------
 4 files changed, 197 insertions(+), 78 deletions(-)

New commits:
commit 13ad29257b5b0ab6501ff7a0f39d75c7a0f40747
Author: Bob Spencer <[email protected]>
Date:   Wed Jan 14 20:25:23 2009 -0700

    Monitor spawned processes
    Show error message in dialog (not console)
    Added hint_window for launching


Diff in this email is a maximum of 400 lines.
diff --git a/src/Makefile.am b/src/Makefile.am
index 7196f2d..1220996 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,7 +5,7 @@ bin_SCRIPTS = kvm-launcher
 # Utility files
 # create .pyc and .pyo (byte-compile) 
 # and place files in /usr/lib/python<ver>/<pkg>/site-packages
-python_PYTHON = sample_utils.py
+python_PYTHON = hint_window.py
 
 desktopentry_DATA = kvm-launcher.desktop
 icon_DATA = kvm-launcher32.png
diff --git a/src/hint_window.py b/src/hint_window.py
new file mode 100644
index 0000000..d0ddb4e
--- /dev/null
+++ b/src/hint_window.py
@@ -0,0 +1,159 @@
+#!/usr/bin/python -ttu
+# vim: ai ts=4 sts=4 et sw=4
+#
+# hint_window.py: A simple window that shows a hint to the user
+#
+# Copyright 2009 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),  
+# to deal in the Software without restriction, including without limitation  
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,  
+# and/or sell copies of the Software, and to permit persons to whom the  
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in 
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+# DEALINGS IN THE SOFTWARE.
+
+
+import gc
+import gobject
+import gtk
+import gtk.gdk
+import gtk.glade
+import os
+import sys
+import time
+import pango
+
+# Import our app's libraries
+#import utils
+
+DEFAULT_DISPLAY_TIME = 2000  # 2 sec to show window if not overridden
+TEXT_OFFSET = 40             # text offset from edge
+LINE_OFFSET = 3              # border offset from edge
+COLOR_BLACK  = "#000000"     # color of background
+COLOR_LTGRAY = "#E2E2E2"     # color of text
+COLOR_GRAY =   "#ADADAD"     # color of border line
+COLOR_DKGRAY = "#404040"     # color of border line2
+
+# Show image in a borderless window for display_time milliseconds.
+# FIXME: Do we know that this works correctly?  One question I have is are we
+# just counting on garbage collection not happening while the hint is being
+# displayed since the object is being created and then immediately discarded in
+# our current usage?
+
+"""Note: This class is a singleton.  See remarks at bottom"""
+class _HintWindow(object):
+    """A borderless window with message to user"""
+    def __init__(self):
+        self.__timeout_id = None
+        
+        #Display short status window centered (e.g. 'Sorting by name')
+        self.ht_window = gtk.Window(type=gtk.WINDOW_POPUP)
+        self.ht_window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
+        self.ht_window.set_decorated(True)
+        self.ht_window.set_modal(False)
+        self.ht_window.set_default_size(0,0)
+
+        self.area = gtk.DrawingArea()
+        #self.area.set_size_request (0,0) #self.width, self.height)
+        self.ht_window.add(self.area)
+        self.area.connect('expose_event', self.expose_event)
+
+        # set bkgd color
+        self.area.modify_bg(gtk.STATE_NORMAL ,
+                            gtk.gdk.color_parse(COLOR_BLACK))
+
+        # create colors for lines and text
+        self.ltgray = self.area.get_colormap().alloc_color(COLOR_LTGRAY)
+        self.gray =   self.area.get_colormap().alloc_color(COLOR_GRAY)
+        self.dkgray = self.area.get_colormap().alloc_color(COLOR_DKGRAY)
+
+    def show_hint(self, msg, display_time=DEFAULT_DISPLAY_TIME):
+        self.msg = msg                       #used in expose_event method
+        self.timer_start(display_time)
+
+        self.ht_window.hide()
+        #self.area.hide()        
+        self.ht_window.show()
+        self.area.show()        
+
+    def hide_hint(self):
+        self.timer_stop()
+        self.ht_window.hide()
+        #self.area.hide()        
+
+    def timer_start(self, time):
+        self.timer_stop()
+        self.__timeout_id = gobject.timeout_add(time, self.timer_callback)
+        return True
+
+    def timer_stop(self):
+        if self.__timeout_id:
+            gobject.source_remove(self.__timeout_id)
+            self.__timeout_id = None
+            return True
+        return False
+    
+    def timer_callback(self):
+        self.ht_window.hide()
+        return False  #stop timer
+
+
+    '''expose_event occurs when drawarea exposed'''
+    def  expose_event(self, area, event):
+        # get graphics context (gc) and drawing window
+        gc = event.window.new_gc()
+        drawwnd = area.window
+
+        # set text, font, get text width/height
+        layout  = area.create_pango_layout(self.msg)
+        layout.set_font_description(pango.FontDescription('Sans'))
+        tw, th = layout.get_pixel_size()
+
+        # size window according to size of text + offset
+        w = tw + TEXT_OFFSET       #width of parent window
+        h = th + TEXT_OFFSET       #height of parent window
+        self.ht_window.resize(w,h)
+        self.area.set_size_request(w,h)
+
+        # draw text
+        gc.foreground = self.ltgray #dkwhite
+        x = (w - tw) / 2
+        y = (h - th) / 2
+        drawwnd.draw_layout(gc, x, y, layout=layout)
+
+        # create simple double line border 
+        o = LINE_OFFSET           #save me some typing
+        gc.foreground = self.dkgray
+        drawwnd.draw_line(gc, o,    o+1, w-o-2,o+1  ) #top
+        drawwnd.draw_line(gc, w-o-2,o+1, w-o-2,h-o)   #right
+        drawwnd.draw_line(gc, w-o-2,h-o, o,    h-o)   #bottom
+        drawwnd.draw_line(gc, o,    h-o, o,    o+1  ) #left
+        gc.foreground = self.gray  
+        drawwnd.draw_line(gc, o+1,  o,    w-o-1,o  )  #top
+        drawwnd.draw_line(gc, w-o-1,o,    w-o-1,h-o-1)#right
+        drawwnd.draw_line(gc, w-o-1,h-o-1,o+1,  h-o-1)#bottom
+        drawwnd.draw_line(gc, o+1,  h-o-1,o+1,  o  )  #left
+
+        return True
+
+
+"""
+The HintWindow is a Singleton. (granted a little awkward in python)
+This ensures callers get the same instance of the HintWindow and
+if they sort repeatedly a bunch of new windows aren't created.
+It also prevents two windows from showing at the same time.
+"""
+
+_hintwindow = _HintWindow()
+def HintWindow (): return _hintwindow
diff --git a/src/kvm-launcher b/src/kvm-launcher
index 7dd5dab..eb935d6 100755
--- a/src/kvm-launcher
+++ b/src/kvm-launcher
@@ -22,19 +22,11 @@ import sys
 import gnome
 import gtk
 import gtk.glade
-
-import popen2
-
-#import gobject
-#import pygtk
-#import re
-#import shutil
-#import time
-#import traceback
-#import signal
+import time
+import subprocess
 import webbrowser
-import hint_window
 
+import hint_window
 
 debug = False
 
@@ -110,7 +102,8 @@ class App(object):
                                    buttons=gtk.BUTTONS_OK_CANCEL, 
                                    message_format="Do you want to exit?")
         if dialog.run() == gtk.RESPONSE_OK:
-            gtk.main_quit()
+            #gtk.main_quit()
+            sys.exit()   #if spawned a child process and user wants to exit now
         dialog.destroy()
 
     def link_clicked(self, widget):
@@ -149,30 +142,46 @@ class App(object):
 
     def launch_kvm_clicked(self, widget):
         image_path = self.image_path_entry.get_text()
-        print "Launching KVM: %s" % image_path
         cmd = "kvm -no-acpi -m 512 -hda " + image_path + \
               " -hdb /var/lib/moblin-image-creator/kvm/mic_vm_share.img " + \
               "-boot c &" 
-        self.launch_app(cmd)
-        
+        self.launch_app(self.widgets.get_widget("launch_kvm"),
+                        cmd, "Starting KVM...")
+
     def launch_qemu_clicked(self, widget):
         image_path = self.image_path_entry.get_text()
-        print "Launching QEMU: %s" % image_path
         cmd = "qemu-kvm -no-acpi -m 512 -hda " + image_path + \
               " -hdb /var/lib/moblin-image-creator/kvm/mic_vm_share.img " + \
               "-boot c &"
-        self.launch_app(cmd)
-
-    def launch_app(self, cmd):
-        os.popen(cmd)
-
-        #TBD: capture error without blocking
-        # the following gets the error, but blocks if no error
-        #p = popen2.popen3(cmd)
-        #err = p[2].read() 
-        #if err:
-        #    self.show_message(gtk.MESSAGE_ERROR, err)
-                    
+        self.launch_app(self.widgets.get_widget("launch_qemu"),
+                        cmd, "Starting QEMU...")
+
+    def launch_app(self, widget, cmd, splash_prompt=""):
+        '''Launch app but allow user to exit'''
+        #disable action buttons for 2sec
+        if splash_prompt != "":
+            hint_window.HintWindow().show_hint (splash_prompt)
+        widget.set_sensitive(False)
+
+        p = subprocess.Popen(cmd, shell=True, close_fds=True,
+                             stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        i=0
+        while p.poll() == None:
+            time.sleep(0.1)
+            while gtk.events_pending():
+                gtk.main_iteration(False)
+            i=i+1
+            if i==20:
+                widget.set_sensitive(True)
+        #process has exited
+        hint_window.HintWindow().hide_hint ()
+
+        (stdoutdata, stderrdata) = p.communicate(None)
+        if stderrdata != "":
+            self.show_message (gtk.MESSAGE_ERROR, "Error: " + stderrdata)
+        print stdoutdata
+        widget.set_sensitive(True)
+        
     def show_message (self, msg_type, msg):
         dialog = gtk.MessageDialog(type=msg_type, 
                                    buttons=gtk.BUTTONS_OK, 
diff --git a/src/sample_utils.py b/src/sample_utils.py
deleted file mode 100644
index b0d6227..0000000
--- a/src/sample_utils.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/python -tt
-# vim: ai ts=4 sts=4 et sw=4
-#
-# sample_utils.py contains utility methods used by kvm-launcher
-#
-# Copyright (C) 2009, Intel Corporation.
-#
-# Author: Praj Karur Mohan <[email protected]>\nBob Spencer 
<[email protected]>
-# 
-# 
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#     * Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above copyright
-#       notice, this list of conditions and the following disclaimer in the
-#       documentation and/or other materials provided with the distribution.
-#     * Neither the name of the PG_ORGANIZATION nor the
-#       names of its contributors may be used to endorse or promote products
-#       derived from this software without specific prior written permission.
-# 
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS-IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
-# POSSIBILITY OF SUCH DAMAGE.
-#
-
-import sys
-
-def printUserInfo(name,age):
-    """Display user name and age"""
-    if name == "" or age < 0 or age > 200:
-        return False
-    print ("\nYour name is %s and you are %d years old\n") % (name,age)
-    return True
-
-# Add fn to exercise code
-def main():
-    printUserInfo("fooname",0)
-
-if '__main__' == __name__:
-    sys.exit(main())
_______________________________________________
Commits mailing list
[email protected]
https://lists.moblin.org/mailman/listinfo/commits

Reply via email to