--- /dev/null
+Mikael Hallendal <micke@imendio.com>
+Richard Hult <richard@imendio.com>
+Martyn Russell <martyn@gnome.org>
+Xavier Claessens <xclaesse@gmail.com>
--- /dev/null
+Andreas Lööw
+Aurelien Naldi
+Bastien Nocera
+Christoffer Olsen
+Frederic Crozat
+Geert-Jan Van den Bogaerde
+Johan Hammar
+Jonatan Magnusson
+Jordi Mallach
+Kim Andersen
+Martyn Russell
+Mike Gratton
+Ross Burton
+Sjoerd Simons
+Thomas Reynolds
+Vincent Untz
+Xavier Claessens
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+2006-03-16 Xavier Claessens <xclaesse@gmail.com>
+
+ * Initial version
+
--- /dev/null
+Xavier Claessens <xclaesse@gmail.com>
--- /dev/null
+SUBDIRS = po profiles pixmaps libempathy libempathy-gtk launcher accounts contact-list chat
+
+DISTCHECK_CONFIGURE_FLAGS = \
+ --disable-scrollkeeper
+
+INTLTOOL = \
+ intltool-extract.in \
+ intltool-merge.in \
+ intltool-update.in
+
+EXTRA_DIST = \
+ ChangeLog \
+ README \
+ CONTRIBUTORS \
+ $(INTLTOOL)
+
+DISTCLEANFILES = \
+ intltool-extract \
+ intltool-merge \
+ intltool-update
+
+# Workaround broken scrollkeeper that doesn't remove its files on
+# uninstall.
+distuninstallcheck_listfiles = find . -type f -print | grep -v '^\./var/scrollkeeper'
--- /dev/null
+How to use empathy ?
+
+1) Install
+$ ./autogen
+$ make && make install
+
+2) Setup and enable some accounts
+$ empathy-accounts
+
+3) Get your contact list
+$ empathy-contact-list
+This will start MC and connect all enabled accounts. If you start a private chat
+or someone is saying something to you, empathy-chat will be started
+automagicaly and display a chat UI for your conversation.
+
--- /dev/null
+Things you can do if you want to help:
+
+ - Find a good name, empathy is already used and gaim had legal problems with it.
+ - Rename all files and functions name to use the new name once we get a cool one.
+ - Porting gossip-account-widget-*.{c,h} from gossip project (Guillaume is already working on IRC widget).
+ - Make a EmpathyChatroom object inherited from EmpathyChat and adding support for topic, invite, members list, etc.
+ - Porting various UI widgets from gossip to libempathy-gtk for contact info, adding contact, personal info, etc.
+ - GtkWidget-ify gossip widgets imported in libempathy-gtk. Actually most window/dialog do not inherit from GtkWindow/GtkDialog...
+ - Set up the translation system and import po files from gossip? Or re-translate everything?
+ - Fix setting subscription for contacts in EmpathyContactList.
+ - Write a MC plugin to filter channels before dispatching them. For example we need a GtkStatusIcon that blink when an event arrives (text/voip/ft channel) and tells the MC to dispatch the channel only when the user clicked the icon. Like in gossip.
+ - Testing and Bugfixing.
+
+SoC projects:
+ - Adding VoIP support based on the patch proposed for gossip.
+ - Adding FileTransfer support.
+
+If you want to contribute you can ask for information at
+ - #telepathy on freenode
+ - Telepathy's mailing list.
--- /dev/null
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -DPREFIX="\"$(prefix)"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ -DDATADIR=\""$(datadir)"\" \
+ -DLIBDIR=\""$(libdir)"\" \
+ $(EMPATHY_CFLAGS) \
+ $(WARN_CFLAGS)
+
+bin_PROGRAMS = empathy-accounts
+
+empathy_accounts_SOURCES = \
+ empathy-accounts-main.c
+
+empathy_accounts_LDADD = \
+ $(top_builddir)/libempathy/libempathy.la \
+ $(top_builddir)/libempathy-gtk/libempathy-gtk.la \
+ $(EMPATHY_LIBS)
+
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Xavier Claessens <xclaesse@gmail.com>
+ *
+ * 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.
+ *
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <libempathy/empathy-session.h>
+#include <libempathy-gtk/gossip-accounts-dialog.h>
+
+static void
+destroy_cb (GtkWidget *dialog,
+ gpointer user_data)
+{
+ empathy_session_finalize ();
+ gtk_main_quit ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *dialog;
+
+ gtk_init (&argc, &argv);
+
+ dialog = gossip_accounts_dialog_show ();
+
+ gtk_widget_show (dialog);
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (destroy_cb),
+ NULL);
+
+ gtk_main ();
+
+ return EXIT_SUCCESS;
+}
+
--- /dev/null
+dnl Turn on the additional warnings last, so -Werror doesn't affect other tests.
+
+AC_DEFUN([IDT_COMPILE_WARNINGS],[
+ if test -f $srcdir/autogen.sh; then
+ default_compile_warnings="error"
+ else
+ default_compile_warnings="no"
+ fi
+
+ AC_ARG_WITH(compile-warnings,
+ AS_HELP_STRING([--with-compile-warnings=@<:@no/yes/error@:>@],
+ [Compiler warnings]),
+ [enable_compile_warnings="$withval"],
+ [enable_compile_warnings="$default_compile_warnings"])
+
+ warnCFLAGS=
+ if test "x$GCC" != xyes; then
+ enable_compile_warnings=no
+ fi
+
+ warning_flags=
+ realsave_CFLAGS="$CFLAGS"
+
+ case "$enable_compile_warnings" in
+ no)
+ warning_flags=
+ ;;
+ yes)
+ warning_flags="-Wall -Wunused -Wmissing-prototypes -Wmissing-declarations"
+ ;;
+ maximum|error)
+ warning_flags="-Wall -Wunused -Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith"
+ CFLAGS="$warning_flags $CFLAGS"
+ for option in -Wno-sign-compare -Wno-pointer-sign; do
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $option"
+ AC_MSG_CHECKING([whether gcc understands $option])
+ AC_TRY_COMPILE([], [],
+ has_option=yes,
+ has_option=no,)
+ CFLAGS="$SAVE_CFLAGS"
+ AC_MSG_RESULT($has_option)
+ if test $has_option = yes; then
+ warning_flags="$warning_flags $option"
+ fi
+ unset has_option
+ unset SAVE_CFLAGS
+ done
+ unset option
+ if test "$enable_compile_warnings" = "error" ; then
+ warning_flags="$warning_flags -Werror"
+ fi
+ ;;
+ *)
+ AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings)
+ ;;
+ esac
+ CFLAGS="$realsave_CFLAGS"
+ AC_MSG_CHECKING(what warning flags to pass to the C compiler)
+ AC_MSG_RESULT($warning_flags)
+
+ WARN_CFLAGS="$warning_flags"
+ AC_SUBST(WARN_CFLAGS)
+])
+
--- /dev/null
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+: ${AUTOCONF=autoconf}
+: ${AUTOHEADER=autoheader}
+: ${AUTOMAKE=automake-1.9}
+: ${ACLOCAL=aclocal-1.9}
+: ${LIBTOOLIZE=libtoolize}
+: ${INTLTOOLIZE=intltoolize}
+: ${LIBTOOL=libtool}
+: ${GNOME_DOC_PREPARE=gnome-doc-prepare}
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+PROJECT="empathy"
+TEST_TYPE=-f
+CONFIGURE=configure.ac
+
+DIE=0
+
+($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have autoconf installed to compile $PROJECT."
+ echo "Download the appropriate package for your distribution,"
+ echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+ DIE=1
+}
+
+(grep "^AC_PROG_INTLTOOL" $srcdir/$CONFIGURE >/dev/null) && {
+ ($INTLTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have \`intltoolize' installed to compile $PROJECT."
+ echo "Get ftp://ftp.gnome.org/pub/GNOME/stable/sources/intltool/intltool-0.35.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ }
+}
+
+(grep "^GNOME_DOC_INIT" $srcdir/$CONFIGURE >/dev/null) && {
+ ($GNOME_DOC_PREPARE --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have \`gnome-doc-prepare' installed to compile $PROJECT."
+ DIE=1
+ }
+}
+
+($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "You must have automake 1.9 installed to compile $PROJECT."
+ echo "Get ftp://ftp.gnu.org/pub/gnu/automake/automake-1.9.6.tar.gz"
+ echo "(or a newer version of 1.9.x if it is available)"
+ DIE=1
+}
+
+(grep "^AM_PROG_LIBTOOL" $CONFIGURE >/dev/null) && {
+ ($LIBTOOL --version) < /dev/null > /dev/null 2>&1 || {
+ echo
+ echo "**Error**: You must have \`libtool' installed to compile $PROJECT."
+ echo "Get ftp://ftp.gnu.org/pub/gnu/libtool/libtool-1.5.22.tar.gz"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ }
+}
+
+if grep "^AM_[A-Z0-9_]\{1,\}_GETTEXT" "$CONFIGURE" >/dev/null; then
+ if grep "sed.*POTFILES" "$CONFIGURE" >/dev/null; then
+ GETTEXTIZE=""
+ else
+ if grep "^AM_GLIB_GNU_GETTEXT" "$CONFIGURE" >/dev/null; then
+ GETTEXTIZE="glib-gettextize"
+ GETTEXTIZE_URL="ftp://ftp.gtk.org/pub/gtk/v2.0/glib-2.0.0.tar.gz"
+ else
+ GETTEXTIZE="gettextize"
+ GETTEXTIZE_URL="ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
+ fi
+
+ $GETTEXTIZE --version < /dev/null > /dev/null 2>&1
+ if test $? -ne 0; then
+ echo
+ echo "**Error**: You must have \`$GETTEXTIZE' installed to compile $PKG_NAME."
+ echo "Get $GETTEXTIZE_URL"
+ echo "(or a newer version if it is available)"
+ DIE=1
+ fi
+ fi
+fi
+
+if test "$DIE" -eq 1; then
+ exit 1
+fi
+
+test $TEST_TYPE $FILE || {
+ echo "You must run this script in the top-level $PROJECT directory"
+ exit 1
+}
+
+#if test -z "$*"; then
+# echo "I am going to run ./configure with no arguments - if you wish "
+# echo "to pass any to it, please specify them on the $0 command line."
+#fi
+
+case $CC in
+*xlc | *xlc\ * | *lcc | *lcc\ *) am_opt=--include-deps;;
+esac
+
+for coin in .
+do
+ dr=`dirname $coin`
+ if test -f $dr/NO-AUTO-GEN; then
+ echo skipping $dr -- flagged as no auto-gen
+ else
+ echo processing $dr
+ macrodirs= #`sed -n -e 's,AM_ACLOCAL_INCLUDE(\(.*\)),\1,gp' < $coin`
+ ( cd $dr
+ aclocalinclude="$ACLOCAL_FLAGS"
+ for k in $macrodirs; do
+ if test -d $k; then
+ aclocalinclude="$aclocalinclude -I $k"
+ ##else
+ ## echo "**Warning**: No such directory \`$k'. Ignored."
+ fi
+ done
+ if grep "^AM_GLIB_GNU_GETTEXT" $CONFIGURE >/dev/null; then
+ if grep "sed.*POTFILES" $CONFIGURE >/dev/null; then
+ : do nothing -- we still have an old unmodified $CONFIGURE
+ else
+ echo "Creating $dr/aclocal.m4 ..."
+ test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
+ echo "Running glib-gettextize... Ignore non-fatal messages."
+ echo "no" | glib-gettextize --force --copy
+ echo "Making $dr/aclocal.m4 writable ..."
+ test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
+ fi
+ fi
+ if grep "^IT_PROG_INTLTOOL" $CONFIGURE >/dev/null; then
+ echo "Running intltoolize..."
+ intltoolize --copy --force --automake
+ fi
+ if grep "^GNOME_DOC_INIT" $CONFIGURE >/dev/null; then
+ echo "Running $GNOME_DOC_PREPARE..."
+ $GNOME_DOC_PREPARE --force --copy || exit 1
+ fi
+ if grep "^AM_PROG_LIBTOOL" $CONFIGURE >/dev/null; then
+ echo "Running $LIBTOOLIZE..."
+ $LIBTOOLIZE --force --copy
+ fi
+ echo "Running $ACLOCAL $aclocalinclude ..."
+ $ACLOCAL $aclocalinclude
+ if grep "^AM_CONFIG_HEADER" $CONFIGURE >/dev/null; then
+ echo "Running $AUTOHEADER..."
+ $AUTOHEADER
+ fi
+ echo "Running $AUTOMAKE --gnu $am_opt ..."
+ $AUTOMAKE --add-missing --gnu $am_opt
+ echo "Running $AUTOCONF ..."
+ $AUTOCONF
+ )
+ fi
+done
+
+conf_flags="--enable-maintainer-mode"
+
+cd "$ORIGDIR"
+
+if test x$NOCONFIGURE = x; then
+ echo Running $srcdir/configure $conf_flags "$@" ...
+ $srcdir/configure $conf_flags "$@" \
+ && echo Now type \`make\' to compile $PROJECT || exit 1
+else
+ echo Skipping configure process.
+fi
--- /dev/null
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -DPREFIX="\"$(prefix)"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ -DDATADIR=\""$(datadir)"\" \
+ -DLIBDIR=\""$(libdir)"\" \
+ $(EMPATHY_CFLAGS) \
+ $(WARN_CFLAGS)
+
+bin_PROGRAMS = empathy-chat
+
+empathy_chat_SOURCES = \
+ empathy-chat-main.c
+
+empathy_chat_LDADD = \
+ $(top_builddir)/libempathy/libempathy.la \
+ $(top_builddir)/libempathy-gtk/libempathy-gtk.la \
+ $(EMPATHY_LIBS)
+
+# Dbus service file
+servicedir = $(datadir)/dbus-1/services
+service_in_files = org.gnome.Empathy.Chat.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+# Rule to make the service file with bindir expanded
+$(service_DATA): $(service_in_files) Makefile
+ @sed -e "s|\@bindir\@|$(bindir)|" $< > $@
+
+chandlerdir = $(datadir)/telepathy/managers
+chandler_DATA = empathy-chat.chandler
+
+
+EXTRA_DIST = \
+ org.gnome.Empathy.Chat.service.in \
+ $(chandler_DATA)
+
+BUILT_SOURCES = \
+ org.gnome.Empathy.Chat.service
+
+CLEANFILES = $(BUILT_SOURCES)
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Xavier Claessens <xclaesse@gmail.com>
+ *
+ * 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.
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <libtelepathy/tp-conn.h>
+#include <libtelepathy/tp-chan.h>
+#include <libmissioncontrol/mc-account.h>
+
+#include <libempathy/gossip-contact.h>
+#include <libempathy/empathy-chandler.h>
+#include <libempathy/empathy-session.h>
+#include <libempathy/empathy-contact-manager.h>
+#include <libempathy/empathy-contact-list.h>
+#include <libempathy-gtk/gossip-private-chat.h>
+#include <libempathy-gtk/gossip-stock.h>
+
+#define BUS_NAME "org.gnome.Empathy.Chat"
+#define OBJECT_PATH "/org/freedesktop/Telepathy/ChannelHandler"
+
+static void
+new_channel_cb (EmpathyChandler *chandler,
+ TpConn *tp_conn,
+ TpChan *tp_chan,
+ gpointer user_data)
+{
+ if (tp_chan->handle_type == TP_HANDLE_TYPE_CONTACT) {
+ MissionControl *mc;
+ McAccount *account;
+ EmpathyContactManager *manager;
+ EmpathyContactList *list;
+ GossipContact *contact;
+ GossipPrivateChat *chat;
+
+ /* We have a private chat channel */
+ mc = empathy_session_get_mission_control ();
+ account = mission_control_get_account_for_connection (mc, tp_conn, NULL);
+ manager = empathy_session_get_contact_manager ();
+ list = empathy_contact_manager_get_list (manager, account);
+ contact = empathy_contact_list_get_from_handle (list, tp_chan->handle);
+
+ chat = gossip_private_chat_new_with_channel (contact, tp_chan);
+ gossip_chat_present (GOSSIP_CHAT (chat));
+
+ g_object_unref (account);
+ g_object_unref (contact);
+ g_object_unref (chat);
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ EmpathyChandler *chandler;
+
+ gtk_init (&argc, &argv);
+ /* FIXME: This is a horrible hack */
+ gossip_stock_init (gtk_window_new (GTK_WINDOW_TOPLEVEL));
+
+ chandler = empathy_chandler_new (BUS_NAME, OBJECT_PATH);
+
+ g_signal_connect (chandler, "new-channel",
+ G_CALLBACK (new_channel_cb),
+ NULL);
+
+ gtk_main ();
+
+ return EXIT_SUCCESS;
+}
+
--- /dev/null
+[ChannelHandler]
+BusName = org.gnome.Empathy.Chat
+ObjectPath = /org/freedesktop/Telepathy/ChannelHandler
+ChannelType = org.freedesktop.Telepathy.Channel.Type.Text
+
--- /dev/null
+[D-BUS Service]
+Name=org.gnome.Empathy.Chat
+Exec=@bindir@/empathy-chat
--- /dev/null
+AC_INIT(Empathy, 0.1)
+AC_PREREQ(2.59)
+AC_COPYRIGHT([Copyright (C) 2003-2007 Imendio AB])
+
+AM_CONFIG_HEADER(config.h)
+AM_INIT_AUTOMAKE(1.9 dist-bzip2 no-define)
+
+AM_MAINTAINER_MODE
+
+AC_ISC_POSIX
+AC_PROG_CC
+AC_HEADER_STDC
+
+AM_PROG_LIBTOOL
+AM_PATH_GLIB_2_0
+AC_PATH_XTRA
+
+AC_PATH_PROG(DBUS_BINDING_TOOL, dbus-binding-tool)
+AC_PATH_PROG(GCONFTOOL, gconftool-2)
+AM_GCONF_SOURCE_2
+
+IT_PROG_INTLTOOL([0.35.0])
+
+GLIB_REQUIRED=2.12.0
+GTK_REQUIRED=2.10.0
+GCONF_REQUIRED=1.2.0
+LIBGLADE_REQUIRED=2.0.0
+TELEPATHY_REQUIRED=0.0.51
+MISSION_CONTROL_REQUIRED=4.20
+
+GLIB_GENMARSHAL=`$PKG_CONFIG glib-2.0 --variable=glib_genmarshal`
+AC_SUBST(GLIB_GENMARSHAL)
+
+IDT_COMPILE_WARNINGS
+
+dnl -----------------------------------------------------------
+dnl Pkg-Config dependency checks
+dnl -----------------------------------------------------------
+
+PKG_CHECK_MODULES(EMPATHY,
+[
+ glib-2.0 >= $GLIB_REQUIRED
+ gobject-2.0
+ gtk+-2.0 >= $GTK_REQUIRED
+ gconf-2.0 >= $GCONF_REQUIRED
+ libglade-2.0 >= $LIBGLADE_REQUIRED
+ libgnomeui-2.0
+ libtelepathy >= $TELEPATHY_REQUIRED
+ libmissioncontrol >= $MISSION_CONTROL_REQUIRED
+])
+
+dnl -----------------------------------------------------------
+dnl Language Support
+dnl -----------------------------------------------------------
+GETTEXT_PACKAGE=empathy
+AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Gettext package name])
+
+AM_GLIB_GNU_GETTEXT
+
+
+dnl -----------------------------------------------------------
+AC_OUTPUT([
+ Makefile
+ po/Makefile.in
+ profiles/Makefile
+ pixmaps/Makefile
+ libempathy/Makefile
+ libempathy-gtk/Makefile
+ launcher/Makefile
+ accounts/Makefile
+ contact-list/Makefile
+ chat/Makefile
+])
+
--- /dev/null
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -DPREFIX="\"$(prefix)"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ -DDATADIR=\""$(datadir)"\" \
+ -DLIBDIR=\""$(libdir)"\" \
+ $(EMPATHY_CFLAGS) \
+ $(WARN_CFLAGS)
+
+bin_PROGRAMS = empathy-contact-list
+
+empathy_contact_list_SOURCES = \
+ empathy-contact-list-main.c
+
+empathy_contact_list_LDADD = \
+ $(top_builddir)/libempathy/libempathy.la \
+ $(top_builddir)/libempathy-gtk/libempathy-gtk.la \
+ $(EMPATHY_LIBS)
+
+
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Xavier Claessens <xclaesse@gmail.com>
+ *
+ * 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.
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <libempathy/gossip-contact.h>
+#include <libempathy/empathy-session.h>
+#include <libempathy-gtk/gossip-contact-list.h>
+#include <libempathy-gtk/gossip-private-chat.h>
+#include <libempathy-gtk/gossip-stock.h>
+
+static void
+destroy_cb (GtkWidget *window,
+ gpointer user_data)
+{
+ gossip_stock_finalize ();
+ empathy_session_finalize ();
+ gtk_main_quit ();
+}
+
+static void
+contact_chat_cb (GtkWidget *list,
+ GossipContact *contact,
+ gpointer user_data)
+{
+ mission_control_request_channel (empathy_session_get_mission_control (),
+ gossip_contact_get_account (contact),
+ TP_IFACE_CHANNEL_TYPE_TEXT,
+ gossip_contact_get_handle (contact),
+ TP_HANDLE_TYPE_CONTACT,
+ NULL, NULL);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *list;
+ GtkWidget *sw;
+
+ gtk_init (&argc, &argv);
+
+ empathy_session_connect ();
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gossip_stock_init (window);
+
+ list = GTK_WIDGET (gossip_contact_list_new ());
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (window), sw);
+ gtk_container_add (GTK_CONTAINER (sw), list);
+
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_widget_set_size_request (sw, 200, 400);
+
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (destroy_cb),
+ NULL);
+ g_signal_connect (list, "contact-chat",
+ G_CALLBACK (contact_chat_cb),
+ NULL);
+
+ gtk_widget_show_all (window);
+
+ gtk_main ();
+
+ return EXIT_SUCCESS;
+}
+
--- /dev/null
+INCLUDES = \
+ -I$(top_srcdir) \
+ $(EMPATHY_CFLAGS) \
+ $(WARN_CFLAGS)
+
+bin_PROGRAMS = empathy-launcher
+empathy_launcher_SOURCES = empathy-launcher.c
+empathy_launcher_LDADD = \
+ $(top_builddir)/libempathy/libempathy.la \
+ $(EMPATHY_LIBS)
+
+
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2007 Xavier Claessens <xclaesse@gmail.com>
+ *
+ * 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.
+ *
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <glib.h>
+
+#include <libempathy/empathy-session.h>
+#include <libempathy/gossip-debug.h>
+
+#define DEBUG_DOMAIN "Launcher"
+
+int
+main (int argc, char *argv[])
+{
+ GMainLoop *main_loop;
+
+ g_type_init ();
+
+ empathy_session_connect ();
+
+ main_loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (main_loop);
+
+ return 0;
+}
+
--- /dev/null
+AM_CPPFLAGS = \
+ -I. \
+ -I$(top_srcdir) \
+ -DDATADIR=\""$(datadir)"\" \
+ -DLOCALEDIR=\""$(datadir)/locale"\" \
+ $(EMPATHY_CFLAGS) \
+ $(WARN_CFLAGS)
+
+noinst_LTLIBRARIES = libempathy-gtk.la
+
+libempathy_gtk_la_SOURCES = \
+ gossip-accounts-dialog.c gossip-accounts-dialog.h \
+ gossip-account-widget-generic.c gossip-account-widget-generic.h \
+ gossip-profile-chooser.c gossip-profile-chooser.h \
+ gossip-cell-renderer-expander.c gossip-cell-renderer-expander.h \
+ gossip-cell-renderer-text.c gossip-cell-renderer-text.h \
+ gossip-stock.c gossip-stock.h \
+ gossip-spell.c gossip-spell.h \
+ gossip-contact-groups.c gossip-contact-groups.h \
+ gossip-contact-list.c gossip-contact-list.h \
+ gossip-preferences.c gossip-preferences.h \
+ gossip-theme-manager.c gossip-theme-manager.h \
+ gossip-chat.c gossip-chat.h \
+ gossip-chat-view.c gossip-chat-view.h \
+ gossip-chat-window.c gossip-chat-window.h \
+ gossip-private-chat.c gossip-private-chat.h \
+ gossip-ui-utils.c gossip-ui-utils.h
+
+libempathy_gtk_la_LIBADD = \
+ $(top_builddir)/libempathy/libempathy.la \
+ $(EMPATHY_LIBS)
+
+libempathy_gtk_includedir = $(includedir)/empathy/
+
+gladedir = $(datadir)/empathy
+glade_DATA = \
+ empathy-accounts.glade \
+ empathy-chat.glade
+
+dtddir = $(datadir)/empathy
+dtd_DATA = \
+ gossip-contact-groups.dtd
+
+schemasdir = $(GCONF_SCHEMA_FILE_DIR)
+schemas_in_files = empathy.schemas.in
+schemas_DATA = $(schemas_in_files:.schemas.in=.schemas)
+@INTLTOOL_SCHEMAS_RULE@
+
+if GCONF_SCHEMAS_INSTALL
+install-data-local:
+ if test -z "$(DESTDIR)" ; then \
+ for p in $(schemas_DATA) ; do \
+ GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$$p ; \
+ done \
+ fi
+else
+install-data-local:
+endif
+
+EXTRA_DIST = \
+ $(glade_DATA) \
+ $(dtd_DATA) \
+ $(schemas_in_files) \
+ $(schemas_DATA)
+
+DISTCLEANFILES = \
+ $(schemas_DATA)
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--*- mode: xml -*-->
+<glade-interface>
+ <widget class="GtkDialog" id="accounts_dialog">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Accounts</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox3">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkHBox" id="hbox146">
+ <property name="visible">True</property>
+ <property name="border_width">6</property>
+ <property name="spacing">18</property>
+ <child>
+ <widget class="GtkVBox" id="vbox195">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow17">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <child>
+ <widget class="GtkTreeView" id="treeview">
+ <property name="height_request">200</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="enable_search">False</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox196">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkButton" id="button_connect">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-connect</property>
+ <property name="use_stock">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox148">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <property name="homogeneous">True</property>
+ <child>
+ <widget class="GtkButton" id="button_add">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-add</property>
+ <property name="use_stock">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_remove">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-remove</property>
+ <property name="use_stock">True</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox214">
+ <property name="width_request">415</property>
+ <property name="visible">True</property>
+ <property name="spacing">18</property>
+ <child>
+ <widget class="GtkVBox" id="vbox_details">
+ <property name="visible">True</property>
+ <property name="spacing">18</property>
+ <child>
+ <widget class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment7">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">20</property>
+ <child>
+ <widget class="GtkVBox" id="vbox213">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkTable" id="table14">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <widget class="GtkLabel" id="label_type">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Jabber</property>
+ </widget>
+ <packing>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label_name">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Imendio </property>
+ <property name="width_chars">0</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkImage" id="image_type">
+ <property name="visible">True</property>
+ <property name="yalign">0</property>
+ <property name="stock">gtk-cut</property>
+ <property name="icon_size">6</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label598">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Account</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment_settings">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">20</property>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label599">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Settings</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkFrame" id="frame_new_account">
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment29">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">20</property>
+ <child>
+ <widget class="GtkVBox" id="vbox216">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkTable" id="table_new_account">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">6</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label638">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_name</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label640">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Type:</property>
+ <property name="use_underline">True</property>
+ </widget>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox180">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkEntry" id="entry_name">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip" translatable="yes">A unique name for this account to identify it personally to you.</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox181">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkButton" id="button_cancel">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_create">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment30">
+ <property name="visible">True</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <child>
+ <widget class="GtkHBox" id="hbox181">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkImage" id="image838">
+ <property name="visible">True</property>
+ <property name="stock">gtk-new</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label642">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Cr_eate!</property>
+ <property name="use_underline">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label643">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>New Account</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkFrame" id="frame_no_account">
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <child>
+ <widget class="GtkAlignment" id="alignment21">
+ <property name="visible">True</property>
+ <property name="top_padding">6</property>
+ <property name="left_padding">12</property>
+ <child>
+ <widget class="GtkLabel" id="label_no_account_blurb">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">To add a new account, you can click on the 'Add' button and a new entry will be created for you to started configuring.
+
+If you do not want to add an account, simply click on the account you want to configure in the list on the left.</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label_no_account">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>No Account Selected</b></property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <child>
+ <widget class="GtkButton" id="button_close">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="label">gtk-close</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <widget class="GtkWindow" id="account_jabber_settings">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">jabber account settings</property>
+ <property name="resizable">False</property>
+ <child>
+ <widget class="GtkTable" id="vbox_jabber_settings">
+ <property name="visible">True</property>
+ <property name="n_rows">6</property>
+ <property name="n_columns">3</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <widget class="GtkLabel" id="label_id">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Login I_D:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_id</property>
+ </widget>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label_password">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Pass_word:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_password</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label_resource">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Reso_urce:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_resource</property>
+ </widget>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label_server">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Server:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_server</property>
+ </widget>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label_port">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Port:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_port</property>
+ </widget>
+ <packing>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="entry_resource">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="entry_server">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="entry_port">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="checkbutton_ssl">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Use encryption (SS_L)</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox174">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkEntry" id="entry_password">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_forget">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip" translatable="yes">Forget password and clear the entry.</property>
+ <child>
+ <widget class="GtkImage" id="image834">
+ <property name="visible">True</property>
+ <property name="stock">gtk-clear</property>
+ <property name="icon_size">1</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_change_password">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">C_hange</property>
+ <property name="use_underline">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="entry_id">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_register">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">R_egister</property>
+ <property name="use_underline">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <widget class="GtkWindow" id="account_msn_settings">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">msn account settings</property>
+ <property name="resizable">False</property>
+ <child>
+ <widget class="GtkTable" id="vbox_msn_settings">
+ <property name="visible">True</property>
+ <property name="n_rows">4</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">12</property>
+ <property name="row_spacing">6</property>
+ <child>
+ <widget class="GtkLabel" id="label_id">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Login I_D:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_id</property>
+ </widget>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label_password">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Pass_word:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_password</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox182">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkEntry" id="entry_password">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="visibility">False</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button_forget">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="tooltip" translatable="yes">Forget password and clear the entry.</property>
+ <child>
+ <widget class="GtkImage" id="image839">
+ <property name="visible">True</property>
+ <property name="stock">gtk-clear</property>
+ <property name="icon_size">1</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="entry_id">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label_server">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Server:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_server</property>
+ </widget>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="entry_server">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label_port">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Port:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">entry_port</property>
+ </widget>
+ <packing>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="entry_port">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">*</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+</glade-interface>
--- /dev/null
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+<requires lib="gnome"/>
+
+<widget class="GtkWindow" id="chat_page_window">
+ <property name="title" translatable="yes">Chat</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="default_width">350</property>
+ <property name="default_height">250</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+
+ <child>
+ <widget class="GtkVBox" id="chat_widget">
+ <property name="border_width">4</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">3</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="chat_view_sw">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="input_text_view_sw">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkWindow" id="chat_window">
+ <property name="title" translatable="yes">Chat</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="default_width">350</property>
+ <property name="default_height">250</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+
+ <child>
+ <widget class="GtkVBox" id="chat_vbox">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkMenuBar" id="chats_menubar">
+ <property name="visible">True</property>
+ <property name="pack_direction">GTK_PACK_DIRECTION_LTR</property>
+ <property name="child_pack_direction">GTK_PACK_DIRECTION_LTR</property>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_conv">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Conversation</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu_conv_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_conv_clear">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">C_lear</property>
+ <property name="use_underline">True</property>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image235">
+ <property name="visible">True</property>
+ <property name="stock">gtk-clear</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_conv_insert_smiley">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Insert _Smiley</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator11">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_conv_log">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_View Previous Conversations</property>
+ <property name="use_underline">True</property>
+ <accelerator key="F3" modifiers="0" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image236">
+ <property name="visible">True</property>
+ <property name="stock">gtk-justify-left</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="menu_conv_separator">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_conv_add_contact">
+ <property name="label" translatable="yes">_Add Contact...</property>
+ <property name="use_underline">True</property>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image237">
+ <property name="visible">True</property>
+ <property name="stock">gtk-add</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_conv_info">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Contact Infor_mation</property>
+ <property name="use_underline">True</property>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image238">
+ <property name="visible">True</property>
+ <property name="stock">gtk-info</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator7">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_conv_close">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Close</property>
+ <property name="use_underline">True</property>
+ <accelerator key="W" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image239">
+ <property name="visible">True</property>
+ <property name="stock">gtk-close</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_room">
+ <property name="label" translatable="yes">_Room</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu_room_menu">
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_room_set_topic">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Change _Topic...</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator12">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_room_join_new">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Join _New...</property>
+ <property name="use_underline">True</property>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image240">
+ <property name="visible">True</property>
+ <property name="stock">gtk-new</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_room_invite">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">In_vite...</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator7">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_room_add">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Add To Favorites</property>
+ <property name="use_underline">True</property>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image241">
+ <property name="visible">True</property>
+ <property name="stock">gtk-add</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator10">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkCheckMenuItem" id="menu_room_show_contacts">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Show Contacts</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <accelerator key="F11" modifiers="0" signal="activate"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_edit">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu_edit_menu">
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_edit_cut">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Cu_t</property>
+ <property name="use_underline">True</property>
+ <accelerator key="X" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image242">
+ <property name="visible">True</property>
+ <property name="stock">gtk-cut</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_edit_copy">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Copy</property>
+ <property name="use_underline">True</property>
+ <accelerator key="C" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image243">
+ <property name="visible">True</property>
+ <property name="stock">gtk-copy</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_edit_paste">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Paste</property>
+ <property name="use_underline">True</property>
+ <accelerator key="V" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+
+ <child internal-child="image">
+ <widget class="GtkImage" id="image244">
+ <property name="visible">True</property>
+ <property name="stock">gtk-paste</property>
+ <property name="icon_size">1</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_tabs">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Tabs</property>
+ <property name="use_underline">True</property>
+
+ <child>
+ <widget class="GtkMenu" id="menu_tabs_menu">
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_tabs_prev">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Previous Tab</property>
+ <property name="use_underline">True</property>
+ <accelerator key="Page_Up" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_tabs_next">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Next Tab</property>
+ <property name="use_underline">True</property>
+ <accelerator key="Page_Down" modifiers="GDK_CONTROL_MASK" signal="activate"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator4">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_tabs_left">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Move Tab _Left</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_tabs_right">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Move Tab _Right</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkMenuItem" id="menu_tabs_detach">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Detach Tab</property>
+ <property name="use_underline">True</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkDialog" id="chat_invite_dialog">
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Invite</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+ <property name="modal">True</property>
+ <property name="default_width">275</property>
+ <property name="default_height">225</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+ <property name="has_separator">False</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="vbox6">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="button_cancel">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button_invite">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">In_vite</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox7">
+ <property name="border_width">5</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">18</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox7">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Select who would you like to invite:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="treeview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <property name="rules_hint">False</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ <property name="fixed_height_mode">False</property>
+ <property name="hover_selection">False</property>
+ <property name="hover_expand">False</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox8">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Invitation _message:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">entry</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes">You have been invited to join a chat conference.</property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">40</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
--- /dev/null
+<gconfschemafile>
+ <schemalist>
+
+ <schema>
+ <key>/schemas/apps/empathy/ui/show_offline</key>
+ <applyto>/apps/empathy/ui/show_offline</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Show offline contacts</short>
+ <long>
+ Whether or not to show contacts that are offline in the contact list.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/ui/show_avatars</key>
+ <applyto>/apps/empathy/ui/show_avatars</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Show avatars</short>
+ <long>
+ Whether or not to show avatars for contacts in the contact
+ list and chat windows.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/ui/compact_contact_list</key>
+ <applyto>/apps/empathy/ui/compact_contact_list</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Compact contact list</short>
+ <long>
+ Whether to show the contact list in compact mode or not.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/ui/main_window_hidden</key>
+ <applyto>/apps/empathy/ui/main_window_hidden</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Hide main window</short>
+ <long>
+ Hide the main window.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/ui/avatar_directory</key>
+ <applyto>/apps/empathy/ui/avatar_directory</applyto>
+ <owner>empathy</owner>
+ <type>string</type>
+ <default></default>
+ <locale name="C">
+ <short>Default directory to select an avatar image from</short>
+ <long>
+ The last directory that an avatar image was chosen from.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/notifications/play_sounds</key>
+ <applyto>/apps/empathy/notifications/play_sounds</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Use notification sounds</short>
+ <long>
+ Whether or not to play a sound when messages arrive.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/notifications/sound_when_away</key>
+ <applyto>/apps/empathy/notifications/sound_when_away</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Enable sound when away</short>
+ <long>
+ Whether or not to play sounds when away.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/notifications/sound_when_busy</key>
+ <applyto>/apps/empathy/notifications/sound_when_busy</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Enable sound when busy</short>
+ <long>
+ Whether or not to play sounds when busy.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/notifications/popup_when_contact_available</key>
+ <applyto>/apps/empathy/notifications/popup_when_contact_available</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Enable popup when contact is available</short>
+ <long>
+ Whether or not to show a popup when a contact becomes available.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/ui/separate_chat_windows</key>
+ <applyto>/apps/empathy/ui/separate_chat_windows</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>false</default>
+ <locale name="C">
+ <short>Open new chats in separate windows</short>
+ <long>
+ Always open a separate chat window for new chats.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/conversation/graphical_smileys</key>
+ <applyto>/apps/empathy/conversation/graphical_smileys</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Use graphical smileys</short>
+ <long>
+ Whether or not to convert smileys into graphical images in
+ conversations.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/conversation/theme</key>
+ <applyto>/apps/empathy/conversation/theme</applyto>
+ <owner>empathy</owner>
+ <type>string</type>
+ <default>classic</default>
+ <locale name="C">
+ <short>Chat window theme</short>
+ <long>
+ The theme that is used to display the conversation in chat windows.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/conversation/theme_chat_room</key>
+ <applyto>/apps/empathy/conversation/theme_chat_room</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Use theme for chat rooms</short>
+ <long>
+ Whether to use the theme for chat rooms or not.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/conversation/spell_checker_languages</key>
+ <applyto>/apps/empathy/conversation/spell_checker_languages</applyto>
+ <owner>empathy</owner>
+ <type>string</type>
+ <default>en</default>
+ <locale name="C">
+ <short>Spell checking languages</short>
+ <long>
+ Comma separated list of spell checker languages to use (e.g. en, fr, nl).
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/conversation/spell_checker_enabled</key>
+ <applyto>/apps/empathy/conversation/spell_checker_enabled</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Enable spell checker</short>
+ <long>
+ Whether or not to check words typed against the languages you
+ want to check with.
+ </long>
+ </locale>
+ </schema>
+
+ <schema>
+ <key>/schemas/apps/empathy/hints/close_main_window</key>
+ <applyto>/apps/empathy/hints/close_main_window</applyto>
+ <owner>empathy</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Show hint about closing the main window</short>
+ <long>
+ Whether or not to show the message dialog about closing the
+ main window with the 'x' button in the title bar.
+ </long>
+ </locale>
+ </schema>
+
+ </schemalist>
+</gconfschemafile>
+
+
+
+
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ * Martyn Russell <martyn@imendio.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+
+#include <libmissioncontrol/mc-account.h>
+#include <libmissioncontrol/mc-protocol.h>
+
+#include <libempathy-gtk/gossip-ui-utils.h>
+
+#include "gossip-account-widget-generic.h"
+
+typedef struct {
+ McAccount *account;
+
+ GtkWidget *sw;
+ GtkWidget *table_settings;
+ GtkSizeGroup *size_group;
+
+ guint n_rows;
+} GossipAccountWidgetGeneric;
+
+static gboolean account_widget_generic_entry_focus_cb (GtkWidget *widget,
+ GdkEventFocus *event,
+ GossipAccountWidgetGeneric *settings);
+static void account_widget_generic_int_changed_cb (GtkWidget *widget,
+ GossipAccountWidgetGeneric *settings);
+static void account_widget_generic_checkbutton_toggled_cb (GtkWidget *widget,
+ GossipAccountWidgetGeneric *settings);
+static gchar * account_widget_generic_format_param_name (const gchar *param_name);
+static void account_widget_generic_setup_foreach (McProtocolParam *param,
+ GossipAccountWidgetGeneric *settings);
+static void account_widget_generic_destroy_cb (GtkWidget *widget,
+ GossipAccountWidgetGeneric *settings);
+
+static gboolean
+account_widget_generic_entry_focus_cb (GtkWidget *widget,
+ GdkEventFocus *event,
+ GossipAccountWidgetGeneric *settings)
+{
+ const gchar *str;
+ const gchar *param_name;
+
+ str = gtk_entry_get_text (GTK_ENTRY (widget));
+ param_name = g_object_get_data (G_OBJECT (widget), "param_name");
+
+ mc_account_set_param_string (settings->account, param_name, str);
+
+ return FALSE;
+}
+
+static void
+account_widget_generic_int_changed_cb (GtkWidget *widget,
+ GossipAccountWidgetGeneric *settings)
+{
+ const gchar *param_name;
+ gint value;
+
+ value = gtk_spin_button_get_value (GTK_SPIN_BUTTON (widget));
+ param_name = g_object_get_data (G_OBJECT (widget), "param_name");
+
+ mc_account_set_param_int (settings->account, param_name, value);
+}
+
+static void
+account_widget_generic_checkbutton_toggled_cb (GtkWidget *widget,
+ GossipAccountWidgetGeneric *settings)
+{
+ gboolean active;
+ const gchar *param_name;
+
+ active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+ param_name = g_object_get_data (G_OBJECT (widget), "param_name");
+
+ mc_account_set_param_boolean (settings->account, param_name, active);
+}
+
+static gchar *
+account_widget_generic_format_param_name (const gchar *param_name)
+{
+ gchar *str;
+ gchar *p;
+
+ str = g_strdup (param_name);
+
+ if (str && g_ascii_isalpha (str[0])) {
+ str[0] = g_ascii_toupper (str[0]);
+ }
+
+ while ((p = strchr (str, '-')) != NULL) {
+ if (p[1] != '\0' && g_ascii_isalpha (p[1])) {
+ p[0] = ' ';
+ p[1] = g_ascii_toupper (p[1]);
+ }
+
+ p++;
+ }
+
+ return str;
+}
+
+static void
+account_widget_generic_setup_foreach (McProtocolParam *param,
+ GossipAccountWidgetGeneric *settings)
+{
+ GtkWidget *widget;
+ gchar *param_name_formatted;
+
+ param_name_formatted = account_widget_generic_format_param_name (param->name);
+
+ gtk_table_resize (GTK_TABLE (settings->table_settings),
+ ++settings->n_rows,
+ 2);
+
+ if (param->signature[0] == 's') {
+ gchar *str = NULL;
+
+ str = g_strdup_printf (_("%s:"), param_name_formatted);
+ widget = gtk_label_new (str);
+ g_free (str);
+
+ gtk_size_group_add_widget (settings->size_group, widget);
+ gtk_table_attach (GTK_TABLE (settings->table_settings),
+ widget,
+ 0, 1,
+ settings->n_rows - 1, settings->n_rows,
+ GTK_FILL, 0,
+ 0, 0);
+
+ str = NULL;
+ widget = gtk_entry_new ();
+ mc_account_get_param_string (settings->account,
+ param->name,
+ &str);
+ if (str) {
+ gtk_entry_set_text (GTK_ENTRY (widget), str);
+ g_free (str);
+ }
+
+ if (strstr (param->name, "password")) {
+ gtk_entry_set_visibility (GTK_ENTRY (widget), FALSE);
+ }
+
+ g_signal_connect (widget, "focus-out-event",
+ G_CALLBACK (account_widget_generic_entry_focus_cb),
+ settings);
+
+ gtk_table_attach (GTK_TABLE (settings->table_settings),
+ widget,
+ 1, 2,
+ settings->n_rows - 1, settings->n_rows,
+ GTK_FILL | GTK_EXPAND, 0,
+ 0, 0);
+ }
+ else if (param->signature[0] == 'q' ||
+ param->signature[0] == 'n') {
+ gchar *str = NULL;
+ gint value = 0;
+
+ str = g_strdup_printf (_("%s:"), param_name_formatted);
+ widget = gtk_label_new (str);
+ g_free (str);
+
+ gtk_size_group_add_widget (settings->size_group, widget);
+ gtk_table_attach (GTK_TABLE (settings->table_settings),
+ widget,
+ 0, 1,
+ settings->n_rows - 1, settings->n_rows,
+ GTK_FILL, 0,
+ 0, 0);
+
+ widget = gtk_spin_button_new_with_range (0, G_MAXINT, 1);
+ mc_account_get_param_int (settings->account,
+ param->name,
+ &value);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
+
+ g_signal_connect (widget, "value-changed",
+ G_CALLBACK (account_widget_generic_int_changed_cb),
+ settings);
+
+ gtk_table_attach (GTK_TABLE (settings->table_settings),
+ widget,
+ 1, 2,
+ settings->n_rows - 1, settings->n_rows,
+ GTK_FILL | GTK_EXPAND, 0,
+ 0, 0);
+ }
+ else if (param->signature[0] == 'b') {
+ gboolean value;
+
+ mc_account_get_param_boolean (settings->account,
+ param->name,
+ &value);
+
+ widget = gtk_check_button_new_with_label (param_name_formatted);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), value);
+
+ g_signal_connect (widget, "toggled",
+ G_CALLBACK (account_widget_generic_checkbutton_toggled_cb),
+ settings);
+
+ gtk_table_attach (GTK_TABLE (settings->table_settings),
+ widget,
+ 0, 2,
+ settings->n_rows - 1, settings->n_rows,
+ GTK_FILL | GTK_EXPAND, 0,
+ 0, 0);
+ } else {
+ g_assert_not_reached ();
+ }
+
+ g_free (param_name_formatted);
+
+ g_object_set_data_full (G_OBJECT (widget), "param_name",
+ g_strdup (param->name), g_free);
+}
+
+static void
+accounts_widget_generic_setup (GossipAccountWidgetGeneric *settings)
+{
+ McProtocol *protocol;
+ McProfile *profile;
+ GSList *params;
+
+ profile = mc_account_get_profile (settings->account);
+ protocol = mc_profile_get_protocol (profile);
+ params = mc_protocol_get_params (protocol);
+
+ g_slist_foreach (params,
+ (GFunc) account_widget_generic_setup_foreach,
+ settings);
+
+ g_slist_free (params);
+}
+
+static void
+account_widget_generic_destroy_cb (GtkWidget *widget,
+ GossipAccountWidgetGeneric *settings)
+{
+ g_object_unref (settings->account);
+ g_object_unref (settings->size_group);
+
+ g_free (settings);
+}
+
+GtkWidget *
+gossip_account_widget_generic_new (McAccount *account,
+ GtkWidget *label_name)
+{
+ GossipAccountWidgetGeneric *settings;
+
+ g_return_val_if_fail (MC_IS_ACCOUNT (account), NULL);
+ g_return_val_if_fail (GTK_IS_WIDGET (label_name), NULL);
+
+ settings = g_new0 (GossipAccountWidgetGeneric, 1);
+
+ settings->account = g_object_ref (account);
+
+ settings->table_settings = gtk_table_new (0, 2, FALSE);
+ gtk_table_set_row_spacings (GTK_TABLE (settings->table_settings), 6);
+ gtk_table_set_col_spacings (GTK_TABLE (settings->table_settings), 6);
+ settings->sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (settings->sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (settings->sw),
+ settings->table_settings);
+
+ settings->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ if (label_name) {
+ gtk_size_group_add_widget (settings->size_group, label_name);
+ }
+
+ accounts_widget_generic_setup (settings);
+
+ g_signal_connect (settings->sw, "destroy",
+ G_CALLBACK (account_widget_generic_destroy_cb),
+ settings);
+
+ gtk_widget_show_all (settings->sw);
+
+ return settings->sw;
+}
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Xavier Claessens <xclaesse@gmail.com>
+ * Martyn Russell <martyn@imendio.com>
+ */
+
+#ifndef __GOSSIP_ACCOUNT_WIDGET_GENERIC_H__
+#define __GOSSIP_ACCOUNT_WIDGET_GENERIC_H__
+
+#include <gtk/gtk.h>
+
+#include <libmissioncontrol/mc-account.h>
+
+G_BEGIN_DECLS
+
+GtkWidget *gossip_account_widget_generic_new (McAccount *account,
+ GtkWidget *label_name);
+
+G_END_DECLS
+
+#endif /* __GOSSIP_ACCOUNT_WIDGET_GENERIC_H__ */
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Martyn Russell <martyn@imendio.com>
+ * Xavier Claessens <xclaesse@gmail.com>
+ */
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+
+#include <libmissioncontrol/mc-account.h>
+#include <libmissioncontrol/mc-profile.h>
+#include <libmissioncontrol/mission-control.h>
+#include <libmissioncontrol/mc-account-monitor.h>
+#include <libtelepathy/tp-constants.h>
+
+#include <libempathy/empathy-session.h>
+#include <libempathy/gossip-debug.h>
+#include <libempathy/gossip-paths.h>
+#include <libempathy/gossip-utils.h>
+#include <libempathy-gtk/gossip-ui-utils.h>
+
+#include "gossip-accounts-dialog.h"
+#include "gossip-profile-chooser.h"
+#include "gossip-account-widget-generic.h"
+
+#define DEBUG_DOMAIN "AccountDialog"
+
+/* Flashing delay for icons (milliseconds). */
+#define FLASH_TIMEOUT 500
+
+typedef struct {
+ GtkWidget *window;
+
+ GtkWidget *alignment_settings;
+
+ GtkWidget *vbox_details;
+ GtkWidget *frame_no_account;
+ GtkWidget *label_no_account;
+ GtkWidget *label_no_account_blurb;
+
+ GtkWidget *treeview;
+
+ GtkWidget *button_remove;
+ GtkWidget *button_connect;
+
+ GtkWidget *frame_new_account;
+ GtkWidget *combobox_profile;
+ GtkWidget *entry_name;
+ GtkWidget *table_new_account;
+ GtkWidget *button_create;
+ GtkWidget *button_cancel;
+
+ GtkWidget *image_type;
+ GtkWidget *label_name;
+ GtkWidget *label_type;
+ GtkWidget *settings_widget;
+
+ gboolean connecting_show;
+ guint connecting_id;
+ gboolean account_changed;
+} GossipAccountsDialog;
+
+enum {
+ COL_NAME,
+ COL_STATUS,
+ COL_ACCOUNT_POINTER,
+ COL_COUNT
+};
+
+static void accounts_dialog_setup (GossipAccountsDialog *dialog);
+static void accounts_dialog_update_account (GossipAccountsDialog *dialog,
+ McAccount *account);
+static void accounts_dialog_model_setup (GossipAccountsDialog *dialog);
+static void accounts_dialog_model_add_columns (GossipAccountsDialog *dialog);
+static void accounts_dialog_model_select_first (GossipAccountsDialog *dialog);
+static void accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GossipAccountsDialog *dialog);
+static McAccount *accounts_dialog_model_get_selected (GossipAccountsDialog *dialog);
+static void accounts_dialog_model_set_selected (GossipAccountsDialog *dialog,
+ McAccount *account);
+static gboolean accounts_dialog_model_remove_selected (GossipAccountsDialog *dialog);
+static void accounts_dialog_model_selection_changed (GtkTreeSelection *selection,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_add_account (GossipAccountsDialog *dialog,
+ McAccount *account);
+static void accounts_dialog_account_added_cb (McAccountMonitor *monitor,
+ gchar *unique_name,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_account_removed_cb (McAccountMonitor *monitor,
+ gchar *unique_name,
+ GossipAccountsDialog *dialog);
+static gboolean accounts_dialog_row_changed_foreach (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data);
+static gboolean accounts_dialog_flash_connecting_cb (GossipAccountsDialog *dialog);
+static void accounts_dialog_status_changed_cb (MissionControl *mc,
+ TelepathyConnectionStatus status,
+ McPresence presence,
+ TelepathyConnectionStatusReason reason,
+ const gchar *unique_name,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_entry_name_changed_cb (GtkWidget *widget,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_button_create_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_button_cancel_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_button_connect_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_button_add_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_remove_response_cb (GtkWidget *dialog,
+ gint response,
+ McAccount *account);
+static void accounts_dialog_button_remove_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_treeview_row_activated_cb (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_response_cb (GtkWidget *widget,
+ gint response,
+ GossipAccountsDialog *dialog);
+static void accounts_dialog_destroy_cb (GtkWidget *widget,
+ GossipAccountsDialog *dialog);
+
+static void
+accounts_dialog_setup (GossipAccountsDialog *dialog)
+{
+ GtkTreeView *view;
+ GtkListStore *store;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GList *accounts, *l;
+ MissionControl *mc;
+
+ view = GTK_TREE_VIEW (dialog->treeview);
+ store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
+ selection = gtk_tree_view_get_selection (view);
+
+ mc = empathy_session_get_mission_control ();
+ accounts = mc_accounts_list ();
+
+ for (l = accounts; l; l = l->next) {
+ McAccount *account;
+ const gchar *name;
+ TelepathyConnectionStatus status;
+
+ account = l->data;
+
+ name = mc_account_get_display_name (account);
+ if (!name) {
+ continue;
+ }
+
+ status = mission_control_get_connection_status (mc, account, NULL);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_NAME, name,
+ COL_STATUS, status,
+ COL_ACCOUNT_POINTER, account,
+ -1);
+
+ accounts_dialog_status_changed_cb (mc,
+ status,
+ MC_PRESENCE_UNSET,
+ TP_CONN_STATUS_REASON_NONE_SPECIFIED,
+ mc_account_get_unique_name (account),
+ dialog);
+
+ g_object_unref (account);
+ }
+
+ g_list_free (accounts);
+}
+
+static void
+accounts_dialog_update_connect_button (GossipAccountsDialog *dialog)
+{
+ McAccount *account;
+ GtkWidget *image;
+ const gchar *stock_id;
+ const gchar *label;
+
+ account = accounts_dialog_model_get_selected (dialog);
+
+ if (!account) {
+ gtk_widget_set_sensitive (dialog->button_connect, FALSE);
+ return;
+ }
+
+ if (mc_account_is_enabled (account)) {
+ label = _("Disable");
+ stock_id = GTK_STOCK_DISCONNECT;
+ } else {
+ label = _("Enable");
+ stock_id = GTK_STOCK_CONNECT;
+ }
+
+ image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
+
+ gtk_button_set_label (GTK_BUTTON (dialog->button_connect), label);
+ gtk_button_set_image (GTK_BUTTON (dialog->button_connect), image);
+}
+
+static void
+accounts_dialog_update_account (GossipAccountsDialog *dialog,
+ McAccount *account)
+{
+ if (dialog->settings_widget) {
+ gtk_widget_destroy (dialog->settings_widget);
+ dialog->settings_widget = NULL;
+ }
+
+ if (!account) {
+ GtkTreeView *view;
+ GtkTreeModel *model;
+
+ gtk_widget_show (dialog->frame_no_account);
+ gtk_widget_hide (dialog->vbox_details);
+
+ gtk_widget_set_sensitive (dialog->button_connect, FALSE);
+ gtk_widget_set_sensitive (dialog->button_remove, FALSE);
+
+ view = GTK_TREE_VIEW (dialog->treeview);
+ model = gtk_tree_view_get_model (view);
+
+ if (gtk_tree_model_iter_n_children (model, NULL) > 0) {
+ gtk_label_set_markup (GTK_LABEL (dialog->label_no_account),
+ _("<b>No Account Selected</b>"));
+ gtk_label_set_markup (GTK_LABEL (dialog->label_no_account_blurb),
+ _("To add a new account, you can click on the "
+ "'Add' button and a new entry will be created "
+ "for you to start configuring.\n"
+ "\n"
+ "If you do not want to add an account, simply "
+ "click on the account you want to configure in "
+ "the list on the left."));
+ } else {
+ gtk_label_set_markup (GTK_LABEL (dialog->label_no_account),
+ _("<b>No Accounts Configured</b>"));
+ gtk_label_set_markup (GTK_LABEL (dialog->label_no_account_blurb),
+ _("To add a new account, you can click on the "
+ "'Add' button and a new entry will be created "
+ "for you to start configuring."));
+ }
+ } else {
+ McProfile *profile;
+ const gchar *config_ui;
+
+ gtk_widget_hide (dialog->frame_no_account);
+ gtk_widget_show (dialog->vbox_details);
+
+ profile = mc_account_get_profile (account);
+ config_ui = mc_profile_get_configuration_ui (profile);
+
+ if (strcmp (config_ui, "blah") == 0) {
+ } else {
+ dialog->settings_widget =
+ gossip_account_widget_generic_new (account,
+ dialog->label_name);
+ }
+
+ gtk_widget_grab_focus (dialog->settings_widget);
+ }
+
+ if (dialog->settings_widget) {
+ gtk_container_add (GTK_CONTAINER (dialog->alignment_settings),
+ dialog->settings_widget);
+ }
+
+ if (account) {
+ McProfile *profile;
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gossip_pixbuf_from_account (account, GTK_ICON_SIZE_DIALOG);
+ gtk_image_set_from_pixbuf (GTK_IMAGE (dialog->image_type), pixbuf);
+ if (pixbuf) {
+ g_object_unref (pixbuf);
+ }
+
+ profile = mc_account_get_profile (account);
+
+ gtk_label_set_text (GTK_LABEL (dialog->label_type),
+ mc_profile_get_display_name (profile));
+ gtk_label_set_text (GTK_LABEL (dialog->label_name),
+ mc_account_get_display_name (account));
+ }
+}
+
+static void
+accounts_dialog_model_setup (GossipAccountsDialog *dialog)
+{
+ GtkListStore *store;
+ GtkTreeSelection *selection;
+
+ store = gtk_list_store_new (COL_COUNT,
+ G_TYPE_STRING, /* name */
+ G_TYPE_UINT, /* status */
+ MC_TYPE_ACCOUNT); /* account */
+
+ gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->treeview),
+ GTK_TREE_MODEL (store));
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->treeview));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
+
+ g_signal_connect (selection, "changed",
+ G_CALLBACK (accounts_dialog_model_selection_changed),
+ dialog);
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
+ COL_NAME, GTK_SORT_ASCENDING);
+
+ accounts_dialog_model_add_columns (dialog);
+
+ g_object_unref (store);
+}
+
+static void
+accounts_dialog_model_add_columns (GossipAccountsDialog *dialog)
+{
+ GtkTreeView *view;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *cell;
+
+ view = GTK_TREE_VIEW (dialog->treeview);
+ gtk_tree_view_set_headers_visible (view, TRUE);
+
+ /* account name/status */
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("Accounts"));
+
+ cell = gtk_cell_renderer_pixbuf_new ();
+ gtk_tree_view_column_pack_start (column, cell, FALSE);
+ gtk_tree_view_column_set_cell_data_func (column, cell,
+ (GtkTreeCellDataFunc)
+ accounts_dialog_model_pixbuf_data_func,
+ dialog,
+ NULL);
+
+ cell = gtk_cell_renderer_text_new ();
+ g_object_set (cell, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
+ gtk_tree_view_column_pack_start (column, cell, TRUE);
+ gtk_tree_view_column_add_attribute (column,
+ cell,
+ "text", COL_NAME);
+
+ gtk_tree_view_column_set_expand (column, TRUE);
+ gtk_tree_view_append_column (view, column);
+}
+
+static void
+accounts_dialog_model_select_first (GossipAccountsDialog *dialog)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+
+ /* select first */
+ view = GTK_TREE_VIEW (dialog->treeview);
+ model = gtk_tree_view_get_model (view);
+
+ if (gtk_tree_model_get_iter_first (model, &iter)) {
+ selection = gtk_tree_view_get_selection (view);
+ gtk_tree_selection_select_iter (selection, &iter);
+ } else {
+ accounts_dialog_update_account (dialog, NULL);
+ }
+}
+
+static void
+accounts_dialog_model_pixbuf_data_func (GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ GossipAccountsDialog *dialog)
+{
+ McAccount *account;
+ GdkPixbuf *pixbuf;
+ TelepathyConnectionStatus status;
+
+ gtk_tree_model_get (model, iter,
+ COL_STATUS, &status,
+ COL_ACCOUNT_POINTER, &account,
+ -1);
+
+ pixbuf = gossip_pixbuf_from_account (account, GTK_ICON_SIZE_BUTTON);
+
+ if (pixbuf) {
+ if (status == TP_CONN_STATUS_DISCONNECTED ||
+ (status == TP_CONN_STATUS_CONNECTING &&
+ !dialog->connecting_show)) {
+ GdkPixbuf *modded_pixbuf;
+
+ modded_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ TRUE,
+ 8,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf));
+
+ gdk_pixbuf_saturate_and_pixelate (pixbuf,
+ modded_pixbuf,
+ 1.0,
+ TRUE);
+ g_object_unref (pixbuf);
+ pixbuf = modded_pixbuf;
+ }
+ }
+
+ g_object_set (cell,
+ "visible", TRUE,
+ "pixbuf", pixbuf,
+ NULL);
+
+ g_object_unref (account);
+ if (pixbuf) {
+ g_object_unref (pixbuf);
+ }
+}
+
+static McAccount *
+accounts_dialog_model_get_selected (GossipAccountsDialog *dialog)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ McAccount *account;
+
+ view = GTK_TREE_VIEW (dialog->treeview);
+ selection = gtk_tree_view_get_selection (view);
+
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ return NULL;
+ }
+
+ gtk_tree_model_get (model, &iter, COL_ACCOUNT_POINTER, &account, -1);
+
+ return account;
+}
+
+static void
+accounts_dialog_model_set_selected (GossipAccountsDialog *dialog,
+ McAccount *account)
+{
+ GtkTreeView *view;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean ok;
+
+ view = GTK_TREE_VIEW (dialog->treeview);
+ model = gtk_tree_view_get_model (view);
+ selection = gtk_tree_view_get_selection (view);
+
+ for (ok = gtk_tree_model_get_iter_first (model, &iter);
+ ok;
+ ok = gtk_tree_model_iter_next (model, &iter)) {
+ McAccount *this_account;
+ gboolean equal;
+
+ gtk_tree_model_get (model, &iter,
+ COL_ACCOUNT_POINTER, &this_account,
+ -1);
+
+ equal = gossip_account_equal (this_account, account);
+ g_object_unref (this_account);
+
+ if (equal) {
+ gtk_tree_selection_select_iter (selection, &iter);
+ break;
+ }
+ }
+}
+
+static gboolean
+accounts_dialog_model_remove_selected (GossipAccountsDialog *dialog)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+
+ view = GTK_TREE_VIEW (dialog->treeview);
+ selection = gtk_tree_view_get_selection (view);
+
+ if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
+ return FALSE;
+ }
+
+ return gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
+}
+
+static void
+accounts_dialog_model_selection_changed (GtkTreeSelection *selection,
+ GossipAccountsDialog *dialog)
+{
+ McAccount *account;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean is_selection;
+
+ is_selection = gtk_tree_selection_get_selected (selection, &model, &iter);
+
+ gtk_widget_set_sensitive (dialog->button_remove, is_selection);
+ gtk_widget_set_sensitive (dialog->button_connect, is_selection);
+
+ accounts_dialog_update_connect_button (dialog);
+
+ account = accounts_dialog_model_get_selected (dialog);
+ accounts_dialog_update_account (dialog, account);
+
+ if (account) {
+ g_object_unref (account);
+ }
+}
+
+static void
+accounts_dialog_add_account (GossipAccountsDialog *dialog,
+ McAccount *account)
+{
+ MissionControl *mc;
+ TelepathyConnectionStatus status;
+ const gchar *name;
+ GtkTreeView *view;
+ GtkTreeModel *model;
+ GtkListStore *store;
+ GtkTreeIter iter;
+ gboolean ok;
+
+ view = GTK_TREE_VIEW (dialog->treeview);
+ model = gtk_tree_view_get_model (view);
+ store = GTK_LIST_STORE (model);
+
+ for (ok = gtk_tree_model_get_iter_first (model, &iter);
+ ok;
+ ok = gtk_tree_model_iter_next (model, &iter)) {
+ McAccount *this_account;
+ gboolean equal;
+
+ gtk_tree_model_get (model, &iter,
+ COL_ACCOUNT_POINTER, &this_account,
+ -1);
+
+ equal = gossip_account_equal (this_account, account);
+ g_object_unref (this_account);
+
+ if (equal) {
+ return;
+ }
+ }
+
+ mc = empathy_session_get_mission_control ();
+ status = mission_control_get_connection_status (mc, account, NULL);
+ name = mc_account_get_display_name (account);
+
+ g_return_if_fail (name != NULL);
+
+ gossip_debug (DEBUG_DOMAIN, "Adding new account: %s", name);
+
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ COL_NAME, name,
+ COL_STATUS, status,
+ COL_ACCOUNT_POINTER, account,
+ -1);
+}
+
+static void
+accounts_dialog_account_added_cb (McAccountMonitor *monitor,
+ gchar *unique_name,
+ GossipAccountsDialog *dialog)
+{
+ McAccount *account;
+
+ account = mc_account_lookup (unique_name);
+ accounts_dialog_add_account (dialog, account);
+ g_object_unref (account);
+}
+
+static void
+accounts_dialog_account_removed_cb (McAccountMonitor *monitor,
+ gchar *unique_name,
+ GossipAccountsDialog *dialog)
+{
+ MissionControl *mc;
+ McAccount *account;
+
+ mc = empathy_session_get_mission_control ();
+ account = mc_account_lookup (unique_name);
+
+ accounts_dialog_model_set_selected (dialog, account);
+ accounts_dialog_model_remove_selected (dialog);
+
+ g_object_unref (account);
+}
+
+static gboolean
+accounts_dialog_row_changed_foreach (GtkTreeModel *model,
+ GtkTreePath *path,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ gtk_tree_model_row_changed (model, path, iter);
+
+ return FALSE;
+}
+
+static gboolean
+accounts_dialog_flash_connecting_cb (GossipAccountsDialog *dialog)
+{
+ GtkTreeView *view;
+ GtkTreeModel *model;
+
+ dialog->connecting_show = !dialog->connecting_show;
+
+ view = GTK_TREE_VIEW (dialog->treeview);
+ model = gtk_tree_view_get_model (view);
+
+ gtk_tree_model_foreach (model, accounts_dialog_row_changed_foreach, NULL);
+
+ return TRUE;
+}
+
+static void
+accounts_dialog_status_changed_cb (MissionControl *mc,
+ TelepathyConnectionStatus status,
+ McPresence presence,
+ TelepathyConnectionStatusReason reason,
+ const gchar *unique_name,
+ GossipAccountsDialog *dialog)
+{
+ GtkTreeView *view;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean ok;
+ McAccount *account;
+ GList *accounts, *l;
+ gboolean found = FALSE;
+
+ /* Update the status in the model */
+ view = GTK_TREE_VIEW (dialog->treeview);
+ selection = gtk_tree_view_get_selection (view);
+ model = gtk_tree_view_get_model (view);
+ account = mc_account_lookup (unique_name);
+
+ for (ok = gtk_tree_model_get_iter_first (model, &iter);
+ ok;
+ ok = gtk_tree_model_iter_next (model, &iter)) {
+ McAccount *this_account;
+ gboolean equal;
+
+ gtk_tree_model_get (model, &iter,
+ COL_ACCOUNT_POINTER, &this_account,
+ -1);
+
+ equal = gossip_account_equal (this_account, account);
+ g_object_unref (this_account);
+
+ if (equal) {
+ GtkTreePath *path;
+
+ gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+ COL_STATUS, status,
+ -1);
+
+ path = gtk_tree_model_get_path (model, &iter);
+ gtk_tree_model_row_changed (model, path, &iter);
+ gtk_tree_path_free (path);
+
+ break;
+ }
+ }
+
+ g_object_unref (account);
+
+ /* Start to flash account if status is connecting */
+ if (status == TP_CONN_STATUS_CONNECTING) {
+ if (!dialog->connecting_id) {
+ dialog->connecting_id = g_timeout_add (FLASH_TIMEOUT,
+ (GSourceFunc) accounts_dialog_flash_connecting_cb,
+ dialog);
+ }
+
+ return;
+ }
+
+ /* Stop to flash if no account is connecting */
+ accounts = mc_accounts_list ();
+ for (l = accounts; l; l = l->next) {
+ McAccount *this_account;
+
+ this_account = l->data;
+
+ if (mission_control_get_connection_status (mc, this_account, NULL) == TP_CONN_STATUS_CONNECTING) {
+ found = TRUE;
+ break;
+ }
+
+ g_object_unref (this_account);
+ }
+ g_list_free (accounts);
+
+ if (!found && dialog->connecting_id) {
+ g_source_remove (dialog->connecting_id);
+ dialog->connecting_id = 0;
+ }
+}
+
+static void
+accounts_dialog_entry_name_changed_cb (GtkWidget *widget,
+ GossipAccountsDialog *dialog)
+{
+ const gchar *str;
+
+ str = gtk_entry_get_text (GTK_ENTRY (widget));
+ gtk_widget_set_sensitive (dialog->button_create, !G_STR_EMPTY (str));
+}
+
+static void
+accounts_dialog_button_create_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog)
+{
+ McProfile *profile;
+ McAccount *account;
+ const gchar *str;
+
+ /* Update widgets */
+ gtk_widget_show (dialog->vbox_details);
+ gtk_widget_hide (dialog->frame_no_account);
+ gtk_widget_hide (dialog->frame_new_account);
+
+ profile = gossip_profile_chooser_get_selected (dialog->combobox_profile);
+
+ /* Create account */
+ account = mc_account_create (profile);
+
+ str = gtk_entry_get_text (GTK_ENTRY (dialog->entry_name));
+ mc_account_set_display_name (account, str);
+
+ accounts_dialog_add_account (dialog, account);
+ accounts_dialog_model_set_selected (dialog, account);
+
+ g_object_unref (account);
+ g_object_unref (profile);
+}
+
+static void
+accounts_dialog_button_cancel_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog)
+{
+ McAccount *account;
+
+ gtk_widget_hide (dialog->vbox_details);
+ gtk_widget_hide (dialog->frame_no_account);
+ gtk_widget_hide (dialog->frame_new_account);
+
+ account = accounts_dialog_model_get_selected (dialog);
+ accounts_dialog_update_account (dialog, account);
+}
+
+static void
+accounts_dialog_button_connect_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog)
+{
+ McAccount *account;
+ gboolean enable;
+
+ account = accounts_dialog_model_get_selected (dialog);
+ enable = (!mc_account_is_enabled (account));
+ mc_account_set_enabled (account, enable);
+ accounts_dialog_update_connect_button (dialog);
+
+ g_object_unref (account);
+}
+
+static void
+accounts_dialog_button_add_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog)
+{
+ gtk_widget_hide (dialog->vbox_details);
+ gtk_widget_hide (dialog->frame_no_account);
+ gtk_widget_show (dialog->frame_new_account);
+
+ gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->combobox_profile), 0);
+ gtk_entry_set_text (GTK_ENTRY (dialog->entry_name), "");
+ gtk_widget_grab_focus (dialog->entry_name);
+}
+
+static void
+accounts_dialog_remove_response_cb (GtkWidget *dialog,
+ gint response,
+ McAccount *account)
+{
+ if (response == GTK_RESPONSE_YES) {
+ mc_account_delete (account);
+ }
+
+ gtk_widget_destroy (dialog);
+}
+
+static void
+accounts_dialog_button_remove_clicked_cb (GtkWidget *button,
+ GossipAccountsDialog *dialog)
+{
+ McAccount *account;
+ GtkWidget *message_dialog;
+
+ account = accounts_dialog_model_get_selected (dialog);
+
+ if (!mc_account_is_complete (account)) {
+ accounts_dialog_model_remove_selected (dialog);
+ return;
+ }
+ message_dialog = gtk_message_dialog_new
+ (GTK_WINDOW (dialog->window),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_NONE,
+ _("You are about to remove your %s account!\n"
+ "Are you sure you want to proceed?"),
+ mc_account_get_display_name (account));
+
+ gtk_message_dialog_format_secondary_text
+ (GTK_MESSAGE_DIALOG (message_dialog),
+ _("Any associated conversations and chat rooms will NOT be "
+ "removed if you decide to proceed.\n"
+ "\n"
+ "Should you decide to add the account back at a later time, "
+ "they will still be available."));
+
+ gtk_dialog_add_button (GTK_DIALOG (message_dialog),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_NO);
+ gtk_dialog_add_button (GTK_DIALOG (message_dialog),
+ GTK_STOCK_REMOVE,
+ GTK_RESPONSE_YES);
+
+ g_signal_connect (message_dialog, "response",
+ G_CALLBACK (accounts_dialog_remove_response_cb),
+ account);
+
+ gtk_widget_show (message_dialog);
+}
+
+static void
+accounts_dialog_treeview_row_activated_cb (GtkTreeView *tree_view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ GossipAccountsDialog *dialog)
+{
+
+ accounts_dialog_button_connect_clicked_cb (dialog->button_connect,
+ dialog);
+}
+
+static void
+accounts_dialog_response_cb (GtkWidget *widget,
+ gint response,
+ GossipAccountsDialog *dialog)
+{
+ gtk_widget_destroy (widget);
+}
+
+static void
+accounts_dialog_destroy_cb (GtkWidget *widget,
+ GossipAccountsDialog *dialog)
+{
+ MissionControl *mc;
+ McAccountMonitor *monitor;
+ GList *accounts, *l;
+
+ mc = empathy_session_get_mission_control ();
+ monitor = mc_account_monitor_new ();
+
+ /* Disconnect signals */
+ g_signal_handlers_disconnect_by_func (monitor,
+ accounts_dialog_account_added_cb,
+ dialog);
+ g_signal_handlers_disconnect_by_func (monitor,
+ accounts_dialog_account_removed_cb,
+ dialog);
+ dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (mc), "AccountStatusChanged",
+ G_CALLBACK (accounts_dialog_status_changed_cb),
+ dialog);
+
+ /* Delete incomplete accounts */
+ accounts = mc_accounts_list ();
+ for (l = accounts; l; l = l->next) {
+ McAccount *account;
+
+ account = l->data;
+ if (!mc_account_is_complete (account)) {
+ /* FIXME: Warn the user the account is not complete
+ * and is going to be removed. */
+ mc_account_delete (account);
+ }
+
+ g_object_unref (account);
+ }
+ g_list_free (accounts);
+
+ if (dialog->connecting_id) {
+ g_source_remove (dialog->connecting_id);
+ }
+
+ g_free (dialog);
+}
+
+GtkWidget *
+gossip_accounts_dialog_show (void)
+{
+ static GossipAccountsDialog *dialog = NULL;
+ MissionControl *mc;
+ McAccountMonitor *monitor;
+ GladeXML *glade;
+ GtkWidget *bbox;
+ GtkWidget *button_close;
+
+ if (dialog) {
+ gtk_window_present (GTK_WINDOW (dialog->window));
+ return dialog->window;
+ }
+
+ dialog = g_new0 (GossipAccountsDialog, 1);
+
+ glade = gossip_glade_get_file ("empathy-accounts.glade",
+ "accounts_dialog",
+ NULL,
+ "accounts_dialog", &dialog->window,
+ "vbox_details", &dialog->vbox_details,
+ "frame_no_account", &dialog->frame_no_account,
+ "label_no_account", &dialog->label_no_account,
+ "label_no_account_blurb", &dialog->label_no_account_blurb,
+ "alignment_settings", &dialog->alignment_settings,
+ "dialog-action_area", &bbox,
+ "treeview", &dialog->treeview,
+ "frame_new_account", &dialog->frame_new_account,
+ "entry_name", &dialog->entry_name,
+ "table_new_account", &dialog->table_new_account,
+ "button_create", &dialog->button_create,
+ "button_cancel", &dialog->button_cancel,
+ "image_type", &dialog->image_type,
+ "label_type", &dialog->label_type,
+ "label_name", &dialog->label_name,
+ "button_remove", &dialog->button_remove,
+ "button_connect", &dialog->button_connect,
+ "button_close", &button_close,
+ NULL);
+
+ gossip_glade_connect (glade,
+ dialog,
+ "accounts_dialog", "destroy", accounts_dialog_destroy_cb,
+ "accounts_dialog", "response", accounts_dialog_response_cb,
+ "button_create", "clicked", accounts_dialog_button_create_clicked_cb,
+ "button_cancel", "clicked", accounts_dialog_button_cancel_clicked_cb,
+ "entry_name", "changed", accounts_dialog_entry_name_changed_cb,
+ "treeview", "row-activated", accounts_dialog_treeview_row_activated_cb,
+ "button_connect", "clicked", accounts_dialog_button_connect_clicked_cb,
+ "button_add", "clicked", accounts_dialog_button_add_clicked_cb,
+ "button_remove", "clicked", accounts_dialog_button_remove_clicked_cb,
+ NULL);
+
+ g_object_add_weak_pointer (G_OBJECT (dialog->window), (gpointer) &dialog);
+
+ g_object_unref (glade);
+
+ /* Create profile chooser */
+ dialog->combobox_profile = gossip_profile_chooser_new ();
+ gtk_table_attach_defaults (GTK_TABLE (dialog->table_new_account),
+ dialog->combobox_profile,
+ 1, 2,
+ 0, 1);
+ gtk_widget_show (dialog->combobox_profile);
+
+ /* Set up signalling */
+ mc = empathy_session_get_mission_control ();
+ monitor = mc_account_monitor_new ();
+
+ /* FIXME: connect account-enabled/disabled too */
+ g_signal_connect (monitor, "account-created",
+ G_CALLBACK (accounts_dialog_account_added_cb),
+ dialog);
+ g_signal_connect (monitor, "account-deleted",
+ G_CALLBACK (accounts_dialog_account_removed_cb),
+ dialog);
+ dbus_g_proxy_connect_signal (DBUS_G_PROXY (mc), "AccountStatusChanged",
+ G_CALLBACK (accounts_dialog_status_changed_cb),
+ dialog, NULL);
+
+ accounts_dialog_model_setup (dialog);
+ accounts_dialog_setup (dialog);
+
+ gtk_widget_show (dialog->window);
+
+ accounts_dialog_model_select_first (dialog);
+
+ return dialog->window;
+}
+
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2005-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Martyn Russell <martyn@imendio.com>
+ */
+
+#ifndef __GOSSIP_ACCOUNTS_DIALOG_H__
+#define __GOSSIP_ACCOUNTS_DIALOG_H__
+
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+GtkWidget *gossip_accounts_dialog_show (void);
+
+G_END_DECLS
+
+#endif /* __GOSSIP_ACCOUNTS_DIALOG_H__ */
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Kristian Rietveld <kris@imendio.com>
+ */
+
+/* To do:
+ * - should probably cancel animation if model changes
+ * - need to handle case where node-in-animation is removed
+ * - it only handles a single animation at a time; but I guess users
+ * aren't fast enough to trigger two or more animations at once anyway :P
+ * (could guard for this by just cancelling the "old" animation, and
+ * start the new one).
+ */
+
+#include <gtk/gtktreeview.h>
+
+#include "gossip-cell-renderer-expander.h"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CELL_RENDERER_EXPANDER, GossipCellRendererExpanderPriv))
+
+static void gossip_cell_renderer_expander_init (GossipCellRendererExpander *expander);
+static void gossip_cell_renderer_expander_class_init (GossipCellRendererExpanderClass *klass);
+static void gossip_cell_renderer_expander_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void gossip_cell_renderer_expander_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gossip_cell_renderer_expander_finalize (GObject *object);
+static void gossip_cell_renderer_expander_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget,
+ GdkRectangle *cell_area,
+ gint *x_offset,
+ gint *y_offset,
+ gint *width,
+ gint *height);
+static void gossip_cell_renderer_expander_render (GtkCellRenderer *cell,
+ GdkWindow *window,
+ GtkWidget *widget,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GdkRectangle *expose_area,
+ GtkCellRendererState flags);
+static gboolean gossip_cell_renderer_expander_activate (GtkCellRenderer *cell,
+ GdkEvent *event,
+ GtkWidget *widget,
+ const gchar *path,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GtkCellRendererState flags);
+
+enum {
+ PROP_0,
+ PROP_EXPANDER_STYLE,
+ PROP_EXPANDER_SIZE,
+ PROP_ACTIVATABLE
+};
+
+typedef struct _GossipCellRendererExpanderPriv GossipCellRendererExpanderPriv;
+
+struct _GossipCellRendererExpanderPriv {
+ GtkExpanderStyle expander_style;
+ gint expander_size;
+
+ GtkTreeView *animation_view;
+ GtkTreeRowReference *animation_node;
+ GtkExpanderStyle animation_style;
+ guint animation_timeout;
+ GdkRectangle animation_area;
+
+ guint activatable : 1;
+ guint animation_expanding : 1;
+};
+
+G_DEFINE_TYPE (GossipCellRendererExpander, gossip_cell_renderer_expander, GTK_TYPE_CELL_RENDERER)
+
+static void
+gossip_cell_renderer_expander_init (GossipCellRendererExpander *expander)
+{
+ GossipCellRendererExpanderPriv *priv;
+
+ priv = GET_PRIV (expander);
+
+ priv->expander_style = GTK_EXPANDER_COLLAPSED;
+ priv->expander_size = 12;
+ priv->activatable = TRUE;
+ priv->animation_node = NULL;
+
+ GTK_CELL_RENDERER (expander)->xpad = 2;
+ GTK_CELL_RENDERER (expander)->ypad = 2;
+ GTK_CELL_RENDERER (expander)->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
+}
+
+static void
+gossip_cell_renderer_expander_class_init (GossipCellRendererExpanderClass *klass)
+{
+ GObjectClass *object_class;
+ GtkCellRendererClass *cell_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ cell_class = GTK_CELL_RENDERER_CLASS (klass);
+
+ object_class->finalize = gossip_cell_renderer_expander_finalize;
+
+ object_class->get_property = gossip_cell_renderer_expander_get_property;
+ object_class->set_property = gossip_cell_renderer_expander_set_property;
+
+ cell_class->get_size = gossip_cell_renderer_expander_get_size;
+ cell_class->render = gossip_cell_renderer_expander_render;
+ cell_class->activate = gossip_cell_renderer_expander_activate;
+
+ g_object_class_install_property (object_class,
+ PROP_EXPANDER_STYLE,
+ g_param_spec_enum ("expander-style",
+ "Expander Style",
+ "Style to use when painting the expander",
+ GTK_TYPE_EXPANDER_STYLE,
+ GTK_EXPANDER_COLLAPSED,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_EXPANDER_SIZE,
+ g_param_spec_int ("expander-size",
+ "Expander Size",
+ "The size of the expander",
+ 0,
+ G_MAXINT,
+ 12,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_ACTIVATABLE,
+ g_param_spec_boolean ("activatable",
+ "Activatable",
+ "The expander can be activated",
+ TRUE,
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private (object_class, sizeof (GossipCellRendererExpanderPriv));
+}
+
+static void
+gossip_cell_renderer_expander_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GossipCellRendererExpander *expander;
+ GossipCellRendererExpanderPriv *priv;
+
+ expander = GOSSIP_CELL_RENDERER_EXPANDER (object);
+ priv = GET_PRIV (expander);
+
+ switch (param_id) {
+ case PROP_EXPANDER_STYLE:
+ g_value_set_enum (value, priv->expander_style);
+ break;
+
+ case PROP_EXPANDER_SIZE:
+ g_value_set_int (value, priv->expander_size);
+ break;
+
+ case PROP_ACTIVATABLE:
+ g_value_set_boolean (value, priv->activatable);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gossip_cell_renderer_expander_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GossipCellRendererExpander *expander;
+ GossipCellRendererExpanderPriv *priv;
+
+ expander = GOSSIP_CELL_RENDERER_EXPANDER (object);
+ priv = GET_PRIV (expander);
+
+ switch (param_id) {
+ case PROP_EXPANDER_STYLE:
+ priv->expander_style = g_value_get_enum (value);
+ break;
+
+ case PROP_EXPANDER_SIZE:
+ priv->expander_size = g_value_get_int (value);
+ break;
+
+ case PROP_ACTIVATABLE:
+ priv->activatable = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gossip_cell_renderer_expander_finalize (GObject *object)
+{
+ GossipCellRendererExpanderPriv *priv;
+
+ priv = GET_PRIV (object);
+
+ if (priv->animation_timeout) {
+ g_source_remove (priv->animation_timeout);
+ priv->animation_timeout = 0;
+ }
+
+ if (priv->animation_node) {
+ gtk_tree_row_reference_free (priv->animation_node);
+ }
+
+ (* G_OBJECT_CLASS (gossip_cell_renderer_expander_parent_class)->finalize) (object);
+}
+
+GtkCellRenderer *
+gossip_cell_renderer_expander_new (void)
+{
+ return g_object_new (GOSSIP_TYPE_CELL_RENDERER_EXPANDER, NULL);
+}
+
+static void
+gossip_cell_renderer_expander_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget,
+ GdkRectangle *cell_area,
+ gint *x_offset,
+ gint *y_offset,
+ gint *width,
+ gint *height)
+{
+ GossipCellRendererExpander *expander;
+ GossipCellRendererExpanderPriv *priv;
+
+ expander = (GossipCellRendererExpander*) cell;
+ priv = GET_PRIV (expander);
+
+ if (cell_area) {
+ if (x_offset) {
+ *x_offset = cell->xalign * (cell_area->width - (priv->expander_size + (2 * cell->xpad)));
+ *x_offset = MAX (*x_offset, 0);
+ }
+
+ if (y_offset) {
+ *y_offset = cell->yalign * (cell_area->height - (priv->expander_size + (2 * cell->ypad)));
+ *y_offset = MAX (*y_offset, 0);
+ }
+ } else {
+ if (x_offset)
+ *x_offset = 0;
+
+ if (y_offset)
+ *y_offset = 0;
+ }
+
+ if (width)
+ *width = cell->xpad * 2 + priv->expander_size;
+
+ if (height)
+ *height = cell->ypad * 2 + priv->expander_size;
+}
+
+static void
+gossip_cell_renderer_expander_render (GtkCellRenderer *cell,
+ GdkWindow *window,
+ GtkWidget *widget,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GdkRectangle *expose_area,
+ GtkCellRendererState flags)
+{
+ GossipCellRendererExpander *expander;
+ GossipCellRendererExpanderPriv *priv;
+ GtkExpanderStyle expander_style;
+ gint x_offset, y_offset;
+
+ expander = (GossipCellRendererExpander*) cell;
+ priv = GET_PRIV (expander);
+
+ if (priv->animation_node) {
+ GtkTreePath *path;
+ GdkRectangle rect;
+
+ /* Not sure if I like this ... */
+ path = gtk_tree_row_reference_get_path (priv->animation_node);
+ gtk_tree_view_get_background_area (priv->animation_view, path,
+ NULL, &rect);
+ gtk_tree_path_free (path);
+
+ if (background_area->y == rect.y)
+ expander_style = priv->animation_style;
+ else
+ expander_style = priv->expander_style;
+ } else
+ expander_style = priv->expander_style;
+
+ gossip_cell_renderer_expander_get_size (cell, widget, cell_area,
+ &x_offset, &y_offset,
+ NULL, NULL);
+
+ gtk_paint_expander (widget->style,
+ window,
+ GTK_STATE_NORMAL,
+ expose_area,
+ widget,
+ "treeview",
+ cell_area->x + x_offset + cell->xpad + priv->expander_size / 2,
+ cell_area->y + y_offset + cell->ypad + priv->expander_size / 2,
+ expander_style);
+}
+
+static void
+invalidate_node (GtkTreeView *tree_view,
+ GtkTreePath *path)
+{
+ GdkWindow *bin_window;
+ GdkRectangle rect;
+
+ bin_window = gtk_tree_view_get_bin_window (tree_view);
+
+ gtk_tree_view_get_background_area (tree_view, path, NULL, &rect);
+
+ rect.x = 0;
+ rect.width = GTK_WIDGET (tree_view)->allocation.width;
+
+ gdk_window_invalidate_rect (bin_window, &rect, TRUE);
+}
+
+static gboolean
+do_animation (GossipCellRendererExpander *expander)
+{
+ GossipCellRendererExpanderPriv *priv;
+ GtkTreePath *path;
+ gboolean done = FALSE;
+
+ priv = GET_PRIV (expander);
+
+ if (priv->animation_expanding) {
+ if (priv->animation_style == GTK_EXPANDER_SEMI_COLLAPSED)
+ priv->animation_style = GTK_EXPANDER_SEMI_EXPANDED;
+ else if (priv->animation_style == GTK_EXPANDER_SEMI_EXPANDED) {
+ priv->animation_style = GTK_EXPANDER_EXPANDED;
+ done = TRUE;
+ }
+ } else {
+ if (priv->animation_style == GTK_EXPANDER_SEMI_EXPANDED)
+ priv->animation_style = GTK_EXPANDER_SEMI_COLLAPSED;
+ else if (priv->animation_style == GTK_EXPANDER_SEMI_COLLAPSED) {
+ priv->animation_style = GTK_EXPANDER_COLLAPSED;
+ done = TRUE;
+ }
+ }
+
+ path = gtk_tree_row_reference_get_path (priv->animation_node);
+ invalidate_node (priv->animation_view, path);
+ gtk_tree_path_free (path);
+
+ if (done) {
+ gtk_tree_row_reference_free (priv->animation_node);
+ priv->animation_node = NULL;
+ priv->animation_timeout = 0;
+ }
+
+ return !done;
+}
+
+static gboolean
+animation_timeout (gpointer data)
+{
+ gboolean retval;
+
+ GDK_THREADS_ENTER ();
+
+ retval = do_animation (data);
+
+ GDK_THREADS_LEAVE ();
+
+ return retval;
+}
+
+static void
+gossip_cell_renderer_expander_start_animation (GossipCellRendererExpander *expander,
+ GtkTreeView *tree_view,
+ GtkTreePath *path,
+ gboolean expanding,
+ GdkRectangle *background_area)
+{
+ GossipCellRendererExpanderPriv *priv;
+
+ priv = GET_PRIV (expander);
+
+ if (expanding) {
+ priv->animation_style = GTK_EXPANDER_SEMI_COLLAPSED;
+ } else {
+ priv->animation_style = GTK_EXPANDER_SEMI_EXPANDED;
+ }
+
+ invalidate_node (tree_view, path);
+
+ priv->animation_expanding = expanding;
+ priv->animation_view = tree_view;
+ priv->animation_node = gtk_tree_row_reference_new (gtk_tree_view_get_model (tree_view), path);
+ priv->animation_timeout = g_timeout_add (50, animation_timeout, expander);
+}
+
+static gboolean
+gossip_cell_renderer_expander_activate (GtkCellRenderer *cell,
+ GdkEvent *event,
+ GtkWidget *widget,
+ const gchar *path_string,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GtkCellRendererState flags)
+{
+ GossipCellRendererExpander *expander;
+ GossipCellRendererExpanderPriv *priv;
+ GtkTreePath *path;
+ gboolean animate;
+ gboolean expanding;
+
+ expander = GOSSIP_CELL_RENDERER_EXPANDER (cell);
+ priv = GET_PRIV (cell);
+
+ if (!GTK_IS_TREE_VIEW (widget) || !priv->activatable)
+ return FALSE;
+
+ path = gtk_tree_path_new_from_string (path_string);
+
+ if (gtk_tree_path_get_depth (path) > 1) {
+ gtk_tree_path_free (path);
+ return TRUE;
+ }
+
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (widget)),
+ "gtk-enable-animations", &animate,
+ NULL);
+
+ if (gtk_tree_view_row_expanded (GTK_TREE_VIEW (widget), path)) {
+ gtk_tree_view_collapse_row (GTK_TREE_VIEW (widget), path);
+ expanding = FALSE;
+ } else {
+ gtk_tree_view_expand_row (GTK_TREE_VIEW (widget), path, FALSE);
+ expanding = TRUE;
+ }
+
+ if (animate) {
+ gossip_cell_renderer_expander_start_animation (expander,
+ GTK_TREE_VIEW (widget),
+ path,
+ expanding,
+ background_area);
+ }
+
+ gtk_tree_path_free (path);
+
+ return TRUE;
+}
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2006-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Kristian Rietveld <kris@imendio.com>
+ */
+
+#ifndef __GOSSIP_CELL_RENDERER_EXPANDER_H__
+#define __GOSSIP_CELL_RENDERER_EXPANDER_H__
+
+#include <gtk/gtkcellrenderer.h>
+
+G_BEGIN_DECLS
+
+#define GOSSIP_TYPE_CELL_RENDERER_EXPANDER (gossip_cell_renderer_expander_get_type ())
+#define GOSSIP_CELL_RENDERER_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOSSIP_TYPE_CELL_RENDERER_EXPANDER, GossipCellRendererExpander))
+#define GOSSIP_CELL_RENDERER_EXPANDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GOSSIP_TYPE_CELL_RENDERER_EXPANDER, GossipCellRendererExpanderClass))
+#define GOSSIP_IS_CELL_RENDERER_EXPANDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOSSIP_TYPE_CELL_RENDERER_EXPANDER))
+#define GOSSIP_IS_CELL_RENDERER_EXPANDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOSSIP_TYPE_CELL_RENDERER_EXPANDER))
+#define GOSSIP_CELL_RENDERER_EXPANDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GOSSIP_TYPE_CELL_RENDERER_EXPANDER, GossipCellRendererExpanderClass))
+
+typedef struct _GossipCellRendererExpander GossipCellRendererExpander;
+typedef struct _GossipCellRendererExpanderClass GossipCellRendererExpanderClass;
+
+struct _GossipCellRendererExpander {
+ GtkCellRenderer parent;
+};
+
+struct _GossipCellRendererExpanderClass {
+ GtkCellRendererClass parent_class;
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+GType gossip_cell_renderer_expander_get_type (void) G_GNUC_CONST;
+GtkCellRenderer *gossip_cell_renderer_expander_new (void);
+
+G_END_DECLS
+
+#endif /* __GOSSIP_CELL_RENDERER_EXPANDER_H__ */
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Mikael Hallendal <micke@imendio.com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "gossip-cell-renderer-text.h"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CELL_RENDERER_TEXT, GossipCellRendererTextPriv))
+
+struct _GossipCellRendererTextPriv {
+ gchar *name;
+ gchar *status;
+ gboolean is_group;
+
+ gboolean is_valid;
+ gboolean is_selected;
+
+ gboolean show_status;
+};
+
+static void gossip_cell_renderer_text_class_init (GossipCellRendererTextClass *klass);
+static void gossip_cell_renderer_text_init (GossipCellRendererText *cell);
+static void cell_renderer_text_finalize (GObject *object);
+static void cell_renderer_text_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void cell_renderer_text_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void cell_renderer_text_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget,
+ GdkRectangle *cell_area,
+ gint *x_offset,
+ gint *y_offset,
+ gint *width,
+ gint *height);
+static void cell_renderer_text_render (GtkCellRenderer *cell,
+ GdkDrawable *window,
+ GtkWidget *widget,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GdkRectangle *expose_area,
+ GtkCellRendererState flags);
+static void cell_renderer_text_update_text (GossipCellRendererText *cell,
+ GtkWidget *widget,
+ gboolean selected);
+
+/* Properties */
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_STATUS,
+ PROP_IS_GROUP,
+ PROP_SHOW_STATUS,
+};
+
+G_DEFINE_TYPE (GossipCellRendererText, gossip_cell_renderer_text, GTK_TYPE_CELL_RENDERER_TEXT);
+
+static void
+gossip_cell_renderer_text_class_init (GossipCellRendererTextClass *klass)
+{
+ GObjectClass *object_class;
+ GtkCellRendererClass *cell_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ cell_class = GTK_CELL_RENDERER_CLASS (klass);
+
+ object_class->finalize = cell_renderer_text_finalize;
+
+ object_class->get_property = cell_renderer_text_get_property;
+ object_class->set_property = cell_renderer_text_set_property;
+
+ cell_class->get_size = cell_renderer_text_get_size;
+ cell_class->render = cell_renderer_text_render;
+
+ g_object_class_install_property (object_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ "Name",
+ "Contact name",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_STATUS,
+ g_param_spec_string ("status",
+ "Status",
+ "Contact status string",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_IS_GROUP,
+ g_param_spec_boolean ("is_group",
+ "Is group",
+ "Whether this cell is a group",
+ FALSE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_SHOW_STATUS,
+ g_param_spec_boolean ("show-status",
+ "Show status",
+ "Whether to show the status line",
+ TRUE,
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private (object_class, sizeof (GossipCellRendererTextPriv));
+}
+
+static void
+gossip_cell_renderer_text_init (GossipCellRendererText *cell)
+{
+ GossipCellRendererTextPriv *priv;
+
+ priv = GET_PRIV (cell);
+
+ g_object_set (cell,
+ "ellipsize", PANGO_ELLIPSIZE_END,
+ NULL);
+
+ priv->name = g_strdup ("");
+ priv->status = g_strdup ("");
+ priv->show_status = TRUE;
+}
+
+static void
+cell_renderer_text_finalize (GObject *object)
+{
+ GossipCellRendererText *cell;
+ GossipCellRendererTextPriv *priv;
+
+ cell = GOSSIP_CELL_RENDERER_TEXT (object);
+ priv = GET_PRIV (cell);
+
+ g_free (priv->name);
+ g_free (priv->status);
+
+ (G_OBJECT_CLASS (gossip_cell_renderer_text_parent_class)->finalize) (object);
+}
+
+static void
+cell_renderer_text_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GossipCellRendererText *cell;
+ GossipCellRendererTextPriv *priv;
+
+ cell = GOSSIP_CELL_RENDERER_TEXT (object);
+ priv = GET_PRIV (cell);
+
+ switch (param_id) {
+ case PROP_NAME:
+ g_value_set_string (value, priv->name);
+ break;
+ case PROP_STATUS:
+ g_value_set_string (value, priv->status);
+ break;
+ case PROP_IS_GROUP:
+ g_value_set_boolean (value, priv->is_group);
+ break;
+ case PROP_SHOW_STATUS:
+ g_value_set_boolean (value, priv->show_status);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+cell_renderer_text_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GossipCellRendererText *cell;
+ GossipCellRendererTextPriv *priv;
+ const gchar *str;
+
+ cell = GOSSIP_CELL_RENDERER_TEXT (object);
+ priv = GET_PRIV (cell);
+
+ switch (param_id) {
+ case PROP_NAME:
+ g_free (priv->name);
+ str = g_value_get_string (value);
+ priv->name = g_strdup (str ? str : "");
+ g_strdelimit (priv->name, "\n\r\t", ' ');
+ priv->is_valid = FALSE;
+ break;
+ case PROP_STATUS:
+ g_free (priv->status);
+ str = g_value_get_string (value);
+ priv->status = g_strdup (str ? str : "");
+ g_strdelimit (priv->status, "\n\r\t", ' ');
+ priv->is_valid = FALSE;
+ break;
+ case PROP_IS_GROUP:
+ priv->is_group = g_value_get_boolean (value);
+ priv->is_valid = FALSE;
+ break;
+ case PROP_SHOW_STATUS:
+ priv->show_status = g_value_get_boolean (value);
+ priv->is_valid = FALSE;
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+cell_renderer_text_get_size (GtkCellRenderer *cell,
+ GtkWidget *widget,
+ GdkRectangle *cell_area,
+ gint *x_offset,
+ gint *y_offset,
+ gint *width,
+ gint *height)
+{
+ GossipCellRendererText *celltext;
+ GossipCellRendererTextPriv *priv;
+
+ celltext = GOSSIP_CELL_RENDERER_TEXT (cell);
+ priv = GET_PRIV (cell);
+
+ /* Only update if not already valid so we get the right size. */
+ cell_renderer_text_update_text (celltext, widget, priv->is_selected);
+
+ (GTK_CELL_RENDERER_CLASS (gossip_cell_renderer_text_parent_class)->get_size) (cell, widget,
+ cell_area,
+ x_offset, y_offset,
+ width, height);
+}
+
+static void
+cell_renderer_text_render (GtkCellRenderer *cell,
+ GdkWindow *window,
+ GtkWidget *widget,
+ GdkRectangle *background_area,
+ GdkRectangle *cell_area,
+ GdkRectangle *expose_area,
+ GtkCellRendererState flags)
+{
+ GossipCellRendererText *celltext;
+
+ celltext = GOSSIP_CELL_RENDERER_TEXT (cell);
+
+ cell_renderer_text_update_text (celltext,
+ widget,
+ (flags & GTK_CELL_RENDERER_SELECTED));
+
+ (GTK_CELL_RENDERER_CLASS (gossip_cell_renderer_text_parent_class)->render) (
+ cell, window,
+ widget,
+ background_area,
+ cell_area,
+ expose_area, flags);
+}
+
+static void
+cell_renderer_text_update_text (GossipCellRendererText *cell,
+ GtkWidget *widget,
+ gboolean selected)
+{
+ GossipCellRendererTextPriv *priv;
+ PangoAttrList *attr_list;
+ PangoAttribute *attr_color, *attr_style, *attr_size;
+ GtkStyle *style;
+ gchar *str;
+
+ priv = GET_PRIV (cell);
+
+ if (priv->is_valid && priv->is_selected == selected) {
+ return;
+ }
+
+ if (priv->is_group) {
+ g_object_set (cell,
+ "visible", TRUE,
+ "weight", PANGO_WEIGHT_BOLD,
+ "text", priv->name,
+ "attributes", NULL,
+ "xpad", 1,
+ "ypad", 1,
+ NULL);
+
+ priv->is_selected = selected;
+ priv->is_valid = TRUE;
+ return;
+ }
+
+ style = gtk_widget_get_style (widget);
+
+ attr_list = pango_attr_list_new ();
+
+ attr_style = pango_attr_style_new (PANGO_STYLE_ITALIC);
+ attr_style->start_index = strlen (priv->name) + 1;
+ attr_style->end_index = -1;
+ pango_attr_list_insert (attr_list, attr_style);
+
+ if (!selected) {
+ GdkColor color;
+
+ color = style->text_aa[GTK_STATE_NORMAL];
+
+ attr_color = pango_attr_foreground_new (color.red, color.green, color.blue);
+ attr_color->start_index = attr_style->start_index;
+ attr_color->end_index = -1;
+ pango_attr_list_insert (attr_list, attr_color);
+ }
+
+ attr_size = pango_attr_size_new (pango_font_description_get_size (style->font_desc) / 1.2);
+
+ attr_size->start_index = attr_style->start_index;
+ attr_size->end_index = -1;
+ pango_attr_list_insert (attr_list, attr_size);
+
+ if (!priv->status || !priv->status[0] || !priv->show_status) {
+ str = g_strdup (priv->name);
+ } else {
+ str = g_strdup_printf ("%s\n%s", priv->name, priv->status);
+ }
+
+ g_object_set (cell,
+ "visible", TRUE,
+ "weight", PANGO_WEIGHT_NORMAL,
+ "text", str,
+ "attributes", attr_list,
+ "xpad", 0,
+ "ypad", 1,
+ NULL);
+
+ g_free (str);
+ pango_attr_list_unref (attr_list);
+
+ priv->is_selected = selected;
+ priv->is_valid = TRUE;
+}
+
+GtkCellRenderer *
+gossip_cell_renderer_text_new (void)
+{
+ return g_object_new (GOSSIP_TYPE_CELL_RENDERER_TEXT, NULL);
+}
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Mikael Hallendal <micke@imendio.com>
+ */
+
+#ifndef __GOSSIP_CELL_RENDERER_TEXT_H__
+#define __GOSSIP_CELL_RENDERER_TEXT_H__
+
+#include <gtk/gtkcellrenderertext.h>
+
+G_BEGIN_DECLS
+
+#define GOSSIP_TYPE_CELL_RENDERER_TEXT (gossip_cell_renderer_text_get_type ())
+#define GOSSIP_CELL_RENDERER_TEXT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOSSIP_TYPE_CELL_RENDERER_TEXT, GossipCellRendererText))
+#define GOSSIP_CELL_RENDERER_TEXT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GOSSIP_TYPE_CELL_RENDERER_TEXT, GossipCellRendererTextClass))
+#define GOSSIP_IS_CELL_RENDERER_TEXT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOSSIP_TYPE_CELL_RENDERER_TEXT))
+#define GOSSIP_IS_CELL_RENDERER_TEXT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_CELL_RENDERER_TEXT))
+#define GOSSIP_CELL_RENDERER_TEXT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_CELL_RENDERER_TEXT, GossipCellRendererTextClass))
+
+typedef struct _GossipCellRendererText GossipCellRendererText;
+typedef struct _GossipCellRendererTextClass GossipCellRendererTextClass;
+typedef struct _GossipCellRendererTextPriv GossipCellRendererTextPriv;
+
+struct _GossipCellRendererText {
+ GtkCellRendererText parent;
+
+ GossipCellRendererTextPriv *priv;
+};
+
+struct _GossipCellRendererTextClass {
+ GtkCellRendererTextClass parent_class;
+};
+
+GType gossip_cell_renderer_text_get_type (void) G_GNUC_CONST;
+GtkCellRenderer * gossip_cell_renderer_text_new (void);
+
+G_END_DECLS
+
+#endif /* __GOSSIP_CELL_RENDERER_TEXT_H__ */
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Martyn Russell <martyn@imendio.com>
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <glib/gi18n.h>
+
+#include <libgossip/gossip-account.h>
+#include <libgossip/gossip-event.h>
+#include <libgossip/gossip-session.h>
+#include <libgossip/gossip-message.h>
+#include <libgossip/gossip-debug.h>
+#include <libgossip/gossip-event-manager.h>
+
+#include "gossip-app.h"
+#include "gossip-chat.h"
+#include "gossip-chat-manager.h"
+
+#define DEBUG_DOMAIN "ChatManager"
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CHAT_MANAGER, GossipChatManagerPriv))
+
+typedef struct _GossipChatManagerPriv GossipChatManagerPriv;
+
+struct _GossipChatManagerPriv {
+ GHashTable *chats;
+ GHashTable *events;
+};
+
+static void chat_manager_finalize (GObject *object);
+static void chat_manager_new_message_cb (GossipSession *session,
+ GossipMessage *msg,
+ GossipChatManager *manager);
+static void chat_manager_event_activated_cb (GossipEventManager *event_manager,
+ GossipEvent *event,
+ GObject *object);
+static void chat_manager_get_chats_foreach (GossipContact *contact,
+ GossipPrivateChat *chat,
+ GList **chats);
+static void chat_manager_chat_removed_cb (GossipChatManager *manager,
+ GossipChat *chat,
+ gboolean is_last_ref);
+
+G_DEFINE_TYPE (GossipChatManager, gossip_chat_manager, G_TYPE_OBJECT);
+
+static void
+gossip_chat_manager_class_init (GossipChatManagerClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = chat_manager_finalize;
+
+ g_type_class_add_private (object_class, sizeof (GossipChatManagerPriv));
+}
+
+static void
+gossip_chat_manager_init (GossipChatManager *manager)
+{
+ GossipChatManagerPriv *priv;
+
+ priv = GET_PRIV (manager);
+
+ priv->chats = g_hash_table_new_full (gossip_contact_hash,
+ gossip_contact_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) g_object_unref);
+
+ priv->events = g_hash_table_new_full (gossip_contact_hash,
+ gossip_contact_equal,
+ (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) g_object_unref);
+
+ /* Connect to signals on GossipSession to listen for new messages */
+ g_signal_connect (gossip_app_get_session (),
+ "new-message",
+ G_CALLBACK (chat_manager_new_message_cb),
+ manager);
+}
+
+static void
+chat_manager_finalize (GObject *object)
+{
+ GossipChatManagerPriv *priv;
+
+ priv = GET_PRIV (object);
+
+ g_hash_table_destroy (priv->chats);
+ g_hash_table_destroy (priv->events);
+
+ G_OBJECT_CLASS (gossip_chat_manager_parent_class)->finalize (object);
+}
+
+static void
+chat_manager_new_message_cb (GossipSession *session,
+ GossipMessage *message,
+ GossipChatManager *manager)
+{
+ GossipChatManagerPriv *priv;
+ GossipPrivateChat *chat;
+ GossipContact *sender;
+ GossipEvent *event = NULL;
+ GossipEvent *old_event;
+
+ priv = GET_PRIV (manager);
+
+ sender = gossip_message_get_sender (message);
+ chat = g_hash_table_lookup (priv->chats, sender);
+
+ old_event = g_hash_table_lookup (priv->events, sender);
+
+ /* Add event to event manager if one doesn't exist already. */
+ if (!chat) {
+ gossip_debug (DEBUG_DOMAIN, "New chat for: %s",
+ gossip_contact_get_id (sender));
+ chat = gossip_chat_manager_get_chat (manager, sender);
+
+ if (!old_event) {
+ event = gossip_event_new (GOSSIP_EVENT_NEW_MESSAGE);
+ }
+ } else {
+ GossipChatWindow *window;
+
+ window = gossip_chat_get_window (GOSSIP_CHAT (chat));
+
+ if (!window && !old_event) {
+ event = gossip_event_new (GOSSIP_EVENT_NEW_MESSAGE);
+ }
+ }
+
+ gossip_private_chat_append_message (chat, message);
+
+ if (event) {
+ gchar *str;
+
+ str = g_strdup_printf (_("New message from %s"),
+ gossip_contact_get_name (sender));
+ g_object_set (event,
+ "message", str,
+ "data", message,
+ NULL);
+ g_free (str);
+
+ gossip_event_manager_add (gossip_app_get_event_manager (),
+ event,
+ chat_manager_event_activated_cb,
+ G_OBJECT (manager));
+
+ g_hash_table_insert (priv->events,
+ g_object_ref (sender),
+ g_object_ref (event));
+ }
+}
+
+static void
+chat_manager_event_activated_cb (GossipEventManager *event_manager,
+ GossipEvent *event,
+ GObject *object)
+{
+ GossipMessage *message;
+ GossipContact *contact;
+
+ message = GOSSIP_MESSAGE (gossip_event_get_data (event));
+ contact = gossip_message_get_sender (message);
+
+ gossip_chat_manager_show_chat (GOSSIP_CHAT_MANAGER (object), contact);
+}
+
+static void
+chat_manager_get_chats_foreach (GossipContact *contact,
+ GossipPrivateChat *chat,
+ GList **chats)
+{
+ const gchar *contact_id;
+
+ contact_id = gossip_contact_get_id (contact);
+ *chats = g_list_prepend (*chats, g_strdup (contact_id));
+}
+
+GossipChatManager *
+gossip_chat_manager_new (void)
+{
+ return g_object_new (GOSSIP_TYPE_CHAT_MANAGER, NULL);
+}
+
+static void
+chat_manager_chat_removed_cb (GossipChatManager *manager,
+ GossipChat *chat,
+ gboolean is_last_ref)
+{
+ GossipChatManagerPriv *priv;
+ GossipContact *contact;
+
+ if (!is_last_ref) {
+ return;
+ }
+
+ priv = GET_PRIV (manager);
+
+ contact = gossip_chat_get_contact (chat);
+
+ gossip_debug (DEBUG_DOMAIN,
+ "Removing an old chat:'%s'",
+ gossip_contact_get_id (contact));
+
+ g_hash_table_remove (priv->chats, contact);
+}
+
+GossipPrivateChat *
+gossip_chat_manager_get_chat (GossipChatManager *manager,
+ GossipContact *contact)
+{
+ GossipChatManagerPriv *priv;
+ GossipPrivateChat *chat;
+
+ g_return_val_if_fail (GOSSIP_IS_CHAT_MANAGER (manager), NULL);
+ g_return_val_if_fail (GOSSIP_IS_CONTACT (contact), NULL);
+
+ priv = GET_PRIV (manager);
+
+ chat = g_hash_table_lookup (priv->chats, contact);
+
+ if (!chat) {
+ GossipSession *session;
+ GossipAccount *account;
+ GossipContact *own_contact;
+
+ session = gossip_app_get_session ();
+ account = gossip_contact_get_account (contact);
+ own_contact = gossip_session_get_own_contact (session, account);
+
+ chat = gossip_private_chat_new (own_contact, contact);
+ g_hash_table_insert (priv->chats,
+ g_object_ref (contact),
+ chat);
+ g_object_add_toggle_ref (G_OBJECT (chat),
+ (GToggleNotify) chat_manager_chat_removed_cb,
+ manager);
+
+ gossip_debug (DEBUG_DOMAIN,
+ "Creating a new chat:'%s'",
+ gossip_contact_get_id (contact));
+ }
+
+ return chat;
+}
+
+GList *
+gossip_chat_manager_get_chats (GossipChatManager *manager)
+{
+ GossipChatManagerPriv *priv;
+ GList *chats = NULL;
+
+ g_return_val_if_fail (GOSSIP_IS_CHAT_MANAGER (manager), NULL);
+
+ priv = GET_PRIV (manager);
+
+ g_hash_table_foreach (priv->chats,
+ (GHFunc) chat_manager_get_chats_foreach,
+ &chats);
+
+ chats = g_list_sort (chats, (GCompareFunc) strcmp);
+
+ return chats;
+}
+
+void
+gossip_chat_manager_remove_events (GossipChatManager *manager,
+ GossipContact *contact)
+{
+ GossipChatManagerPriv *priv;
+ GossipEvent *event;
+
+ g_return_if_fail (GOSSIP_IS_CHAT_MANAGER (manager));
+ g_return_if_fail (GOSSIP_IS_CONTACT (contact));
+
+ gossip_debug (DEBUG_DOMAIN,
+ "Removing events for contact:'%s'",
+ gossip_contact_get_id (contact));
+
+ priv = GET_PRIV (manager);
+
+ event = g_hash_table_lookup (priv->events, contact);
+ if (event) {
+ gossip_event_manager_remove (gossip_app_get_event_manager (),
+ event, G_OBJECT (manager));
+ g_hash_table_remove (priv->events, contact);
+ }
+}
+
+void
+gossip_chat_manager_show_chat (GossipChatManager *manager,
+ GossipContact *contact)
+{
+ GossipPrivateChat *chat;
+
+ g_return_if_fail (GOSSIP_IS_CHAT_MANAGER (manager));
+ g_return_if_fail (GOSSIP_IS_CONTACT (contact));
+
+ chat = gossip_chat_manager_get_chat (manager, contact);
+
+ gossip_chat_present (GOSSIP_CHAT (chat));
+
+ gossip_chat_manager_remove_events(manager, contact);
+}
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2004-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Martyn Russell <martyn@imendio.com>
+ */
+
+#ifndef __GOSSIP_CHAT_MANAGER_H__
+#define __GOSSIP_CHAT_MANAGER_H__
+
+#include <glib-object.h>
+
+#include <libempathy/gossip-contact.h>
+
+G_BEGIN_DECLS
+
+#define GOSSIP_TYPE_CHAT_MANAGER (gossip_chat_manager_get_type ())
+#define GOSSIP_CHAT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GOSSIP_TYPE_CHAT_MANAGER, GossipChatManager))
+#define GOSSIP_CHAT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GOSSIP_TYPE_CHAT_MANAGER, GossipChatManagerClass))
+#define GOSSIP_IS_CHAT_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GOSSIP_TYPE_CHAT_MANAGER))
+#define GOSSIP_IS_CHAT_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GOSSIP_TYPE_CHAT_MANAGER))
+#define GOSSIP_CHAT_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GOSSIP_TYPE_CHAT_MANAGER, GossipChatManagerClass))
+
+typedef struct _GossipChatManager GossipChatManager;
+typedef struct _GossipChatManagerClass GossipChatManagerClass;
+
+#include "gossip-private-chat.h"
+
+struct _GossipChatManager {
+ GObject parent;
+};
+
+struct _GossipChatManagerClass {
+ GObjectClass parent_class;
+};
+
+GType gossip_chat_manager_get_type (void) G_GNUC_CONST;
+GossipChatManager *gossip_chat_manager_new (void);
+GossipPrivateChat *gossip_chat_manager_get_chat (GossipChatManager *manager,
+ GossipContact *contact);
+GList * gossip_chat_manager_get_chats (GossipChatManager *manager);
+void gossip_chat_manager_remove_events (GossipChatManager *manager,
+ GossipContact *contact);
+void gossip_chat_manager_show_chat (GossipChatManager *manager,
+ GossipContact *contact);
+
+G_END_DECLS
+
+#endif /* __GOSSIP_CHAT_MANAGER_H__ */
+
--- /dev/null
+# gossip-chat-manager.lo - a libtool object file
+# Generated by ltmain.sh - GNU libtool 1.5.22 Debian 1.5.22-4 (1.1220.2.365 2005/12/18 22:14:06)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002-2007 Imendio AB
+ *
+ * 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.
+ *
+ * Authors: Mikael Hallendal <micke@imendio.com>
+ * Richard Hult <richard@imendio.com>
+ * Martyn Russell <martyn@imendio.com>
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <string.h>
+#include <time.h>
+
+#include <glib/gi18n.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkimage.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkimagemenuitem.h>
+#include <gtk/gtkstock.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtksizegroup.h>
+#include <glade/glade.h>
+
+#include <libmissioncontrol/mc-account.h>
+
+#include <libempathy/gossip-utils.h>
+#include <libempathy/gossip-debug.h>
+#include <libempathy/gossip-conf.h>
+
+#include "gossip-chat-view.h"
+#include "gossip-chat.h"
+#include "gossip-preferences.h"
+#include "gossip-theme-manager.h"
+#include "gossip-ui-utils.h"
+
+#define DEBUG_DOMAIN "ChatView"
+
+/* Number of seconds between timestamps when using normal mode, 5 minutes. */
+#define TIMESTAMP_INTERVAL 300
+
+#define MAX_LINES 800
+
+#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GOSSIP_TYPE_CHAT_VIEW, GossipChatViewPriv))
+
+typedef enum {
+ BLOCK_TYPE_NONE,
+ BLOCK_TYPE_SELF,
+ BLOCK_TYPE_OTHER,
+ BLOCK_TYPE_EVENT,
+ BLOCK_TYPE_TIME,
+ BLOCK_TYPE_INVITE
+} BlockType;
+
+struct _GossipChatViewPriv {
+ GtkTextBuffer *buffer;
+
+ gboolean irc_style;
+ time_t last_timestamp;
+ BlockType last_block_type;
+
+ gboolean allow_scrolling;
+ gboolean is_group_chat;
+
+ GtkTextMark *find_mark_previous;
+ GtkTextMark *find_mark_next;
+ gboolean find_wrapped;
+ gboolean find_last_direction;
+
+ /* This is for the group chat so we know if the "other" last contact
+ * changed, so we know whether to insert a header or not.
+ */
+ GossipContact *last_contact;
+
+ guint notify_system_fonts_id;
+ guint notify_show_avatars_id;
+};
+
+typedef struct {
+ GossipSmiley smiley;
+ const gchar *pattern;
+} GossipSmileyPattern;
+
+static const GossipSmileyPattern smileys[] = {
+ /* Forward smileys. */
+ { GOSSIP_SMILEY_NORMAL, ":)" },
+ { GOSSIP_SMILEY_WINK, ";)" },
+ { GOSSIP_SMILEY_WINK, ";-)" },
+ { GOSSIP_SMILEY_BIGEYE, "=)" },
+ { GOSSIP_SMILEY_NOSE, ":-)" },
+ { GOSSIP_SMILEY_CRY, ":'(" },
+ { GOSSIP_SMILEY_SAD, ":(" },
+ { GOSSIP_SMILEY_SAD, ":-(" },
+ { GOSSIP_SMILEY_SCEPTICAL, ":/" },
+ { GOSSIP_SMILEY_SCEPTICAL, ":\\" },
+ { GOSSIP_SMILEY_BIGSMILE, ":D" },
+ { GOSSIP_SMILEY_BIGSMILE, ":-D" },
+ { GOSSIP_SMILEY_INDIFFERENT, ":|" },
+ { GOSSIP_SMILEY_TOUNGE, ":p" },
+ { GOSSIP_SMILEY_TOUNGE, ":-p" },
+ { GOSSIP_SMILEY_TOUNGE, ":P" },
+ { GOSSIP_SMILEY_TOUNGE, ":-P" },
+ { GOSSIP_SMILEY_TOUNGE, ";p" },
+ { GOSSIP_SMILEY_TOUNGE, ";-p" },
+ { GOSSIP_SMILEY_TOUNGE, ";P" },
+ { GOSSIP_SMILEY_TOUNGE, ";-P" },
+ { GOSSIP_SMILEY_SHOCKED, ":o" },
+ { GOSSIP_SMILEY_SHOCKED, ":-o" },
+ { GOSSIP_SMILEY_SHOCKED, ":O" },
+ { GOSSIP_SMILEY_SHOCKED, ":-O" },
+ { GOSSIP_SMILEY_COOL, "8)" },
+ { GOSSIP_SMILEY_COOL, "B)" },
+ { GOSSIP_SMILEY_SORRY, "*|" },
+ { GOSSIP_SMILEY_KISS, ":*" },
+ { GOSSIP_SMILEY_SHUTUP, ":#" },
+ { GOSSIP_SMILEY_SHUTUP, ":-#" },
+ { GOSSIP_SMILEY_YAWN, "|O" },
+ { GOSSIP_SMILEY_CONFUSED, ":S" },
+ { GOSSIP_SMILEY_CONFUSED, ":s" },
+ { GOSSIP_SMILEY_ANGEL, "<)" },
+ { GOSSIP_SMILEY_OOOH, ":x" },
+ { GOSSIP_SMILEY_LOOKAWAY, "*)" },
+ { GOSSIP_SMILEY_LOOKAWAY, "*-)" },
+ { GOSSIP_SMILEY_BLUSH, "*S" },
+ { GOSSIP_SMILEY_BLUSH, "*s" },
+ { GOSSIP_SMILEY_BLUSH, "*$" },
+ { GOSSIP_SMILEY_COOLBIGSMILE, "8D" },
+ { GOSSIP_SMILEY_ANGRY, ":@" },
+ { GOSSIP_SMILEY_BOSS, "@)" },
+ { GOSSIP_SMILEY_MONKEY, "#)" },
+ { GOSSIP_SMILEY_SILLY, "O)" },
+ { GOSSIP_SMILEY_SICK, "+o(" },
+
+ /* Backward smileys. */
+ { GOSSIP_SMILEY_NORMAL, "(:" },
+ { GOSSIP_SMILEY_WINK, "(;" },
+ { GOSSIP_SMILEY_WINK, "(-;" },
+ { GOSSIP_SMILEY_BIGEYE, "(=" },
+ { GOSSIP_SMILEY_NOSE, "(-:" },
+ { GOSSIP_SMILEY_CRY, ")':" },
+ { GOSSIP_SMILEY_SAD, "):" },
+ { GOSSIP_SMILEY_SAD, ")-:" },
+ { GOSSIP_SMILEY_SCEPTICAL, "/:" },
+ { GOSSIP_SMILEY_SCEPTICAL, "//:" },
+ { GOSSIP_SMILEY_INDIFFERENT, "|:" },
+ { GOSSIP_SMILEY_TOUNGE, "d:" },
+ { GOSSIP_SMILEY_TOUNGE, "d-:" },
+ { GOSSIP_SMILEY_TOUNGE, "d;" },
+ { GOSSIP_SMILEY_TOUNGE, "d-;" },
+ { GOSSIP_SMILEY_SHOCKED, "o:" },
+ { GOSSIP_SMILEY_SHOCKED, "O:" },
+ { GOSSIP_SMILEY_COOL, "(8" },
+ { GOSSIP_SMILEY_COOL, "(B" },
+ { GOSSIP_SMILEY_SORRY, "|*" },
+ { GOSSIP_SMILEY_KISS, "*:" },
+ { GOSSIP_SMILEY_SHUTUP, "#:" },
+ { GOSSIP_SMILEY_SHUTUP, "#-:" },
+ { GOSSIP_SMILEY_YAWN, "O|" },
+ { GOSSIP_SMILEY_CONFUSED, "S:" },
+ { GOSSIP_SMILEY_CONFUSED, "s:" },
+ { GOSSIP_SMILEY_ANGEL, "(>" },
+ { GOSSIP_SMILEY_OOOH, "x:" },
+ { GOSSIP_SMILEY_LOOKAWAY, "(*" },
+ { GOSSIP_SMILEY_LOOKAWAY, "(-*" },
+ { GOSSIP_SMILEY_BLUSH, "S*" },
+ { GOSSIP_SMILEY_BLUSH, "s*" },
+ { GOSSIP_SMILEY_BLUSH, "$*" },
+ { GOSSIP_SMILEY_ANGRY, "@:" },
+ { GOSSIP_SMILEY_BOSS, "(@" },
+ { GOSSIP_SMILEY_MONKEY, "#)" },
+ { GOSSIP_SMILEY_SILLY, "(O" },
+ { GOSSIP_SMILEY_SICK, ")o+" }
+};
+
+static void gossip_chat_view_class_init (GossipChatViewClass *klass);
+static void gossip_chat_view_init (GossipChatView *view);
+static void chat_view_finalize (GObject *object);
+static gboolean chat_view_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time);
+static void chat_view_size_allocate (GtkWidget *widget,
+ GtkAllocation *alloc);
+static void chat_view_setup_tags (GossipChatView *view);
+static void chat_view_system_font_update (GossipChatView *view);
+static void chat_view_notify_system_font_cb (GossipConf *conf,
+ const gchar *key,
+ gpointer user_data);
+static void chat_view_notify_show_avatars_cb (GossipConf *conf,
+ const gchar *key,
+ gpointer user_data);
+static void chat_view_populate_popup (GossipChatView *view,
+ GtkMenu *menu,
+ gpointer user_data);
+static gboolean chat_view_event_cb (GossipChatView *view,
+ GdkEventMotion *event,
+ GtkTextTag *tag);
+static gboolean chat_view_url_event_cb (GtkTextTag *tag,
+ GObject *object,
+ GdkEvent *event,
+ GtkTextIter *iter,
+ GtkTextBuffer *buffer);
+static void chat_view_open_address_cb (GtkMenuItem *menuitem,
+ const gchar *url);
+static void chat_view_copy_address_cb (GtkMenuItem *menuitem,
+ const gchar *url);
+static void chat_view_clear_view_cb (GtkMenuItem *menuitem,
+ GossipChatView *view);
+static void chat_view_insert_text_with_emoticons (GtkTextBuffer *buf,
+ GtkTextIter *iter,
+ const gchar *str);
+static gboolean chat_view_is_scrolled_down (GossipChatView *view);
+static void chat_view_theme_changed_cb (GossipThemeManager *manager,
+ GossipChatView *view);
+static void chat_view_maybe_append_date_and_time (GossipChatView *view,
+ GossipMessage *msg);
+static void chat_view_append_spacing (GossipChatView *view);
+static void chat_view_append_text (GossipChatView *view,
+ const gchar *body,
+ const gchar *tag);
+static void chat_view_maybe_append_fancy_header (GossipChatView *view,
+ GossipMessage *msg);
+static void chat_view_append_irc_action (GossipChatView *view,
+ GossipMessage *msg);
+static void chat_view_append_fancy_action (GossipChatView *view,
+ GossipMessage *msg);
+static void chat_view_append_irc_message (GossipChatView *view,
+ GossipMessage *msg);
+static void chat_view_append_fancy_message (GossipChatView *view,
+ GossipMessage *msg);
+
+G_DEFINE_TYPE (GossipChatView, gossip_chat_view, GTK_TYPE_TEXT_VIEW);
+
+static void
+gossip_chat_view_class_init (GossipChatViewClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->finalize = chat_view_finalize;
+ widget_class->size_allocate = chat_view_size_allocate;
+ widget_class->drag_motion = chat_view_drag_motion;
+
+ g_type_class_add_private (object_class, sizeof (GossipChatViewPriv));
+}
+
+static void
+gossip_chat_view_init (GossipChatView *view)
+{
+ GossipChatViewPriv *priv;
+ gboolean show_avatars;
+
+ priv = GET_PRIV (view);
+
+ priv->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+ priv->last_block_type = BLOCK_TYPE_NONE;
+ priv->last_timestamp = 0;
+
+ priv->allow_scrolling = TRUE;
+
+ priv->is_group_chat = FALSE;
+
+ g_object_set (view,
+ "wrap-mode", GTK_WRAP_WORD_CHAR,
+ "editable", FALSE,
+ "cursor-visible", FALSE,
+ NULL);
+
+ priv->notify_system_fonts_id =
+ gossip_conf_notify_add (gossip_conf_get (),
+ "/desktop/gnome/interface/document_font_name",
+ chat_view_notify_system_font_cb,
+ view);
+ chat_view_system_font_update (view);
+
+ priv->notify_show_avatars_id =
+ gossip_conf_notify_add (gossip_conf_get (),
+ GOSSIP_PREFS_UI_SHOW_AVATARS,
+ chat_view_notify_show_avatars_cb,
+ view);
+
+ chat_view_setup_tags (view);
+
+ gossip_theme_manager_apply_saved (gossip_theme_manager_get (), view);
+
+ show_avatars = FALSE;
+ gossip_conf_get_bool (gossip_conf_get (),
+ GOSSIP_PREFS_UI_SHOW_AVATARS,
+ &show_avatars);
+
+ gossip_theme_manager_update_show_avatars (gossip_theme_manager_get (),
+ view, show_avatars);
+
+ g_signal_connect (view,
+ "populate-popup",
+ G_CALLBACK (chat_view_populate_popup),
+ NULL);
+
+ g_signal_connect_object (gossip_theme_manager_get (),
+ "theme-changed",
+ G_CALLBACK (chat_view_theme_changed_cb),
+ view,
+ 0);
+}
+
+static void
+chat_view_finalize (GObject *object)
+{
+ GossipChatView *view;
+ GossipChatViewPriv *priv;
+
+ view = GOSSIP_CHAT_VIEW (object);
+ priv = GET_PRIV (view);
+
+ gossip_debug (DEBUG_DOMAIN, "finalize: %p", object);
+
+ gossip_conf_notify_remove (gossip_conf_get (), priv->notify_system_fonts_id);
+ gossip_conf_notify_remove (gossip_conf_get (), priv->notify_show_avatars_id);
+
+ if (priv->last_contact) {
+ g_object_unref (priv->last_contact);
+ }
+
+ G_OBJECT_CLASS (gossip_chat_view_parent_class)->finalize (object);
+}
+
+static gboolean
+chat_view_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ /* Don't handle drag motion, since we don't want the view to scroll as
+ * the result of dragging something across it.
+ */
+
+ return FALSE;
+}
+
+static void
+chat_view_size_allocate (GtkWidget *widget,
+ GtkAllocation *alloc)
+{
+ gboolean down;
+
+ down = chat_view_is_scrolled_down (GOSSIP_CHAT_VIEW (widget));
+
+ GTK_WIDGET_CLASS (gossip_chat_view_parent_class)->size_allocate (widget, alloc);
+
+ if (down) {
+ gossip_chat_view_scroll_down (GOSSIP_CHAT_VIEW (widget));
+ }
+}
+
+static void
+chat_view_setup_tags (GossipChatView *view)
+{
+ GossipChatViewPriv *priv;
+ GtkTextTag *tag;
+
+ priv = GET_PRIV (view);
+
+ gtk_text_buffer_create_tag (priv->buffer,
+ "cut",
+ NULL);
+
+ /* FIXME: Move to the theme and come up with something that looks a bit
+ * nicer.
+ */
+ gtk_text_buffer_create_tag (priv->buffer,
+ "highlight",
+ "background", "yellow",
+ NULL);
+
+ tag = gtk_text_buffer_create_tag (priv->buffer,
+ "link",
+ NULL);
+
+ g_signal_connect (tag,
+ "event",
+ G_CALLBACK (chat_view_url_event_cb),
+ priv->buffer);
+
+ g_signal_connect (view,
+ "motion-notify-event",
+ G_CALLBACK (chat_view_event_cb),
+ tag);
+}
+
+static void
+chat_view_system_font_update (GossipChatView *view)
+{
+ PangoFontDescription *font_description = NULL;
+ gchar *font_name;
+
+ if (gossip_conf_get_string (gossip_conf_get (),
+ "/desktop/gnome/interface/document_font_name",
+ &font_name) && font_name) {
+ font_description = pango_font_description_from_string (font_name);
+ g_free (font_name);
+ } else {
+ font_description = NULL;
+ }
+
+ gtk_widget_modify_font (GTK_WIDGET (view), font_description);
+
+ if (font_description) {
+ pango_font_description_free (font_description);
+ }
+}
+
+static void
+chat_view_notify_system_font_cb (GossipConf *conf,
+ const gchar *key,
+ gpointer user_data)
+{
+ GossipChatView *view;
+ gboolean show_avatars = FALSE;
+
+ view = user_data;
+
+ chat_view_system_font_update (view);
+
+ /* Ugly, again, to adjust the vertical position of the nick... Will fix
+ * this when reworking the theme manager so that view register
+ * themselves with it instead of the other way around.
+ */
+ gossip_conf_get_bool (conf,
+ GOSSIP_PREFS_UI_SHOW_AVATARS,
+ &show_avatars);
+
+ gossip_theme_manager_update_show_avatars (gossip_theme_manager_get (),
+ view, show_avatars);
+}
+
+static void
+chat_view_notify_show_avatars_cb (GossipConf *conf,
+ const gchar *key,
+ gpointer user_data)
+{
+ GossipChatView *view;
+ GossipChatViewPriv *priv;
+ gboolean show_avatars = FALSE;
+
+ view = user_data;
+ priv = GET_PRIV (view);
+
+ gossip_conf_get_bool (conf, key, &show_avatars);
+
+ gossip_theme_manager_update_show_avatars (gossip_theme_manager_get (),
+ view, show_avatars);
+}
+
+static void
+chat_view_populate_popup (GossipChatView *view,
+ GtkMenu *menu,
+ gpointer user_data)
+{
+ GossipChatViewPriv *priv;
+ GtkTextTagTable *table;
+ GtkTextTag *tag;
+ gint x, y;
+ GtkTextIter iter, start, end;
+ GtkWidget *item;
+ gchar *str = NULL;
+
+ priv = GET_PRIV (view);
+
+ /* Clear menu item */
+ if (gtk_text_buffer_get_char_count (priv->buffer) > 0) {
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ item = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ g_signal_connect (item,
+ "activate",
+ G_CALLBACK (chat_view_clear_view_cb),
+ view);
+ }
+
+ /* Link context menu items */
+ table = gtk_text_buffer_get_tag_table (priv->buffer);
+ tag = gtk_text_tag_table_lookup (table, "link");
+
+ gtk_widget_get_pointer (GTK_WIDGET (view), &x, &y);
+
+ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view),
+ GTK_TEXT_WINDOW_WIDGET,
+ x, y,
+ &x, &y);
+
+ gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view), &iter, x, y);
+
+ start = end = iter;
+
+ if (gtk_text_iter_backward_to_tag_toggle (&start, tag) &&
+ gtk_text_iter_forward_to_tag_toggle (&end, tag)) {
+ str = gtk_text_buffer_get_text (priv->buffer,
+ &start, &end, FALSE);
+ }
+
+ if (G_STR_EMPTY (str)) {
+ g_free (str);
+ return;
+ }
+
+ /* NOTE: Set data just to get the string freed when not needed. */
+ g_object_set_data_full (G_OBJECT (menu),
+ "url", str,
+ (GDestroyNotify) g_free);
+
+ item = gtk_menu_item_new ();
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Copy Link Address"));
+ g_signal_connect (item,
+ "activate",
+ G_CALLBACK (chat_view_copy_address_cb),
+ str);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+
+ item = gtk_menu_item_new_with_mnemonic (_("_Open Link"));
+ g_signal_connect (item,
+ "activate",
+ G_CALLBACK (chat_view_open_address_cb),
+ str);
+ gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show (item);
+}
+
+static gboolean
+chat_view_event_cb (GossipChatView *view,
+ GdkEventMotion *event,
+ GtkTextTag *tag)
+{
+ static GdkCursor *hand = NULL;
+ static GdkCursor *beam = NULL;
+ GtkTextWindowType type;
+ GtkTextIter iter;
+ GdkWindow *win;
+ gint x, y, buf_x, buf_y;
+
+ type = gtk_text_view_get_window_type (GTK_TEXT_VIEW (view),
+ event->window);
+
+ if (type != GTK_TEXT_WINDOW_TEXT) {
+ return FALSE;
+ }
+
+ /* Get where the pointer really is. */
+ win = gtk_text_view_get_window (GTK_TEXT_VIEW (view), type);
+ if (!win) {
+ return FALSE;
+ }
+
+ gdk_window_get_pointer (win, &x, &y, NULL);
+
+ /* Get the iter where the cursor is at */
+ gtk_text_view_window_to_buffer_coords (GTK_TEXT_VIEW (view), type,
+ x, y,
+ &buf_x, &buf_y);
+
+ gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (view),
+ &iter,
+ buf_x, buf_y);
+
+ if (gtk_text_iter_has_tag (&iter, tag)) {
+ if (!hand) {
+ hand = gdk_cursor_new (GDK_HAND2);
+ beam = gdk_cursor_new (GDK_XTERM);
+ }
+ gdk_window_set_cursor (win, hand);
+ } else {
+ if (!beam) {
+ beam = gdk_cursor_new (GDK_XTERM);
+ }
+ gdk_window_set_cursor (win, beam);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+chat_view_url_event_cb (GtkTextTag *tag,
+ GObject *object,
+ GdkEvent *event,
+ GtkTextIter *iter,
+ GtkTextBuffer *buffer)
+{
+ GtkTextIter start, end;
+ gchar *str;
+
+ /* If the link is being selected, don't do anything. */
+ gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+ if (gtk_text_iter_get_offset (&start) != gtk_text_iter_get_offset (&end)) {
+ return FALSE;
+ }
+
+ if (event->type == GDK_BUTTON_RELEASE && event->button.button == 1) {
+ start = end = *iter;
+
+ if (gtk_text_iter_backward_to_tag_toggle (&start, tag) &&
+ gtk_text_iter_forward_to_tag_toggle (&end, tag)) {
+ str = gtk_text_buffer_get_text (buffer,
+ &start,
+ &end,
+ FALSE);
+
+ gossip_url_show (str);
+ g_free (str);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+chat_view_open_address_cb (GtkMenuItem *menuitem, const gchar *url)
+{
+ gossip_url_show (url);
+}
+
+static void
+chat_view_copy_address_cb (GtkMenuItem *menuitem, const gchar *url)
+{
+ GtkClipboard *clipboard;
+
+ clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text (clipboard, url, -1);
+
+ clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+ gtk_clipboard_set_text (clipboard, url, -1);
+}
+
+static void
+chat_view_clear_view_cb (GtkMenuItem *menuitem, GossipChatView *view)
+{
+ gossip_chat_view_clear (view);
+}
+
+static void
+chat_view_insert_text_with_emoticons (GtkTextBuffer *buf,
+ GtkTextIter *iter,
+ const gchar *str)
+{
+ const gchar *p;
+ gunichar c, prev_c;
+ gint i;
+ gint match;
+ gint submatch;
+ gboolean use_smileys = FALSE;
+
+ gossip_conf_get_bool (gossip_conf_get (),
+ GOSSIP_PREFS_CHAT_SHOW_SMILEYS,
+ &n