📄 appuifwmodule.cpp
字号:
/*
* ====================================================================
* appuifwmodule.cpp
*
* Python API to Series 60 application UI framework facilities
*
* Implements currently (16.03.05) following Python types and functions:
*
* Application (an implicit instance "app" always present)
* unicode full_name()
* set_tabs(list<unicode>, callable)
* activate_tab(int)
* set_exit()
* callable exit_key_handler
* list<tuple<unicode, callable>> menu
* ui_control body
* unicode title
* mode screen
* callable(focus) focus
* layout(int)
*
* Listbox
* Listbox(list<unicode OR tuple<unicode, unicode>>, callable)
* int current()
* set_list(list<unicode OR tuple<unicode, unicode>>, [int])
* bind(event_code, callable)
*
* Form
* Form(list<tuple<unicode, string, unicode>>, int)
* execute()
* add_menu_item()
* insert(), pop(), sequence methods: length, item, assignment
*
* Text
* unicode get()
* set(unicode)
* add(unicode)
* int len()
* clear()
* set_pos(int)
* int get_pos()
* bind(event_code, callable)
* bool focus
* attributes:
* focus
* style
* color
* highlight_color
* font
*
* Canvas
* line((x1,y1),(x2,y2),(r,g,b))
* - draw line from (x1,y1) to (x2,y2) with color (r,g,b)
* rectfill((x1,y1),(x2,y2),(r,g,b))
* - fill rectangle with corners at (x1,y1) and (x2,y2) with color (r,g,b)
* clear([(r,g,b)])
* - clear entire canvas to white or to given color
* text((x,y),unicode,(r,g,b))
* - draw text to (x,y) with given color
* bind(event_code, callable)
* CObject _ccoecontrol()
* - return the pointer to the canvas CCoeControl as CObject
* attributes:
* draw (read/write)
* - called when refreshing the display is needed with parameters:
* (Canvas,((x1,y1),(x2,y2)))
* resize (read/write)
* - called when the canvas is resized with Canvas as parameter
*
* Content_handler
* Content_handler([callable])
* open(unicode OR string)
* open_standalone(unicode OR string)
*
* int selection_list(list<unicode> [, int])
*
* tuple<int> multi_selection_list(list<unicode> [, string, int])
*
* <query_result_type> query(unicode, string [,<initial_value>])
*
* note(unicode, string)
*
* (unicode, unicode)
* multi_query(unicode, unicode)
*
* int popup_menu(list<unicode OR tuple<unicode, unicode>>, [unicode])
*
* list<unicode> available_fonts()
*
*
* Copyright (c) 2005-2007 Nokia Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
#include "appuifwmodule.h"
#include "appuifw_callbacks.h"
#include "colorspec.cpp"
// Yuck. This is ugly but will do for now until a better solution is implemented
// for shared functionality between appuifw and graphics modules. Perhaps they
// should just be merged?
#include "../../ext/graphics/fontspec.cpp"
#if SERIES60_VERSION>=28
#include "akniconutils.h"
#include "GULICON.H"
#define SCALABLE_UI
#endif /* SERIES60_VERSION */
#define UICONTROLAPI_NAME "_uicontrolapi"
struct Application_data {
Application_data(CAmarettoAppUi* aAppUi, Application_object* aOp):
appui(aAppUi), ob_exit_key_cb(aOp,aAppUi), ob_event_cb(aOp,aAppUi),
ob_command_cb(aOp,aAppUi), ob_menu_cb(aOp,aAppUi),
ob_tab_cb(aOp,aAppUi), ob_focus_cb(aOp,aAppUi)
{
rsc_offset = (-1);
appui->SetMenuDynInitFunc(&(ob_menu_cb));
appui->SetMenuCommandFunc(&(ob_command_cb));
}
~Application_data() {
if (rsc_offset != (-1))
(CEikonEnv::Static())->DeleteResourceFile(rsc_offset);
appui->SetMenuDynInitFunc(NULL);
appui->SetMenuCommandFunc(NULL);
appui->SetExitFunc(NULL);
appui->SetHostedControl(NULL, NULL);
appui->SetFocusFunc(NULL);
}
CAmarettoAppUi* appui;
TInt rsc_offset;
CAppuifwExitKeyCallback ob_exit_key_cb;
CAppuifwEventCallback ob_event_cb;
CAppuifwCommandCallback ob_command_cb;
CAppuifwMenuCallback ob_menu_cb;
CAppuifwTabCallback ob_tab_cb;
CAppuifwFocusCallback ob_focus_cb;
};
/*
* An utility for obtaining the Application object
*/
static Application_object* get_app()
{
PyInterpreterState *interp = PyThreadState_Get()->interp;
PyObject* m = PyDict_GetItemString(interp->modules, "_appuifw");
return (Application_object*)PyDict_GetItemString(PyModule_GetDict(m),
"app");
}
/* A function that is used with CAsyncCallBack.
* It is called to destroy the object after
* UI processing is done.
*/
TInt decrefObject(TAny* aObj)
{
PyEval_RestoreThread(PYTHON_TLS->thread_state);
Py_DECREF((PyObject*)aObj);
PyEval_SaveThread();
return 1;
}
/*
* A helper function for the implementation of callbacks
* from C/C++ code to Python callables
*/
TInt app_callback_handler(TAny* func)
{
// Strictly speaking this violates the Python/C API spec.
// We should pass an empty tuple instead of NULL.
return app_callback_handler(func, NULL);
}
TInt app_callback_handler(TAny* func, TAny* arg)
{
TInt error = KErrNone;
PyObject* rval = PyEval_CallObject((PyObject*)func, (PyObject*)arg);
if (!rval) {
error = KErrPython;
if (PyErr_Occurred() == PyExc_OSError) {
PyObject *type, *value, *traceback;
// Note that PyErr_Fetch gives us ownership of these objects, so
// we must remember to DECREF them.
PyErr_Fetch(&type, &value, &traceback);
if (PyInt_Check(value))
error = PyInt_AS_LONG(value);
Py_XDECREF(type);
Py_XDECREF(value);
Py_XDECREF(traceback);
} else {
PyErr_Print();
}
}
else
Py_DECREF(rval);
return error;
}
TInt
AppuifwControl_Check(PyObject *obj)
{
return (AppuifwControl_AsControl(obj))?1:0;
}
struct _control_object *
AppuifwControl_AsControl(PyObject *obj)
{
PyObject *controlapi_cobject=NULL;
if (!(controlapi_cobject=PyObject_GetAttrString(obj, UICONTROLAPI_NAME)) ||
!(PyCObject_Check(controlapi_cobject))) {
Py_XDECREF(controlapi_cobject);
return NULL;
}
struct _control_object *control_object=
(struct _control_object *)PyCObject_AsVoidPtr(controlapi_cobject);
Py_DECREF(controlapi_cobject);
return control_object;
}
static void _uicontrolapi_decref(void *control_obj)
{
Py_DECREF((PyObject *)control_obj);
}
/*
* Implementation of appuifw.Application (an implicit instance
* of this type with name "app" comes with this module, new
* instances can not be created from Python)
*/
extern "C" {static void application_dealloc(Application_object *op);}
/*
* SPy_S60app_New() -- C API only!
*/
extern "C" PyObject *
SPy_S60app_New()
{
Application_object *op = PyObject_New(Application_object,
&Application_type);
if (op == NULL)
return PyErr_NoMemory();
op->ob_dict_attr = NULL;
op->ob_menu = NULL;
op->ob_body = Py_None;
Py_INCREF(Py_None);
op->ob_title = NULL;
op->ob_screen = Py_BuildValue("s", "normal");
op->ob_data = NULL;
#ifdef EKA2
op->ob_orientation = Py_BuildValue("s", "automatic");
#endif
CEikonEnv* env = CEikonEnv::Static();
CAmarettoAppUi* appui = STATIC_CAST(CAmarettoAppUi*, env->EikAppUi());
TInt error;
const TDesC* title;
TRAP(error,
(title =
((CAknTitlePane*)
((env->AppUiFactory()->StatusPane())->
ControlL(TUid::Uid(EEikStatusPaneUidTitle))))->Text())
);
if (error != KErrNone) {
application_dealloc(op);
return SPyErr_SetFromSymbianOSErr(error);
}
if (!(op->ob_title =
PyUnicode_FromUnicode(title->Ptr(), title->Length())) ||
(!(op->ob_data = new Application_data(appui, op))) ||
(!(op->ob_menu = PyList_New(0)))) {
application_dealloc(op);
return NULL;
}
TParse f;
TFileName fn = op->ob_data->appui->Application()->AppFullName();
f.Set(KAppuiFwRscFile, &fn, NULL);
TRAP(error,
(op->ob_data->rsc_offset = env->AddResourceFileL(f.FullName())));
if (error != KErrNone) {
application_dealloc(op);
return SPyErr_SetFromSymbianOSErr(error);
}
return (PyObject *) op;
}
extern "C" PyObject *
app_full_name(Application_object *self)
{
TFileName n = ((self->ob_data)->appui)->Application()->AppFullName();
return Py_BuildValue("u#", n.Ptr(), n.Length());
}
extern "C" PyObject *
app_uid(Application_object *self)
{
TUid uid = ((self->ob_data)->appui)->Application()->AppDllUid();
TBuf<KMaxUidName> uidName(uid.Name());
uidName.Delete(KMaxUidName-1,1);
uidName.Delete(0,1);
return Py_BuildValue("u#", uidName.Ptr(), uidName.Length());
}
extern "C" PyObject *
app_set_tabs(Application_object *self, PyObject *args)
{
TInt error = KErrNone;
PyObject* list;
PyObject* cb;
if (!PyArg_ParseTuple(args, "O!O", &PyList_Type, &list, &cb))
return NULL;
int sz = PyList_Size(list);
if ((sz > 1) && !PyCallable_Check(cb)) {
PyErr_SetString(PyExc_TypeError, "callable expected");
return NULL;
}
CDesCArray *tab_text_list = NULL;
if (sz > 1) {
if (!(tab_text_list = new CDesCArrayFlat(sz)))
return PyErr_NoMemory();
for (int i = 0; i < sz; i++) {
PyObject* s = PyList_GetItem(list, i);
if (!PyUnicode_Check(s))
error = KErrArgument;
else {
TPtr buf(PyUnicode_AsUnicode(s), PyUnicode_GetSize(s),
PyUnicode_GetSize(s));
TRAP(error, tab_text_list->AppendL(buf));
}
if (error != KErrNone)
break;
}
}
else
cb = Py_None;
if (error == KErrNone) {
self->ob_data->ob_tab_cb.Set(cb);
Py_BEGIN_ALLOW_THREADS
error = self->ob_data->appui->EnableTabs(tab_text_list,
&self->ob_data->ob_tab_cb);
Py_END_ALLOW_THREADS
}
delete tab_text_list;
RETURN_ERROR_OR_PYNONE(error);
}
extern "C" PyObject *
app_activate_tab(Application_object *self, PyObject *args)
{
TInt index;
if (!PyArg_ParseTuple(args, "i", &index))
return NULL;
Py_BEGIN_ALLOW_THREADS
self->ob_data->appui->SetActiveTab(index);
Py_END_ALLOW_THREADS
Py_INCREF(Py_None);
return Py_None;
}
#if SERIES60_VERSION>=28
extern "C" PyObject *
app_layout(Application_object *self, PyObject *args)
{
TInt layout = 0;
TRect rect;
TBool available = EFalse;
if (!PyArg_ParseTuple(args, "i", &layout))
return NULL;
available = AknLayoutUtils::LayoutMetricsRect((AknLayoutUtils::TAknLayoutMetrics)layout, rect);
if(available) {
// size, position:
return Py_BuildValue("((ii),(ii))", rect.Width(),
rect.Height(),
rect.iTl.iX,
rect.iTl.iY
);
} else {
PyErr_SetString(PyExc_ValueError, "unknown layout");
return NULL;
}
}
#endif /* SERIES60_VERSION */
extern "C" PyObject *
app_set_exit(Application_object *self, PyObject* /*args*/)
{
self->ob_data->appui->SetExitFlag();
Py_INCREF(Py_None);
return Py_None;
}
extern "C" {
static void
application_dealloc(Application_object *op)
{
delete op->ob_data;
op->ob_data = NULL;
Py_XDECREF(op->ob_dict_attr);
Py_XDECREF(op->ob_menu);
Py_XDECREF(op->ob_body);
Py_XDECREF(op->ob_title);
Py_XDECREF(op->ob_screen);
#ifdef EKA2
Py_XDECREF(op->ob_orientation);
#endif
PyObject_Del(op);
}
static const PyMethodDef application_methods[] = {
{"set_exit", (PyCFunction)app_set_exit, METH_NOARGS},
{"full_name", (PyCFunction)app_full_name, METH_NOARGS},
{"uid", (PyCFunction)app_uid, METH_NOARGS},
{"set_tabs", (PyCFunction)app_set_tabs, METH_VARARGS},
{"activate_tab", (PyCFunction)app_activate_tab, METH_VARARGS},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -