[Tkabber-dev] r487 - in trunk/plugins/notes: . xmpp

tkabber-svn at jabber.ru tkabber-svn at jabber.ru
Mon May 2 04:31:31 MSD 2011


Author: Totktonada
Date: 2011-05-02 04:31:31 +0400 (Mon, 02 May 2011)
New Revision: 487

Added:
   trunk/plugins/notes/xmpp/
   trunk/plugins/notes/xmpp/pkgIndex.tcl
   trunk/plugins/notes/xmpp/xmpp-notes.tcl
Modified:
   trunk/plugins/notes/TODO
   trunk/plugins/notes/notes.tcl
Log:
Split notes plugin to xmpp-library and interface.
Download notes after connect, upload after edit.
Support for >1 connections.

BUGS:
Disconnect or reconnect with opened notes tab ?\226?\128?\148 perhaps uncorrent list of connections.


Modified: trunk/plugins/notes/TODO
===================================================================
--- trunk/plugins/notes/TODO	2011-04-07 10:09:28 UTC (rev 486)
+++ trunk/plugins/notes/TODO	2011-05-02 00:31:31 UTC (rev 487)
@@ -4,6 +4,7 @@
 "/notes add" - появляется окошко с полями ввода
 "/notes del #n"
 "/notes edit #n" - окошко с полями ввода
+
 Длинные команды:
 
 /notes add
@@ -16,10 +17,23 @@
 title
 text
 
+Команда "/todo текст текст текст" - добавляет новую заметку с тегом "todo".
+Заголовок - ?
+
+=======================
+
 Можно вообще таб в Juick-style сделать. Пишешь туда — добавляешь заметку. E #номер — редактирование. D #номер — удалить. #номер *tag — добавить/удалить тег. # — вывести все заметки.
 
-Быстрая запись в заметку жуйкосущностей, ссылок и прочего. Возможность прикрепить заметку к JID'у, смотреть из меню соотв. контакта. Сохранять время последней модицикации.
+======================
 
+Быстрая запись в заметку жуйкосущностей, ссылок и прочего. Возможность прикрепить заметку к JID'у, смотреть из меню соотв. контакта. Сохранять время последней модицикации. Выделение -> ПКМ -> заметки.
+
 Обработка разнообразных ошибок при чтении из хранилища или записи в него.
 
 Удаление заметок.
+
+[15:10:16]<ancestor> Totktonada, думаю для текста заметки нужно сделать многострочное текстовое поле, так было бы удобней.
+[16:13:37]<rejjin> Totktonada: text в panedwindow (можно будет поле регулировать (размер) как в чатах).
+[16:14:09]<rejjin> Totktonada: panedwindow простой, и там pack/place/grid не нужен.
+
+[01:54:36]<Totktonada> ancestor: Оно уже есть. Другая реализация. Да, я хотел прикрутить их к JID'ам, но как бы опционально и с отображением в едином списке. Теперь надо думать ещё и над тем, делать ли совместимо с теми заметками или лучше просто добавить возможность импорта оттуда.

Modified: trunk/plugins/notes/notes.tcl
===================================================================
--- trunk/plugins/notes/notes.tcl	2011-04-07 10:09:28 UTC (rev 486)
+++ trunk/plugins/notes/notes.tcl	2011-05-02 00:31:31 UTC (rev 487)
@@ -1,6 +1,9 @@
-package require msgcat
-
 namespace eval notes {
+    set scriptdir [file dirname [info script]]
+    lappend ::auto_path $scriptdir
+    package require xmpp::private::notes
+
+    package require msgcat
     ::msgcat::mcload [file join [file dirname [info script]] msgs]
 
     if {![::plugins::is_registered notes]} {
@@ -16,29 +19,47 @@
 
 proc notes::load {} {
     variable notes
+    array set notes {}
+    variable current_xlib
+
     hook::add finload_hook [namespace current]::setup_menu
+    hook::add disconnected_hook [namespace current]::disconnected
+    hook::add connected_hook [namespace current]::connected
     setup_menu
 }
 
 proc notes::unload {} {
     variable notes
+    variable current_xlib
     hook::remove finload_hook [namespace current]::setup_menu
+    hook::remove disconnected_hook [namespace current]::disconnected
+    hook::remove connected_hook [namespace current]::connected
     desetup_menu
-    catch {unset notes}
+    array unset notes
+    catch { unset current_xlib }
 }
 
 proc notes::open_window {} {
-    variable notes
-
-    # create tab
+    variable current_xlib
     set w .notes
+
     if {[winfo exists $w]} {
-	raise_win $w
-	return
+        raise_win $w
+        return
     }
 
+    if {[llength [connections]] == 0} return
+
+    add_win $w -title [::msgcat::mc "Notes"] \
+        -tabtitle [::msgcat::mc "Notes"] \
+        -class Notes \
+        -raise 1
+
     create_notes_tab $w
-#    request_server_notes
+
+    # TODO: store notes immediately after edit (now)
+    # or after close tab (see next line).
+#    bind $w <Destroy> +[list [namespace current]::store_all_notes]
 }
 
 # ############################
@@ -65,164 +86,129 @@
 
 ##############################################################################
 
-proc notes::request_server_notes {} {
-    set xlib [lindex [connections] 0]
-    ::xmpp::sendIQ $xlib get \
-        -query [ \
-            ::xmpp::xml::create "query" \
-            -xmlns "jabber:iq:private" \
-            -subelement [ \
-                ::xmpp::xml::create "storage" \
-                -xmlns "http://miranda-im.org/storage#notes" \
-            ] \
-        ] \
-        -command [list [namespace current]::receive_server_notes]
+proc notes::free_notes {xlib} {
+    variable notes
+    array unset notes $xlib
 }
 
-proc notes::receive_server_notes {res child0} {
-    variable notes
-    set notes {}
+proc notes::request_notes {xlib} {
+    ::xmpp::private::notes::retrieve $xlib \
+        -command [list [namespace current]::process_notes $xlib]
+}
 
-    if {![string equal $res "ok"]} return
+proc notes::disconnected {xlib} {
+    variable current_xlib
 
-    ::xmpp::xml::split $child0 tag0 xmlns0 attrs0 cdata0 subels0
+    free_notes $xlib
 
-    if {![cequal $tag0 "query"]} return
-    if {![cequal $xmlns0 "jabber:iq:private"]} return
+    if {[llength [connections]] == 0} {
+        unset current_xlib
+# TODO: if exist one connection, notes tab closed after reconnect
+#        catch { destroy_win .notes }
+        return
+    }
 
-    set child1 [lindex $subels0 0]
-    ::xmpp::xml::split $child1 tag1 xmlns1 attrs1 cdata1 subels1
+    if {[cequal $current_xlib $xlib]} {
+        set current_xlib [lindex [connections] 0]
+    }
 
-    if {![cequal $tag1 "storage"]} return
-    if {![cequal $xmlns1 "http://miranda-im.org/storage#notes"]} return
+# TODO: remove $xlib from #conn_button.menu
+}
 
-    foreach child2 $subels1 {
-        array set current_note [list \
-            tags "" \
-            title "" \
-            text ""]
-        ::xmpp::xml::split $child2 tag2 xmlns2 attrs2 cdata2 subels2
-        if {![cequal $tag2 "note"]} continue
+proc notes::connected {xlib} {
+    variable current_xlib
 
-        set current_note(tags) \
-            [split [::xmpp::xml::getAttr $attrs2 "tags"] " "]
+    request_notes $xlib
 
-	foreach child3 $subels2 {
-            ::xmpp::xml::split $child3 tag3 xmlns3 attrs3 cdata3 subels3
-            switch -- $tag3 {
-                title -
-                text {
-                    set current_note($tag3) $cdata3
-                }
-            }
-        }
-
-	lappend notes [array get current_note]
+    if {![info exist current_xlib]} {
+        set current_xlib $xlib
+#        set current_xlib [lindex [connections] 0]
     }
 
-    puts $notes
-
-    update_lbox
-    return
+# TODO: add $xlib to $conn_button.menu
+#    if {[winfo exist .notes]} {        }
+#        .notes.tools.conn_button.menu
+#{    }
 }
 
-proc notes::send_notes {} {
+proc notes::process_notes {xlib status noteslist} {
     variable notes
-    set xlib [lindex [connections] 0]
+    variable current_xlib
 
-    ::xmpp::sendIQ $xlib set \
-        -query [ \
-            ::xmpp::xml::create "query" \
-            -xmlns "jabber:iq:private" \
-            -subelement [ \
-                ::xmpp::xml::create "storage" \
-                -xmlns "http://miranda-im.org/storage#notes" \
-                -subelements [notes_to_xml] \
-            ] \
-        ] \
-        -command [list [namespace current]::check_send_notes_result]
-}
+    if {$status != "ok"} return
 
-proc notes::notes_to_xml {} {
-    variable notes
-    set xml_notes {}
+    free_notes $xlib
+    set notes($xlib) $noteslist
 
-    foreach note $notes {
-        set title ""
-        set tags_str ""
-        set text ""
-
-        foreach {key value} $note {
-            switch -- $key {
-                title -
-                text {
-                    set $key $value
-                }
-                tags {
-                    set tags_str [join $value " "]
-                }
-            }
-        }
-
-        lappend xml_notes [ \
-            ::xmpp::xml::create "note" \
-                -attrs [list "tags" $tags_str] \
-                -subelement [ \
-                    ::xmpp::xml::create "title" \
-                        -cdata $title \
-                ] \
-                -subelement [ \
-                    ::xmpp::xml::create "text" \
-                        -cdata $text \
-                ] \
-        ]
+    if {[expr [winfo exists .notes] && [cequal $current_xlib $xlib]]} {
+        update_lbox $xlib
     }
-
-    return $xml_notes
+    return
 }
 
+proc notes::store_notes {xlib} {
+    variable notes
 
-proc notes::check_send_notes_result {res child0} {
+    ::xmpp::private::notes::store $xlib $notes($xlib) \
+        -command [list [namespace current]::store_notes_result]
+}
+
+proc notes::store_notes_result {res child0} {
 # TODO
 }
 
+proc notes::store_all_notes {} {
+    variable notes
+    foreach xlib [array names notes] {
+        store_notes $xlib
+    }
+}
+
 ##############################################################################
 
 proc notes::create_notes_tab {w} {
-#    set w .notes
-#    if {![winfo exists $w]} return
+    variable current_xlib
 
-    # base widget
-    add_win $w -title [::msgcat::mc "Notes"] \
-	-tabtitle [::msgcat::mc "Notes"] \
-	-class Notes \
-	-raise 1
-
     # button box
     set tools [frame $w.tools -borderwidth 5]
-    pack $tools -side right -fill y -anchor w
+    pack $tools -side top -fill y -anchor w
 
-    set download_button [button $tools.download_button -text [::msgcat::mc "Download"] \
-        -command [list [namespace current]::request_server_notes]]
-    set upload_button [button $tools.upload_button -text [::msgcat::mc "Upload"] \
-        -command [list [namespace current]::send_notes]]
     set new_button [button $tools.new_button -text [::msgcat::mc "New note"] \
-        -command [list [namespace current]::open_note "" -1 ""]]
+        -command [list [namespace current]::edit_note -1]]
+    pack $new_button -anchor w -side left
 
-    pack $download_button -anchor w -side top
-    pack $upload_button -anchor w -side top
-    pack $new_button -anchor w -side top
+# TODO: from menubutton to OptionMenu?
+#    set conn_menu [OptionMenu $tools.conn_menu [connections]]
+    
+    # ==== List of connections ====
+    set conn_button [menubutton $tools.conn_button \
+        -text [connection_jid $current_xlib] \
+        -menu $tools.conn_button.menu]
 
+    set conn_menu [menu $conn_button.menu -tearoff 0]
+    foreach conn [connections] {
+        $conn_menu add command \
+            -label [connection_jid $conn] \
+            -command [namespace code [format {
+                variable current_xlib
+                set current_xlib %1$s
+                update_lbox %1$s} $conn]]
+    }
+
+    pack $conn_button -anchor w -side left
+    # ==== ====
+
     # main frame
-    set main_frame [frame $w.main_frame]
-    pack $main_frame -side left -fill both -expand true -anchor w
+    set lbox_frame [frame $w.lbox_frame]
+    pack $lbox_frame -side left -fill both -expand true -anchor w
 
     # main frame widget
-    grid columnconfigure $main_frame 0 -weight 1
-    set sw [ScrolledWindow $main_frame.sw]
+    grid columnconfigure $lbox_frame 0 -weight 1
+    set sw [ScrolledWindow $lbox_frame.sw]
 
-    set lbox [listbox $main_frame.lbox -takefocus 1 -exportselection 0]
+    set lbox [listbox $lbox_frame.lbox -takefocus 1 -exportselection 0]
     $lbox selection clear 0 end
+    update_lbox $current_xlib
     $lbox selection set 0
     focus $lbox
 
@@ -232,28 +218,29 @@
     bind Listbox <Button-1> {+ if {[winfo exists %W]} {focus %W}}
 
     bind $lbox <Double-Button-1> [namespace code {
-	open_note %W [%W nearest %y]
+        edit_note [%W nearest %y]
     }]
 
     bind $lbox <Return> [namespace code {
-	open_note %W [%W index active]
+        edit_note [%W index active]
     }]
 # ====  ====
 
     $sw setwidget $lbox
     grid $sw -sticky news
-    grid rowconfigure $main_frame 0 -weight 1
+    grid rowconfigure $lbox_frame 0 -weight 1
 }
 
-proc notes::open_note {w idx args} {
+proc notes::edit_note {idx args} {
     variable notes
+    variable current_xlib
 
     set title ""
     set tags_str ""
     set text ""
 
     if {$idx >= 0} {
-        set source_note [lindex $notes $idx]
+        set source_note [lindex $notes($current_xlib) $idx]
         foreach {key value} $source_note {
             switch -- $key {
                 title -
@@ -294,13 +281,13 @@
     grid $dialog_frame.text   -row 2 -column 1 -sticky ew
 
     $dialog_w add -text [::msgcat::mc "Ok"] \
-        -command [list [namespace current]::update_one_note $idx $dialog_w]
+        -command [list [namespace current]::edit_note_cmd_ok $dialog_w $idx $current_xlib]
     $dialog_w add -text [::msgcat::mc "Cancel"] \
         -command [list destroy $dialog_w]
     $dialog_w draw $dialog_frame.title
 }
 
-proc notes::update_one_note {idx dialog_w} {
+proc notes::edit_note_cmd_ok {dialog_w idx xlib} {
     variable notes
 
     set dialog_frame [$dialog_w getframe]
@@ -316,36 +303,35 @@
     ]
 
     if {$idx >= 0} {
-        lset notes $idx $new_note
+        lset notes($xlib) $idx $new_note
+        store_notes $xlib
         update_lbox_at $idx $new_note
     } else {
-        lappend notes $new_note
+        lappend notes($xlib) $new_note
+        store_notes $xlib
         append_to_lbox $new_note
     }
     destroy $dialog_w
 }
 
 proc notes::update_lbox_at {idx new_note} {
-    variable notes
-    set lbox .notes.main_frame.lbox
+    set lbox .notes.lbox_frame.lbox
     $lbox delete $idx $idx
     $lbox insert $idx [get_short_string $new_note]
 }
 
 proc notes::append_to_lbox {new_note} {
-    variable notes
-
-    set lbox .notes.main_frame.lbox
+    set lbox .notes.lbox_frame.lbox
     $lbox insert end [get_short_string $new_note]
 }
 
-proc notes::update_lbox {} {
+proc notes::update_lbox {xlib} {
     variable notes
 
-    set lbox .notes.main_frame.lbox
+    set lbox .notes.lbox_frame.lbox
     $lbox delete 0 end
 
-    foreach note $notes {
+    foreach note $notes($xlib) {
 	$lbox insert end [get_short_string $note]
     }
 #    $lbox selection clear 0 end
@@ -362,4 +348,3 @@
     }
     return "Empty title?"
 }
-

Added: trunk/plugins/notes/xmpp/pkgIndex.tcl
===================================================================
--- trunk/plugins/notes/xmpp/pkgIndex.tcl	                        (rev 0)
+++ trunk/plugins/notes/xmpp/pkgIndex.tcl	2011-05-02 00:31:31 UTC (rev 487)
@@ -0,0 +1,11 @@
+# Tcl package index file, version 1.1
+# This file is generated by the "pkg_mkIndex" command
+# and sourced either when an application starts up or
+# by a "package unknown" script.  It invokes the
+# "package ifneeded" command to set up package-related
+# information so that packages will be loaded automatically
+# in response to "package require" commands.  When this
+# script is sourced, the variable $dir must contain the
+# full path name of this file's directory.
+
+package ifneeded xmpp::private::notes 0.1 [list source [file join $dir xmpp-notes.tcl]]

Added: trunk/plugins/notes/xmpp/xmpp-notes.tcl
===================================================================
--- trunk/plugins/notes/xmpp/xmpp-notes.tcl	                        (rev 0)
+++ trunk/plugins/notes/xmpp/xmpp-notes.tcl	2011-05-02 00:31:31 UTC (rev 487)
@@ -0,0 +1,148 @@
+package require xmpp::private
+
+package provide xmpp::private::notes 0.1
+
+namespace eval ::xmpp::private::notes {
+    namespace export store retrieve serialize deserialize
+}
+
+proc ::xmpp::private::notes::retrieve {xlib args} {
+    set commands {}
+    set timeout 0
+
+    foreach {key val} $args {
+        switch -- $key {
+            -timeout {
+                set timeout $val
+            }
+            -command {
+                set commands [list $val]
+            }
+            default {
+                return -code error \
+                   [::msgcat::mc "Illegal option \"%s\"" $key]
+            }
+        }
+    }
+
+    set id [::xmpp::private::retrieve $xlib \
+        [list [::xmpp::xml::create storage \
+        -xmlns "http://miranda-im.org/storage#notes"]] \
+        -command [namespace code [list ProcessRetrieveAnswer $commands]] \
+        -timeout $timeout]
+    return $id
+}
+
+proc ::xmpp::private::notes::ProcessRetrieveAnswer {commands status xml} {
+    if {[llength $commands] == 0} return
+
+    if {![string equal $status ok]} {
+        uplevel #0 [lindex $commands 0] [list $status $xml]
+    }
+
+    uplevel #0 [lindex $commands 0] [list ok [deserialize $xml]]
+    return
+}
+
+proc ::xmpp::private::notes::deserialize {xml} {
+    set notes {}
+
+    foreach xmldata $xml {
+    ::xmpp::xml::split $xmldata tag xmlns attrs cdata subels
+
+    if {[cequal $xmlns "http://miranda-im.org/storage#notes"]} {
+        foreach note $subels {
+            ::xmpp::xml::split $note n_tag n_xmlns n_attrs n_cdata n_subels
+
+            set tags [split [::xmpp::xml::getAttr $n_attrs "tags"] " "]
+            set title ""
+            set text ""
+
+            foreach n_subel $n_subels {
+                ::xmpp::xml::split $n_subel nc_tag nc_xmlns nc_attrs nc_cdata nc_subels
+                switch -- $nc_tag {
+                    title -
+                    text {
+                        set $nc_tag $nc_cdata
+                    }
+                }
+            }
+
+            lappend notes [list tags $tags title $title text $text]
+            }
+        }
+    }
+
+    return $notes
+}
+
+proc ::xmpp::private::notes::serialize {notes} {
+    set tags {}
+    foreach note $notes {
+        set title ""
+        set tags_str ""
+        set text ""
+
+        foreach {key value} $note {
+            switch -- $key {
+                title -
+                text {
+                    set $key $value
+                }
+                tags {
+                    set tags_str [join $value " "]
+                }
+            }
+        }
+
+        lappend tags [ \
+            ::xmpp::xml::create "note" \
+                -attrs [list "tags" $tags_str] \
+                -subelement [ \
+                    ::xmpp::xml::create "title" \
+                        -cdata $title \
+                ] \
+                -subelement [ \
+                    ::xmpp::xml::create "text" \
+                        -cdata $text \
+                ] \
+        ]
+    }
+
+    return [::xmpp::xml::create storage \
+        -xmlns "http://miranda-im.org/storage#notes" \
+        -subelements $tags]
+}
+
+proc ::xmpp::private::notes::store {xlib notes args} {
+    set commands {}
+    set timeout 0
+
+    foreach {key val} $args {
+        switch -- $key {
+            -timeout {
+                set timeout $val
+            }
+            -command {
+                set commands [list $val]
+            }
+            default {
+                return -code error \
+                   [::msgcat::mc "Illegal option \"%s\"" $key]
+            }
+        }
+    }
+
+    set id [::xmpp::private::store $xlib \
+        [list [serialize $notes]] \
+        -command [namespace code [list ProcessStoreAnswer $commands]] \
+        -timeout $timeout]
+    return $id
+}
+
+proc ::xmpp::private::notes::ProcessStoreAnswer {commands status xml} {
+    if {[llength $commands] > 0} {
+        uplevel #0 [lindex $commands 0] [list $status $xml]
+    }
+    return
+}



More information about the Tkabber-dev mailing list