Python plugin: Make it possible to get folder tree from a Mailbox
[claws.git] / src / plugins / python / foldertype.c
1 /* Python plugin for Claws-Mail
2  * Copyright (C) 2009 Holger Berndt
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #ifdef HAVE_CONFIG_H
19 #  include "config.h"
20 #include "claws-features.h"
21 #endif
22
23 #include <glib/gi18n.h>
24
25 #include "foldertype.h"
26 #include "folderpropertiestype.h"
27 #include "messageinfotype.h"
28 #include "mailboxtype.h"
29
30 #include <structmember.h>
31
32
33 typedef struct {
34     PyObject_HEAD
35     PyObject *properties;
36     FolderItem *folderitem;
37 } clawsmail_FolderObject;
38
39
40 static void Folder_dealloc(clawsmail_FolderObject* self)
41 {
42   Py_XDECREF(self->properties);
43   self->ob_type->tp_free((PyObject*)self);
44 }
45
46 static int Folder_init(clawsmail_FolderObject *self, PyObject *args, PyObject *kwds)
47 {
48   const char *ss = NULL;
49   FolderItem *folderitem = NULL;
50   char create = 0;
51
52   /* optional constructor argument: folderitem id string */
53   if(!PyArg_ParseTuple(args, "|sb", &ss, &create))
54     return -1;
55
56   if(ss) {
57     if(create == 0) {
58       folderitem = folder_find_item_from_identifier(ss);
59       if(!folderitem) {
60         PyErr_SetString(PyExc_ValueError, "A folder with that path does not exist, and the create parameter was False.");
61         return -1;
62       }
63     }
64     else {
65       folderitem = folder_get_item_from_identifier(ss);
66       if(!folderitem) {
67         PyErr_SetString(PyExc_IOError, "A folder with that path does not exist, and could not be created.");
68         return -1;
69       }
70     }
71   }
72
73   self->folderitem = folderitem;
74   if(folderitem)
75     self->properties = clawsmail_folderproperties_new(folderitem->prefs);
76   else {
77     Py_INCREF(Py_None);
78     self->properties = Py_None;
79   }
80
81   return 0;
82 }
83
84 static PyObject* Folder_str(clawsmail_FolderObject *self)
85 {
86   return PyString_FromFormat("Folder: %s", self->folderitem->name);
87 }
88
89 static PyObject* Folder_get_identifier(clawsmail_FolderObject *self, PyObject *args)
90 {
91   PyObject *obj;
92   gchar *id;
93   if(!self->folderitem)
94     return NULL;
95   id = folder_item_get_identifier(self->folderitem);
96   obj = Py_BuildValue("s", id);
97   g_free(id);
98   return obj;
99 }
100
101 static PyObject* Folder_get_messages(clawsmail_FolderObject *self, PyObject *args)
102 {
103   GSList *msglist, *walk;
104   PyObject *retval;
105   Py_ssize_t pos;
106
107   if(!self->folderitem)
108     return NULL;
109
110   msglist = folder_item_get_msg_list(self->folderitem);
111   retval = PyTuple_New(g_slist_length(msglist));
112   if(!retval) {
113     procmsg_msg_list_free(msglist);
114     Py_INCREF(Py_None);
115     return Py_None;
116   }
117
118   for(pos = 0, walk = msglist; walk; walk = walk->next, ++pos) {
119     PyObject *msg;
120     msg = clawsmail_messageinfo_new(walk->data);
121     PyTuple_SET_ITEM(retval, pos, msg);
122   }
123   procmsg_msg_list_free(msglist);
124
125   return retval;
126 }
127
128 static PyObject* get_name(clawsmail_FolderObject *self, void *closure)
129 {
130   if(self->folderitem && self->folderitem->name)
131     return PyString_FromString(self->folderitem->name);
132   Py_RETURN_NONE;
133 }
134
135 static PyObject* get_path(clawsmail_FolderObject *self, void *closure)
136 {
137   if(self->folderitem && self->folderitem->path)
138     return PyString_FromString(self->folderitem->path);
139   Py_RETURN_NONE;
140 }
141
142 static PyObject* get_mailbox_name(clawsmail_FolderObject *self, void *closure)
143 {
144   if(self->folderitem && self->folderitem->folder && self->folderitem->folder->name)
145     return PyString_FromString(self->folderitem->folder->name);
146   Py_RETURN_NONE;
147 }
148
149 static PyObject* get_mailbox(clawsmail_FolderObject *self, void *closure)
150 {
151   if(self->folderitem && self->folderitem->folder)
152     return clawsmail_mailbox_new(self->folderitem->folder);
153   Py_RETURN_NONE;
154 }
155
156
157 static PyObject* get_identifier(clawsmail_FolderObject *self, void *closure)
158 {
159   if(self->folderitem) {
160     gchar *id;
161     id = folder_item_get_identifier(self->folderitem);
162     if(id) {
163       PyObject *retval;
164       retval = PyString_FromString(id);
165       g_free(id);
166       return retval;
167     }
168   }
169   Py_RETURN_NONE;
170 }
171
172
173 static PyObject* get_properties(clawsmail_FolderObject *self, void *closure)
174 {
175   Py_INCREF(self->properties);
176   return self->properties;
177 }
178
179 static PyMethodDef Folder_methods[] = {
180     {"get_identifier", (PyCFunction)Folder_get_identifier, METH_NOARGS,
181      "get_identifier() - get identifier\n"
182      "\n"
183      "Get identifier for folder as a string (e.g. #mh/foo/bar)."},
184     {"get_messages", (PyCFunction)Folder_get_messages, METH_NOARGS,
185      "get_messages() - get a tuple of messages in folder\n"
186      "\n"
187      "Get a tuple of MessageInfos for the folder."},
188     {NULL}
189 };
190
191 static PyGetSetDef Folder_getset[] = {
192     {"name", (getter)get_name, (setter)NULL,
193      "name - name of folder", NULL},
194
195     {"path", (getter)get_path, (setter)NULL,
196      "path - path of folder", NULL},
197
198     {"identifier", (getter)get_identifier, (setter)NULL,
199      "identifier - identifier of folder", NULL},
200
201     {"mailbox", (getter)get_mailbox, (setter)NULL,
202      "mailbox - corresponding mailbox", NULL},
203
204     {"mailbox_name", (getter)get_mailbox_name, (setter)NULL,
205      "mailbox_name - name of the corresponding mailbox\n\n"
206      "DEPRECATED: Use folder.mailbox.name instead", NULL},
207
208     {"properties", (getter)get_properties, (setter)NULL,
209      "properties - folder properties object", NULL},
210
211     {NULL}
212 };
213
214
215 static PyTypeObject clawsmail_FolderType = {
216     PyObject_HEAD_INIT(NULL)
217     0,                         /* ob_size*/
218     "clawsmail.Folder",        /* tp_name*/
219     sizeof(clawsmail_FolderObject), /* tp_basicsize*/
220     0,                         /* tp_itemsize*/
221     (destructor)Folder_dealloc, /* tp_dealloc*/
222     0,                         /* tp_print*/
223     0,                         /* tp_getattr*/
224     0,                         /* tp_setattr*/
225     0,                         /* tp_compare*/
226     0,                         /* tp_repr*/
227     0,                         /* tp_as_number*/
228     0,                         /* tp_as_sequence*/
229     0,                         /* tp_as_mapping*/
230     0,                         /* tp_hash */
231     0,                         /* tp_call*/
232     (reprfunc)Folder_str,      /* tp_str*/
233     0,                         /* tp_getattro*/
234     0,                         /* tp_setattro*/
235     0,                         /* tp_as_buffer*/
236     Py_TPFLAGS_DEFAULT,        /* tp_flags*/
237     "Folder objects.\n\n"      /* tp_doc */
238     "The __init__ function takes two optional arguments:\n"
239     "folder = Folder(identifier, [create_if_not_existing=False])\n"
240     "The identifier is an id string (e.g. '#mh/Mail/foo/bar'),"
241     "create_if_not_existing is a boolean expression.",
242     0,                         /* tp_traverse */
243     0,                         /* tp_clear */
244     0,                         /* tp_richcompare */
245     0,                         /* tp_weaklistoffset */
246     0,                         /* tp_iter */
247     0,                         /* tp_iternext */
248     Folder_methods,            /* tp_methods */
249     0,                         /* tp_members */
250     Folder_getset,             /* tp_getset */
251     0,                         /* tp_base */
252     0,                         /* tp_dict */
253     0,                         /* tp_descr_get */
254     0,                         /* tp_descr_set */
255     0,                         /* tp_dictoffset */
256     (initproc)Folder_init,     /* tp_init */
257     0,                         /* tp_alloc */
258     0,                         /* tp_new */
259 };
260
261 gboolean cmpy_add_folder(PyObject *module)
262 {
263   clawsmail_FolderType.tp_new = PyType_GenericNew;
264   if(PyType_Ready(&clawsmail_FolderType) < 0)
265     return FALSE;
266
267   Py_INCREF(&clawsmail_FolderType);
268   return (PyModule_AddObject(module, "Folder", (PyObject*)&clawsmail_FolderType) == 0);
269 }
270
271 PyObject* clawsmail_folder_new(FolderItem *folderitem)
272 {
273   clawsmail_FolderObject *ff;
274   PyObject *arglist;
275   gchar *id;
276
277   if(!folderitem)
278     return NULL;
279
280   id = folder_item_get_identifier(folderitem);
281   if(id) {
282     arglist = Py_BuildValue("(s)", id);
283     g_free(id);
284     ff = (clawsmail_FolderObject*) PyObject_CallObject((PyObject*) &clawsmail_FolderType, arglist);
285     Py_DECREF(arglist);
286     return (PyObject*)ff;
287   }
288   Py_RETURN_NONE;
289 }
290
291 FolderItem* clawsmail_folder_get_item(PyObject *self)
292 {
293   return ((clawsmail_FolderObject*)self)->folderitem;
294 }
295
296 PyTypeObject* clawsmail_folder_get_type_object()
297 {
298   return &clawsmail_FolderType;
299 }
300
301 gboolean clawsmail_folder_check(PyObject *self)
302 {
303   return (PyObject_TypeCheck(self, &clawsmail_FolderType) != 0);
304 }