context: // Smuxi - Smart MUltipleXed Irc
  //
  // Copyright (c) 2013 Oliver Schneider <smuxi@oli-obk.de>
  //
  // Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
  //
  // This program is free software; you can redistribute it and/or modify
  // it under the terms of the GNU General Public License as published by
  // the Free Software Foundation; either version 2 of the License, or
  // (at your option) any later version.
  //
  // This program is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  // GNU General Public License for more details.
  //
  // You should have received a copy of the GNU General Public License
  // along with this program; if not, write to the Free Software
  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  using System;
  using Smuxi.Common;
  using Smuxi.Engine;
  using System.Threading;
  using System.Collections.Generic;
  
  namespace Smuxi.Frontend.Gnome
  {
      [ChatViewInfo(ChatType = ChatType.Group, ProtocolManagerType = typeof(XmppProtocolManager))]
      public class XmppGroupChatView : GroupChatView
      {
          private static readonly string _LibraryTextDomain = "smuxi-frontend-gnome-xmpp";
          private XmppProtocolManager XmppProtocolManager { get; set; }
  
          public bool IsContactList {
              get {
                  return ID == "Contacts";
              }
          }
  
          public XmppGroupChatView(GroupChatModel chat) : base(chat)
          {
              Trace.Call(chat);
          }
  
          protected override void OnMessageTextViewMessageAdded(object sender, MessageTextViewMessageAddedEventArgs e)
          {
              if (!IsActive) {
                  switch (e.Message.MessageType) {
                      case MessageType.PresenceStateOffline:
                      case MessageType.PresenceStateAway:
                      case MessageType.PresenceStateOnline:
                          HasEvent = true;
                          break;
                  }
              }
              base.OnMessageTextViewMessageAdded(sender, e);
          }
  
          void OnPersonRenameEditingStarted(object o, Gtk.EditingStartedArgs e)
          {
              Trace.Call(o, e);
  
              // only allow editing once from the context menu
              IdentityNameCellRenderer.Editable = false;
  
              Gtk.TreeIter iter;
              if (!PersonTreeView.Model.GetIterFromString(out iter, e.Path)) {
                  return;
              }
              var person = (PersonModel) PersonTreeView.Model.GetValue(iter, 0);
              var entry = (Gtk.Entry) e.Editable;
              entry.Text = person.IdentityName;
          }
  
          private static string _(string msg)
          {
              return LibraryCatalog.GetString(msg, _LibraryTextDomain);
          }
  
          public override void Sync()
          {
              Trace.Call();
  
              base.Sync();
  
              XmppProtocolManager = (XmppProtocolManager) ProtocolManager;
          }
  
          void _OnUserListMenuWhoisActivated(object sender, EventArgs e)
          {
              Trace.Call(sender, e);
              
              IList<PersonModel> persons = GetSelectedPersons();
              if (persons == null) {
                  return;
              }
  
              foreach (PersonModel person in persons) {
                  var per = person;
              
                  ThreadPool.QueueUserWorkItem(delegate {
                      try {
                          XmppProtocolManager.CommandWhoIs(
                              new CommandModel(
                                  Frontend.FrontendManager,
                                  ChatModel,
                                  per.ID
                              )
                           );
                      } catch (Exception ex) {
                          Frontend.ShowException(ex);
                      }
                  });
              }
          }
  
          void OnUserListMenuRemoveActivated(object sender, EventArgs e)
          {
              Trace.Call(sender, e);
  
              IList<PersonModel> persons = GetSelectedPersons();
              if (persons == null) {
                  return;
              }
  
              foreach (PersonModel person in persons) {
                  var per = person;
  
                  ThreadPool.QueueUserWorkItem(delegate {
                      try {
                          XmppProtocolManager.CommandContact(
                              new CommandModel(
                                  Frontend.FrontendManager,
                                  ChatModel,
                                  "remove " + per.ID
                              )
                          );
                      } catch (Exception ex) {
                          Frontend.ShowException(ex);
                      }
                  });
              }
          }
  
          void _OnUserListMenuQueryActivated (object sender, EventArgs e)
          {
              Trace.Call(sender, e);
              
              IList<PersonModel> persons = GetSelectedPersons();
              if (persons == null) {
                  return;
              }
  
              foreach (PersonModel person in persons) {
                  var per = person;
              
                  ThreadPool.QueueUserWorkItem(delegate {
                      try {
                          XmppProtocolManager.CommandMessageQuery(
                              new CommandModel(
                                  Frontend.FrontendManager,
                                  ChatModel,
                                  per.ID
                              )
                           );
                      } catch (Exception ex) {
                          Frontend.ShowException(ex);
                      }
                  });
              }
          }
  
          void _OnMenuAddToContactsItemActivated(object sender, EventArgs e)
          {
              Trace.Call(sender, e);
  
              IList<PersonModel> persons = GetSelectedPersons();
              if (persons == null) {
                  return;
              }
  
              foreach (PersonModel person in persons) {
                  var per = person;
  
                  // is this a groupchat contact whose real id is unknown
                  if (person.ID.StartsWith(ID)) {
                      continue;
                  }
  
                  ThreadPool.QueueUserWorkItem(delegate {
                      try {
                          XmppProtocolManager.CommandContact(
                              new CommandModel(
                                  Frontend.FrontendManager,
                                  ChatModel,
                                  "add " + per.ID
                              )
                           );
                      } catch (Exception ex) {
                          Frontend.ShowException(ex);
                      }
                  });
              }
          }
  
          void OnPersonRenameEdited(object o, Gtk.EditedArgs e)
          {
              Trace.Call(o, e);
  
              Gtk.TreeIter iter;
              if (!PersonTreeView.Model.GetIterFromString(out iter, e.Path)) {
                  return;
              }
              PersonModel person = (PersonModel) PersonTreeView.Model.GetValue(iter, 0);
  
              ThreadPool.QueueUserWorkItem(delegate {
                  try {
                      XmppProtocolManager.CommandContact(
                          new CommandModel(
                              Frontend.FrontendManager,
                              ChatModel,
                              "rename " + person.ID + " " + e.NewText
                          )
                      );
                  } catch (Exception ex) {
                      Frontend.ShowException(ex);
                  }
              });
          }
  
          protected override void OnPersonMenuShown(object sender, EventArgs e)
          {
              Trace.Call(sender, e);
  
  
gt:             foreach (var child in PersonMenu.Children) {