mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
New examples by Tony Ingraldi, using dns-lookup in stead of the funny interslip
module.
This commit is contained in:
parent
43fd1f75db
commit
2450a25fcd
12 changed files with 241 additions and 333 deletions
|
@ -1,5 +1,6 @@
|
|||
<HTML><HEAD><TITLE>Using python to create Macintosh applications, part one</TITLE></HEAD>
|
||||
<BODY>
|
||||
|
||||
<H1>Using python to create Macintosh applications, part one</H1>
|
||||
<HR>
|
||||
|
||||
|
@ -8,34 +9,26 @@ application using Python. We will glance at how to use dialogs and
|
|||
resources. <p>
|
||||
|
||||
The example application we look at will be a simple program with a
|
||||
dialog that allows you to control and monitor InterSLIP, a device
|
||||
driver that connects your mac to the Internet via a modem connection.
|
||||
<A HREF="example1/InterslipControl-1.py">Source</A> and resource file
|
||||
(in binary and <A
|
||||
HREF="example1/InterslipControl-1.rsrc.hqx">BinHex</A> form for
|
||||
downloading) for this application are available in the <A
|
||||
dialog that allows you to perform domain name lookups on IP addresses
|
||||
and hostnames.
|
||||
The <A HREF="example1/dnslookup-1.py">source code</A> and
|
||||
<A HREF="example1/dnslookup-1.rsrc">resource file</A>
|
||||
for this application are available in the <A
|
||||
HREF="example1">example1</A> folder (which you will have to download
|
||||
if you are reading this document over the net and if you want to look
|
||||
at the resources). <p>
|
||||
|
||||
We will use a C extension module module "interslip" that allows a
|
||||
Python program to control and monitor the behaviour of the low-level
|
||||
driver, and we will create the user interface around that. If you want
|
||||
to actually run the code, you will obvously need InterSLIP and the
|
||||
interslip module. The latter is available as a dynamically loadable
|
||||
extension for PowerPC/cfm68k Pythons, and may be compiled in your static 68K
|
||||
Python. As of this writing there is still a slight
|
||||
problem with the Python interslip module causing it to say "file not
|
||||
found" if the driver is not loaded yet. The workaround is to load the
|
||||
driver by starting InterSLIP Control and quitting it. <p>
|
||||
We will use the builtin module "socket" that allows a
|
||||
Python program to perform all sorts of networking functions, and we
|
||||
will create the user interface around that. You should be able to run
|
||||
the sample code with the standard Python distribution.<p>
|
||||
|
||||
<CITE>
|
||||
If you are interested in building your own extensions to python you
|
||||
should check out the companion document <A
|
||||
HREF="plugins.html">Creating Macintosh Python C extensions</A>,
|
||||
which tells you how to build your own C extension. Not completely
|
||||
coincidental this document uses the interslip module that we will use
|
||||
here as an example. <p>
|
||||
which tells you how to build your own C extension.
|
||||
<p>
|
||||
</CITE>
|
||||
|
||||
<H2><A NAME="dialog-resources">Creating dialog resources</A></H2>
|
||||
|
@ -62,19 +55,24 @@ conflicts arise: once you have opened your resource file any attempt
|
|||
by the interpreter to open a dialog will also search your resource
|
||||
file. <p>
|
||||
|
||||
Okay, let's have a look at InterslipControl-1.rsrc, our resource file.
|
||||
Okay, let's have a look at dnslookup-1.rsrc, our resource file.
|
||||
The DLOG and accompanying DITL resource both have number 512. Since
|
||||
ResEdit creates both with default ID=128 you should take care to
|
||||
change the number on both. The dialog itself is pretty basic: four
|
||||
buttons (connect, disconnect, update status and quit), two labels and
|
||||
two status fields. <p>
|
||||
change the number on both. The dialog itself is pretty basic: two
|
||||
buttons (Lookup and Quit), two labels and
|
||||
two text entry areas, one of which is used for output only. Here's what
|
||||
the dialog will look like at run time<p>
|
||||
<div align=center>
|
||||
<img width=324 height=189 src="example1/dnslookup-1.gif" alt="dialog image">
|
||||
</div>
|
||||
<p>
|
||||
|
||||
<H2><A NAME="modal-dialog">An application with a modal dialog</A></H2>
|
||||
|
||||
Next, we will have to write the actual application. For this example,
|
||||
we will use a modal dialog. This means that we will put up the dialog
|
||||
and go into a loop asking the dialog manager for events (buttons
|
||||
pushed). We handle the actions requested by the user until the quit
|
||||
pushed). We handle the actions requested by the user until the Quit
|
||||
button is pressed, upon which we exit our loop (and the program). This
|
||||
way of structuring your program is actually rather antisocial, since
|
||||
you force the user to do whatever you, the application writer, happen
|
||||
|
@ -86,8 +84,8 @@ answer because the data you needed was obscured by the dialog itself?
|
|||
In the next example we will look at an application that does pretty
|
||||
much the same as this one but in a more user-friendly way. <p>
|
||||
|
||||
On to the code itself, in file <A
|
||||
HREF="example1/InterslipControl-1.py"> InterslipControl-1.py</A>. Have
|
||||
The code itself is contained in the file <A
|
||||
HREF="example1/dnslookup-1.py"> dnslookup-1.py</A>. Have
|
||||
a copy handy before you read on. The file starts off with a
|
||||
textstring giving a short description. Not many tools do anything with
|
||||
this as yet, but at some point in the future we <EM>will</EM> have all
|
||||
|
@ -122,39 +120,29 @@ as in <CODE>print Res.OpenResFile.__doc__</CODE>
|
|||
Similarly, <A NAME="dlg"><CODE>Dlg</CODE></A> is an interface to the
|
||||
Dialog manager (with Dialogs being implemented as python objects and
|
||||
routines with Dialog arguments being methods). The sys module you
|
||||
know, I hope. <A NAME="interslip"><CODE>Interslip</CODE></A>,
|
||||
finally, is the module with the interface to the InterSLIP driver. We
|
||||
use four calls from it:
|
||||
know, I hope. The string module is an often used module that enables
|
||||
you to perform many string related operations. In this case however, we
|
||||
are only using the "digits" constant from the string module. We could
|
||||
have simply defined "digits" as "0123456789". The socket module enables
|
||||
us to perform the domain name lookups. We
|
||||
use two calls from it:
|
||||
<UL>
|
||||
<LI> <CODE>open()</CODE>
|
||||
opens the driver
|
||||
<LI> <CODE>connect()</CODE>
|
||||
asks it to initiate a connection procedure (without waiting)
|
||||
<LI> <CODE>disconnect()</CODE>
|
||||
asks it to initiate a disconnection procedure (without waiting)
|
||||
<LI> <CODE>status()</CODE>
|
||||
returns the current connection status in the form of an integer state,
|
||||
an integer "message sequence number" and a message string.
|
||||
<LI> <CODE>gethostbyaddr()</CODE>
|
||||
returns the hostname associated with an IP address
|
||||
<LI> <CODE>gethostbyname()</CODE>
|
||||
returns the IP address associated with a hostname
|
||||
</UL>
|
||||
|
||||
Next in the source file we get definitions for our dialog resource
|
||||
number and for the item numbers in our dialog. These should match the
|
||||
situation in our resource file InterslipControl-1.rsrc,
|
||||
obviously. Then we get an array converting numeric state codes
|
||||
returned by <CODE>interslip.status()</CODE> to textual messages. <p>
|
||||
situation in our resource file dnslookup-1.rsrc,
|
||||
obviously.<p>
|
||||
|
||||
On to the main program. We start off with opening our resource file,
|
||||
which should live in the same folder as the python source. If we
|
||||
cannot open it we use <CODE>EasyDialogs</CODE> to print a message and
|
||||
exit. You can try it: just move the resource file somewhere else for a
|
||||
moment. Then, we try to open the interslip driver, again catching an
|
||||
error. All modules that raise <A NAME="macos-errors">MacOS error
|
||||
exceptions</A> will pass a 2-tuple to the exception handler with the
|
||||
first item being the numeric <CODE>OSErr</CODE> code and the second
|
||||
one being an informative message. If no informative message is
|
||||
available it will be the rather uninformative <CODE>"MacOS Error
|
||||
-12345"</CODE>, but at least the second item will always be a
|
||||
printable string. Finally we call do_dialog() to do the real work. <p>
|
||||
moment. Then we call do_dialog() to do the real work. <p>
|
||||
|
||||
<CODE>Do_dialog()</CODE> uses <CODE>Dlg.GetNewDialog()</CODE> to open
|
||||
a dialog window initialized from 'DLOG' resource ID_MAIN and putting
|
||||
|
@ -166,13 +154,12 @@ slightly more complicated things also, like the user typing into
|
|||
simple textfields, but it will <EM>not</EM> do things like updating
|
||||
the physical appearance of radio buttons, etc. See Inside Mac or
|
||||
another programming guide for how to handle this
|
||||
yourself. Fortunately, our simple application doesn't have to bother
|
||||
with this, since buttons are the only active elements we have. So, we
|
||||
do a simple switch on item number and call the appropriate routine to
|
||||
implement the action requested. Upon the user pressing "quit" we
|
||||
simply leave the loop and, hence, <CODE>do_dialog()</CODE>. This will
|
||||
cause the python dialog object <CODE>my_dlg</CODE> to be deleted and
|
||||
the on-screen dialog to disappear. <p>
|
||||
yourself. Fortunately, our simple application doesn't have to bother with this,
|
||||
since buttons and textfields are the only active elements we have. So, we do a
|
||||
simple switch on item number and call the appropriate routine to implement the
|
||||
action requested. Upon the user pressing "Quit" we simply leave the loop and,
|
||||
hence, <CODE>do_dialog()</CODE>. This will cause the python dialog object
|
||||
<CODE>my_dlg</CODE> to be deleted and the on-screen dialog to disappear. <p>
|
||||
|
||||
<A NAME="dialog-warning">Time for a warning</A>: be very careful what
|
||||
you do as long as a dialog is on-screen. Printing something, for
|
||||
|
@ -183,8 +170,8 @@ may or may not work in this situation. I have also seen crashes in
|
|||
such a situation, probably due to the multiple event loops involved or
|
||||
some oversight in the interpreter. You have been warned. <p>
|
||||
|
||||
The implementation of the "update status" command can use a bit more
|
||||
explaining: we get the new information with <CODE>do_status()</CODE>
|
||||
The implementation of the "Lookup" command can use a bit more
|
||||
explaining: we get the necessary information with <CODE>dnslookup()</CODE>
|
||||
but now we have to update the on-screen dialog to present this
|
||||
information to the user. The <CODE>GetDialogItem()</CODE> method of
|
||||
the dialog returns three bits of information about the given item: its
|
||||
|
@ -195,18 +182,12 @@ here that python programmers need not bother with the C-string versus
|
|||
pascal-string controversy: the python glue module knows what is needed
|
||||
and converts the python string to the correct type. <p>
|
||||
|
||||
Finally, the three implementation routines <CODE>do_connect()</CODE>,
|
||||
<CODE>do_disconnect()</CODE> and <CODE>do_status()</CODE> are simply
|
||||
boring wrappers around the corresponding interslip methods that will
|
||||
put up a dialog in case of an error. <p>
|
||||
|
||||
And that concludes our first example of the use of resources and
|
||||
dialogs. Next, you could have a look at the source of EasyDialogs for
|
||||
some examples of using input fields and filterprocs. Or, go on with
|
||||
reading the <A HREF="example2.html">second part</A> of this document
|
||||
to see how to implement a better version of this application. Not only
|
||||
will it allow the user to go back to the finder (or other apps) when
|
||||
your application is running, it will also free her of the RSI-inducing
|
||||
chore of pressing "update status" continuously... <p>
|
||||
to see how to implement a better version of this application.<p>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
"""Sample program handling InterSLIP control and showing off EasyDialogs,
|
||||
Res and Dlg in the process"""
|
||||
|
||||
import EasyDialogs
|
||||
import Res
|
||||
import Dlg
|
||||
import sys
|
||||
import interslip
|
||||
#
|
||||
# Definitions for our resources
|
||||
ID_MAIN=512
|
||||
|
||||
ITEM_CONNECT=1
|
||||
ITEM_DISCONNECT=2
|
||||
ITEM_UPDATE=3
|
||||
ITEM_QUIT=4
|
||||
ITEM_STATUS=5
|
||||
ITEM_MESSAGE=6
|
||||
|
||||
status2text = ["<idle>", "<wait-modem>", "<dialling>", "<logging in>",
|
||||
"<connected>", "<disconnecting>"]
|
||||
|
||||
|
||||
def main():
|
||||
"""Main routine: open resourcefile, open interslip, call dialog handler"""
|
||||
try:
|
||||
Res.OpenResFile("InterslipControl-1.rsrc")
|
||||
except Res.Error, arg:
|
||||
EasyDialogs.Message("Cannot open resource file InterslipControl-1.rsrc: "+
|
||||
arg[1])
|
||||
sys.exit(1)
|
||||
try:
|
||||
interslip.open()
|
||||
except interslip.error, arg:
|
||||
EasyDialogs.Message("Cannot open interslip: "+arg[1])
|
||||
sys.exit(1)
|
||||
do_dialog()
|
||||
|
||||
def do_dialog():
|
||||
"""Post dialog and handle user interaction until quit"""
|
||||
my_dlg = Dlg.GetNewDialog(ID_MAIN, -1)
|
||||
while 1:
|
||||
n = Dlg.ModalDialog(None)
|
||||
if n == ITEM_CONNECT:
|
||||
do_connect()
|
||||
elif n == ITEM_DISCONNECT:
|
||||
do_disconnect()
|
||||
elif n == ITEM_UPDATE:
|
||||
status, msg = do_status()
|
||||
|
||||
# Convert status number to a text string
|
||||
try:
|
||||
txt = status2text[status]
|
||||
except IndexError:
|
||||
txt = "<unknown state %d>"%status
|
||||
|
||||
# Set the status text field
|
||||
tp, h, rect = my_dlg.GetDialogItem(ITEM_STATUS)
|
||||
Dlg.SetDialogItemText(h, txt)
|
||||
|
||||
# Set the message text field
|
||||
tp, h, rect = my_dlg.GetDialogItem(ITEM_MESSAGE)
|
||||
Dlg.SetDialogItemText(h, msg)
|
||||
elif n == ITEM_QUIT:
|
||||
break
|
||||
|
||||
def do_connect():
|
||||
"""Connect, posting error message in case of failure"""
|
||||
try:
|
||||
interslip.connect()
|
||||
except interslip.error, arg:
|
||||
EasyDialogs.Message("Cannot connect: "+arg[1])
|
||||
|
||||
def do_disconnect():
|
||||
"""Disconnect, posting error message in case of failure"""
|
||||
try:
|
||||
interslip.disconnect()
|
||||
except interslip.error, arg:
|
||||
EasyDialogs.Message("Cannot disconnect: "+arg[1])
|
||||
|
||||
def do_status():
|
||||
"""Get status as (state_index, message),
|
||||
posting error message in case of failure"""
|
||||
try:
|
||||
status, msgnum, msg = interslip.status()
|
||||
except interslip.error, arg:
|
||||
EasyDialogs.Message("Cannot get status: "+arg[1])
|
||||
return 0, ''
|
||||
return status, msg
|
||||
|
||||
|
||||
main()
|
Binary file not shown.
BIN
Mac/Demo/example1/dnslookup-1.gif
Normal file
BIN
Mac/Demo/example1/dnslookup-1.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
61
Mac/Demo/example1/dnslookup-1.py
Normal file
61
Mac/Demo/example1/dnslookup-1.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
"""Sample program performing domain name lookups and showing off EasyDialogs,
|
||||
Res and Dlg in the process"""
|
||||
|
||||
import EasyDialogs
|
||||
import Res
|
||||
import Dlg
|
||||
import sys
|
||||
import socket
|
||||
import string
|
||||
#
|
||||
# Definitions for our resources
|
||||
ID_MAIN=512
|
||||
|
||||
ITEM_LOOKUP_ENTRY=1
|
||||
ITEM_RESULT=2
|
||||
ITEM_LOOKUP_BUTTON=3
|
||||
ITEM_QUIT_BUTTON=4
|
||||
|
||||
|
||||
def main():
|
||||
"""Main routine: open resource file, call dialog handler"""
|
||||
try:
|
||||
Res.OpenResFile("dnslookup-1.rsrc")
|
||||
except Res.Error:
|
||||
EasyDialogs.Message("Cannot open dnslookup-1.rsrc")
|
||||
sys.exit(1)
|
||||
do_dialog()
|
||||
|
||||
def do_dialog():
|
||||
"""Post dialog and handle user interaction until quit"""
|
||||
my_dlg = Dlg.GetNewDialog(ID_MAIN, -1)
|
||||
while 1:
|
||||
n = Dlg.ModalDialog(None)
|
||||
if n == ITEM_LOOKUP_BUTTON:
|
||||
tp, h, rect = my_dlg.GetDialogItem(ITEM_LOOKUP_ENTRY)
|
||||
txt = Dlg.GetDialogItemText(h)
|
||||
|
||||
tp, h, rect = my_dlg.GetDialogItem(ITEM_RESULT)
|
||||
Dlg.SetDialogItemText(h, dnslookup(txt))
|
||||
elif n == ITEM_QUIT_BUTTON:
|
||||
break
|
||||
|
||||
def dnslookup(str):
|
||||
""" Perform DNS lookup on str. If first character of digit is numeric,
|
||||
assume that str contains an IP address. Otherwise, assume that str
|
||||
contains a hostname."""
|
||||
if str == '': str = ' '
|
||||
if str[0] in string.digits:
|
||||
try:
|
||||
value = socket.gethostbyaddr(str)[0]
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
else:
|
||||
try:
|
||||
value = socket.gethostbyname(str)
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
return value
|
||||
|
||||
main()
|
||||
|
BIN
Mac/Demo/example1/dnslookup-1.rsrc
Normal file
BIN
Mac/Demo/example1/dnslookup-1.rsrc
Normal file
Binary file not shown.
|
@ -6,52 +6,51 @@
|
|||
In this document we rewrite the application of the <A
|
||||
HREF="example1.html">previous example</A> to use modeless dialogs. We
|
||||
will use an application framework, and we will have a look at creating
|
||||
applets, standalone applications written in Python. <A
|
||||
HREF="example2/InterslipControl-2.py">Source</A> and resource file (in
|
||||
binary and <A HREF="example2/InterslipControl-2.rsrc.hqx">BinHex</A>
|
||||
form for downloading) are available in the folder <A
|
||||
HREF="example2">example2</A>. <p>
|
||||
applets, standalone applications written in Python. The <A
|
||||
HREF="example2/dnslookup-2.py">source code</A> and
|
||||
<A HREF="example2/dnslookup-2.rsrc">resource file</A> are available in the folder
|
||||
<A HREF="example2">example2</A>. <p>
|
||||
|
||||
Again, we start with ResEdit to create our dialogs. Not only do we
|
||||
want a main dialog this time but also an "About" dialog, and we
|
||||
provide the <A NAME="bundle">BNDL resource</A> and related stuff that
|
||||
an application cannot be without. (Actually, a python applet can be
|
||||
without, <A HREF="#no-bundle">see below</A>). "Inside Mac" or various
|
||||
books on macintosh programming will help here. Also, you can refer to
|
||||
want a main dialog this time but also an "About" dialog. This example is less
|
||||
than complete since we do not provide a <A NAME="bundle">BNDL resource</A>
|
||||
and related stuff that an application cannot be without. We are able to do this
|
||||
when building a python applet since BuildApplet will substitute default resources
|
||||
for BNDL, etc. when none are supplied (<A HREF="#no-bundle">See below</A>.)
|
||||
"Inside Mac" or various
|
||||
books on Macintosh programming will help here. Also, you can refer to
|
||||
the resource files provided in the Python source distribution for some
|
||||
of the python-specific points of BNDL programming: the
|
||||
"appletbundle.rsrc" file is what is used for creating applets if you
|
||||
don't provide your own resource file. <p>
|
||||
|
||||
Let's have a look at InterslipControl-2.rsrc, our resource file. First
|
||||
off, there's the standard BNDL combo. I've picked 'PYTi' as signature
|
||||
for the application. I tend to pick PYT plus one lower-case letter for
|
||||
my signatures. The finder gets confused if you have two applications
|
||||
with the same signature. This may be due to some incorrectness on the
|
||||
side of "BuildApplet", I am not sure. There is one case when you
|
||||
definitely need a unique signature: when you create an applet that has
|
||||
its own data files and you want the user to be able to start your
|
||||
When creating your own BNDL resouorces, keep in mind that the Finder gets
|
||||
confused if you have more than one application with the same signature. This may be due
|
||||
to some incorrectness on the side of "BuildApplet", I am not sure. There is one
|
||||
case when you definitely need a unique signature: when you create an applet that
|
||||
has its own data files and you want the user to be able to start your
|
||||
applet by double-clicking one of the datafiles. <p>
|
||||
|
||||
There's little to tell about the BNDL stuff: I basically copied the
|
||||
generic Python applet icons and pasted in the symbol for
|
||||
InterSLIP. The two dialogs are equally unexciting: dialog 512 is our
|
||||
main window which has four static text fields (two of which we will be
|
||||
modifying during runtime, to show the status of the connection) and
|
||||
two buttons "connect" and "disconnect". The "quit" and "update status"
|
||||
buttons have disappeared, because they are handled by a menu choice
|
||||
and automatically, respectively. <p>
|
||||
Let's have a look at dnslookup-2.rsrc, our resource file. Dialog 512 is the
|
||||
main window which has one button (Lookup), two labels and
|
||||
two text entry areas, one of which is used for output only. The "Quit" and
|
||||
button has disappeared, because its function is handled by a menu choice. Here's
|
||||
what it will look like at run time:<p>
|
||||
<div align=center>
|
||||
<img width=324 height=205 src="example2/dnslookup-2.gif" alt="dialog image">
|
||||
</div>
|
||||
<p>
|
||||
|
||||
<H2>A modeless dialog application using FrameWork</H2>
|
||||
|
||||
On to the source code in <A
|
||||
HREF="example2/InterslipControl-2.py">InterslipControl-2.py</A>. The
|
||||
HREF="example2/dnslookup-2.py">dnslookup-2.py</A>. The
|
||||
start is similar to our previous example program <A
|
||||
HREF="example1/InterslipControl-1.py">InterSlipControl-1.py</A>, with
|
||||
HREF="example1/dnslookup-1.py">dnslookup-1.py</A>, with
|
||||
one extra module being imported. To make life more simple we will use
|
||||
the <CODE>FrameWork</CODE> module, a nifty piece of code that handles
|
||||
all the gory mac details of event loop programming, menubar
|
||||
installation and all the other code that is the same for every mac
|
||||
all the gory Mac details of event loop programming, menubar
|
||||
installation and all the other code that is the same for every Mac
|
||||
program in the world. Like most standard modules, FrameWork will run
|
||||
some sample test code when you invoke it as a main program, so try it
|
||||
now. It will create a menu bar with an Apple menu with the about box
|
||||
|
@ -68,7 +67,7 @@ also continue with this document.
|
|||
|
||||
After the imports we get the definitions of resource-IDs in our
|
||||
resource file, slightly changed from the previous version of our
|
||||
program, and the state to string mapping. The main program is also
|
||||
program. The main program is also
|
||||
similar to our previous version, with one important exception: we
|
||||
first check to see whether our resource is available before opening
|
||||
the resource file. Why is this? Because later, when we will have
|
||||
|
@ -77,13 +76,13 @@ the applet file and we don't need the separate resource file
|
|||
anymore. <p>
|
||||
|
||||
Next comes the definition of our main class,
|
||||
<CODE>InterslipControl</CODE>, which inherits
|
||||
<CODE>DNSLookup</CODE>, which inherits
|
||||
<CODE>FrameWork.Application</CODE>. The Application class handles the
|
||||
menu bar and the main event loop and event dispatching. In the
|
||||
<CODE>__init__</CODE> routine we first let the base class initialize
|
||||
itself, then we create our modeless dialog and finally we jump into
|
||||
the main loop. The main loop continues until we call <CODE>self._quit</CODE>,
|
||||
which we will do when the user selects "quit". When we create
|
||||
which we will do when the user selects "Quit". When we create
|
||||
the instance of <CODE>MyDialog</CODE> (which inherits
|
||||
<CODE>DialogWindow</CODE>, which inherits <CODE>Window</CODE>) we pass
|
||||
a reference to the application object, this reference is used to tell
|
||||
|
@ -104,31 +103,17 @@ familiar to you from the previous example program. That do_about is
|
|||
called when the user selects About from the Apple menu is, again,
|
||||
taken care of by the __init__ routine of Application. <p>
|
||||
|
||||
Our main object finally overrides <CODE>idle()</CODE>, the method
|
||||
called when no event is available. It passes the call on to our dialog
|
||||
object to give it a chance to update the status fields, if needed. <p>
|
||||
|
||||
The <CODE>MyDialog</CODE> class is the container for our main
|
||||
window. Initialization is again done by first calling the base class
|
||||
<CODE>__init__</CODE> function and finally setting two local variables
|
||||
that are used by <CODE>updatestatus()</CODE> later. <p>
|
||||
<CODE>__init__</CODE> function and finally setting the local variable
|
||||
"parent." <p>
|
||||
|
||||
<CODE>Do_itemhit()</CODE> is called when an item is selected in this
|
||||
dialog by the user. We are passed the item number (and the original
|
||||
event structure, which we normally ignore). The code is similar to the
|
||||
main loop of our previous example program: a switch depending on the
|
||||
item selected. <CODE>Connect()</CODE> and <CODE>disconnect()</CODE>
|
||||
are again quite similar to our previous example. <p>
|
||||
|
||||
<CODE>Updatestatus()</CODE> is different, however. It is now
|
||||
potentially called many times per second instead of only when the
|
||||
user presses a button we don't want to update the display every time
|
||||
since that would cause some quite horrible flashing. Luckily,
|
||||
<CODE>interslip.status()</CODE> not only provides us with a state and
|
||||
a message but also with a message sequence number. If neither state
|
||||
nor message sequence number has changed since the last call there is
|
||||
no need to update the display, so we just return. For the rest,
|
||||
nothing has changed. <p>
|
||||
item selected. <CODE>Dnslookup()</CODE> is quite similar to our previous
|
||||
example. <p>
|
||||
|
||||
<H2><IMG SRC="html.icons/mkapplet.gif"><A NAME="applets">Creating applets</A></H2>
|
||||
|
||||
|
@ -158,13 +143,8 @@ resources from that file will be copied to your applet too. If there
|
|||
is no resource file for your script a set of default resources will be
|
||||
used, and the applet will have the default creator 'Pyt0'. The latter
|
||||
also happens if you do have a resource file but without the BNDL
|
||||
combo. <A NAME="no-bundle">Actually</A>, for our example that would
|
||||
have been the most logical solution, since our applet does not have
|
||||
its own data files. It would have saved us hunting for an unused
|
||||
creator code. The only reason for using the BNDL in this case is
|
||||
having the custom icon, but that could have been done by pasting an
|
||||
icon on the finder Info window, or by providing an custon icon in your
|
||||
resource file and setting the "custom icon" finder bit. <p>
|
||||
combo. <A NAME="no-bundle">Actually</A>, as in the present example.
|
||||
<p>
|
||||
|
||||
If you need slightly more control over the BuildApplet process you can
|
||||
double-click it, and you will get dialogs for source and
|
||||
|
@ -178,3 +158,5 @@ interpreter still work. <p>
|
|||
|
||||
That's all for this example, you may now return to the <A HREF="index.html">
|
||||
table of contents</A> to pick another topic. <p>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
|
|
@ -1,116 +0,0 @@
|
|||
import FrameWork
|
||||
import EasyDialogs
|
||||
import Res
|
||||
import Dlg
|
||||
import sys
|
||||
import interslip
|
||||
#
|
||||
# Definitions for our resources
|
||||
ID_MAIN=512
|
||||
ID_ABOUT=513
|
||||
|
||||
ITEM_CONNECT=1
|
||||
ITEM_DISCONNECT=2
|
||||
ITEM_STATUS=3
|
||||
ITEM_MESSAGE=4
|
||||
|
||||
status2text = ["<idle>", "<wait-modem>", "<dialling>", "<logging in>",
|
||||
"<connected>", "<disconnecting>"]
|
||||
|
||||
def main():
|
||||
try:
|
||||
interslip.open()
|
||||
except interslip.error, arg:
|
||||
EasyDialogs.Message("Cannot open interslip: "+arg[1])
|
||||
sys.exit(1)
|
||||
try:
|
||||
dummy = Res.GetResource('DLOG', ID_MAIN)
|
||||
except Res.Error:
|
||||
try:
|
||||
Res.OpenResFile("InterslipControl-2.rsrc")
|
||||
except Res.error:
|
||||
EasyDialogs.Message("Cannot open InterslipControl-2.rsrc: "+arg[1])
|
||||
sys.exit(1)
|
||||
InterslipControl()
|
||||
|
||||
class InterslipControl(FrameWork.Application):
|
||||
"Application class for InterslipControl"
|
||||
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
# Next create our dialog
|
||||
self.main_dialog = MyDialog(self)
|
||||
# Now open the dialog
|
||||
self.main_dialog.open(ID_MAIN)
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def do_about(self, *args):
|
||||
f = Dlg.GetNewDialog(ID_ABOUT, -1)
|
||||
while 1:
|
||||
n = Dlg.ModalDialog(None)
|
||||
if n == 1:
|
||||
return
|
||||
|
||||
def idle(self, event):
|
||||
"Idle routine - update status"
|
||||
self.main_dialog.updatestatus()
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for InterslipControl"
|
||||
def __init__(self, parent):
|
||||
FrameWork.DialogWindow.__init__(self, parent)
|
||||
self.last_status = None
|
||||
self.last_msgnum = None
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == ITEM_DISCONNECT:
|
||||
self.disconnect()
|
||||
elif item == ITEM_CONNECT:
|
||||
self.connect()
|
||||
|
||||
def connect(self):
|
||||
try:
|
||||
interslip.connect()
|
||||
except interslip.error, arg:
|
||||
EasyDialogs.Message("Cannot connect: "+arg[1])
|
||||
|
||||
def disconnect(self):
|
||||
try:
|
||||
interslip.disconnect()
|
||||
except interslip.error, arg:
|
||||
EasyDialogs.Message("Cannot disconnect: "+arg[1])
|
||||
|
||||
def updatestatus(self):
|
||||
try:
|
||||
status, msgnum, msg = interslip.status()
|
||||
except interslip.error, arg:
|
||||
EasyDialogs.Message("Cannot get status: "+arg[1])
|
||||
sys.exit(1)
|
||||
if status == self.last_status and msgnum == self.last_msgnum:
|
||||
return
|
||||
self.last_status = status
|
||||
self.last_msgnum = msgnum
|
||||
if msgnum == 0:
|
||||
msg = ''
|
||||
|
||||
try:
|
||||
txt = status2text[status]
|
||||
except IndexError:
|
||||
txt = "<unknown state %d>"%status
|
||||
|
||||
tp, h, rect = self.wid.GetDialogItem(ITEM_STATUS)
|
||||
Dlg.SetDialogItemText(h, txt)
|
||||
|
||||
tp, h, rect = self.wid.GetDialogItem(ITEM_MESSAGE)
|
||||
Dlg.SetDialogItemText(h, msg)
|
||||
|
||||
main()
|
Binary file not shown.
BIN
Mac/Demo/example2/dnslookup-2.gif
Normal file
BIN
Mac/Demo/example2/dnslookup-2.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
92
Mac/Demo/example2/dnslookup-2.py
Normal file
92
Mac/Demo/example2/dnslookup-2.py
Normal file
|
@ -0,0 +1,92 @@
|
|||
import FrameWork
|
||||
import EasyDialogs
|
||||
import Res
|
||||
import Dlg
|
||||
import sys
|
||||
import socket
|
||||
import string
|
||||
#
|
||||
# Definitions for our resources
|
||||
ID_MAIN=512
|
||||
ID_ABOUT=513
|
||||
|
||||
ITEM_LOOKUP_ENTRY=1
|
||||
ITEM_RESULT=2
|
||||
ITEM_LOOKUP_BUTTON=3
|
||||
|
||||
def main():
|
||||
try:
|
||||
dummy = Res.GetResource('DLOG', ID_MAIN)
|
||||
except Res.Error:
|
||||
try:
|
||||
Res.OpenResFile("dnslookup-2.rsrc")
|
||||
except Res.Error:
|
||||
EasyDialogs.Message("Cannot open dnslookup-2.rsrc")
|
||||
sys.exit(1)
|
||||
DNSLookup()
|
||||
|
||||
class DNSLookup(FrameWork.Application):
|
||||
"Application class for DNS Lookup"
|
||||
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
# Next create our dialog
|
||||
self.main_dialog = MyDialog(self)
|
||||
# Now open the dialog
|
||||
self.main_dialog.open(ID_MAIN)
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def do_about(self, *args):
|
||||
f = Dlg.GetNewDialog(ID_ABOUT, -1)
|
||||
while 1:
|
||||
n = Dlg.ModalDialog(None)
|
||||
if n == 1:
|
||||
return
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for DNSLookup"
|
||||
def __init__(self, parent):
|
||||
FrameWork.DialogWindow.__init__(self, parent)
|
||||
self.parent = parent
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == ITEM_LOOKUP_BUTTON:
|
||||
self.dolookup()
|
||||
|
||||
def dolookup(self):
|
||||
"""Get text entered in the lookup entry area. Place result of the
|
||||
call to dnslookup in the result entry area."""
|
||||
tp, h, rect = self.wid.GetDialogItem(ITEM_LOOKUP_ENTRY)
|
||||
txt = Dlg.GetDialogItemText(h)
|
||||
|
||||
tp, h, rect = self.wid.GetDialogItem(ITEM_RESULT)
|
||||
Dlg.SetDialogItemText(h, self.dnslookup(txt))
|
||||
|
||||
def dnslookup(self, str):
|
||||
""" Perform DNS lookup on str. If first character of digit is numeric,
|
||||
assume that str contains an IP address. Otherwise, assume that str
|
||||
contains a hostname."""
|
||||
if str == '': str = ' '
|
||||
if str[0] in string.digits:
|
||||
try:
|
||||
value = socket.gethostbyaddr(str)[0]
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
else:
|
||||
try:
|
||||
value = socket.gethostbyname(str)
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
return value
|
||||
|
||||
|
||||
main()
|
BIN
Mac/Demo/example2/dnslookup-2.rsrc
Normal file
BIN
Mac/Demo/example2/dnslookup-2.rsrc
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue