diff --git a/src/Xournalpp.cpp b/src/Xournalpp.cpp
index 1d2a305c..d4a2a9c1 100644
--- a/src/Xournalpp.cpp
+++ b/src/Xournalpp.cpp
@@ -13,9 +13,6 @@
#include "util/CrashHandler.h"
#include "util/Stacktrace.h"
-// TODO: debug
-#include "model/eraser/EraseableStrokePart.h"
-
int main(int argc, char * argv[]) {
// init crash handler
installCrashHandlers();
diff --git a/src/control/Control.cpp b/src/control/Control.cpp
index 18c82a35..a231ca80 100644
--- a/src/control/Control.cpp
+++ b/src/control/Control.cpp
@@ -119,6 +119,13 @@ Control::~Control() {
this->scheduler->stop();
+ for (GList * l = this->changedPages; l != NULL; l = l->next) {
+ XojPage * page = (XojPage *) l->data;
+ page->unreference();
+ }
+ g_list_free(this->changedPages);
+ this->changedPages = NULL;
+
delete this->clipboardHandler;
this->clipboardHandler = NULL;
delete this->recent;
@@ -168,10 +175,13 @@ bool Control::checkChangedDocument(Control * control) {
return true;
}
for (GList * l = control->changedPages; l != NULL; l = l->next) {
- int p = control->doc->indexOf((XojPage *) l->data);
+ XojPage * page = (XojPage *) l->data;
+ int p = control->doc->indexOf(page);
if (p != -1) {
control->firePageChanged(p);
}
+
+ page->unreference();
}
g_list_free(control->changedPages);
control->changedPages = NULL;
@@ -1489,8 +1499,9 @@ void Control::undoRedoPageChanged(PageRef page) {
}
}
- // TODO: reference / unrefrerence!!
- this->changedPages = g_list_append(this->changedPages, (XojPage *)page);
+ XojPage * p = (XojPage *)page;
+ this->changedPages = g_list_append(this->changedPages, p);
+ p->reference();
}
void Control::selectTool(ToolType type) {
diff --git a/src/control/XournalMain.cpp b/src/control/XournalMain.cpp
index 898abae1..4d3248d4 100644
--- a/src/control/XournalMain.cpp
+++ b/src/control/XournalMain.cpp
@@ -79,6 +79,7 @@ int XournalMain::run(int argc, char * argv[]) {
gchar * pdfFilename = NULL;
#ifdef ENABLE_PYTHON
gchar * scriptFilename = NULL;
+ gchar * scriptArg = NULL;
#endif
int openAtPageNumber = -1;
@@ -89,7 +90,8 @@ int XournalMain::run(int argc, char * argv[]) {
{ "page", 'n', 0, G_OPTION_ARG_INT, &openAtPageNumber, "Jump to Page (first Page: 1)", "N" },
#ifdef ENABLE_PYTHON
- { "script", 'n', 0, G_OPTION_ARG_FILENAME, &scriptFilename, "Runs a Python script as plugin", NULL },
+ { "script", 0, 0, G_OPTION_ARG_STRING, &scriptFilename, "Runs a Python script as plugin", NULL },
+ { "script-arg", 0, 0, G_OPTION_ARG_STRING, &scriptArg, "Python script parameter", NULL },
#endif
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &optFilename, "", NULL },
{ NULL }
@@ -187,11 +189,10 @@ int XournalMain::run(int argc, char * argv[]) {
}
#ifdef ENABLE_PYTHON
- PythonRunner * runner = NULL;
+ PythonRunner::initPythonRunner(control);
if(scriptFilename) {
- runner = new PythonRunner(control);
- runner->runScript(scriptFilename, "xournalTest");
+ PythonRunner::runScript(scriptFilename, "xournalTest", scriptArg);
}
#endif
@@ -202,7 +203,7 @@ int XournalMain::run(int argc, char * argv[]) {
win->getXournal()->clearSelection();
#ifdef ENABLE_PYTHON
- delete runner;
+ PythonRunner::releasePythonRunner();
#endif
delete win;
diff --git a/src/gui/XournalView.cpp b/src/gui/XournalView.cpp
index d9c7115d..11fc36a3 100644
--- a/src/gui/XournalView.cpp
+++ b/src/gui/XournalView.cpp
@@ -219,7 +219,7 @@ RepaintHandler * XournalView::getRepaintHandler() {
return this->repaintHandler;
}
-bool XournalView::onKeyReleaseEvent(GdkEventKey *event) {
+bool XournalView::onKeyReleaseEvent(GdkEventKey * event) {
XOJ_CHECK_TYPE(XournalView);
int p = getCurrentPage();
diff --git a/src/plugin/python/PythonRunner.cpp b/src/plugin/python/PythonRunner.cpp
index 46b1ad96..46ddd3e2 100644
--- a/src/plugin/python/PythonRunner.cpp
+++ b/src/plugin/python/PythonRunner.cpp
@@ -3,23 +3,116 @@
#include "bindings/PyXournal.h"
+class ScriptData {
+public:
+ ScriptData(String name, String function, String parameter) {
+ this->name = name;
+ this->function = function;
+ this->parameter = parameter;
+ }
+
+public:
+ String name;
+ String function;
+ String parameter;
+};
+
+PythonRunner * PythonRunner::instance = NULL;
+
PythonRunner::PythonRunner(Control * control) {
XOJ_INIT_TYPE(PythonRunner);
this->control = control;
this->pythonInitialized = false;
+
+ this->callbackId = 0;
+
+ this->mutex = g_mutex_new();
+ this->scripts = NULL;
}
PythonRunner::~PythonRunner() {
XOJ_CHECK_TYPE(PythonRunner);
- if(this->pythonInitialized) {
+ if (this->callbackId) {
+ g_source_remove(this->callbackId);
+ this->callbackId = 0;
+ }
+
+ if (this->pythonInitialized) {
Py_Finalize();
}
+ g_mutex_free(this->mutex);
+ this->mutex = NULL;
+
+ for (GList * l = this->scripts; l != NULL; l = l->next) {
+ ScriptData * s = (ScriptData *) l->data;
+ delete s;
+ }
+ g_list_free(this->scripts);
+ this->scripts = NULL;
+
XOJ_RELEASE_TYPE(PythonRunner);
}
+void PythonRunner::initPythonRunner(Control * control) {
+ if (instance) {
+ g_warning("PythonRunner already initialized!");
+ return;
+ }
+
+ instance = new PythonRunner(control);
+}
+
+void PythonRunner::releasePythonRunner() {
+ if (instance) {
+ delete instance;
+ instance = NULL;
+ }
+}
+
+void PythonRunner::runScript(String name, String function, String parameter) {
+ if (instance == NULL) {
+ g_warning("PythonRunner not initialized!");
+ return;
+ }
+
+ g_mutex_lock(instance->mutex);
+
+ if (instance->callbackId == 0) {
+ instance->callbackId = g_idle_add((GSourceFunc) scriptRunner, instance);
+ }
+
+ instance->scripts = g_list_append(instance->scripts, new ScriptData(name, function, parameter));
+
+ g_mutex_unlock(instance->mutex);
+}
+
+bool PythonRunner::scriptRunner(PythonRunner * runner) {
+ g_mutex_lock(runner->mutex);
+ GList * first = g_list_first(runner->scripts);
+ ScriptData * data = (ScriptData *) first->data;
+ runner->scripts = g_list_delete_link(runner->scripts, first);
+ g_mutex_unlock(runner->mutex);
+
+ runner->runScriptInt(data->name, data->function, data->parameter);
+
+ delete data;
+
+ bool callAgain = false;
+ g_mutex_lock(runner->mutex);
+ if (runner->scripts) {
+ callAgain = true;
+ } else {
+ callAgain = false;
+ runner->callbackId = 0;
+ }
+ g_mutex_unlock(runner->mutex);
+
+ return callAgain;
+}
+
void PythonRunner::addPath(String path, String & cmd) {
XOJ_CHECK_TYPE(PythonRunner);
@@ -32,18 +125,20 @@ void PythonRunner::addPath(String path, String & cmd) {
void PythonRunner::initPython() {
XOJ_CHECK_TYPE(PythonRunner);
- if(this->pythonInitialized) {
+ if (this->pythonInitialized) {
return;
}
- Py_SetProgramName("Xournal");
+ Py_SetProgramName("Xournal");
- Py_Initialize();
+ Py_Initialize();
PyXournal_initPython(this->control);
char buffer[512] = { 0 };
const char * path = getcwd(buffer, sizeof(buffer));
+ //TODO: PYTHONPATH
+
String cmd = "import sys\n";
if (path != NULL) {
@@ -59,7 +154,7 @@ void PythonRunner::initPython() {
PyRun_SimpleString(cmd.c_str());
}
-void PythonRunner::runScript(String path, String function) {
+void PythonRunner::runScriptInt(String path, String function, String parameter) {
XOJ_CHECK_TYPE(PythonRunner);
initPython();
@@ -75,7 +170,14 @@ void PythonRunner::runScript(String path, String function) {
/* pFunc is a new reference */
if (pFunc && PyCallable_Check(pFunc)) {
- PyObject * pArgs = PyTuple_New(0);
+ PyObject * pArgs = NULL;
+
+ if (parameter.c_str() == NULL) {
+ pArgs = PyTuple_New(0);
+ } else {
+ pArgs = PyTuple_New(1);
+ PyTuple_SetItem(pArgs, 0, PyString_FromString(parameter.c_str()));
+ }
PyObject * pValue = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
diff --git a/src/plugin/python/PythonRunner.h b/src/plugin/python/PythonRunner.h
index 773203a7..2dff84e2 100644
--- a/src/plugin/python/PythonRunner.h
+++ b/src/plugin/python/PythonRunner.h
@@ -19,14 +19,21 @@
class Control;
class PythonRunner {
-public:
+private:
PythonRunner(Control * control);
virtual ~PythonRunner();
public:
- void runScript(String path, String function);
+ static void initPythonRunner(Control * control);
+ static void releasePythonRunner();
+
+ static void runScript(String name, String function, String parameter = NULL);
+
+private:
+ static bool scriptRunner(PythonRunner * runner);
private:
+ void runScriptInt(String path, String function, String parameter);
void addPath(String path, String & cmd);
void initPython();
@@ -34,8 +41,16 @@ private:
private:
XOJ_TYPE_ATTRIB;
+ static PythonRunner * instance;
+
+ GMutex * mutex;
+
+ GList * scripts;
+
bool pythonInitialized;
Control * control;
+
+ int callbackId;
};
#endif /* __PYTHONRUNNER_H__ */
diff --git a/src/plugin/python/bindings/PyXournal.cpp b/src/plugin/python/bindings/PyXournal.cpp
index 36e7230e..1bde0c5a 100644
--- a/src/plugin/python/bindings/PyXournal.cpp
+++ b/src/plugin/python/bindings/PyXournal.cpp
@@ -1,5 +1,7 @@
#include "PyXournal.h"
#include "../../../control/Control.h"
+#include "../../../gui/XournalView.h"
+#include "../../../gui/widgets/XournalWidget.h"
#include
#include "structmember.h"
@@ -17,6 +19,7 @@ typedef struct {
PyObject_HEAD
Control * control;
PyObject * undoRedoHandler;
+ PyObject * document;
} PyXournal;
static Control * PyXournal_control = NULL;
@@ -29,30 +32,29 @@ void PyXournal_initPython(Control * control) {
initxournal();
}
-static void PyXournal_dealloc(PyXournal* self) {
- self->ob_type->tp_free((PyObject*) self);
+static void PyXournal_dealloc(PyXournal * self) {
+ self->ob_type->tp_free((PyObject *) self);
}
static PyObject *
-PyXournal_new(PyTypeObject *type, PyObject *args, PyObject *kwds) {
+PyXournal_new(PyTypeObject * type, PyObject * args, PyObject * kwds) {
PyXournal *self;
self = (PyXournal *) type->tp_alloc(type, 0);
if (self != NULL) {
self->control = PyXournal_control;
self->undoRedoHandler = PyLong_FromLong(5);
+ self->document = PyLong_FromLong(20);
}
return (PyObject *) self;
}
-static int PyXournal_init(PyXournal *self, PyObject *args, PyObject *kwds) {
+static int PyXournal_init(PyXournal * self, PyObject * args, PyObject * kwds) {
return 0;
}
static PyMemberDef PyXournal_members[] = {
- { "undoRedoHandler", T_OBJECT, offsetof(PyXournal, undoRedoHandler), 0, "Undo- / Redohandler" },
-
{ NULL } /* Sentinel */
};
@@ -135,7 +137,7 @@ PyXournal_setSelectedTool(PyXournal * self, PyObject * args) {
}
static PyObject *
-PyXournal_getSelectedTool(PyXournal* self) {
+PyXournal_getSelectedTool(PyXournal * self) {
ToolType tt = self->control->getToolHandler()->getToolType();
return PyLong_FromLong(tt);
@@ -151,8 +153,33 @@ PyXournal_mousePressed(PyXournal * self, PyObject * args) {
return NULL;
}
- // TODO: implememnt
- g_warning("NOT IMPLEMENTED!\n");
+ MainWindow * win = self->control->getWindow();
+ if(!win) {
+ PyErr_SetString(PyExc_AttributeError, "Window not yet initialized!");
+ return NULL;
+ }
+
+ int pageNo = self->control->getCurrentPageNo();
+ XournalView * xournal = win->getXournal();
+ double zoom = xournal->getZoom();
+ PageView * v = xournal->getViewFor(pageNo);
+
+ GdkEventButton event;
+ memset(&event, 0, sizeof(GdkEventButton));
+ event.type = GDK_BUTTON_PRESS;
+ event.window = (GdkWindow *)*win;
+ event.send_event = true;
+ event.time = 0;
+ event.x = x * zoom + v->getX();
+ event.y = y * zoom + v->getY();
+ event.axes = NULL;
+ event.state = GDK_MOD2_MASK;
+ event.button = 1;
+ event.device = gdk_device_get_core_pointer();
+ event.x_root = 0;
+ event.y_root = 0;
+
+ gtk_widget_event(xournal->getWidget(), (GdkEvent *)&event);
Py_RETURN_NONE;
}
@@ -167,26 +194,69 @@ PyXournal_mouseMoved(PyXournal * self, PyObject * args) {
return NULL;
}
- // TODO: implememnt
- g_warning("NOT IMPLEMENTED!\n");
+ MainWindow * win = self->control->getWindow();
+ if(!win) {
+ PyErr_SetString(PyExc_AttributeError, "Window not yet initialized!");
+ return NULL;
+ }
+
+ int pageNo = self->control->getCurrentPageNo();
+ XournalView * xournal = win->getXournal();
+ double zoom = xournal->getZoom();
+ PageView * v = xournal->getViewFor(pageNo);
+
+ GdkEventMotion event;
+ memset(&event, 0, sizeof(GdkEventMotion));
+ event.type = GDK_MOTION_NOTIFY;
+ event.window = (GdkWindow *)*win;
+ event.send_event = true;
+ event.time = 0;
+ event.x = x * zoom + v->getX();
+ event.y = y * zoom + v->getY();
+ event.axes = NULL;
+ event.state = GDK_MOD2_MASK;
+ event.is_hint = 0;
+ event.device = gdk_device_get_core_pointer();
+ event.x_root = 0;
+ event.y_root = 0;
+
+ gtk_widget_event(xournal->getWidget(), (GdkEvent *)&event);
Py_RETURN_NONE;
}
static PyObject *
PyXournal_mouseReleased(PyXournal * self) {
- // TODO: implememnt
- g_warning("NOT IMPLEMENTED!\n");
+ MainWindow * win = self->control->getWindow();
+ if(!win) {
+ PyErr_SetString(PyExc_AttributeError, "Window not yet initialized!");
+ return NULL;
+ }
+
+ GdkEventButton event;
+ memset(&event, 0, sizeof(GdkEventButton));
+ event.type = GDK_BUTTON_RELEASE;
+ event.window = (GdkWindow *)*win;
+ event.send_event = true;
+ event.time = 0;
+ event.x = 0;
+ event.y = 0;
+ event.axes = NULL;
+ event.state = GDK_MOD2_MASK;
+ event.button = 1;
+ event.device = gdk_device_get_core_pointer();
+ event.x_root = 0;
+ event.y_root = 0;
+
+ gtk_widget_event(win->getXournal()->getWidget(), (GdkEvent *)&event);
Py_RETURN_NONE;
}
static PyObject *
PyXournal_getUndoRedoHandler(PyXournal * self) {
- // TODO: implememnt
- g_warning("NOT IMPLEMENTED!\n");
-
- Py_RETURN_NONE;
+ Py_INCREF(self->undoRedoHandler);
+ return self->undoRedoHandler;
}
static PyObject *
@@ -198,10 +268,8 @@ PyXournal_getSelectedPage(PyXournal * self) {
static PyObject *
PyXournal_getDocument(PyXournal * self) {
- // TODO: implememnt
- g_warning("NOT IMPLEMENTED!\n");
-
- Py_RETURN_NONE;
+ Py_INCREF(self->document);
+ return self->document;
}
static PyObject *
@@ -304,8 +372,9 @@ void initxournal() {
m = Py_InitModule3("xournal", module_methods, "Xournal api modul");
- if (m == NULL)
+ if (m == NULL) {
return;
+ }
Py_INCREF(&XournalType);
PyModule_AddObject(m, "Xournal", (PyObject *) &XournalType);
diff --git a/testing/Test.py b/testing/Test.py
index 6f772302..6adfc828 100644
--- a/testing/Test.py
+++ b/testing/Test.py
@@ -1,9 +1,43 @@
import xournal
+import undo.UndoRedoTest
+import os
-def xournalTest():
- print 'Testmethode'
+def xournalTest(args = ''):
+ print 'Xournal testsuit started...'
xoj = xournal.Xournal()
+
+ xournalRunTestInSubfolder(xoj, 'tools');
+ xournalRunTestInSubfolder(xoj, 'undo');
+
+
+def xournalRunTestInSubfolder(xoj, subfolder):
+ path = os.path.realpath(__file__)
+ path = os.path.dirname(path)
+ folder = os.path.join(path, subfolder)
+
+ print 'Running scripts in %s' % folder
+
+ for name in os.listdir(folder):
+ dirfile = os.path.join(folder, name)
+
+ if os.path.isdir(dirfile) and not name.startswith('.') and os.path.exists(os.path.join(dirfile, 'Test.py')):
+ print 'Run test in %s' % dirfile
+ print 'Debug: import %s from %s' % (name, subfolder + '.' + name + '.Test')
+ __import__(subfolder + '.' + name + '.Test', fromlist = name)
+ cls = globals()[name]
+ inst = cls()
+ inst.
+
+
+
+# print xoj.openFile('/home/andreas/tmp/Notiz-10-03-2011-16-57.xoj')
+
+""" xoj.mousePressed(10, 10)
+ xoj.mouseMoved(20, 20)
+ xoj.mouseReleased()
+
+ ud = ColorUndoAction()
+"""
- print xoj.openFile('/home/andreas/tmp/Notiz-10-03-2011-16-57.xoj')
diff --git a/testing/undo/ColorUndoAction/Test.py b/testing/undo/ColorUndoAction/Test.py
new file mode 100644
index 00000000..be9216d9
--- /dev/null
+++ b/testing/undo/ColorUndoAction/Test.py
@@ -0,0 +1,16 @@
+# Xournal++
+#
+# Testclass for Undo / Redohandler
+#
+# @author Xournal Team
+# http://xournal.sf.net
+#
+# @license GPL
+
+from undo.UndoRedoTest import UndoRedoTest
+
+class ColorUndoAction(UndoRedoTest):
+ def __init__(self):
+ UndoRedoTest.__init__(self)
+ print 'ColorUndoAction'
+
diff --git a/testing/undo/ColorUndoAction/Test.pyc b/testing/undo/ColorUndoAction/Test.pyc
new file mode 100644
index 00000000..cee0add7
Binary files /dev/null and b/testing/undo/ColorUndoAction/Test.pyc differ
diff --git a/testing/undo/ColorUndoAction/__init__.py b/testing/undo/ColorUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/ColorUndoAction/__init__.pyc b/testing/undo/ColorUndoAction/__init__.pyc
new file mode 100644
index 00000000..1754fee0
Binary files /dev/null and b/testing/undo/ColorUndoAction/__init__.pyc differ
diff --git a/testing/undo/DeleteUndoAction/__init__.py b/testing/undo/DeleteUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/EraseUndoAction/__init__.py b/testing/undo/EraseUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/FontUndoAction/__init__.py b/testing/undo/FontUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/InsertDeletePageUndoAction/__init__.py b/testing/undo/InsertDeletePageUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/InsertLayerUndoAction/__init__.py b/testing/undo/InsertLayerUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/InsertUndoAction/__init__.py b/testing/undo/InsertUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/MoveUndoAction/__init__.py b/testing/undo/MoveUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/PageBackgroundChangedUndoAction/__init__.py b/testing/undo/PageBackgroundChangedUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/PageLayerPosEntry/__init__.py b/testing/undo/PageLayerPosEntry/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/RecognizerUndoAction/__init__.py b/testing/undo/RecognizerUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/RemoveLayerUndoAction/__init__.py b/testing/undo/RemoveLayerUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/ScaleUndoAction/__init__.py b/testing/undo/ScaleUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/SizeUndoAction/__init__.py b/testing/undo/SizeUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/TextUndoAction/__init__.py b/testing/undo/TextUndoAction/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/UndoRedoTest.py b/testing/undo/UndoRedoTest.py
new file mode 100644
index 00000000..6a07d3d8
--- /dev/null
+++ b/testing/undo/UndoRedoTest.py
@@ -0,0 +1,17 @@
+# Xournal++
+#
+# Textclass for Undo / Redohandler
+#
+# @author Xournal Team
+# http://xournal.sf.net
+#
+# @license GPL
+
+
+class UndoRedoTest:
+ def __init__(self):
+ print 'UndoRedoTest\n'
+
+ def runTest(self):
+ print 'run test called!\n'
+
diff --git a/testing/undo/UndoRedoTest.pyc b/testing/undo/UndoRedoTest.pyc
new file mode 100644
index 00000000..28be8346
Binary files /dev/null and b/testing/undo/UndoRedoTest.pyc differ
diff --git a/testing/undo/__init__.py b/testing/undo/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/testing/undo/__init__.pyc b/testing/undo/__init__.pyc
new file mode 100644
index 00000000..6ea628a2
Binary files /dev/null and b/testing/undo/__init__.pyc differ