Skip to content

Commit

Permalink
introduce "ios" python module, with the first "send_email" method tha…
Browse files Browse the repository at this point in the history
…t use MessageUI framework.
  • Loading branch information
tito committed Mar 12, 2012
1 parent 54e0ff7 commit 2f7c173
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 0 deletions.
108 changes: 108 additions & 0 deletions src/ios/ios.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
'''
IOS module
==========
IOS module is wrapping some part of the IOS features.
'''

from python_ref cimport Py_INCREF, Py_DECREF

cdef extern from "ios_wrapper.h":
ctypedef void (*ios_send_email_cb)(char *, void *)
int ios_send_email(char *subject, char *text, char *mimetype, char
*filename, ios_send_email_cb cb, void *userdata)

cdef void _send_email_done(char *status, void *data):
cdef object callback = <object>data
callback(status)
Py_DECREF(callback)


#
# API
#

__version__ = (1, 0, 0)

def send_email(subject, text, mimetype=None, filename=None, callback=None):
'''Send an email using the IOS api.
:Parameters:
`subject`: str
Subject of the email
`text`: str
Content of the email
`mimetype`: str
Mimetype of the attachment if exist
`filename`: str
Full path of the filename to attach, must be used with mimetype.
`callback`: func(status)
Callback that can be called when the email interface have been
removed. A status will be passed as the first argument: "cancelled",
"saved", "sent", "failed", "unknown".
.. note::
The application must have the window created to be able to use that
method. Trying to send an email without the application running will
crash.
Example for sending a simple hello world::
ios.send_email('This is my subject',
'Hello you!\n\nThis is an hello world.')
Send a mail with an attachment::
from os.path import realpath
ios.send_email('Mail with attachment',
'Your attachment will be just after this message.',
mimetype='image/png',
filename=realpath('mylogo.png'))
Getting the status of the mail with the callback
from kivy.app import App
class EmailApp(App):
def callback_email(self, status):
print 'The email have been', status
def send_email(self, *largs):
print 'Sending an email'
ios.send_email('Hello subject', 'World body',
callback=self.callback_email)
def build(self):
btn = Button(text='Click me')
btn.bind(on_release=self.send_email)
return btn
if __name__ == '__main__':
EmailApp().run()
'''
cdef char *j_mimetype = NULL
cdef char *j_filename = NULL
cdef char *j_subject = NULL
cdef char *j_text = NULL
cdef char *j_title = NULL

if subject is not None:
j_subject = <bytes>subject
if text is not None:
j_text = <bytes>text
if mimetype is not None:
j_mimetype = <bytes>mimetype
if filename is not None:
j_filename = <bytes>filename

Py_INCREF(callback)

if ios_send_email(j_subject, j_text, j_mimetype, j_filename,
_send_email_done, <void *>callback) == 0:
callback('failed')
return 0

return 1
106 changes: 106 additions & 0 deletions src/ios/ios_mail.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Email support
*
* Very basic, could be upgraded to support HTML, and multiple attachment. No
* need to let the user manipulate directly uikit API.
*/

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#include "ios_wrapper.h"

/* guess the view controller from our SDL window.
*/
UIViewController *get_viewcontroller(void) {
NSArray *windows = [[UIApplication sharedApplication] windows];
if ( windows == NULL ) {
printf("ios_wrapper: unable to get windows from shared application\n");
return NULL;
}
UIWindow *uiWindow = [windows objectAtIndex:0];
UIView* view = [uiWindow.subviews objectAtIndex:0];
id nextResponder = [view nextResponder];
if( [nextResponder isKindOfClass:[UIViewController class]] )
return (UIViewController *)nextResponder;
return NULL;
}

@interface InAppEmailViewController : UIViewController <MFMailComposeViewControllerDelegate> {
ios_send_email_cb callback;
void * userdata;
}

@property(nonatomic, assign) ios_send_email_cb callback;
@property(nonatomic, assign) void *userdata;

@end

@implementation InAppEmailViewController

@synthesize userdata;
@synthesize callback;

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
UIViewController* viewController = get_viewcontroller();
static char *statuses[] = {"unknown", "cancelled", "saved", "sent", "failed"};

if ( callback != NULL ) {
char *status = statuses[0];
switch (result)
{
case MFMailComposeResultCancelled: status = statuses[1]; break;
case MFMailComposeResultSaved: status = statuses[2]; break;
case MFMailComposeResultSent: status = statuses[3]; break;
case MFMailComposeResultFailed: status = statuses[4]; break;
default: break;
}
callback(status, userdata);
}

[viewController becomeFirstResponder];
[viewController dismissModalViewControllerAnimated:YES];
}

@end

int ios_send_email(char *subject, char *text, char *mimetype, char *filename,
ios_send_email_cb callback, void *userdata)
{

UIViewController* viewController = get_viewcontroller();
if ( viewController == NULL ) {
printf("ios_send_email: unable to get view controller");
return 0;
}

MFMailComposeViewController *controller = [[MFMailComposeViewController alloc] init];
InAppEmailViewController *inAppVc = [[InAppEmailViewController alloc] init];
inAppVc.callback = callback;
inAppVc.userdata = userdata;
controller.mailComposeDelegate = inAppVc;

if ( subject != NULL ) {
NSString *nssubject = [NSString stringWithCString:(char *)subject encoding:NSUTF8StringEncoding];
[controller setSubject:nssubject];
}

if ( text != NULL ) {
NSString *nstext = [NSString stringWithCString:(char *)text encoding:NSUTF8StringEncoding];
[controller setMessageBody:nstext isHTML:NO];
}

if ( mimetype != NULL && filename != NULL ) {
NSString *nsmimetype = [NSString stringWithCString:(char *)mimetype encoding:NSUTF8StringEncoding];
NSString *nsfilename = [NSString stringWithCString:(char *)filename encoding:NSUTF8StringEncoding];
NSData *myData = [NSData dataWithContentsOfFile:nsfilename];
[controller addAttachmentData:myData mimeType:nsmimetype fileName:nsfilename];
}

controller.modalPresentationStyle = UIModalPresentationPageSheet;
[viewController presentModalViewController:controller animated:YES];
[controller release];

return 1;
}

9 changes: 9 additions & 0 deletions src/ios/ios_wrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#ifndef __IOS_WRAPPER
#define __IOS_WRAPPER

typedef void (*ios_send_email_cb)(char *, void *);

int ios_send_email(char *subject, char *text, char *mimetype, char *filename,
ios_send_email_cb callback, void *userdata);

#endif
13 changes: 13 additions & 0 deletions src/ios/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from distutils.core import setup, Extension
import os

setup(name='ios',
version='1.0',
ext_modules=[
Extension(
'ios', ['ios.c', 'ios_mail.m'],
libraries=[ ],
library_dirs=[],
)
]
)
1 change: 1 addition & 0 deletions tools/build-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

try $(dirname $0)/build-python.sh
try $(dirname $0)/reduce-python.sh
try $(dirname $0)/build-ios.sh
try $(dirname $0)/build-sdl.sh
try $(dirname $0)/build-freetype.sh
try $(dirname $0)/build-sdlttf.sh
Expand Down
28 changes: 28 additions & 0 deletions tools/build-ios.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

. $(dirname $0)/environment.sh

OLD_CC="$CC"
OLD_LDFLAGS="$LDFLAGS"
OLD_LDSHARED="$LDSHARED"
export CC="$ARM_CC -I$BUILDROOT/include"
export LDFLAGS="$ARM_LDFLAGS"
export LDSHARED="$KIVYIOSROOT/tools/liblink"

try pushd $KIVYIOSROOT/src/ios
HOSTPYTHON=$TMPROOT/Python-$PYTHON_VERSION/hostpython
try cython *.pyx
try $HOSTPYTHON setup.py build_ext
try $HOSTPYTHON setup.py install -O2 --root iosbuild
try find iosbuild | grep -E '*\.(py|pyc|so\.o|so\.a|so\.libs)$$' | xargs rm
try rm -rdf "$BUILDROOT/python/lib/python2.7/site-packages/ios*"
try cp iosbuild/usr/local/lib/python2.7/site-packages/ios.so "$BUILDROOT/python/lib/python2.7/site-packages"
popd

export CC="$OLD_CC"
export LDFLAGS="$OLD_LDFLAGS"
export LDSHARED="$OLD_LDSHARED"

bd=$KIVYIOSROOT/src/ios/build/lib.macosx-*/
try $KIVYIOSROOT/tools/biglink $BUILDROOT/lib/libios.a $bd
deduplicate $BUILDROOT/lib/libios.a

0 comments on commit 2f7c173

Please sign in to comment.