ANN: PyGUI 1.7.2-1

G

greg

I have uploaded a new PyGUI 1.7.2 package to correct
a couple of errors in the setup.py file.

http://www.cosc.canterbury.ac.nz/~greg/python_gui/

-----------------------------------------------------

What is PyGUI?
--------------

PyGUI is an experimental highly-Pythonic cross-platform
GUI API. Implementations are currently available for
MacOSX and Gtk. For a full description of the project
goals, see the PyGUI web page at the above address.
 
H

hale

greg said:
I have uploaded a new PyGUI 1.7.2 package to correct
a couple of errors in the setup.py file.

http://www.cosc.canterbury.ac.nz/~greg/python_gui/

-----------------------------------------------------

What is PyGUI?
--------------

PyGUI is an experimental highly-Pythonic cross-platform
GUI API. Implementations are currently available for
MacOSX and Gtk. For a full description of the project
goals, see the PyGUI web page at the above address.

I downloaded the new version of PyGUI, but I am having
some problems with running it in the IDLE ide.

I will use BlobEdit.py as an example.

If I run the the makefile, then blobedit runs ok as an application.

If I use the terminal, and execute pythonw with argument blobedit.py,
then it runs ok.

However, if I try to run blobedit.py in the IDLE ide, I get an error
since it tries to open a file when no file was given. Looking at your
code, I see that you noticed certain situation where this occurs
and tried to handle it by comparing path == sys.argv[0] and skipping
opening the file in this case.

But, when running it within IDLE, the path is equal to "8833" for some
reason. I tried to hunt down where the problem occurs, but I was led
to the method "application_openFile_(self, ns_app, path)" in the
class _PyGui_NSApplication. I couldn't find out how this method
ever got called though.

Is there some way to work around this problem?

Thanks.

-- Bill Hale
 
G

greg

if I try to run blobedit.py in the IDLE ide ...
> the path is equal to "8833" for some
reason.

I believe that IDLE sets up some kind of debugging
connection to its child process. That number might
be a processs ID or port number or something related
to that.
I tried to hunt down where the problem occurs, but I was led
to the method "application_openFile_(self, ns_app, path)" in the
class _PyGui_NSApplication. I couldn't find out how this method
ever got called though.

It's called by the Cocoa framework to handle files
passed to the application from the Finder. It also
seems to get called when there are command-line
arguments. But it works on the C-level argv, which
means it can pick up stuff that doesn't normally
end up in sys.argv. The check for sys.argv[0]
is there to work around one of the side effects of
that. It appears that you've encountered another
one.

I'm using a different method of dealing with
this now, which will probably fix your problem as
well. I've attached a replacement for
GUI/Cocoa/Applications.py. Let me know if it
works for you.

--
Greg

#
# Python GUI - Application class - PyObjC
#

import os, sys, traceback
import objc
#from ExceptionHandling import \
# NSExceptionHandler, NSLogUncaughtExceptionMask, NSLogAndHandleEveryExceptionMask
from Foundation import NSObject, NSBundle, NSDefaultRunLoopMode
import AppKit
from AppKit import NSApplication, NSResponder, NSScreen, NSMenu, NSMenuItem, \
NSKeyDown, NSKeyUp, NSMouseMoved, NSLeftMouseDown, NSSystemDefined, \
NSCommandKeyMask, NSPasteboard, NSStringPboardType, NSModalPanelRunLoopMode, \
NSAnyEventMask
import GApplications
from GApplications import application, Application as GApplication
from Events import Event
from Exceptions import Cancel, Quit
from Menus import _ns_standard_actions

#------------------------------------------------------------------------------

ns_application = None
ns_screen_height = None
ns_last_mouse_moved_event = None

#------------------------------------------------------------------------------

class Application(GApplication):
# _ns_app _PyGui_NSApplication
# _ns_pasteboard NSPasteboard
# _ns_key_window Window

_ns_menubar_update_pending = False

def __init__(self, **kwds):
#print "Application.__init__: argv =", sys.argv ###
create_ns_application()
self._ns_app = ns_application
self._ns_app.pygui_app = self
self._ns_init_standard_menu_items()
self._ns_pasteboard = NSPasteboard.generalPasteboard()
self._ns_key_window = None
GApplication.__init__(self, **kwds)
ns_application.init_application_name()

def destroy(self):
del self.menus[:]
import Windows
Windows._ns_zombie_window = None
self._ns_app.pygui_app = None
self._ns_app = None
self._ns_pasteboard = None
GApplication.destroy(self)

def set_menus(self, menu_list):
GApplication.set_menus(self, menu_list)
self._update_menubar()

def _update_menubar(self):
ns_app = self._ns_app
ns_menubar = NSMenu.alloc().initWithTitle_("")
menu_list = self._effective_menus()
for menu in menu_list:
ns_item = NSMenuItem.alloc()
ns_item.initWithTitle_action_keyEquivalent_(menu.title, '', "")
ns_menubar.addItem_(ns_item)
ns_menu = menu._ns_menu
# An NSMenu can only be a submenu of one menu at a time, so
# remove it from the old menubar if necessary.
old_supermenu = ns_menu.supermenu()
if old_supermenu:
i = old_supermenu.indexOfItemWithSubmenu_(ns_menu)
old_supermenu.removeItemAtIndex_(i)
ns_menubar.setSubmenu_forItem_(ns_menu, ns_item)
ns_app.setMainMenu_(ns_menubar)
# Apple's docs fail to explain that the menu you pass to setAppleMenu_
# must *also* be a member of the menu bar.
ns_app_menu = menu_list[0]._ns_menu
self._ns_app.setAppleMenu_(ns_app_menu)

def handle_events(self):
#print "Application.handle_events: entering NS run loop" ###
#try:
self._ns_app.run()
#finally:
#print "Application.handle_events: exiting NS run loop" ###

def handle_next_event(self, modal_window = None):
#print "Application.handle_next_event" ###
ns_app = self._ns_app
if modal_window:
ns_mode = NSModalPanelRunLoopMode
ns_modal_window = modal_window._ns_window
else:
ns_mode = NSDefaultRunLoopMode
ns_modal_window = None
ns_event = ns_app.nextEventMatchingMask_untilDate_inMode_dequeue_(
NSAnyEventMask, None, ns_mode, True)
if ns_event:
ns_window = ns_event.window()
if not ns_window or not ns_modal_window or ns_window == ns_modal_window:
ns_app.sendEvent_(ns_event)

def _find_target_window(self):
# NSApplication.keyWindow() isn't reliable enough. We keep track
# of the key window ourselves.
return self._ns_key_window

def zero_windows_allowed(self):
return 1

def query_clipboard(self):
pb = self._ns_pasteboard
pb_types = pb.types()
return NSStringPboardType in pb_types

def get_clipboard(self):
raise NotImplementedError("TODO: Application.get_clipboard")

def set_clipboard(self, data):
raise NotImplementedError("TODO: Application.set_clipboard")

def _quit(self):
#print "Application._quit" ###
self._ns_app.stop_(self)

def _ns_init_standard_menu_items(self):
self._ns_standard_menu_items = {}
for (cmd_name, ns_selector) in _ns_standard_actions.iteritems():
self._ns_standard_menu_items[cmd_name] = NSMenuItem.alloc().\
initWithTitle_action_keyEquivalent_("", ns_selector, "")

def _dispatch_menu_setup(self, m):
for (cmd_name, ns_menu_item) in self._ns_standard_menu_items.iteritems():
ns_selector = ns_menu_item.action()
target = self._ns_app.targetForAction_(ns_selector)
if target and target.respondsToSelector_('validateMenuItem:'):
valid = target.validateMenuItem_(ns_menu_item)
m[cmd_name].enabled = valid
GApplication._dispatch_menu_setup(self, m)

def setup_menus(self, m):
if not self._ns_app.modalWindow():
GApplication.setup_menus(self, m)

def process_args(self, args):
# Don't need to do anything, since args seem to get passed to
# us via application_openFile_ automatically when run with pythonw.
# Note: When using py2app, argv_emulation should be disabled.
#pass
if args and args[0].startswith("-psn"):
# Launched from MacOSX Finder -- wait for file open/app launch messages
pass
else:
# Not launched from Finder or using argv emulation
self._ns_app.using_clargs = True
GApplication.process_args(self, args)

def run(self):
try:
GApplication.run(self)
except (KeyboardInterrupt, SystemExit):
pass
except:
traceback.print_exc()
# A py2app bundled application seems to crash on exit if we don't
# bail out really quickly here (Python 2.3, PyObjC 1.3.7, py2app 0.2.1,
# MacOSX 10.4.4)
os._exit(0)

#------------------------------------------------------------------------------

_ns_key_event_mask = AppKit.NSKeyDownMask | AppKit.NSKeyUpMask

#------------------------------------------------------------------------------

class _PyGui_NSApplication(NSApplication):

pygui_app = None
files_opened = False
using_clargs = False

def sendEvent_(self, ns_event):
# Perform special processing of key events.
# Perform menu setup when menu bar is clicked.
# Remember the most recent mouse-moved event to use as the
# location of event types which do not have a location themselves.
if pending_exception:
raise_pending_exception()
ns_type = ns_event.type()
#print "sendEvent_:", ns_event ###
if (1 << ns_type) & _ns_key_event_mask:
self.process_key_event(ns_event)
else:
if ns_type == NSMouseMoved:
global ns_last_mouse_moved_event
ns_last_mouse_moved_event = ns_event
elif ns_type == NSSystemDefined and ns_event.subtype() == 7 \
and not ns_event.window():
# Mouse down in the menu bar. We detect it by means of this strange
# event because mouse-down events in the menu bar don't make it to
# sendEvent: until it's too late.
self.perform_menu_setup()
NSApplication.sendEvent_(self, ns_event)

def process_key_event(self, ns_event):
# Perform menu setup before command-key events.
# Send non-command key events to associated window if any,
# otherwise pass them to the pygui application. This is necessary
# because otherwise there is no way of receiving key events when
# there are no windows.
if ns_event.modifierFlags() & NSCommandKeyMask:
self.perform_menu_setup()
NSApplication.sendEvent_(self, ns_event)
else:
ns_window = ns_event.window()
if ns_window:
ns_window.sendEvent_(ns_event)
else:
self.pass_event_to_application(ns_event)

def perform_menu_setup(self):
app = self.pygui_app
if app:
app._perform_menu_setup()

def pass_event_to_application(self, ns_event):
app = self.pygui_app
if app:
event = Event(ns_event)
app.handle(event.kind, event)

# def sendAction_to_from_(self, action, target, sender):
# print "_PyGui_NSApplication.sendAction_to_from_", action, target, sender ###
# return NSApplication.sendAction_to_from_(self, action, target, sender)

def menuSelection_(self, ns_menu_item):
command = ns_menu_item.representedObject()
index = ns_menu_item.tag()
if index >= 0:
self.dispatch_to_app(command, index)
else:
self.dispatch_to_app(command)

def dispatch_to_app(self, *args):
app = self.pygui_app
if app:
app.dispatch(*args)

def validateMenuItem_(self, item):
return False

def undo_(self, sender):
self.dispatch_to_app('undo_cmd')

def redo_(self, sender):
self.dispatch_to_app('redo_cmd')

def cut_(self, sender):
self.dispatch_to_app('cut_cmd')

def copy_(self, sender):
self.dispatch_to_app('copy_cmd')

def paste_(self, sender):
self.dispatch_to_app('paste_cmd')

def clear_(self, sender):
self.dispatch_to_app('clear_cmd')

def select_all_(self, sender):
self.dispatch_to_app('select_all_cmd')

def init_application_name(self):
# Arrange for the application name to be used as the title
# of the application menu.
ns_bundle = NSBundle.mainBundle()
if ns_bundle:
ns_info = ns_bundle.localizedInfoDictionary()
if ns_info:
if ns_info['CFBundleName'] == "Python":
ns_info['CFBundleName'] = GApplications.application_name
return
#raise RuntimeError("No bundle information found. "
# "Perhaps the application was not run with pythonw?")

def application_openFile_(self, ns_app, path):
if self.using_clargs:
True
#print "PyGUI_NSApplication.application_openFile_:", path ###
# Bizarrely, argv[0] gets passed to application_openFile_ under
# some circumstances. We don't want to try to open it!
if path == sys.argv[0]:
return True
self.files_opened = True
try:
self.pygui_app.open_path(path)
return True
except Exception, e:
self.pygui_app.report_error()
return False

def applicationDidFinishLaunching_(self, notification):
if self.using_clargs:
return
#print "PyGUI_NSApplication.applicationDidFinishLaunching_"
try:
if not self.files_opened:
self.pygui_app.open_app()
except Exception, e:
self.pygui_app.report_error()
return False

#------------------------------------------------------------------------------

pending_exception = None

def raise_pending_exception():
global pending_exception
exc_type, exc_value, exc_tb = pending_exception
pending_exception = None
raise exc_type, exc_value, exc_tb

def create_ns_application():
global ns_application
ns_application = _PyGui_NSApplication.sharedApplication()
ns_application.setDelegate_(ns_application)

ns_screen_height = NSScreen.mainScreen().frame().size.height

#------------------------------------------------------------------------------

# Disable this for now, since MachSignals.signal segfaults. :-(
#
#def _install_sigint_handler():
# print "_install_sigint_handler" ###
# from Foundation import NSRunLoop
# run_loop = NSRunLoop.currentRunLoop()
# if not run_loop:
# print "...No current run loop" ###
# sys.exit(1) ###
# MachSignals.signal(signal.SIGINT, _sigint_handler)
# #from PyObjCTools.AppHelper import installMachInterrupt
# #installMachInterrupt()
# print "...done" ###
#
#def _sigint_handler(signum):
# print "_sigint_handler" ###
# raise KeyboardInterrupt

#def _install_sigint_handler():
# import signal
# signal.signal(signal.SIGINT, _raise_keyboard_interrupt)
#
#def _raise_keyboard_interrupt(signum, frame):
# raise KeyboardInterrupt

#_install_sigint_handler()
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

ANN: PyGUI 1.7.2 0
ANN: PyGUI 1.7.1 0
ANN: PyGUI Mailing List 2
ANN: PyGUI 1.4 0
ANN: PyGUI 1.5.1 0
ANN: PyGUI 1.7 0
ANN: PyGUI 1.6 1
ANN: PyGUI 1.5 0

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top