From 3eb7e7688dea39fa83f41c1f9aba79a962ef1a15 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 25 Jun 2010 04:36:06 +0200 Subject: Create conversation tabs for new conversations --- data/ephraim.glade | 42 ++++++++++++++++++++++++++++++++++++++ src/core/ephraim.erl | 10 ++++++--- src/core/ephraim_conn.erl | 4 ++-- src/core/ephraim_conv.erl | 7 ++++--- src/core/ephraim_event.erl | 6 +++++- src/gui/CMakeLists.txt | 1 + src/gui/Conversation.vala | 51 ++++++++++++++++++++++++++++++++++++++++++++++ src/gui/CoreConnector.vala | 17 ++++++++++++---- src/gui/Ephraim.vala | 24 ++++++++++++++++++---- src/gui/Roster.vala | 8 ++++++++ 10 files changed, 153 insertions(+), 17 deletions(-) create mode 100644 src/gui/Conversation.vala diff --git a/data/ephraim.glade b/data/ephraim.glade index c4f2740..1b53b1b 100644 --- a/data/ephraim.glade +++ b/data/ephraim.glade @@ -129,4 +129,46 @@ + + True + vertical + 5 + + + True + 5 + label + + + False + 0 + + + + + True + queue + + + True + True + False + + + + + 1 + + + + + True + True + + + False + 2 + + + diff --git a/src/core/ephraim.erl b/src/core/ephraim.erl index bd36118..61c3c68 100644 --- a/src/core/ephraim.erl +++ b/src/core/ephraim.erl @@ -32,17 +32,21 @@ init() -> -spec get_conv(#state{},exmpp_jid:jid()) -> {#state{},pid()|undefined}. get_conv(State, JID) -> - Key = exmpp_jid:to_lower(JID), - case Key of - {_,_,undefined} -> + {Node, Domain, Resource} = exmpp_jid:to_lower(exmpp_jid:parse(JID)), + + case Resource of + undefined -> {State, undefined}; _ -> + Key = list_to_binary([Node, <<"@">>, Domain, <<"/">>, Resource]), + case dict:find(Key, State#state.convs) of {ok, Conv} -> {State, Conv}; error -> Conv = spawn(ephraim_conv, init, [Key]), Dict = dict:store(Key, Conv, State#state.convs), + self() ! {ui_update, {new_conversation, Key}}, {State#state{convs=Dict}, Conv} end end. diff --git a/src/core/ephraim_conn.erl b/src/core/ephraim_conn.erl index 28e72b3..bce4d07 100644 --- a/src/core/ephraim_conn.erl +++ b/src/core/ephraim_conn.erl @@ -21,10 +21,10 @@ init() -> session(State) -> io:format("Logging in...~n"), exmpp_session:login(State#conn_state.session), - io:format("Setting presence...~n"), - exmpp_session:send_packet(State#conn_state.session, exmpp_presence:set_status(exmpp_presence:available(), "Foo/Test\\Bar")), io:format("Getting roster...~n"), exmpp_session:send_packet(State#conn_state.session, exmpp_client_roster:get_roster("foo")), + io:format("Setting presence...~n"), + exmpp_session:send_packet(State#conn_state.session, exmpp_presence:set_status(exmpp_presence:available(), "Foo/Test\\Bar")), io:format("Ok.~n"), loop(State). diff --git a/src/core/ephraim_conv.erl b/src/core/ephraim_conv.erl index b502166..3010036 100644 --- a/src/core/ephraim_conv.erl +++ b/src/core/ephraim_conv.erl @@ -2,12 +2,13 @@ -compile([debug_info, export_all]). -record(conv_state, { - jid :: exmpp_jid:jid() + jid :: binary() }). --spec init(exmpp_jid:jid()) -> ok. +-spec init(binary()) -> ok. init(JID) -> io:format("Starting a conversation with ~p~n", [JID]), + loop(#conv_state{jid=JID}), io:format("Stopping a conversation with ~p~n", [JID]). @@ -18,7 +19,7 @@ loop(State) -> ok; {receive_message, Packet} -> - io:format("Received packet from ~p:~n~p~n", [State#conv_state.jid, Packet]), + io:format("Received message from ~p:~n~p~n", [State#conv_state.jid, Packet]), loop(State); Msg -> diff --git a/src/core/ephraim_event.erl b/src/core/ephraim_event.erl index dd86a7b..d32914a 100644 --- a/src/core/ephraim_event.erl +++ b/src/core/ephraim_event.erl @@ -9,10 +9,14 @@ init() -> -spec handleEvent(binary(), #xmlel{}) -> ok. handleEvent(From, Item) -> HasAvatarData = exmpp_xml:has_element(Item, 'urn:xmpp:avatar:data', data), + HasAvatarMetaData = exmpp_xml:has_element(Item, 'urn:xmpp:avatar:metadata', metadata), if HasAvatarData -> Element = exmpp_xml:get_element(Item, 'urn:xmpp:avatar:data', data), Data = base64:decode(exmpp_xml:get_cdata_from_list(Element#xmlel.children)), - ephraim ! {roster, {avatar, From, Data}}; + ephraim ! {roster, {avatar, From, Data}}, + ok; + HasAvatarMetaData -> + ok; true -> io:format("Received unhandled event from ~p:~n~p~n", [From, Item]) end. diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 6208e62..dc65a0c 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -6,6 +6,7 @@ vala_precompile(VALA_C "CellRendererContact.vala" "CellRendererPresence.vala" "Contact.vala" + "Conversation.vala" "CoreConnector.vala" "Roster.vala" PACKAGES diff --git a/src/gui/Conversation.vala b/src/gui/Conversation.vala new file mode 100644 index 0000000..321fba9 --- /dev/null +++ b/src/gui/Conversation.vala @@ -0,0 +1,51 @@ +public class Conversation { + private Gtk.Notebook conversations; + private Gtk.Widget widget; + private string jid; + private string display_name; + + + private class TabLabel : Gtk.HBox { + public TabLabel(string label) { + pack_start(new Gtk.Label(label), false, true, 0); + + Gtk.Button closeButton = new Gtk.Button(); + Gdk.Pixbuf closeImage = render_icon(Gtk.STOCK_CLOSE, (Gtk.IconSize)(-1), null); + //Gtk.Image closeImage = new Gtk.Image.from_stock(Gtk.STOCK_CLOSE, (Gtk.IconSize)4); + closeButton.image = new Gtk.Image.from_pixbuf(closeImage.scale_simple(16, 16, Gdk.InterpType.BILINEAR)); + //closeButton.width_request = 20; + closeButton.height_request = 20; + pack_end(closeButton, false, false, 0); + + show_all(); + } + } + + public Conversation(Gtk.Notebook conversations0, string jid0, string? display_name0) { + conversations = conversations0; + jid = jid0; + + if(display_name0 != null) + display_name = display_name0; + else + display_name = jid; + + Gtk.Builder builder = new Gtk.Builder(); + try { + builder.add_objects_from_file("ephraim.glade", {"Conversation"}); + } catch(Error e) { + + } + + widget = builder.get_object("Conversation") as Gtk.Widget; + unowned Gtk.Label title = builder.get_object("ConversationTitle") as Gtk.Label; + + title.set_text("Conversation with " + display_name); + + conversations.append_page(widget, new TabLabel(display_name)); + } + + ~Conversation() { + conversations.remove(widget); + } +} diff --git a/src/gui/CoreConnector.vala b/src/gui/CoreConnector.vala index 9c492b7..18cef2d 100644 --- a/src/gui/CoreConnector.vala +++ b/src/gui/CoreConnector.vala @@ -6,7 +6,8 @@ public class CoreConnector { Erl.Connection con; Erl.Term self; - Roster roster; + public signal void update_contact(Contact contact); + public signal void new_conversation(string jid); private class TermStore { public Erl.Term term; @@ -16,9 +17,8 @@ public class CoreConnector { Erl.init(); } - public CoreConnector(Roster roster0) { + public CoreConnector() { running = false; - roster = roster0; } public bool start() { @@ -166,7 +166,16 @@ public class CoreConnector { } } - roster.update_contact(contact); + update_contact(contact); + } + else if((match_term = match("{new_conversation,JID}", term)) != null) { + Erl.Term jid_term = match_term.var_content("JID"); + if(!jid_term.is_binary()) + // TODO Debug output + return; + string jid = ((string)jid_term.bin_ptr()).ndup(jid_term.bin_size()); + + new_conversation(jid); } else { Erl.print_term(stdout, term); diff --git a/src/gui/Ephraim.vala b/src/gui/Ephraim.vala index 5130247..9d3083c 100644 --- a/src/gui/Ephraim.vala +++ b/src/gui/Ephraim.vala @@ -4,16 +4,15 @@ public class Ephraim { Gtk.Builder builder = new Gtk.Builder(); try { - builder.add_from_file("ephraim.glade"); + builder.add_objects_from_file("ephraim.glade", {"MainWindow"}); } catch(Error e) { return 1; } Roster roster = new Roster(); - CoreConnector coreconn = new CoreConnector(roster); + CoreConnector coreconn = new CoreConnector(); - if(!coreconn.start()) - return 1; + coreconn.update_contact.connect(roster.update_contact); unowned Gtk.Window window = builder.get_object("MainWindow") as Gtk.Window; window.hide.connect(Gtk.main_quit); @@ -24,6 +23,23 @@ public class Ephraim { unowned Gtk.TreeView rosterView = builder.get_object("Roster") as Gtk.TreeView; rosterView.set_model(roster); + Gee.TreeMap conversations = new Gee.TreeMap(); + unowned Gtk.Notebook conversationNotebook = builder.get_object("Conversations") as Gtk.Notebook; + + coreconn.new_conversation.connect((jid) => { + Contact contact = roster.get_contact(jid); + + if(contact != null) { + conversations[jid] = new Conversation(conversationNotebook, jid, contact.display_string); + } + else { + conversations[jid] = new Conversation(conversationNotebook, jid, null); + } + }); + + if(!coreconn.start()) + return 1; + rosterView.query_tooltip.connect((x, y, keyboard_tip, tooltip) => { Gtk.TreeModel model; Gtk.TreeIter iter; diff --git a/src/gui/Roster.vala b/src/gui/Roster.vala index f25584c..72134e6 100644 --- a/src/gui/Roster.vala +++ b/src/gui/Roster.vala @@ -25,7 +25,15 @@ public class Roster : Object, Gtk.TreeModel { else row_changed(path, iter); } + + public Contact get_contact(string jid) { + string bareJID = jid.split("/", 2)[0]; + + stdout.printf("Getting Contact for %s\n", bareJID); + return entries[bareJID]; + } + public Type get_column_type (int index) { switch(index) { case 0: -- cgit v1.2.3