From 2bda8f7717adf28da4af0d34fb82f63d2868c31d Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeutils@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- superkaramba/src/misc_python.cpp | 852 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 852 insertions(+) create mode 100644 superkaramba/src/misc_python.cpp (limited to 'superkaramba/src/misc_python.cpp') diff --git a/superkaramba/src/misc_python.cpp b/superkaramba/src/misc_python.cpp new file mode 100644 index 0000000..ba67573 --- /dev/null +++ b/superkaramba/src/misc_python.cpp @@ -0,0 +1,852 @@ +/**************************************************************************** +* misc_python.cpp - Misc Functions for python api +* +* Copyright (C) 2003 Hans Karlsson +* Copyright (C) 2003-2004 Adam Geitgey +* Copyright (C) 2004 Petri Damst� +* Copyright (C) 2004, 2005 Luke Kenneth Casson Leighton +* +* This file is part of SuperKaramba. +* +* SuperKaramba is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* SuperKaramba is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with SuperKaramba; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +****************************************************************************/ + +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif + +#include +#include +#include + +#include +#include + +#include "kdebug.h" +#include "karamba.h" +#include "karambaapp.h" +#include "themefile.h" +#include "themelocale.h" +#include "meter.h" +#include "meter_python.h" +#include "misc_python.h" + +/* now a method we need to expose to Python */ +long acceptDrops(long widget) +{ + karamba* currTheme = (karamba*)widget; + + currTheme->setAcceptDrops(true); + + return 1; +} + +PyObject* py_accept_drops(PyObject *, PyObject *args) +{ + long widget; + + if (!PyArg_ParseTuple(args, (char*)"l", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", acceptDrops(widget)); +} + +// Runs a command, returns 0 if it could not start command +PyObject* py_run_command(PyObject*, PyObject* args) +{ + char* name; + char* command; + char* icon; + PyObject *lst; + if (!PyArg_ParseTuple(args, (char*)"sssO:run", &name, &command, &icon, &lst) || + lst == NULL || !PyList_Check(lst)) + return NULL; + + QString n; + QString c; + QString i; + + n.setAscii(name); + c.setAscii(command); + i.setAscii(icon); + + KService svc(n, c, i); + KURL::List l; + + for (int i = 0; i < PyList_Size(lst); i++) + { + l.append(PyString2QString(PyList_GetItem(lst, i))); + } + KRun::run(svc, l); + return Py_BuildValue("l", 1); +} + +// Runs a command, returns 0 if it could not start command +PyObject* py_execute_command(PyObject *, PyObject* args) +{ + PyObject* s; + + if (!PyArg_ParseTuple(args, (char*)"O:execute", &s)) + return NULL; + return Py_BuildValue((char*)"l", KRun::runCommand(PyString2QString(s))); +} + +// Runs a command, returns 0 if it could not start command +PyObject* py_execute_command_interactive(PyObject *, PyObject* args) +{ + long widget; + //if (!PyArg_ParseTuple(args, (char*)"ls", &widget, &command)) + // return NULL; + + int numLines; /* how many lines we passed for parsing */ + QString line; /* pointer to the line as a string */ + + PyObject * listObj; /* the list of strings */ + PyObject * strObj; /* one string in the list */ + + /* the O! parses for a Python object (listObj) checked + to be of type PyList_Type */ + if (! PyArg_ParseTuple(args, (char*)"lO!", &widget, &PyList_Type, &listObj)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + karamba* currTheme = (karamba*)widget; + + currTheme->currProcess = new KProcess; + + /* get the number of lines passed to us */ + numLines = PyList_Size(listObj); + + /* should raise an error here. */ + if (numLines < 0) return NULL; /* Not a list */ + + /* iterate over items of the list, grabbing strings, and parsing + for numbers */ + for (int i=0; icurrProcess) << line; + + } + QApplication::connect(currTheme->currProcess, + SIGNAL(processExited(KProcess *)), + currTheme, + SLOT(processExited(KProcess *))); + QApplication::connect(currTheme->currProcess, + SIGNAL(receivedStdout(KProcess *, char *, int)), + currTheme, + SLOT(receivedStdout(KProcess *, char *, int))); + currTheme->currProcess->start(KProcess::NotifyOnExit, KProcess::Stdout); + + return Py_BuildValue((char*)"l", (int)(currTheme->currProcess->pid())); +} + +long attachClickArea(long widget, long meter, QString LeftButton, QString MiddleButton, QString RightButton) +{ + karamba* currTheme = (karamba*) widget; + Meter* currMeter = (Meter*) meter; + + // Look if currMeter has an ClickArea attached. + bool meterAlreadyClickable = currTheme->clickList->containsRef(currMeter); + + // if currMeter is of type ImageLabel* + if (ImageLabel* image = dynamic_cast(currMeter)) + { + image -> attachClickArea(LeftButton, MiddleButton, RightButton); + if (!meterAlreadyClickable) + { + //qWarning("attachClickArea : meter is image"); + currTheme -> clickList -> append(image); + } + } + // else if currMeter is of type TextLabel* + else if (TextLabel* text = dynamic_cast(currMeter)) + { + text -> attachClickArea(LeftButton, MiddleButton, RightButton); + if (!meterAlreadyClickable) + { + //qWarning("attachClickArea : meter is text"); + currTheme -> clickList -> append(text); + } + } + else + { + //The given meter does not support attached clickAreas. + qWarning("The given meter is not of type image or text"); + return 0; + } + return 1; +} + +PyObject* py_attach_clickArea(PyObject*, PyObject* args, PyObject* dict) +{ + long widget; + long meter; + char* LeftButton = NULL; + char* MiddleButton = NULL; + char* RightButton = NULL; + const char* mouseButtons[] = {"Widget", "Meter", "LeftButton", "MiddleButton", + "RightButton", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, dict, (char*)"ll|sss:attachClickArea", + (char**)mouseButtons, &widget, &meter, &LeftButton, &MiddleButton, &RightButton)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + QString lB, mB, rB; + if (LeftButton != NULL) + { + lB.setAscii(LeftButton); + } + else + { + lB.setAscii(""); + } + if (MiddleButton != NULL) + { + mB.setAscii(MiddleButton); + } + else + { + mB.setAscii(""); + } + if (RightButton != NULL) + { + rB.setAscii(RightButton); + } + else + { + rB.setAscii(""); + } + return Py_BuildValue((char*)"l", attachClickArea(widget, meter, lB, mB, rB)); +} + +/* now a method we need to expose to Python */ +long toggleShowDesktop(long) +{ + ShowDesktop *s = ShowDesktop::the(); + s->toggle(); + return 1; +} + +PyObject* py_toggle_show_desktop(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:toggleShowDesktop", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", toggleShowDesktop(widget)); +} + +/* now a method we need to expose to Python */ +const char* getPrettyName(long widget) { + karamba* currTheme = (karamba*)widget; + + return currTheme->prettyName.ascii(); +} + +PyObject* py_get_pretty_name(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getPrettyThemeName", &widget)) + return NULL; + return Py_BuildValue((char*)"s", getPrettyName(widget)); +} + +/* now a method we need to expose to Python */ +const char* getThemePath(long widget) { + karamba* currTheme = (karamba*)widget; + + return currTheme->theme().path().ascii(); +} + +PyObject* py_get_theme_path(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getThemePath", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"s", getThemePath(widget)); +} + +PyObject* py_language(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:language", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"s", + ((karamba*)widget)->theme().locale()->language().ascii()); +} + +PyObject* py_userLanguage(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:language", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"s", KGlobal::locale()->language().ascii()); +} + +PyObject* py_userLanguages(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:language", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + + unsigned int noOfLangs = KGlobal::locale()->languageList().count(); + + PyObject *list, *item; + list = PyList_New(noOfLangs); + + for(unsigned int i = 0; i < noOfLangs; i++) + { + item = Py_BuildValue((char*)"s", KGlobal::locale()->languageList()[i].ascii()); + PyList_SetItem(list, i, item); + } + + return list; +} + +PyObject* py_read_theme_file(PyObject *, PyObject *args) +{ + long widget; + char *file; + if (!PyArg_ParseTuple(args, (char*)"ls:readThemeFile", &widget, &file)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + karamba* k = (karamba*)widget; + QByteArray ba = k->theme().readThemeFile(file); + return PyString_FromStringAndSize(ba.data(), ba.size()); +} + +/* now a method we need to expose to Python */ +long removeClickArea(long widget, long click) { + + karamba* currTheme = (karamba*)widget; + ClickArea *tmp = (ClickArea*)click; + + currTheme -> clickList -> remove(tmp); + + delete tmp; + return (long)tmp; +} + +/* now a method we need to expose to Python */ +long createServiceClickArea(long widget, long x, long y, long w, long h, char *name, char* exec, char *icon) { + + karamba* currTheme = (karamba*)widget; + ClickArea *tmp = new ClickArea( currTheme, x, y, w, h ); + QString n; + QString e; + QString i; + + n.setAscii(name); + e.setAscii(exec); + i.setAscii(icon); + + tmp->setServiceOnClick(n, e, i); + + currTheme -> clickList -> append(tmp); + return (long)tmp; +} + +long createClickArea(long widget, long x, long y, long w, long h, char* text) { + + karamba* currTheme = (karamba*)widget; + ClickArea *tmp = new ClickArea(currTheme, x, y, w, h ); + QString onclick; + + onclick.setAscii(text); + + tmp->setOnClick(onclick ); + + currTheme -> clickList -> append(tmp); + return (long)tmp; +} + +PyObject* py_remove_click_area(PyObject *, PyObject *args) +{ + long widget, click; + if (!PyArg_ParseTuple(args, (char*)"ll:removeClickArea", &widget, &click)) + return NULL; + return Py_BuildValue((char*)"l", removeClickArea(widget, click)); +} + +PyObject* py_create_service_click_area(PyObject *, PyObject *args) +{ + long widget, x, y, w, h; + char *name; + char *exec; + char *icon; + if (!PyArg_ParseTuple(args, (char*)"lllllsss:createServiceClickArea", &widget, &x, &y, + &w, &h, &name, &exec, &icon)) + return NULL; + return Py_BuildValue((char*)"l", createServiceClickArea(widget, x, y, w, h, name, exec, icon)); +} + +PyObject* py_create_click_area(PyObject *, PyObject *args) +{ + long widget, x, y, w, h; + char *text; + if (!PyArg_ParseTuple(args, (char*)"llllls:createClickArea", &widget, &x, &y, + &w, &h, &text)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", createClickArea(widget, x, y, w, h, text)); +} + +static long callTheme(long widget, char* path, char *str) +{ + karamba* currTheme = (karamba*) widget; + + if (currTheme) + currTheme->callTheme(QString(path), QString(str)); + + return (long)currTheme; +} + +static long setIncomingData(long widget, char* path, char *obj) +{ + karamba* currTheme = (karamba*) widget; + + if (currTheme) + currTheme->setIncomingData(QString(path), QString(obj)); + + return (long)currTheme; +} + +static QString getIncomingData(long widget) +{ + karamba* currTheme = (karamba*) widget; + + if (currTheme) + return currTheme->getIncomingData(); + + return QString(""); +} + +/* + * openNamedTheme. this function checks to see whether the theme + * being opened is unique or not (against all running karamba widgets). + * this is important, as loading themes with the same name causes + * grief. + */ +long openNamedTheme(char* path, char *name, bool is_sub_theme) { + + QString filename; + karamba* currTheme = 0; + + filename.setAscii(path); + + QFileInfo file( filename ); + + if( file.exists() ) + { + QCString prettyName(name); + KarambaApplication* app = (KarambaApplication*)qApp; + if (!app->themeExists(prettyName)) + { + currTheme = new karamba( filename, prettyName, false , + -1, is_sub_theme); + currTheme->show(); + } + } + return (long)currTheme; +} + +/* now a method we need to expose to Python */ +long openTheme(char* path) +{ + + QString filename; + karamba* currTheme = 0; + + filename.setAscii(path); + + QFileInfo file( filename ); + + if( file.exists() ) + { + currTheme = new karamba( filename, QString() ); + currTheme->show(); + } + + return (long)currTheme; +} + +PyObject* py_get_incoming_data(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getIncomingData", &widget)) + return NULL; + return Py_BuildValue((char*)"O", QString2PyString(getIncomingData(widget))); +} + +PyObject* py_set_incoming_data(PyObject *, PyObject *args) +{ + char *themePath; + long widget; + char *obj; + if (!PyArg_ParseTuple(args, (char*)"lss:setIncomingData", &widget, &themePath, &obj)) + return NULL; + return Py_BuildValue((char*)"l", setIncomingData(widget, themePath, obj)); +} + +PyObject* py_call_theme(PyObject *, PyObject *args) +{ + char *themePath; + char *str; + long widget; + if (!PyArg_ParseTuple(args, (char*)"lss:callTheme", &widget, &themePath, &str)) + return NULL; + return Py_BuildValue((char*)"l", callTheme(widget, themePath, str)); +} + +PyObject* py_open_named_theme(PyObject *, PyObject *args) +{ + char *themePath; + char *themeName; + long is_sub_theme; + if (!PyArg_ParseTuple(args, (char*)"ssl:openNamedTheme", &themePath, &themeName, &is_sub_theme)) + return NULL; + return Py_BuildValue((char*)"l", openNamedTheme(themePath, themeName, is_sub_theme ? true : false)); +} + +PyObject* py_open_theme(PyObject *, PyObject *args) +{ + char *themePath; + if (!PyArg_ParseTuple(args, (char*)"s:openTheme", &themePath)) + return NULL; + return Py_BuildValue((char*)"l", openTheme(themePath)); +} + +PyObject* py_reload_theme(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:reloadTheme", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + ((karamba*)widget)->reloadConfig(); + return Py_BuildValue((char*)"l", 1); +} + +/* now a method we need to expose to Python */ +int getNumberOfDesktops(long widget) +{ + karamba* currTheme = (karamba*)widget; + + return currTheme->kWinModule->numberOfDesktops(); +} + +PyObject* py_get_number_of_desktops(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:getNumberOfDesktops", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", getNumberOfDesktops(widget)); +} + +/* now a method we need to expose to Python */ +int translateAll(long widget, int x, int y) +{ + karamba* currTheme = (karamba*)widget; + + QObjectListIt it2( *currTheme->meterList ); // iterate over meters + + while ( it2 != 0 ) + { + ((Meter*) *it2)->setSize(((Meter*) *it2)->getX()+x, + ((Meter*) *it2)->getY()+y, + ((Meter*) *it2)->getWidth(), + ((Meter*) *it2)->getHeight()); + ++it2; + } + + if (currTheme->systray != 0) + { + currTheme->systray->move(currTheme->systray->x()+x, + currTheme->systray->y()+y); + } + return 0; +} + +PyObject* py_translate_all(PyObject *, PyObject *args) +{ + long widget; + int x, y; + if (!PyArg_ParseTuple(args, (char*)"lii:translateAll", &widget, &x, &y)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"lii", translateAll(widget, x, y)); +} + +/* now a method we need to expose to Python */ +int show(long widget) +{ + karamba* currTheme = (karamba*)widget; + currTheme->show(); + return 0; +} + +PyObject* py_show(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:show", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", show(widget)); +} + +/* now a method we need to expose to Python */ +int hide(long widget) +{ + karamba* currTheme = (karamba*)widget; + currTheme->hide(); + return 0; +} + +PyObject* py_hide(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:hide", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"l", hide(widget)); +} + +/*Putting includes here to show the dependency for the call(s) below (if we ever decide to move the networking callbacks into a separate file*/ +#include +#include +#include +#include +#if defined(__FreeBSD__) || defined(__DragonFly__) +#include +#endif +#if defined(Q_OS_SOLARIS) +#include +#endif +/* now a method we need to expose to Python */ +QString getIp(char *device_name) +{ + int i, sd, numdevs; + struct ifconf ifc_conf; + char ifc_conf_buf[sizeof ( struct ifreq ) * 32]; + struct ifreq *devptr; + int ifc_conf_buf_size; + static struct in_addr host; + QString retval; + + retval = "Disconnected"; + + /* + * Open a socket, any type will do so we choose UDP, and ask it with + * an ioctl call what devices are behind it. + */ + if ((sd = socket(AF_INET,SOCK_DGRAM,0)) < 0) + { + qWarning("Error: Unable to create socket (socket)"); + return "Error"; + } + + /* + * Fill the buffer with our static buffer, probably big enough, and get + * the interface configuration. + */ + ifc_conf_buf_size = sizeof ifc_conf_buf; + ifc_conf.ifc_len = ifc_conf_buf_size; + ifc_conf.ifc_buf = ifc_conf_buf; + if (ioctl(sd,SIOCGIFCONF,&ifc_conf) < 0) + { + qWarning("Error: Unable to get network interface conf (ioctl)"); + close(sd); + return "Error"; + } + + /* + * An array of devices were returned. Which ones are up right now and + * have broadcast capability? + */ + numdevs = ifc_conf.ifc_len / sizeof (struct ifreq); + //qDebug("numdevs = %d", numdevs); + for (i = 0; i < numdevs; i++) + { + //qDebug("iterations: %d", i); + /* devptr points into an array of ifreq structs. */ + devptr = &ifc_conf.ifc_req[i]; + + if (ioctl(sd, SIOCGIFADDR, devptr) < 0 || devptr->ifr_addr.sa_family != AF_INET) + continue; + + if (ioctl(sd,SIOCGIFFLAGS,devptr) < 0) + { + qWarning("Error: Unable to get device interface flags (ioctl)."); + close(sd); + return "Error"; + } + + //We generally don't want probing of the loopback devices + if ((devptr->ifr_flags & IFF_LOOPBACK) != 0) + continue; + + if ((devptr->ifr_flags & IFF_UP) == 0) + continue; + + if ((devptr->ifr_flags & IFF_BROADCAST) == 0) + continue; + + /* Get the broadcast address. */ + if (ioctl(sd,SIOCGIFFLAGS,devptr) < 0) + { + qWarning("Error: Unable to get device interface flags (ioctl)."); + close(sd); + return "Error"; + } + else + { + if (!strcmp((char*)devptr->ifr_name, device_name)) + { + host.s_addr = ((struct sockaddr_in*)&devptr->ifr_addr)->sin_addr.s_addr; + retval = inet_ntoa(host); + break; + } + } + } + close(sd); + return retval; +} + +PyObject* py_set_update_time(PyObject *, PyObject *args) +{ + long widget; + double time; + if (!PyArg_ParseTuple(args, (char*)"ld:setUpdateTime", &widget, &time)) + return NULL; + karamba* currTheme = (karamba*)widget; + currTheme->setUpdateTime(time); + return Py_BuildValue((char*)"l", 1); +} + +PyObject* py_get_update_time(PyObject *, PyObject *args) +{ + long widget; + double time; + if (!PyArg_ParseTuple(args, (char*)"l:getUpdateTime", &widget, &time)) + return NULL; + karamba* currTheme = (karamba*)widget; + return Py_BuildValue((char*)"d", currTheme->getUpdateTime()); +} + +PyObject* py_get_ip(PyObject *, PyObject *args) +{ + long widget; + char *interface; + if (!PyArg_ParseTuple(args, (char*)"ls:getIp", &widget, &interface)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + return Py_BuildValue((char*)"O", QString2PyString(getIp(interface))); +} + +static void management_popup(long widget) +{ + karamba* currTheme = (karamba*)widget; + currTheme->management_popup(); +} + +PyObject* py_management_popup(PyObject *, PyObject *args) +{ + long widget; + if (!PyArg_ParseTuple(args, (char*)"l:managementPopup", &widget)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + management_popup(widget); + return Py_BuildValue((char*)"l", 1); +} + +static void set_want_right_button(long widget, long yesno) +{ + karamba* currTheme = (karamba*)widget; + currTheme->setWantRightButton(yesno); +} + +PyObject* py_want_right_button(PyObject *, PyObject *args) +{ + long widget, i; + if (!PyArg_ParseTuple(args, (char*)"ll:setWantRightButton", &widget, &i)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + set_want_right_button(widget, i); + return Py_BuildValue((char*)"l", 1); +} + +static void set_want_wheel_event(long widget, long yesno) +{ + karamba* currTheme = (karamba*)widget; + currTheme->setWantMeterWheelEvent(yesno); +} + +PyObject* py_want_wheel_event(PyObject *, PyObject *args) +{ + long widget, i; + if (!PyArg_ParseTuple(args, (char*)"ll:setWantMeterWheelEvent", &widget, &i)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + set_want_wheel_event(widget, i); + return Py_BuildValue((char*)"l", 1); +} + +static void changeInterval(long widget, long interval) +{ + karamba* currTheme = (karamba*)widget; + currTheme->changeInterval(interval); +} + +PyObject* py_change_interval(PyObject *, PyObject *args) +{ + long widget, i; + if (!PyArg_ParseTuple(args, (char*)"ll:changeInterval", &widget, &i)) + return NULL; + if (!checkKaramba(widget)) + return NULL; + changeInterval(widget, i); + return Py_BuildValue((char*)"l", 1); +} + + -- cgit v1.2.1