1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "window.h"
30
31 #include "davcontroller.h"
32 #include "appsettings.h"
33 #include "xml.h"
34
35 #include <ui/stock.h>
36 #include <ui/dnd.h>
37
38 #include <libidav/utils.h>
39
40 #include <cx/printf.h>
41
42 static UiIcon* folder_icon;
43 static UiIcon* file_icon;
44
45 static UiPathElm* dav_get_pathelm(
const char *full_path,
size_t len,
size_t *ret_nelm,
void* data);
46
47 static UiMenuBuilder *contextmenu;
48
49 void window_init(
void) {
50 folder_icon = ui_foldericon(
16);
51 file_icon = ui_fileicon(
16);
52
53
54 ui_contextmenu(&contextmenu) {
55 ui_menuitem(.label =
"New Folder", .onclick = action_mkcol, .groups =
UI_GROUPS(
APP_STATE_BROWSER_SESSION));
56 ui_menuitem(.label =
"New File", .onclick = action_newfile, .groups =
UI_GROUPS(
APP_STATE_BROWSER_SESSION));
57 ui_menuseparator();
58
59
60
61 ui_menuitem(.label =
"Download", .onclick = action_download, .groups =
UI_GROUPS(
APP_STATE_BROWSER_SESSION,
APP_STATE_BROWSER_SELECTION));
62 ui_menuitem(.label =
"Delete", .onclick = action_delete, .groups =
UI_GROUPS(
APP_STATE_BROWSER_SESSION));
63 ui_menuitem(.label =
"Select All", .onclick = action_selectall, .groups =
UI_GROUPS(
APP_STATE_BROWSER_SESSION));
64 ui_menuseparator();
65 ui_menuitem(.label =
"Rename", .onclick = action_rename, .groups =
UI_GROUPS(
APP_STATE_BROWSER_SESSION,
APP_STATE_BROWSER_SELECTION));
66 ui_menuseparator();
67 ui_menuitem(
"Open Properties", .onclick = action_open_properties, .groups =
UI_GROUPS(
APP_STATE_BROWSER_SESSION,
APP_STATE_BROWSER_SELECTION));
68 ui_menuitem(
"Open as Text File", .onclick = action_open_properties, .onclickdata =
"text/plain", .groups =
UI_GROUPS(
APP_STATE_BROWSER_SESSION,
APP_STATE_BROWSER_SELECTION));
69 }
70 }
71
72 UiObject* window_create(
void) {
73 UiObject* obj = ui_window(
"iDAV",
NULL);
74 ui_window_size(obj,
900,
700);
75
76 MainWindow* wdata = ui_malloc(obj->ctx,
sizeof (MainWindow));
77 memset(wdata,
0,
sizeof (MainWindow));
78 obj->window = wdata;
79
80 wdata->progress = ui_int_new(obj->ctx,
"progress");
81
82
83
84 ui_hbox(obj, .fill =
UI_OFF, .margin =
8, .spacing =
8) {
85 ui_hbox(obj, .fill =
UI_OFF, .style_class=
"linked") {
86 ui_button(obj, .icon =
UI_ICON_GO_BACK, .onclick = action_go_back);
87 ui_button(obj, .icon =
UI_ICON_GO_FORWARD, .onclick = action_go_forward);
88 }
89
90 ui_path_textfield(obj, .fill =
UI_ON, .getpathelm = dav_get_pathelm, .onactivate = action_path_selected, .varname =
"path");
91 ui_progressspinner(obj, .value = wdata->progress);
92 }
93
94
95 UiModel* model = ui_model(obj->ctx,
UI_ICON_TEXT,
"Name",
UI_STRING_FREE,
"Flags",
UI_STRING,
"Type",
UI_STRING_FREE,
"Last Modified",
UI_STRING_FREE,
"Size", -
1);
96 model->columnsize[
0] = -
1;
97 model->columnsize[
2] =
150;
98 model->getvalue = (ui_getvaluefunc) window_resource_table_getvalue;
99 ui_table(obj,
100 .fill =
UI_ON,
101 .model = model,
102 .onselection = action_list_selection,
103 .onactivate = action_list_activate,
104 .ondragstart = action_dnd_start,
105 .ondragcomplete = action_dnd_end,
106 .ondrop = action_dnd_drop,
107 .varname =
"reslist",
108 .multiselection =
TRUE,
109 .contextmenu = contextmenu);
110
111
112
113 ui_hbox(obj, .fill =
UI_OFF) {
114 ui_label(obj, .label =
"");
115 }
116
117 return obj;
118 }
119
120 void* window_resource_table_getvalue(DavResource *res,
int col) {
121 switch (col) {
122 case 0: {
123 return res->iscollection ? folder_icon : file_icon;
124 }
125 case 1: {
126 return res->name;
127 }
128 case 2: {
129 char *keyprop = dav_get_string_property_ns(
130 res,
131 DAV_NS,
132 "crypto-key");
133 DavXmlNode *lockdiscovery = dav_get_property(res,
"D:lockdiscovery");
134 char *executable = dav_get_string_property_ns(
135 res,
136 "http://apache.org/dav/props/",
137 "executable");
138 cxmutstr flags = cx_asprintf(
"%s%s%s",
139 appsettings_get_cryptoflag(keyprop ?
1 :
0),
140 appsettings_get_lockflag(lockdiscovery ?
1 :
0),
141 appsettings_get_execflag(executable ?
1 :
0));
142 return flags.ptr;
143 }
144 case 3: {
145 return res->iscollection ?
"Collection" : (res->contenttype ? res->contenttype :
"Resource");
146 }
147 case 4: {
148 return util_date_str(res->lastmodified);
149 }
150 case 5: {
151 return util_size_str(res->iscollection, res->contentlength);
152 }
153 }
154 return NULL;
155 }
156
157 void window_progress(MainWindow *win,
int on) {
158 ui_set(win->progress, on);
159 }
160
161 void action_dnd_start(UiEvent *event,
void *data) {
162
163 char *uri =
"file:///export/home/olaf/test.txt";
164 ui_selection_seturis(event->eventdata, &uri,
1);
165 }
166
167 void action_dnd_end(UiEvent *event,
void *data) {
168
169 }
170
171
172
173
174 static void resourceviewer_close(UiEvent *event,
void *data) {
175 DavResourceViewer *doc = data;
176 doc->window_closed =
TRUE;
177 if(doc->loaded) {
178 dav_resourceviewer_destroy(doc);
179 }
180
181 if (doc->tmp_file) {
182 unlink(doc->tmp_file);
183 free(doc->tmp_file);
184 }
185 }
186
187 void resourceviewer_new(DavBrowser *browser,
const char *path, DavResourceViewType type) {
188 const char *name = util_resource_name(path);
189 UiObject *win = ui_simple_window(name,
NULL);
190 ui_window_size(win,
600,
600);
191
192 ui_headerbar(win, .showtitle =
TRUE) {
193 ui_headerbar_start(win) {
194 ui_button(win, .label =
"Save", .onclick = action_resourceviewer_save, .groups =
UI_GROUPS(
RESOURCEVIEWER_STATE_MODIFIED));
195 }
196 }
197
198 DavResourceViewer *doc = dav_resourceviewer_create(win, browser->sn, path, type);
199 ui_attach_document(win->ctx, doc);
200 ui_context_closefunc(win->ctx, resourceviewer_close, doc);
201
202 ui_tabview(win, .tabview =
UI_TABVIEW_INVISIBLE, .varname =
"tabview") {
203
204 ui_tab(win,
NULL) {
205 ui_hbox(win, .margin =
16, .spacing =
10, .fill =
UI_OFF) {
206 ui_progressspinner(win, .varname =
"loading");
207 ui_label(win, .varname =
"message");
208 }
209 }
210
211
212 ui_tab(win,
NULL) {
213 ui_tabview0(win) {
214 if(type ==
DAV_RESOURCE_VIEW_TEXT) {
215 ui_tab(win,
"Content") {
216 ui_textarea(win, .varname =
"text", .onchange = action_resourceviewer_text_modified);
217 }
218 }
else if(type ==
DAV_RESOURCE_VIEW_IMAGE) {
219 ui_tab(win,
"Preview") {
220 ui_imageviewer(win, .varname =
"image");
221 }
222 }
223
224 ui_tab(win,
"Info") {
225 ui_grid(win, .margin =
16, .columnspacing =
30, .rowspacing =
6) {
226 ui_llabel(win, .label =
"URL");
227 ui_llabel(win, .varname =
"info_url");
228 ui_newline(win);
229
230 ui_llabel(win, .label =
"Name");
231 ui_llabel(win, .varname =
"info_name");
232 ui_newline(win);
233
234 ui_llabel(win, .label =
"Type");
235 ui_llabel(win, .varname =
"info_type");
236 ui_newline(win);
237
238 ui_llabel(win, .label =
"Encrypted");
239 ui_llabel(win, .varname =
"info_encrypted");
240 ui_newline(win);
241
242 ui_llabel(win, .label =
"ETag");
243 ui_llabel(win, .varname =
"info_etag");
244 ui_newline(win);
245
246 ui_llabel(win, .label =
"Size");
247 ui_llabel(win, .varname =
"info_size");
248 ui_newline(win);
249 }
250 }
251
252 ui_tab(win,
"Properties") {
253 UiModel* model = ui_model(win->ctx,
UI_STRING,
"Namespace",
UI_STRING,
"Name",
UI_STRING,
"Value", -
1);
254 model->getvalue = (ui_getvaluefunc) resourceviewer_proplist_getvalue;
255 ui_table(win, .fill =
UI_ON, .model = model, .varname =
"properties", .onselection = action_resourceviewer_property_select, .onactivate = action_resourceviewer_property_activate);
256 ui_hbox(win, .fill =
UI_OFF, .margin =
4, .spacing =
4) {
257 ui_button(win, .label =
"Add", .onclick = action_resourceviewer_property_add);
258 ui_button(win, .label =
"Edit", .onclick = action_resourceviewer_property_edit, .groups =
UI_GROUPS(
RESOURCEVIEWER_STATE_PROP_SELECTED));
259 ui_button(win, .label =
"Remove", .onclick = action_resourceviewer_property_remove, .groups =
UI_GROUPS(
RESOURCEVIEWER_STATE_PROP_SELECTED));
260 }
261 }
262 }
263 }
264 }
265
266 dav_resourceviewer_load(win, doc);
267
268 ui_show(win);
269 }
270
271 void* resourceviewer_proplist_getvalue(DavPropertyList *property,
int col) {
272 switch(col) {
273 case 0: {
274 return property->ns;
275 }
276 case 1: {
277 return property->name;
278 }
279 case 2: {
280 return property->value_simplified ? property->value_simplified : property->value_full;
281 }
282 }
283
284 return NULL;
285 }
286
287
288 typedef struct AuthDialogWindow {
289 UiString *user;
290 UiString *password;
291 } AuthDialogWindow;
292
293 static void auth_dialog_action(UiEvent *event,
void *data) {
294 SessionAuthData *auth = data;
295 AuthDialogWindow *wdata = event->window;
296 int result =
0;
297 if(event->intval ==
4) {
298 char *user = ui_get(wdata->user);
299 char *password = ui_get(wdata->password);
300 davbrowser_auth_set_user_pwd(auth, user, password);
301 result =
1;
302 }
303 ui_condvar_signal(auth->cond,
NULL, result);
304 ui_close(event->obj);
305 }
306
307 void auth_dialog(SessionAuthData *auth) {
308 UiObject *obj = ui_dialog_window(auth->obj,
309 .title =
"Authentication",
310 .lbutton1 =
"Cancel",
311 .rbutton4 =
"Connect",
312 .default_button =
4,
313 .show_closebutton =
UI_OFF,
314 .onclick = auth_dialog_action,
315 .onclickdata = auth);
316
317 AuthDialogWindow *wdata = ui_malloc(obj->ctx,
sizeof(AuthDialogWindow));
318 wdata->user = ui_string_new(obj->ctx,
NULL);
319 wdata->password = ui_string_new(obj->ctx,
NULL);
320 obj->window = wdata;
321
322 ui_grid(obj, .margin =
20, .columnspacing =
12, .rowspacing =
12) {
323 cxmutstr heading = cx_asprintf(
"Authentication required for: %s", auth->sn->base_url);
324 ui_llabel(obj, .label = heading.ptr, .colspan =
2);
325 free(heading.ptr);
326 ui_newline(obj);
327
328 ui_llabel(obj, .label =
"User");
329 ui_textfield(obj, .value = wdata->user, .hexpand =
TRUE);
330 ui_newline(obj);
331
332 ui_llabel(obj, .label =
"Password");
333 ui_passwordfield(obj, .value = wdata->password, .hexpand =
TRUE);
334 }
335
336 if(auth->user) {
337 ui_set(wdata->user, auth->user);
338 }
339
340 ui_show(obj);
341 }
342
343
344 void transfer_window_init(UiObject *dialog, ui_callback btncallback) {
345 ui_window_size(dialog,
550,
120);
346 ui_grid(dialog, .margin =
10, .spacing =
10, .fill =
TRUE) {
347 ui_llabel(dialog, .varname =
"label_top_left", .hexpand =
TRUE);
348 ui_rlabel(dialog, .varname =
"label_top_right");
349 ui_newline(dialog);
350
351 ui_progressbar(dialog, .varname =
"progressbar", .min =
0, .max =
100, .colspan =
2, .hexpand =
TRUE);
352 ui_newline(dialog);
353
354 ui_llabel(dialog, .varname =
"label_bottom_left", .hexpand =
TRUE);
355 ui_rlabel(dialog, .varname =
"label_bottom_right");
356 ui_newline(dialog);
357
358 ui_label(dialog, .vexpand =
TRUE);
359 ui_newline(dialog);
360
361 ui_hbox(dialog, .colspan =
2, .hexpand =
TRUE) {
362 ui_label(dialog, .hexpand =
TRUE);
363 ui_button(dialog, .label =
"Cancel", .onclick = btncallback);
364 }
365 }
366 }
367
368
369 static UiPathElm* dav_get_pathelm(
const char *full_path,
size_t len,
size_t *ret_nelm,
void* data) {
370 if (len ==
0) {
371 *ret_nelm =
0;
372 return NULL;
373 }
374
375 cxstring fpath = cx_strn(full_path, len);
376 int protocol =
0;
377 if (cx_strcaseprefix(fpath,
CX_STR(
"http://"))) {
378 protocol =
7;
379 }
else if (cx_strcaseprefix(fpath,
CX_STR(
"https://"))) {
380 protocol =
8;
381 }
382
383 size_t start =
0;
384 size_t end =
0;
385 for (
size_t i = protocol; i < len; i++) {
386 if (full_path[i] ==
'/') {
387 end = i;
388 break;
389 }
390 }
391
392 int skip =
0;
393 if (end ==
0) {
394
395 end = len >
0 && full_path[
0] ==
'/' ?
1 : len;
396 }
else if (end +
1 <= len) {
397 skip++;
398 }
399
400
401 cxmutstr base = cx_strdup(cx_strn(full_path, end));
402 cxmutstr base_path = cx_strcat(
2, cx_strcast(base),
CX_STR(
"/"));
403 cxstring path = cx_strsubs(fpath, end + skip);
404
405 cxstring trail = cx_str(len >
0 && full_path[len-
1] ==
'/' ?
"/" :
"");
406
407 cxstring *pathelms;
408 size_t nelm =
0;
409
410 if (path.length >
0) {
411 nelm = cx_strsplit_a(cxDefaultAllocator, path,
CX_STR(
"/"),
4096, &pathelms);
412 if (nelm ==
0) {
413 *ret_nelm =
0;
414 return NULL;
415 }
416 }
417
418 UiPathElm* elms = (UiPathElm*) calloc(nelm +
1,
sizeof (UiPathElm));
419 size_t n = nelm +
1;
420 elms[
0].name = base.ptr;
421 elms[
0].name_len = base.length;
422 elms[
0].path = base_path.ptr;
423 elms[
0].path_len = base_path.length;
424
425 int j =
1;
426 for (
int i =
0; i < nelm; i++) {
427 cxstring c = pathelms[i];
428 if (c.length ==
0) {
429 if (i ==
0) {
430 c.length =
1;
431 }
else {
432 n--;
433 continue;
434 }
435 }
436
437 cxmutstr m = cx_strdup(c);
438 elms[j].name = m.ptr;
439 elms[j].name_len = m.length;
440
441 size_t elm_path_len = c.ptr + c.length - full_path;
442 cxmutstr elm_path = cx_strcat(
2, cx_strn(full_path, elm_path_len), i+
1 < nelm ?
CX_STR(
"/") : trail);
443 elms[j].path = elm_path.ptr;
444 elms[j].path_len = elm_path.length;
445
446 j++;
447 }
448 *ret_nelm = n;
449
450 return elms;
451 }
452
453 void action_go_parent(UiEvent *event,
void *data) {
454 DavBrowser *browser = event->document;
455 davbrowser_navigation_parent(event->obj, browser);
456 }
457
458 void action_go_back(UiEvent *event,
void *data) {
459 DavBrowser *browser = event->document;
460 davbrowser_navigation_back(event->obj, browser);
461 }
462
463 void action_go_forward(UiEvent *event,
void *data) {
464 DavBrowser *browser = event->document;
465 davbrowser_navigation_forward(event->obj, browser);
466 }
467
468 void action_path_selected(UiEvent *event,
void *data) {
469 DavBrowser *browser = event->document;
470 char *path = event->eventdata;
471 if (path && strlen(path) >
0) {
472 davbrowser_query_url(event->obj, browser, path);
473 }
474 }
475
476 void action_list_selection(UiEvent *event,
void *data) {
477 UiListSelection *selection = event->eventdata;
478 if (selection->count >
0) {
479 ui_set_group(event->obj->ctx,
APP_STATE_BROWSER_SELECTION);
480 }
else {
481 ui_unset_group(event->obj->ctx,
APP_STATE_BROWSER_SELECTION);
482 }
483 }
484
485 void action_list_activate(UiEvent *event,
void *data) {
486 UiListSelection *selection = event->eventdata;
487 DavBrowser *browser = event->document;
488
489 if (selection->count ==
1) {
490 DavResource *res = ui_list_get(browser->resources, selection->rows[
0]);
491 if (res) {
492 if (res->iscollection) {
493 davbrowser_query_path(event->obj, browser, res->path);
494 }
else {
495 davbrowser_open_resource(event->obj, browser, res,
NULL);
496 }
497 }
498 }
499 }
500
501 static int filelist_uri2path(UiFileList *files) {
502 for(
int i=
0;i<files->nfiles;i++) {
503 char *uri = files->files[i];
504 if(uri[
0] ==
'/') {
505 continue;
506 }
507
508 cxstring uri_s = cx_str(uri);
509 if(!cx_strprefix(uri_s,
CX_STR(
"file://"))) {
510 return 1;
511 }
512
513 files->files[i] = cx_strdup(cx_strsubs(uri_s,
7)).ptr;
514 free(uri);
515 }
516
517 return 0;
518 }
519
520 void action_dnd_drop(UiEvent *event,
void *data) {
521 UiDnD *dnd = event->eventdata;
522 UiFileList files = ui_selection_geturis(dnd);
523 if(files.nfiles ==
0) {
524 return;
525 }
526
527 if(filelist_uri2path(&files)) {
528 ui_dnd_accept(dnd,
FALSE);
529 ui_filelist_free(files);
530 return;
531 }
532
533 davbrowser_upload_files(event->obj, event->document, files);
534 }
535
536
537
538
539 void action_resourceviewer_text_modified(UiEvent *event,
void *data) {
540 DavResourceViewer *doc = event->document;
541 if(doc->loaded) {
542 ui_set_group(event->obj->ctx,
RESOURCEVIEWER_STATE_MODIFIED);
543 }
544 }
545
546 void action_resourceviewer_save(UiEvent *event,
void *data) {
547 DavResourceViewer *doc = event->document;
548 dav_resourceviewer_save(event->obj, doc);
549 }
550
551 void action_resourceviewer_property_select(UiEvent *event,
void *data) {
552 DavResourceViewer *doc = event->document;
553 UiListSelection *selection = event->eventdata;
554 if(selection->count ==
1) {
555 ui_set_group(event->obj->ctx,
RESOURCEVIEWER_STATE_PROP_SELECTED);
556 doc->selected_property = ui_list_get(doc->properties, selection->rows[
0]);
557 }
else {
558 ui_unset_group(event->obj->ctx,
RESOURCEVIEWER_STATE_PROP_SELECTED);
559 doc->selected_property =
NULL;
560 }
561 }
562
563 void action_resourceviewer_property_activate(UiEvent *event,
void *data) {
564 action_resourceviewer_property_select(event, data);
565 action_resourceviewer_property_edit(event, data);
566 }
567
568
569 typedef struct PropertyDialog {
570 UiInteger *type;
571 UiString *ns;
572 UiString *name;
573 UiText *value;
574 } PropertyDialog;
575
576 static void propertydialog_action(UiEvent *event,
void *data) {
577 DavResourceViewer *res = data;
578 if(event->intval ==
4) {
579 char *ns = ui_get(res->property_ns);
580 char *name = ui_get(res->property_name);
581 int type = ui_get(res->property_type);
582 char *nsdef = ui_get(res->property_nsdef);
583 char *value = ui_get(res->property_value);
584
585 if(strlen(ns) ==
0) {
586 ui_set(res->property_errormsg,
"Namespace must not be empty!");
587 return;
588 }
589 if(strlen(name) ==
0) {
590 ui_set(res->property_errormsg,
"Name must not be empty!");
591 return;
592 }
593
594 char *textvalue =
NULL;
595 DavXmlNode *xmlvalue =
NULL;
596 if(type ==
0) {
597
598 textvalue = value;
599 }
else {
600
601 }
602
603 DavBool add =
FALSE;
604 if(res->edit_property) {
605 if(strcmp(res->edit_property->ns, ns) || strcmp(res->edit_property->name, name)) {
606
607 dav_resourceviewer_property_remove(res, res->edit_property);
608 add =
TRUE;
609 }
610 }
else {
611 add =
TRUE;
612 }
613
614 if(add) {
615 if(textvalue) {
616 dav_resourceviewer_property_add_text(res, ns, name, textvalue);
617 }
else {
618 dav_resourceviewer_property_add_xml(res, ns, name, nsdef, xmlvalue);
619 }
620 }
else {
621 if(textvalue) {
622 dav_resourceviewer_property_update_text(res, res->edit_property, textvalue);
623 }
else {
624 dav_resourceviewer_property_update_xml(res, res->edit_property, xmlvalue);
625 }
626 }
627 }
628 ui_close(event->obj);
629 }
630
631 static void prop_type_changed(UiEvent *event,
void *data) {
632 DavResourceViewer *res = data;
633 switch(ui_get(res->property_type)) {
634 case 0: {
635 ui_unset_group(event->obj->ctx,
RESOURCEVIEWER_STATE_PROP_XML);
636 break;
637 }
638 case 1: {
639 ui_set_group(event->obj->ctx,
RESOURCEVIEWER_STATE_PROP_XML);
640 char *ns = ui_get(res->property_ns);
641 char *nsdef = ui_get(res->property_nsdef);
642 if(strlen(nsdef) ==
0) {
643 cxmutstr def = cx_asprintf(
"xmlns:x0=\"%s\"", ns);
644 ui_set(res->property_nsdef, def.ptr);
645 free(def.ptr);
646 }
647
648 break;
649 }
650 }
651 }
652
653 static void edit_property_dialog(DavResourceViewer *res,
const char *title, DavPropertyList *prop) {
654 res->edit_property = prop;
655
656 UiObject *obj = ui_dialog_window(res->obj,
657 .title = title,
658 .show_closebutton =
UI_OFF,
659 .lbutton1 =
"Cancel",
660 .rbutton4 =
"Save",
661 .default_button =
4,
662 .onclick = propertydialog_action,
663 .onclickdata = res,
664 .width =
600,
665 .height =
500);
666
667 ui_grid(obj, .margin =
16, .columnspacing =
8, .rowspacing =
12) {
668 ui_llabel(obj, .label =
"Namespace");
669 ui_textfield(obj, .hexpand =
TRUE, .value = res->property_ns);
670 ui_newline(obj);
671
672 ui_llabel(obj, .label =
"Property Name");
673 ui_textfield(obj, .hexpand =
TRUE, .value = res->property_name);
674 ui_newline(obj);
675
676 ui_llabel(obj, .label =
"Type");
677 ui_hbox(obj, .spacing =
8, .colspan =
2) {
678 ui_radiobutton(obj, .label =
"Text", .value = res->property_type, .onchange = prop_type_changed, .onchangedata = res);
679 ui_radiobutton(obj, .label =
"XML", .value = res->property_type, .onchange = prop_type_changed, .onchangedata = res);
680 }
681 ui_newline(obj);
682
683 ui_llabel(obj, .label =
"Namespace Declarations");
684 ui_textfield(obj, .hexpand =
TRUE, .value = res->property_nsdef, .groups =
UI_GROUPS(
RESOURCEVIEWER_STATE_PROP_XML));
685 ui_newline(obj);
686
687 ui_textarea(obj, .value = res->property_value, .hexpand =
TRUE, .vexpand =
TRUE, .colspan =
2);
688 ui_newline(obj);
689
690 ui_llabel(obj, .colspan =
2, .value = res->property_errormsg);
691 }
692
693 if(prop && prop->ns && prop->name) {
694 ui_set(res->property_ns, prop->ns);
695 ui_set(res->property_name, prop->name);
696 if(prop->value_full) {
697 ui_set(res->property_type,
0);
698 ui_set(res->property_nsdef,
"");
699 ui_set(res->property_value, prop->value_full);
700 ui_unset_group(obj->ctx,
RESOURCEVIEWER_STATE_PROP_XML);
701 }
else if(prop->xml) {
702 ui_set(res->property_type,
1);
703 cxmutstr xml;
704 cxmutstr nsdef;
705 property_xml2str(prop->xml, prop->ns, &xml, &nsdef);
706 ui_set(res->property_nsdef, nsdef.ptr);
707 ui_set(res->property_value, xml.ptr);
708 free(xml.ptr);
709 free(nsdef.ptr);
710 ui_set_group(obj->ctx,
RESOURCEVIEWER_STATE_PROP_XML);
711 }
712 }
else {
713 ui_set(res->property_ns,
"");
714 ui_set(res->property_name,
"");
715 ui_set(res->property_nsdef,
"");
716 ui_set(res->property_type,
0);
717 ui_set(res->property_value,
"");
718 }
719
720 ui_set(res->property_errormsg,
"");
721
722 ui_show(obj);
723 }
724
725 void action_resourceviewer_property_add(UiEvent *event,
void *data) {
726 DavResourceViewer *doc = event->document;
727 edit_property_dialog(doc,
"Add Property",
NULL);
728 }
729
730 void action_resourceviewer_property_edit(UiEvent *event,
void *data) {
731 DavResourceViewer *doc = event->document;
732 edit_property_dialog(doc,
"Edit Property", doc->selected_property);
733 }
734
735 void action_resourceviewer_property_remove(UiEvent *event,
void *data) {
736 DavResourceViewer *doc = event->document;
737 if(!doc->selected_property) {
738 return;
739 }
740 dav_resourceviewer_property_remove(doc, doc->selected_property);
741 }
742
743