1# $Id$
2#
3# Bookmarks (XEP-0048) support (conference bookmarks in roster)
4#
5# In addition to XEP-0048, Tkabber stores roster groups using
6# proprietory namespace tkabber:bookmarks:groups inside
7# jabber:iq:private storage (XEP-0049)
8#
9#   tkabber:bookmarks:groups description:
10#
11#   setting:
12#   <iq type='set' id='setgroups'>
13#	<query xmlns='jabber:iq:private'>
14#	    <storage xmlns='tkabber:bookmarks:groups'>
15#		<conference jid='talks@conference.jabber.ru'>
16#		    <group>Conferences</group>
17#		    <group>jabber.ru</group>
18#		</conference>
19#	    </storage>
20#	</query>
21#   </iq>
22#
23#   getting:
24#   <iq type='get' id='getgroups'>
25#	<query xmlns='jabber:iq:private'>
26#	    <storage xmlns='tkabber:bookmarks:groups'/>
27#	</query>
28#   </iq>
29#
30
31package require xmpp::roster::bookmarks
32
33namespace eval conferences {
34    # variable to store roster conference bookmarks
35    array set bookmarks {}
36
37    set ::NS(tkabber:groups) "tkabber:bookmarks:groups"
38
39    custom::defvar options(ignore_autojoin) 0 \
40	[::msgcat::mc "Ignore autojoin option and do not automatically join\
41		       conference rooms on login."] \
42	-type boolean -group Chat
43
44    custom::defvar options(roster_group) [::msgcat::mc "Conferences"] \
45	[::msgcat::mc "Default group for conferences in roster."] \
46	-type string -group Hidden
47}
48
49###############################################################################
50#
51#   Free bookmarks on disconnect
52#
53
54proc conferences::free_bookmarks {xlib} {
55    variable bookmarks
56
57    array unset bookmarks $xlib,*
58}
59
60hook::add disconnected_hook [namespace current]::conferences::free_bookmarks
61
62###############################################################################
63#
64#   Retrieve bookmarks on connect
65#
66
67proc conferences::request_bookmarks {xlib} {
68    variable bookmarks
69    variable responds
70
71    set responds($xlib) 0
72    array unset bookmarks $xlib,*
73    set bookmarks($xlib) {}
74
75    ::xmpp::roster::bookmarks::retrieve $xlib \
76	    -command [list [namespace current]::process_bookmarks $xlib]
77
78    ::xmpp::private::retrieve $xlib [list [::xmpp::xml::create storage \
79						-xmlns $::NS(tkabber:groups)]] \
80	    -command [list [namespace current]::process_groups $xlib]
81}
82
83hook::add connected_hook [namespace current]::conferences::request_bookmarks 20
84
85proc conferences::process_bookmarks {xlib status bmlist} {
86    variable bookmarks
87    variable responds
88    global NS
89
90    if {$status != "ok"} return
91
92    incr responds($xlib)
93
94    foreach bookmark $bmlist {
95	create_muc_bookmark $xlib $bookmark
96    }
97
98    if {$responds($xlib) < 2} return
99
100    push_bookmarks_to_roster $xlib
101    after idle [list [namespace current]::autojoin_groups $xlib]
102}
103
104proc conferences::process_groups {xlib status xmlList} {
105    variable bookmarks
106    variable responds
107    global NS
108
109    if {$status != "ok"} return
110
111    incr responds($xlib)
112
113    foreach xml $xmlList {
114	::xmpp::xml::split $xml tag xmlns attrs cdata subels
115
116	if {$xmlns == $NS(tkabber:groups)} {
117	    foreach bookmark $subels {
118		create_muc_bmgroup $xlib $bookmark
119	    }
120	}
121    }
122
123    if {$responds($xlib) < 2} return
124
125    push_bookmarks_to_roster $xlib
126    after idle [list [namespace current]::autojoin_groups $xlib]
127}
128
129proc conferences::create_muc_bookmark {xlib bookmark args} {
130    variable bookmarks
131
132    set merge 0
133    foreach {opt val} $args {
134	switch -- $opt {
135	    -merge { set merge $val }
136	    default {
137		return -code error "Bad option \"$opt\": must be -merge"
138	    }
139	}
140    }
141
142    array set n $bookmark
143
144    set jid [::xmpp::jid::normalize $n(jid)]
145
146    if {$merge && [info exists bookmarks($xlib,jid,$jid)]} {
147	return 0
148    } else {
149	if {[lsearch -exact $bookmarks($xlib) $jid] < 0} {
150	    lappend bookmarks($xlib) $jid
151	}
152	set bookmarks($xlib,jid,$jid) $jid
153
154	set bookmarks($xlib,name,$jid) ""
155	set bookmarks($xlib,nick,$jid) ""
156	set bookmarks($xlib,password,$jid) ""
157	set bookmarks($xlib,autojoin,$jid) 0
158
159	if {[info exists n(name)]} {
160	    set bookmarks($xlib,name,$jid) $n(name)
161	}
162	if {[info exists n(nick)]} {
163	    set bookmarks($xlib,nick,$jid) $n(nick)
164	}
165	if {[info exists n(password)]} {
166	    set bookmarks($xlib,password,$jid) $n(password)
167	}
168	if {[info exists n(autojoin)]} {
169	    set bookmarks($xlib,autojoin,$jid) $n(autojoin)
170	}
171
172	if {![info exists bookmarks($xlib,groups,$jid)]} {
173	    set bookmarks($xlib,groups,$jid) {}
174	    set bookmarks($xlib,hasgroups,$jid) 0
175	} else {
176	    set bookmarks($xlib,hasgroups,$jid) 1
177	}
178
179	return 1
180    }
181}
182
183proc conferences::create_muc_bmgroup {xlib xmldata args} {
184    variable bookmarks
185
186    set merge 0
187    foreach {opt val} $args {
188	switch -- $opt {
189	    -merge { set merge $val }
190	    default {
191		return -code error "Bad option \"$opt\":\
192		    must be -merge"
193	    }
194	}
195    }
196
197    ::xmpp::xml::split $xmldata tag xmlns attrs cdata subels
198
199    if {![string equal $tag conference]} return
200
201    set jid [::xmpp::jid::normalize [::xmpp::xml::getAttr $attrs jid]]
202
203    set groups [list]
204    foreach subel $subels {
205	::xmpp::xml::split $subel stag sxmlns sattrs scdata ssubels
206	if {[string equal $stag group]} {
207	    lappend groups $scdata
208	}
209    }
210
211    if {$merge && [info exists bookmarks($xlib,jid,$jid)]
212		&& $bookmarks($xlib,hasgroups,$jid)} {
213	return 0
214    } else {
215	set bookmarks($xlib,groups,$jid) $groups
216	set bookmarks($xlib,hasgroups,$jid) 1
217	return 1
218    }
219}
220
221proc conferences::push_bookmarks_to_roster {xlib} {
222    variable bookmarks
223
224    foreach idx [array names bookmarks $xlib,jid,*] {
225	set jid $bookmarks($idx)
226	client:roster_push $xlib $jid \
227			   -name $bookmarks($xlib,name,$jid) \
228			   -groups $bookmarks($xlib,groups,$jid) \
229			   -subscription bookmark
230	roster::override_category_and_subtype $xlib $jid conference ""
231    }
232}
233
234###############################################################################
235#
236#   Store bookmarks
237#
238
239proc conferences::serialize_bookmarks {xlib} {
240    variable bookmarks
241
242    set bookmarklist {}
243    set grouplist {}
244    foreach jid $bookmarks($xlib) {
245	set name $bookmarks($xlib,name,$jid)
246	set autojoin $bookmarks($xlib,autojoin,$jid)
247
248	set vars [list jid $jid name $name autojoin $autojoin]
249
250	if {$bookmarks($xlib,nick,$jid) != ""} {
251	    lappend vars nick $bookmarks($xlib,nick,$jid)
252	}
253	if {$bookmarks($xlib,password,$jid) != ""} {
254	    lappend vars password $bookmarks($xlib,password,$jid)
255	}
256	lappend bookmarklist $vars
257
258	set vars [list jid $jid]
259	set groups {}
260	foreach group $bookmarks($xlib,groups,$jid) {
261	    lappend groups [::xmpp::xml::create group \
262				    -cdata $group]
263	}
264	lappend grouplist [::xmpp::xml::create conference \
265				-attrs $vars \
266				-subelements $groups]
267    }
268
269    return [list $bookmarklist \
270		 [::xmpp::xml::create storage \
271			    -xmlns $::NS(tkabber:groups) \
272			    -subelements $grouplist]]
273}
274
275proc conferences::store_bookmarks {xlib args} {
276    set command [list [namespace current]::store_bookmarks_result $xlib]
277    foreach {opt val} $args {
278	switch -- $opt {
279	    -command { set command $val }
280	    default {
281		return -code error "Bad option \"$opt\":\
282		    must be -command"
283	    }
284	}
285    }
286
287    lassign [serialize_bookmarks $xlib] bookmarks groups
288
289    ::xmpp::roster::bookmarks::store $xlib $bookmarks -command $command
290    ::xmpp::private::store $xlib [list $groups] -command $command
291}
292
293proc conferences::store_bookmarks_result {xlib res child} {
294
295    if {$res == "ok"} return
296
297    if {[winfo exists .store_bookmarks_error]} {
298	return
299    }
300
301    MessageDlg .store_bookmarks_error -aspect 50000 -icon error \
302	-message [::msgcat::mc "Storing conferences failed: %s" \
303			 [error_to_string $child]] \
304	-type user -buttons ok -default 0 -cancel 0
305}
306
307###############################################################################
308#
309#   Menu item for conference window
310#
311
312proc conferences::add_conference_menu_item {m xlib jid} {
313    set chatid [chat::chatid $xlib $jid]
314
315    if {[info exists ::muc::muc_password($chatid)]} {
316	set password $::muc::muc_password($chatid)
317    } else {
318	set password ""
319    }
320
321    $m add command -label [::msgcat::mc "Add conference to roster..."] \
322	-command [list [namespace current]::add_conference_dialog $xlib \
323		       -group [::xmpp::jid::node $jid] \
324		       -server [::xmpp::jid::server $jid] \
325		       -password $password]
326}
327
328hook::add chat_create_conference_menu_hook \
329    [namespace current]::conferences::add_conference_menu_item 35
330
331###############################################################################
332#
333#   Add conference to roster dialog
334#
335
336proc conferences::add_conference_dialog {xlib args} {
337    variable options
338    variable gra_group
339    variable gra_server
340    variable gra_nick
341    variable gra_password
342    variable gra_autojoin
343    variable gra_xlib
344
345    if {[lempty [connections]]} return
346
347    set gw .addgroup
348    catch { destroy $gw }
349
350    if {$xlib == ""} {
351	set xlib [lindex [connections] 0]
352    }
353    set gra_server conference.[connection_server $xlib]
354    set gra_group ""
355    set gra_password ""
356    set gra_autojoin 0
357    catch { unset gra_nick }
358
359    foreach {key val} $args {
360	switch -- $key {
361	    -group { set gra_group $val }
362	    -server { set gra_server $val }
363	    -nick { set gra_nick $val }
364	    -password { set gra_password $val }
365	    -autojoin { set gra_autojoin $val }
366	}
367    }
368
369    if {![info exists gra_nick]} {
370	set gra_nick [get_group_nick $xlib [::xmpp::jid::jid $gra_group $gra_server]]
371    }
372    set gra_xlib [connection_jid $xlib]
373
374    Dialog $gw -title [::msgcat::mc "Add Conference to Roster"] -separator 1 -anchor e \
375	    -default 0 -cancel 1 -modal none
376
377    set gf [$gw getframe]
378    grid columnconfigure $gf 0 -weight 0
379    grid columnconfigure $gf 1 -weight 1
380
381    label $gf.lgroup -text [::msgcat::mc "Conference:"]
382    entry $gf.group -textvariable [namespace current]::gra_group
383    label $gf.lserver -text [::msgcat::mc "Server:"]
384    entry $gf.server -textvariable [namespace current]::gra_server
385    label $gf.lnick -text [::msgcat::mc "Nick:"]
386    entry $gf.nick -textvariable [namespace current]::gra_nick
387    label $gf.lpassword -text [::msgcat::mc "Password:"]
388    entry $gf.password -show * -textvariable [namespace current]::gra_password
389    checkbutton $gf.autojoin -text [::msgcat::mc "Automatically join conference upon connect"] \
390	-variable [namespace current]::gra_autojoin
391    label $gf.lrostergroup -text [::msgcat::mc "Roster group:"]
392    ComboBox $gf.rostergroup -textvariable [namespace current]::options(roster_group) \
393	-values [get_groups $xlib]
394
395    grid $gf.lgroup  -row 0 -column 0 -sticky e
396    grid $gf.group   -row 0 -column 1 -sticky ew
397    grid $gf.lserver -row 1 -column 0 -sticky e
398    grid $gf.server  -row 1 -column 1 -sticky ew
399    grid $gf.lnick -row 2 -column 0 -sticky e
400    grid $gf.nick  -row 2 -column 1 -sticky ew
401    grid $gf.lpassword -row 3 -column 0 -sticky e
402    grid $gf.password  -row 3 -column 1 -sticky ew
403    grid $gf.autojoin -row 4 -column 0 -sticky w -columnspan 2
404    grid $gf.lrostergroup  -row 5 -column 0 -sticky e
405    grid $gf.rostergroup   -row 5 -column 1 -sticky ew
406
407    if {[llength [connections]] > 1} {
408	foreach c [connections] {
409	    lappend connections [connection_jid $c]
410	}
411	label $gf.lconnection -text [::msgcat::mc "Connection:"]
412	ComboBox $gf.connection -textvariable [namespace current]::gra_xlib \
413				-values $connections -editable 0 \
414				-modifycmd [list [namespace current]::change_groups \
415						 $gf.rostergroup]
416
417	grid $gf.lconnection -row 6 -column 0 -sticky e
418	grid $gf.connection  -row 6 -column 1 -sticky ew
419    }
420
421
422    $gw add -text [::msgcat::mc "Add"] -command [list [namespace current]::add_conference $gw]
423    $gw add -text [::msgcat::mc "Cancel"] -command [list destroy $gw]
424
425    $gw draw $gf.group
426}
427
428proc conferences::change_groups {combo args} {
429    variable gra_xlib
430
431    foreach xlib [connections] {
432        if {[connection_jid $xlib] == $gra_xlib} {
433	    $combo configure -values [get_groups $xlib]
434	    return
435	}
436    }
437}
438
439proc conferences::get_groups {xlib} {
440    return [roster::get_groups $xlib \
441		-nested $::ifacetk::roster::options(nested) \
442		-delimiter $::ifacetk::roster::options(nested_delimiter) \
443		-undefined 0]
444}
445
446proc conferences::add_conference {gw} {
447    variable options
448    variable bookmarks
449    variable gra_group
450    variable gra_server
451    variable gra_nick
452    variable gra_password
453    variable gra_autojoin
454    variable gra_xlib
455
456    destroy $gw
457
458    set jid [::xmpp::jid::normalize ${gra_group}@$gra_server]
459    if {$options(roster_group) == ""} {
460	set groups {}
461    } else {
462	set groups [list $options(roster_group)]
463    }
464
465    foreach c [connections] {
466	if {[connection_jid $c] == $gra_xlib} {
467	    set xlib $c
468	}
469    }
470    if {![info exists xlib]} {
471	# Disconnect while dialog is opened
472	return
473    }
474
475    if {[info exists bookmarks($xlib,jid,$jid)]} {
476	update_bookmark $xlib $jid -name $gra_group -nick $gra_nick \
477			-password $gra_password -autojoin $gra_autojoin \
478			-groups $groups
479    } else {
480	add_bookmark $xlib $jid -name $gra_group -nick $gra_nick \
481		     -password $gra_password -autojoin $gra_autojoin \
482		     -groups $groups
483    }
484}
485
486###############################################################################
487#
488#   Add bookmark to roster
489#
490
491proc conferences::add_bookmark {xlib jid args} {
492    variable bookmarks
493
494    if {[info exists bookmarks($xlib,jid,$jid)]} return
495
496    foreach {key val} $args {
497	switch -- $key {
498	    -name { set name $val }
499	    -nick { set nick $val }
500	    -password { set password $val }
501	    -autojoin { set autojoin $val }
502	    -groups { set groups $val }
503	}
504    }
505
506    if {![info exists name]} {
507	set name [::xmpp::jid::node $jid]
508    }
509    if {![info exists nick]} {
510	set nick [get_group_nick $xlib $jid]
511    }
512    if {![info exists password]} {
513	set password ""
514    }
515    if {![info exists autojoin]} {
516	set autojoin 0
517    }
518    if {![info exists groups]} {
519	set groups {}
520    }
521
522    if {[lsearch -exact $bookmarks($xlib) $jid] < 0} {
523	lappend bookmarks($xlib) $jid
524    }
525    set bookmarks($xlib,jid,$jid) $jid
526    set bookmarks($xlib,name,$jid) $name
527    set bookmarks($xlib,nick,$jid) $nick
528    set bookmarks($xlib,password,$jid) $password
529    set bookmarks($xlib,autojoin,$jid) $autojoin
530    set bookmarks($xlib,groups,$jid) $groups
531    set bookmarks($xlib,hasgroups,$jid) 1
532
533    # TODO should we remove $jid from the roster if it is here?
534    client:roster_push $xlib $jid \
535		       -name $name \
536		       -groups $groups \
537		       -subscription bookmark
538    roster::override_category_and_subtype $xlib $jid conference ""
539    store_bookmarks $xlib
540}
541
542###############################################################################
543#
544#   Update bookmark in roster
545#
546
547proc conferences::update_bookmark {xlib jid args} {
548    variable bookmarks
549
550    set store 0
551
552    foreach {key val} $args {
553	switch -- $key {
554	    -name { set name $val }
555	    -nick { set nick $val }
556	    -password { set password $val }
557	    -autojoin { set autojoin $val }
558	    -groups { set groups $val }
559	}
560    }
561
562    if {[info exists name] && $name != $bookmarks($xlib,name,$jid)} {
563	set bookmarks($xlib,name,$jid) $name
564	set store 1
565    }
566    if {[info exists nick] && $nick != $bookmarks($xlib,nick,$jid)} {
567	set bookmarks($xlib,nick,$jid) $nick
568	set store 1
569    }
570    if {[info exists password] && $password != $bookmarks($xlib,password,$jid)} {
571	set bookmarks($xlib,password,$jid) $password
572	set store 1
573    }
574    if {[info exists autojoin] && $autojoin != $bookmarks($xlib,autojoin,$jid)} {
575	set bookmarks($xlib,autojoin,$jid) $autojoin
576	set store 1
577    }
578    if {[info exists groups] && [lsort $groups] != [lsort $bookmarks($xlib,groups,$jid)]} {
579	set bookmarks($xlib,groups,$jid) $groups
580	set store 1
581    }
582    if {$store} {
583	client:roster_push $xlib $jid \
584			   -name $bookmarks($xlib,name,$jid) \
585			   -groups $bookmarks($xlib,groups,$jid) \
586			   -subscription bookmark
587	roster::override_category_and_subtype $xlib $jid conference ""
588	store_bookmarks $xlib
589    }
590}
591
592###############################################################################
593#
594#   Add or update item in roster
595#
596
597proc conferences::send_bookmark {xlib jid} {
598
599    if {[roster::itemconfig $xlib $jid -subsc] != "bookmark"} return
600
601    set groups [roster::itemconfig $xlib $jid -group]
602
603    add_bookmark $xlib $jid -groups $groups
604    update_bookmark $xlib $jid -groups $groups
605
606    return stop
607}
608
609hook::add roster_send_item_hook [namespace current]::conferences::send_bookmark
610
611###############################################################################
612#
613#   Remove bookmark from roster
614#
615
616proc conferences::remove_bookmark {xlib jid} {
617    variable bookmarks
618
619    if {[roster::itemconfig $xlib $jid -subsc] != "bookmark"} return
620
621    if {![info exists bookmarks($xlib,jid,$jid)]} return
622
623    client:roster_push $xlib $jid \
624		       -name $bookmarks($xlib,name,$jid) \
625		       -groups $bookmarks($xlib,groups,$jid) \
626		       -subscription remove
627
628    if {[set idx [lsearch -exact $bookmarks($xlib) $jid]] >= 0} {
629	set bookmarks($xlib) [lreplace $bookmarks($xlib) $idx $idx]
630    }
631    catch { unset bookmarks($xlib,jid,$jid) }
632    catch { unset bookmarks($xlib,name,$jid) }
633    catch { unset bookmarks($xlib,nick,$jid) }
634    catch { unset bookmarks($xlib,password,$jid) }
635    catch { unset bookmarks($xlib,autojoin,$jid) }
636    catch { unset bookmarks($xlib,groups,$jid) }
637    catch { unset bookmarks($xlib,hasgroups,$jid) }
638
639    store_bookmarks $xlib
640
641    return stop
642}
643
644hook::add roster_remove_item_hook \
645    [namespace current]::conferences::remove_bookmark
646
647###############################################################################
648#
649#   Rename group in roster bookmarks
650#
651
652proc conferences::rename_group {xlib name new_name} {
653    variable bookmarks
654
655    set store 0
656    foreach idx [array names bookmarks $xlib,jid,*] {
657	set jid $bookmarks($idx)
658
659	set groups $bookmarks($xlib,groups,$jid)
660	if {[lcontain $groups $name] || \
661		($name == $roster::undef_group_name && $groups == {})} {
662	    set idx [lsearch -exact $groups $name]
663	    if {$new_name != ""} {
664		set groups [lreplace $groups $idx $idx $new_name]
665	    } else {
666		set groups [lreplace $groups $idx $idx]
667	    }
668	    set groups [lrmdups $groups]
669	    client:roster_push $xlib $jid \
670			       -name $bookmarks($xlib,name,$jid) \
671			       -groups $groups \
672			       -subscription bookmark
673	    roster::override_category_and_subtype $xlib $jid conference ""
674	    set bookmarks($xlib,groups,$jid) $groups
675	    set store 1
676	}
677    }
678    if {$store} {
679	store_bookmarks $xlib
680    }
681}
682
683hook::add roster_rename_group_hook \
684    [namespace current]::conferences::rename_group
685
686###############################################################################
687#
688#   Remove group name from roster bookmarks
689#
690
691proc conferences::remove_bookmarks_group {xlib name} {
692    variable bookmarks
693
694    set store 0
695    foreach idx [array names bookmarks $xlib,jid,*] {
696	set jid $bookmarks($idx)
697
698	set groups $bookmarks($xlib,groups,$jid)
699	if {[lcontain $groups $name] || \
700		(($name == $roster::undef_group_name) && ($groups == {}))} {
701
702	    client:roster_push $xlib $jid \
703			       -name $bookmarks($xlib,name,$jid) \
704			       -groups $groups \
705			       -subscription remove
706
707	    if {[set idx [lsearch -exact $bookmarks($xlib) $jid]] >= 0} {
708		set bookmarks($xlib) [lreplace $bookmarks($xlib) $idx $idx]
709	    }
710	    catch { unset bookmarks($xlib,jid,$jid) }
711	    catch { unset bookmarks($xlib,name,$jid) }
712	    catch { unset bookmarks($xlib,nick,$jid) }
713	    catch { unset bookmarks($xlib,password,$jid) }
714	    catch { unset bookmarks($xlib,autojoin,$jid) }
715	    catch { unset bookmarks($xlib,groups,$jid) }
716	    catch { unset bookmarks($xlib,hasgroups,$jid) }
717
718	    set store 1
719	}
720    }
721    if {$store} {
722	store_bookmarks $xlib
723    }
724}
725
726hook::add roster_remove_users_group_hook \
727    [namespace current]::conferences::remove_bookmarks_group
728
729###############################################################################
730#
731#   Join group on roster item doubleclick
732#
733
734proc conferences::join_group {xlib jid} {
735    variable bookmarks
736
737    set args {}
738    if {$bookmarks($xlib,nick,$jid) != ""} {
739	set nick $bookmarks($xlib,nick,$jid)
740    } else {
741	set nick [get_group_nick $xlib $jid]
742    }
743    if {$bookmarks($xlib,password,$jid) != ""} {
744	set password $bookmarks($xlib,password,$jid)
745    } else {
746	set password ""
747    }
748    muc::join_group_raise $xlib $jid $nick $password
749}
750
751###############################################################################
752#
753#   Join group during autojoin
754#
755
756proc conferences::autojoin_group {xlib jid} {
757    variable bookmarks
758
759    if {$bookmarks($xlib,nick,$jid) != ""} {
760	set nick $bookmarks($xlib,nick,$jid)
761    } else {
762	set nick [get_group_nick $xlib $jid]
763    }
764    if {$bookmarks($xlib,password,$jid) != ""} {
765	set password $bookmarks($xlib,password,$jid)
766    } else {
767	set password ""
768    }
769    after idle [list muc::join_group $xlib $jid $nick $password]
770}
771
772###############################################################################
773#
774#   Autojoin groups
775#
776
777proc conferences::autojoin_groups {xlib} {
778    variable options
779    variable bookmarks
780
781    if {$options(ignore_autojoin)} return
782
783    foreach idx [array names bookmarks $xlib,jid,*] {
784	set jid $bookmarks($idx)
785	set chatid [chat::chatid $xlib $jid]
786	if {$bookmarks($xlib,autojoin,$jid) && ![chat::is_opened $chatid]} {
787	    autojoin_group $xlib $jid
788	}
789    }
790}
791
792###############################################################################
793#
794#   "Join" item in roster conference popup menu
795#
796
797proc conferences::popup_menu {m xlib jid} {
798    variable bookmarks
799
800    set args {}
801    if {[roster::itemconfig $xlib $jid -subsc] == "bookmark"} {
802	if {$bookmarks($xlib,nick,$jid) != ""} {
803	    lappend args -nick $bookmarks($xlib,nick,$jid)
804	}
805	if {$bookmarks($xlib,password,$jid) != ""} {
806	    lappend args -password $bookmarks($xlib,password,$jid)
807	}
808    }
809
810    $m add command -label [::msgcat::mc "Join..."] \
811	-command [list eval [list join_group_dialog $xlib \
812				  -server [::xmpp::jid::server $jid] \
813				  -group [::xmpp::jid::node $jid]] \
814				  $args]
815
816    # TODO: Check for real MUC? Move to muc.tcl?
817    ::add_muc_menu_items $m $xlib $jid
818}
819
820hook::add roster_conference_popup_menu_hook \
821    [namespace current]::conferences::popup_menu 20
822
823###############################################################################
824#
825#   Roster doubleclick
826#
827
828proc conferences::roster_doubleclick {xlib jid category subtype} {
829    switch -- $category {
830	conference {
831	    if {[roster::itemconfig $xlib $jid -subsc] == "bookmark"} {
832		join_group $xlib $jid
833	    } else {
834		muc::join_group_raise $xlib $jid [get_group_nick $xlib $jid]
835	    }
836	    return stop
837	}
838    }
839}
840
841hook::add roster_jid_doubleclick \
842    [namespace current]::conferences::roster_doubleclick
843
844###############################################################################
845#
846#   Main menu setup
847#
848
849proc conferences::main_menu {} {
850    set m [.mainframe getmenu services]
851    $m insert 2 command -label [::msgcat::mc "Add conference to roster..."] \
852	-command [list [namespace current]::add_conference_dialog ""]
853}
854
855hook::add finload_hook [namespace current]::conferences::main_menu
856
857###############################################################################
858#
859#   Edit roster item
860#
861
862proc conferences::edit_item_setup {f xlib jid} {
863    variable egra_name
864    variable egra_nick
865    variable egra_password
866    variable egra_autojoin
867    variable bookmarks
868
869    if {[roster::itemconfig $xlib $jid -subsc] != "bookmark"} return
870
871    set tf [TitleFrame $f.prop \
872		-text [::msgcat::mc "Edit properties for %s" $jid]]
873    set slaves [pack slaves $f]
874    if {$slaves == ""} {
875	pack $tf -side top -expand yes -fill both
876    } else {
877	pack $tf -side top -expand yes -fill both -before [lindex $slaves 0]
878    }
879    set g [$tf getframe]
880
881    set egra_name $bookmarks($xlib,name,$jid)
882    set egra_autojoin [string is true -strict $bookmarks($xlib,autojoin,$jid)]
883    if {[info exists bookmarks($xlib,nick,$jid)]} {
884        set egra_nick $bookmarks($xlib,nick,$jid)
885    } else {
886        set egra_nick ""
887    }
888    if {[info exists bookmarks($xlib,password,$jid)]} {
889        set egra_password $bookmarks($xlib,password,$jid)
890    } else {
891        set egra_password ""
892    }
893
894    label $g.lname -text [string trim [::msgcat::mc "Name: "]]
895    entry $g.name -textvariable [namespace current]::egra_name
896    label $g.lnick -text [::msgcat::mc "Nick:"]
897    entry $g.nick -textvariable [namespace current]::egra_nick
898    label $g.lpassword -text [::msgcat::mc "Password:"]
899    entry $g.password -show * -textvariable [namespace current]::egra_password
900    checkbutton $g.autojoin \
901	-text [::msgcat::mc "Automatically join conference upon connect"] \
902        -variable [namespace current]::egra_autojoin
903    grid columnconfigure $g 0 -weight 0
904    grid columnconfigure $g 1 -weight 1
905
906    grid $g.lname  -row 0 -column 0 -sticky e
907    grid $g.name   -row 0 -column 1 -sticky ew
908    grid $g.lnick -row 1 -column 0 -sticky e
909    grid $g.nick  -row 1 -column 1 -sticky ew
910    grid $g.lpassword -row 2 -column 0 -sticky e
911    grid $g.password  -row 2 -column 1 -sticky ew
912    grid $g.autojoin -row 3 -column 0 -sticky w -columnspan 2
913
914    return stop
915}
916
917hook::add roster_itemedit_setup_hook \
918    [namespace current]::conferences::edit_item_setup
919
920proc conferences::commit_bookmark_changes {xlib jid groups} {
921    variable egra_name
922    variable egra_nick
923    variable egra_password
924    variable egra_autojoin
925
926    if {[roster::itemconfig $xlib $jid -subsc] != "bookmark"} return
927
928    plugins::conferences::update_bookmark $xlib $jid \
929	-name $egra_name -nick $egra_nick -password $egra_password \
930	-autojoin $egra_autojoin -groups $groups
931
932    return stop
933}
934
935hook::add roster_itemedit_commit_hook \
936    [namespace current]::conferences::commit_bookmark_changes
937
938###############################################################################
939
940proc conferences::disco_node_menu_setup {m bw tnode data parentdata} {
941    lassign $data type xlib jid node
942    lassign $parentdata ptype pxlib pjid pnode
943    switch -- $type {
944	item -
945	item2 {
946	    set identities [::disco::browser::get_identities $bw $tnode]
947
948	    if {[lempty $identities]} {
949		set identities [::disco::browser::get_parent_identities $bw $tnode]
950	    }
951
952	    # JID with resource is not a room JID
953	    if {[::xmpp::jid::resource $jid] != ""} return
954
955	    foreach id $identities {
956		if {[::xmpp::xml::getAttr $id category] == "conference"} {
957		    $m add command -label [::msgcat::mc "Add conference to roster..."] \
958			-command [list [namespace current]::add_conference_dialog $xlib \
959				       -group [::xmpp::jid::node $jid] \
960				       -server [::xmpp::jid::server $jid]]
961		    break
962		}
963	    }
964	}
965    }
966}
967
968hook::add disco_node_menu_hook \
969	  [namespace current]::conferences::disco_node_menu_setup 50
970
971# vim:ts=8:sw=4:sts=4:noet
972